Commit 568e03d1 authored by Nawasan Wisitsingkhon's avatar Nawasan Wisitsingkhon

delete product

parent bbf90a9e
...@@ -25,15 +25,61 @@ const AdminProductController = { ...@@ -25,15 +25,61 @@ const AdminProductController = {
await db.$disconnect(); await db.$disconnect();
res.json({ status: 201, message: "add product success" }); res.json({ status: 201, message: "add product success" });
} catch (err) { } catch (err) {
console.log(err); console.log(err);
res.json({ res.json({
status: 200, status: 200,
message: "error in server", message: "error in server",
err err,
}); });
} }
}, },
/**
*
* @param {Request} req
* @param {Response} res
*/
async update(req, res) {
try {
const { id, name, price, detail, discount, stock, image, category } =
req.body;
await db.product.update({
where: { id: Number(id) },
data: {
name,
price,
detail,
discount: Number(discount),
stock,
image,
cateId: Number(category),
},
});
await db.$disconnect();
return res.json({ status: 301, message: "update success" });
} catch (err) {
console.log(err);
res.json({
status: 300,
message: "update failed with some error on server",
});
}
},
/**
*
* @param {Request} req
* @param {Response} res
*/
async delete(req, res) {
try {
const { id } = req.query;
if (!id) throw 400;
await db.product.delete({ where: { id: Number(id) } });
res.json({ status: 401, message: "delete success" });
} catch (err) {
console.log(err);
res.json({ status: 400, message: "delete failed with some error" });
}
},
};
} export default AdminProductController;
export default AdminProductController;
\ No newline at end of file
...@@ -6,8 +6,11 @@ const adminRouter = express.Router(); ...@@ -6,8 +6,11 @@ const adminRouter = express.Router();
adminRouter.get("/user", AdminUserController.index); adminRouter.get("/user", AdminUserController.index);
adminRouter.post("/product", AdminProductController.create); adminRouter.post("/product", AdminProductController.create);
adminRouter.put("/product", AdminProductController.update);
adminRouter.delete("/product", AdminProductController.delete);
adminRouter.post("/category", CategoryController.create); adminRouter.post("/category", CategoryController.create);
adminRouter.put("/category", CategoryController.update); adminRouter.put("/category", CategoryController.update);
adminRouter.delete('/category', CategoryController.delete) adminRouter.delete("/category", CategoryController.delete);
export default adminRouter; export default adminRouter;
import { useState, useEffect, useContext } from "react"; import { useState, useContext } from "react";
import Button from "@mui/material/Button"; import Button from "@mui/material/Button";
import TextField from "@mui/material/TextField";
import Dialog from "@mui/material/Dialog"; import Dialog from "@mui/material/Dialog";
import DialogActions from "@mui/material/DialogActions"; import DialogActions from "@mui/material/DialogActions";
import DialogContent from "@mui/material/DialogContent"; import DialogContent from "@mui/material/DialogContent";
......
...@@ -6,6 +6,7 @@ import DialogActions from "@mui/material/DialogActions"; ...@@ -6,6 +6,7 @@ import DialogActions from "@mui/material/DialogActions";
import DialogContent from "@mui/material/DialogContent"; import DialogContent from "@mui/material/DialogContent";
import DialogTitle from "@mui/material/DialogTitle"; import DialogTitle from "@mui/material/DialogTitle";
import { import {
Alert,
FormControl, FormControl,
InputLabel, InputLabel,
MenuItem, MenuItem,
...@@ -78,12 +79,8 @@ export default function AddProduct({ open, handleClose }) { ...@@ -78,12 +79,8 @@ export default function AddProduct({ open, handleClose }) {
<> <>
<Snackbar <Snackbar
anchorOrigin={{ horizontal: "center", vertical: "top" }} anchorOrigin={{ horizontal: "center", vertical: "top" }}
ContentProps={{ open={!!message.message.length}
className: message.error ? "bg-red-500" : "bg-green-500", ><Alert severity={message.error ? "error" : "success"}>{message.message}</Alert></Snackbar>
}}
open={!!message.message.length}
message={message.message}
/>
<Dialog open={open} onClose={handleClose}> <Dialog open={open} onClose={handleClose}>
<form onSubmit={fetchAddProduct}> <form onSubmit={fetchAddProduct}>
<DialogTitle>เพิ่มสินค้า</DialogTitle> <DialogTitle>เพิ่มสินค้า</DialogTitle>
......
import { useState, useContext } from "react";
import Button from "@mui/material/Button";
import Dialog from "@mui/material/Dialog";
import DialogActions from "@mui/material/DialogActions";
import DialogContent from "@mui/material/DialogContent";
import DialogTitle from "@mui/material/DialogTitle";
import { Alert, Snackbar } from "@mui/material";
import axios from "axios";
import { UserContext } from "@/pages/_app";
export default function DeleteProduct({ open, handleClose, id }) {
const user = useContext(UserContext);
const [message, setMessage] = useState({ message: "", error: false });
async function onDeleteProduct() {
try {
let response = await axios.delete(`/api/admin/product?id=${id}`, {
headers: { token: user.value.token },
});
if (response.data.status === 401) {
setMessage({ error: false, message: "สบสำเร็จ!" });
setTimeout(() => {
handleClose();
setMessage({ error: false, message: "" });
}, 1000);
}
} catch (err) {
setMessage({ error: true, message: "พบข้อผิดพลาด ไม่สามารถลบได้" });
setTimeout(() => {
setMessage({ error: false, message: "" });
}, 3000);
}
}
return (
<>
<Snackbar
anchorOrigin={{ horizontal: "center", vertical: "top" }}
ContentProps={{
className: message.error ? "bg-red-500" : "bg-green-500",
}}
open={!!message.message.length}
message={message.message}
>
<Alert severity={message.error ? "error" : "success"}>
{message.message}
</Alert>
</Snackbar>
<Dialog open={open} onClose={handleClose}>
<DialogTitle>ยืนยันการลบ</DialogTitle>
<DialogContent className="text-center">
เมื่อกดลบแล้วจะไม่สามารถกู้คืนได้
</DialogContent>
<DialogActions>
<Button color="error" onClick={handleClose}>
ยกเลิก
</Button>
<Button onClick={onDeleteProduct}>ยืนยัน</Button>
</DialogActions>
</Dialog>
</>
);
}
import { useState, useEffect, useContext } from "react";
import Button from "@mui/material/Button";
import TextField from "@mui/material/TextField";
import Dialog from "@mui/material/Dialog";
import DialogActions from "@mui/material/DialogActions";
import DialogContent from "@mui/material/DialogContent";
import DialogTitle from "@mui/material/DialogTitle";
import {
Alert,
FormControl,
InputLabel,
MenuItem,
Select,
Snackbar,
} from "@mui/material";
import axios from "axios";
import { UserContext } from "@/pages/_app";
export default function UpdateProduct({ open, handleClose, data }) {
const user = useContext(UserContext);
const [categoryList, setCategoryList] = useState([]);
const [message, setMessage] = useState({ message: "", error: false });
const [name, setName] = useState(data.name);
const [price, setPrice] = useState(data.price);
const [detail, setDetail] = useState(data.detail);
const [discount, setDiscount] = useState(data.discount);
const [stock, setStock] = useState(data.stock);
const [image, setImage] = useState(data.image);
const [category, setCategory] = useState(Number(data.cateId));
useEffect(() => {
axios.get("/api/category").then((res) => {
setCategoryList(res.data);
});
}, []);
/**
*
* @param {FormDataEvent} e
*/
async function fetchUpdateProduct(e) {
e.preventDefault();
let response = await axios.put(
"/api/admin/product",
{
id: data.id,
name,
price,
detail,
discount,
stock,
image,
category,
},
{ headers: { token: user.value.token } }
);
console.log(response.data);
if (response.data.status === 301) {
setMessage({ message: "แก้ไขสินค้าสำเร็จ", error: false });
setTimeout(() => {
handleClose();
setMessage({ message: "", error: false });
}, 2000);
} else {
setMessage({ message: "เกิดข้อผิดพลาด กรุณาลองอีกคร้ัง", error: true });
setTimeout(() => {
setMessage({ message: "", error: false });
}, 3000);
}
}
return (
<>
<Snackbar
anchorOrigin={{ horizontal: "center", vertical: "top" }}
open={!!message.message.length}
message={message.message}
>
<Alert severity={message.error ? "error" : "success"}>
{message.message}
</Alert>
</Snackbar>
<Dialog open={open} onClose={handleClose}>
<form onSubmit={fetchUpdateProduct}>
<DialogTitle>แก้ไขสินค้า</DialogTitle>
<DialogContent className="text-center">
<TextField
className="m-1"
label="ชื่อสินค้า"
variant="standard"
value={name}
onChange={(e) => setName(e.target.value)}
required
/>
<TextField
className="m-1"
label="ราคา"
variant="standard"
type="number"
value={price}
onChange={(e) => setPrice(Number(e.target.value))}
required
/>
<div className="text-left">
<TextField
fullWidth
className="m-1"
label="รายละเอียด"
variant="standard"
multiline
rows={3}
value={detail}
onChange={(e) => setDetail(e.target.value)}
required
/>
</div>
<div className="text-left">
<TextField
className="m-1"
label="ส่วนลด (%)"
variant="standard"
type="number"
value={discount}
onChange={(e) => setDiscount(e.target.value)}
required
/>
<TextField
className="m-1"
label="จำนวนสินค้า"
variant="standard"
type="number"
value={stock}
onChange={(e) => setStock(e.target.value)}
required
/>
</div>
<TextField
label="รูปภาพ"
variant="standard"
fullWidth
helperText="https://www.domain.com/image.png"
value={image}
onChange={(e) => setImage(e.target.value)}
/>
<FormControl
className="m-1"
variant="standard"
sx={{ minWidth: 100 }}
>
<InputLabel>หมวดหมู่</InputLabel>
<Select
value={category}
onChange={(e) => setCategory(Number(e.target.value))}
required
>
{categoryList.map((cat, idx) => (
<MenuItem key={idx} value={cat.id}>
{cat.name}
</MenuItem>
))}
</Select>
</FormControl>
</DialogContent>
<DialogActions>
<Button color="error" onClick={handleClose}>
ยกเลิก
</Button>
<Button type="submit">เพิ่ม</Button>
</DialogActions>
</form>
</Dialog>
</>
);
}
import { AddShoppingCart } from "@mui/icons-material"; import { AddShoppingCart } from "@mui/icons-material";
import AddProduct from "@/components/AddProduct"; import AddProduct from "@/components/product/AddProduct";
import { import {
Box, Box,
Button, Button,
...@@ -18,17 +18,21 @@ import axios from "axios"; ...@@ -18,17 +18,21 @@ import axios from "axios";
import Head from "next/head"; import Head from "next/head";
import { Delete } from "@mui/icons-material"; import { Delete } from "@mui/icons-material";
import { Edit } from "@mui/icons-material"; import { Edit } from "@mui/icons-material";
import UpdateProduct from "@/components/product/UpdateProduct";
import DeleteProduct from "@/components/product/DeleteProduct";
export default function Stock() { export default function Stock() {
const [modal, setModal] = useState(false); const [modal, setModal] = useState(false);
const [products, setProducts] = useState([]); const [products, setProducts] = useState([]);
const [updateState, setUpdateState] = useState({ open: false, data: {} });
const [deleteState, setDeleteState] = useState({ open: false, id: -1 });
const [category, setCategory] = useState([]); const [category, setCategory] = useState([]);
useEffect(() => { useEffect(() => {
axios.get("/api/product").then((res) => { axios.get("/api/product").then((res) => {
console.log(res.data);
setProducts(res.data); setProducts(res.data);
}); });
}, [modal]); }, [modal, updateState, deleteState]);
useEffect(() => { useEffect(() => {
axios.get("/api/category").then((res) => { axios.get("/api/category").then((res) => {
setCategory(res.data); setCategory(res.data);
...@@ -37,64 +41,88 @@ export default function Stock() { ...@@ -37,64 +41,88 @@ export default function Stock() {
return ( return (
<> <>
<Head> <Head>
<title>รายการสินค้า | admin</title> <title>รายการสินค้า | admin</title>
</Head> </Head>
<Box> <Box>
<Box sx={{ mb: 2, textAlign: "right" }}> <Box sx={{ mb: 2, textAlign: "right" }}>
<Button onClick={() => setModal(!modal)}> <Button onClick={() => setModal(!modal)}>
<AddShoppingCart /> <AddShoppingCart />
เพิ่มสินค้า เพิ่มสินค้า
</Button> </Button>
</Box>
{products.map((product, idx) => (
<Card
key={idx}
sx={{
m: 1,
px: 1,
width: 300,
height: 500,
display: "inline-block",
}}
>
<Box sx={{ px: 1 }}>
<h5 className="h-[40px] overflow-y-hidden">{product.name}</h5>
</Box>
<CardMedia
className="rounded"
component={"img"}
height={150}
image={product.image.length ? product.image : "/empty.jpg"}
/>
<CardContent sx={{ px: 1 }}>
<Typography
sx={{ height: 70, overflowY: "scroll" }}
variant="body2"
color={"text.secondary"}
>
{product.detail}
</Typography>
<Table sx={{ m: 0, p: 0 }}>
<TableBody>
<TableRow sx={{ m: 0, p: 0 }}>
<TableCell sx={{ m: 0, p: 0, textAlign: "center " }}>
{Number(product.price).toLocaleString() + " บาท"}
</TableCell>
<TableCell> {`ส่วนลด ${product.discount}%`}</TableCell>
</TableRow>
<TableRow>
<TableCell>เข้าชม {product.watch_count} ครั้ง</TableCell>
<TableCell>คงเหลือ {product.stock} ชิ้น</TableCell>
</TableRow>
</TableBody>
</Table>
</CardContent>
<CardActions disableSpacing sx={{ justifyContent: "end" }}>
<Button
color="warning"
onClick={() => setUpdateState({ open: true, data: product })}
>
<Edit /> แก้ไข
</Button>
<Button color="error" onClick={() => setDeleteState({open: true, id: product.id})}>
<Delete /> ลบ
</Button>
</CardActions>
</Card>
))}
<AddProduct open={modal} handleClose={() => setModal(false)} />
</Box> </Box>
{products.map((product, idx) => ( {updateState.open && (
<Card <UpdateProduct
sx={{ m: 1, px: 1, width: 300, height: 500, display: "inline-block" }} open={updateState.open}
> handleClose={() => setUpdateState({ open: false, data: {} })}
<Box sx={{ px: 1 }}> data={updateState.data}
<h5 className="h-[40px] overflow-y-hidden">{product.name}</h5> />
</Box> )}
<CardMedia {deleteState.open && (
className="rounded" <DeleteProduct
component={"img"} open={deleteState.open}
height={150} handleClose={() => setDeleteState({ open: false, id: -1 })}
image={product.image.length ? product.image : "/empty.jpg"} id={deleteState.id}
/> />
<CardContent sx={{ px: 1 }}> )}
<Typography
sx={{ height: 70, overflowY: "scroll" }}
variant="body2"
color={"text.secondary"}
>
{product.detail}
</Typography>
<Table sx={{ m: 0, p: 0 }}>
<TableBody>
<TableRow sx={{ m: 0, p: 0 }}>
<TableCell sx={{ m: 0, p: 0, textAlign: "center " }}>
{Number(product.price).toLocaleString() + " บาท"}
</TableCell>
<TableCell> {`ส่วนลด ${product.discount}%`}</TableCell>
</TableRow>
<TableRow>
<TableCell>เข้าชม {product.watch_count} ครั้ง</TableCell>
<TableCell>คงเหลือ {product.stock} ชิ้น</TableCell>
</TableRow>
</TableBody>
</Table>
</CardContent>
<CardActions disableSpacing sx={{ justifyContent: "end" }}>
<Button color="warning">
<Edit /> แก้ไข
</Button>
<Button color="error">
<Delete /> ลบ
</Button>
</CardActions>
</Card>
))}
<AddProduct open={modal} handleClose={() => setModal(false)} />
</Box>
</> </>
); );
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment