added delete function to product table

This commit is contained in:
2026-05-29 23:04:41 +02:00
parent 6bacd1c605
commit 9cab32ddea
6 changed files with 97 additions and 8 deletions
+1
View File
@@ -35,6 +35,7 @@ CREATE TABLE IF NOT EXISTS products (
picture VARCHAR(500) DEFAULT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
deleted BOOLEAN DEFAULT FALSE NOT NULL,
FOREIGN KEY (storage_location) REFERENCES storage_locations(uuid) ON DELETE CASCADE
);
@@ -90,6 +90,7 @@ export const allProducts = async () => {
p.updated_at
FROM products p
JOIN storage_locations s ON p.storage_location = s.uuid
WHERE p.deleted = 0
`);
if (result.length > 0) {
@@ -137,3 +138,16 @@ export const updateItem = async (itemUUID, newValues) => {
return { code: "ep005" }; // error
}
};
export const deleteProduct = async (uuid) => {
const [result] = await pool.query(
`UPDATE products SET deleted = 1 WHERE uuid = UUID_TO_BIN(?);`,
[uuid],
);
if (result.affectedRows > 0) {
return { code: "sp006" }; // success
} else {
return { code: "ep006" }; // error
}
};
+30
View File
@@ -3,6 +3,7 @@ import dotenv from "dotenv";
import { authenticate } from "../../services/tokenService.js";
import {
allProducts,
deleteProduct,
newProduct,
productDetails,
setAmount,
@@ -147,4 +148,33 @@ router.post("/mutate/update-item", authenticate, async (req, res) => {
}
});
router.post("/delete-selection", authenticate, async (req, res) => {
let isError = false;
const uuidArray = req.body;
for (const uuid of uuidArray) {
const response = await deleteProduct(uuid);
if (response.code === "ep006" || !response) {
isError = true;
break;
}
}
if (isError === false) {
res.status(202).json({
success: true,
code: "sp006",
data: null,
message: "",
});
} else {
res.status(500).json({
success: false,
code: "ep006",
data: null,
message: "",
});
}
});
export default router;
+34 -7
View File
@@ -25,8 +25,8 @@ import FilterListIcon from "@mui/icons-material/FilterList";
import KeyboardArrowLeftIcon from "@mui/icons-material/KeyboardArrowLeft";
import KeyboardArrowRightIcon from "@mui/icons-material/KeyboardArrowRight";
import ArrowDownwardIcon from "@mui/icons-material/ArrowDownward";
import { useQuery } from "@tanstack/react-query";
import { getProducts } from "../utils/uxFncs";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { getProducts, deleteSelectedProducts } from "../utils/uxFncs";
import { visuallyHidden } from "@mui/utils";
import { formatDate } from "../utils/uxFncs";
import Cookies from "js-cookie";
@@ -182,8 +182,22 @@ const EnhancedTableHead = (props: EnhancedTableHeadProps) => {
);
};
const EnhancedTableToolbar = ({ numSelected }: { numSelected: number }) => {
const EnhancedTableToolbar = ({
numSelected,
selected,
}: {
numSelected: number;
selected: readonly string[];
}) => {
const { t } = useTranslation();
const queryClient = useQueryClient();
const { mutate } = useMutation({
mutationFn: (values: string[]) => deleteSelectedProducts(values),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["products"] });
},
});
return (
<Box
@@ -205,16 +219,26 @@ const EnhancedTableToolbar = ({ numSelected }: { numSelected: number }) => {
>
{numSelected > 0 ? (
<Typography sx={{ flex: "1 1 100%" }} component="div">
{numSelected} ausgewahlt
{numSelected} {t("selected")}
</Typography>
) : (
<Typography level="body-lg" sx={{ flex: "1 1 100%" }} component="div">
<Typography
level="body-lg"
fontWeight={"bold"}
sx={{ flex: "1 1 100%" }}
component="div"
>
{t("inventory")}
</Typography>
)}
{numSelected > 0 ? (
<Tooltip title="Delete">
<IconButton size="sm" color="danger" variant="solid">
<IconButton
onClick={() => mutate([...selected])}
size="sm"
color="danger"
variant="solid"
>
<DeleteIcon />
</IconButton>
</Tooltip>
@@ -346,7 +370,10 @@ export const InventoryPage = () => {
variant="outlined"
className="mt-6 overflow-hidden rounded-2xl border border-slate-200 bg-white/80 shadow-sm"
>
<EnhancedTableToolbar numSelected={selected.length} />
<EnhancedTableToolbar
numSelected={selected.length}
selected={selected}
/>
<Table
aria-labelledby="tableTitle"
hoverRow
+2 -1
View File
@@ -38,5 +38,6 @@
"quick-tips-1": "Update the app name to personalize the sidebar and login header.",
"quick-tips-2": "Choose a currency code that matches your pricing display, e.g. EUR, CHF, or USD.",
"settings-sub": "Manage your app preferences and store defaults.",
"preferences": "Preferences"
"preferences": "Preferences",
"selected": "selected"
}
+16
View File
@@ -273,3 +273,19 @@ export const fetchSettings = async () => {
return { success: true, data: response.data, code: response.code };
}
};
export const deleteSelectedProducts = async (uuids: string[]) => {
const result = await fetch(`${API_BASE}/products/delete-selection`, {
method: "POST",
body: JSON.stringify(uuids),
headers: {
Authorization: `Bearer ${Cookies.get("token") || ""}`,
"Content-Type": "application/json",
Accept: "application/json",
},
});
const response = await result.json();
console.log(response);
};