Commit eb6f7e3a authored by Nawasan Wisitsingkhon's avatar Nawasan Wisitsingkhon

create and show cart in controller;

create: cart list ui;
parent a2278911
import { Request, Response } from "express";
import db from "../models/prismaClient";
const CartController = {
/**
*
* @param {Request} req
* @param {Response} res
*/
async index(req, res) {
try {
let cart = await db.cart.findMany({
where: { user_id: Number(req.user.id) },
});
res.json({ status: 101, message: "fetch success", cart });
} catch (err) {
res.json({ status: 100, message: "error on server" });
}
},
/**
*
* @param {Request} req
* @param {Response} res
*/
async create(req, res) {
try {
const { id } = req.body;
if (!id) throw 200;
let check_cart = await db.cart.findFirst({
where: {
AND: { product_id: Number(id), user_id: Number(req.user.id) },
},
});
if (check_cart) throw 202;
await db.cart.create({
data: {
user_id: Number(req.user.id),
product_id: Number(id),
},
});
await db.$disconnect();
res.json({ status: 201, message: "add to cart success" });
} catch (err) {
if (err === 202)
return res.json({
status: 202,
message: "this product was added",
});
res.json({ status: 200, message: "found some error on server" });
}
},
};
export default CartController;
import express from "express"; import express from "express";
import WishlistController from "../controllers/WishlistController"; import WishlistController from "../controllers/WishlistController";
import CartController from "../controllers/CartController";
const UserRouter = express.Router(); const UserRouter = express.Router();
UserRouter.get("/wishlist", WishlistController.index); UserRouter.get("/wishlist", WishlistController.index);
UserRouter.post("/wishlist", WishlistController.create); UserRouter.post("/wishlist", WishlistController.create);
UserRouter.delete("/wishlist", WishlistController.delete); UserRouter.delete("/wishlist", WishlistController.delete);
UserRouter.get("/cart", CartController.index);
UserRouter.post("/cart", CartController.create);
export default UserRouter; export default UserRouter;
...@@ -14,7 +14,7 @@ import MenuIcon from "@mui/icons-material/Menu"; ...@@ -14,7 +14,7 @@ import MenuIcon from "@mui/icons-material/Menu";
import SearchIcon from "@mui/icons-material/Search"; import SearchIcon from "@mui/icons-material/Search";
import AccountCircle from "@mui/icons-material/AccountCircle"; import AccountCircle from "@mui/icons-material/AccountCircle";
import ShoppingCart from "@mui/icons-material/ShoppingCart"; import ShoppingCart from "@mui/icons-material/ShoppingCart";
import { UserContext, WishlistContext } from "@/pages/_app"; import { CartContext, UserContext, WishlistContext } from "@/pages/_app";
import Link from "next/link"; import Link from "next/link";
import { Favorite } from "@mui/icons-material"; import { Favorite } from "@mui/icons-material";
import { Logout, SupervisedUserCircle } from "@mui/icons-material"; import { Logout, SupervisedUserCircle } from "@mui/icons-material";
...@@ -64,6 +64,7 @@ function Navbar(props) { ...@@ -64,6 +64,7 @@ function Navbar(props) {
const router = useRouter(); const router = useRouter();
const [search, setSearch] = React.useState(router.query?.q ?? ""); const [search, setSearch] = React.useState(router.query?.q ?? "");
const wishlist = useContext(WishlistContext); const wishlist = useContext(WishlistContext);
const cart = useContext(CartContext)
const user = useContext(UserContext); const user = useContext(UserContext);
const { window } = props; const { window } = props;
...@@ -139,7 +140,7 @@ function Navbar(props) { ...@@ -139,7 +140,7 @@ function Navbar(props) {
aria-label="show 4 new mails" aria-label="show 4 new mails"
color="inherit" color="inherit"
> >
<Badge badgeContent={4} color="error"> <Badge badgeContent={cart.value.length} color="error">
<ShoppingCart /> <ShoppingCart />
</Badge> </Badge>
</IconButton> </IconButton>
......
...@@ -18,18 +18,22 @@ import { UserContext } from "@/pages/_app"; ...@@ -18,18 +18,22 @@ import { UserContext } from "@/pages/_app";
import axios from "axios"; import axios from "axios";
import { headers } from "../../next.config"; import { headers } from "../../next.config";
export default function ProductCard({ product, isFav, favHandler }) { export default function ProductCard({
const user = useContext(UserContext); product,
const fav = isFav isFav,
favHandler,
cartHandler,
}) {
const fav = isFav;
/** /**
* *
* @param {number} id * @param {number} id
* @param {boolean} isRemove * @param {boolean} isRemove
*/ */
return ( return (
<div <div
className="p-1 m-1 w-[300px] inline-block bg-white rounded hover:shadow duration-300" className="p-1 m-1 w-[300px] inline-block bg-white rounded hover:shadow duration-300"
sx={{ sx={{
m: 1, m: 1,
px: 1, px: 1,
...@@ -69,7 +73,7 @@ export default function ProductCard({ product, isFav, favHandler }) { ...@@ -69,7 +73,7 @@ export default function ProductCard({ product, isFav, favHandler }) {
> >
{fav ? <Favorite /> : <FavoriteBorder />} {fav ? <Favorite /> : <FavoriteBorder />}
</Button> </Button>
<Button title="เพิ่มลงตระกร้า" color="warning"> <Button title="เพิ่มลงตระกร้า" color="warning" onClick={cartHandler}>
<ShoppingCart /> <ShoppingCart />
</Button> </Button>
</span> </span>
......
...@@ -14,12 +14,23 @@ import axios from "axios"; ...@@ -14,12 +14,23 @@ import axios from "axios";
export const UserContext = createContext(null); export const UserContext = createContext(null);
export const WishlistContext = createContext(null); export const WishlistContext = createContext(null);
export const CartContext = createContext(null);
export default function App({ Component, pageProps }) { export default function App({ Component, pageProps }) {
const [user, setUser] = useState({}); const [user, setUser] = useState({});
const [wishlist, setWishlist] = useState([]); const [wishlist, setWishlist] = useState([]);
const [cart, setCart] = useState([]);
const pathname = usePathname(); const pathname = usePathname();
const fetchCart = async () => {
if (!user.token) return;
let response = await axios.get("/api/u/cart", {
headers: { token: user.token },
});
if (response.data.status === 101) {
setCart(response.data.cart);
}
};
const fetchWishlist = async () => { const fetchWishlist = async () => {
if (!user?.token) return; if (!user?.token) return;
let response = await axios.get("/api/u/wishlist", { let response = await axios.get("/api/u/wishlist", {
...@@ -40,30 +51,35 @@ export default function App({ Component, pageProps }) { ...@@ -40,30 +51,35 @@ export default function App({ Component, pageProps }) {
}, []); }, []);
useEffect(() => { useEffect(() => {
fetchCart();
fetchWishlist(); fetchWishlist();
}, [user]); }, [user]);
return ( return (
<UserContext.Provider value={{ value: user, set: setUser }}> <UserContext.Provider value={{ value: user, set: setUser }}>
<WishlistContext.Provider value={{ value: wishlist, set: setWishlist }}> <CartContext.Provider
{pathname.split("/")[1] === "admin" ? ( value={{ value: cart, set: setCart, fetch: fetchCart }}
<> >
{user.rank ? ( <WishlistContext.Provider value={{ value: wishlist, set: setWishlist }}>
<AdminLayout> {pathname.split("/")[1] === "admin" ? (
<Component {...pageProps} /> <>
</AdminLayout> {user.rank ? (
) : ( <AdminLayout>
<UserLayout> <Component {...pageProps} />
<Error /> </AdminLayout>
</UserLayout> ) : (
)} <UserLayout>
</> <Error />
) : ( </UserLayout>
<UserLayout> )}
<Component {...pageProps} /> </>
</UserLayout> ) : (
)} <UserLayout>
</WishlistContext.Provider> <Component {...pageProps} />
</UserLayout>
)}
</WishlistContext.Provider>
</CartContext.Provider>
</UserContext.Provider> </UserContext.Provider>
); );
} }
import {
Box,
Button,
Paper,
Table,
TableBody,
TableCell,
TableHead,
TableRow,
} from "@mui/material";
import React, { useContext, useEffect, useState } from "react";
import { CartContext, UserContext, WishlistContext } from "./_app";
import { useRouter } from "next/router";
import axios from "axios";
import { Delete } from "@mui/icons-material";
import { ShoppingCart } from "@mui/icons-material";
import PopupAlert from "@/components/PopupAlert";
import Head from "next/head";
export default function Cart() {
const user = useContext(UserContext);
const wishlist = useContext(WishlistContext);
const cart = useContext(CartContext);
const [products, setProducts] = useState([]);
const [message, setMessage] = useState({ error: false, message: "" });
const router = useRouter();
const [CartProduct, setCartProduct] = useState([]);
const removeFromCart = async (id) => {};
const fetchProduct = async () => {
try {
let product = await axios.get("/api/product");
setProducts(product.data);
} catch (err) {}
};
useEffect(() => {
fetchProduct();
}, []);
useEffect(() => {
setCartProduct(
cart.value.map(
(ct) => products.filter((pd) => pd.id === ct.product_id)[0]
)
);
}, [cart, products]);
return (
<>
<Head>
<title>ตระกร้าสินค้า | OpenShop</title>
</Head>
<Box>
<PopupAlert
open={!!message.message.length}
isError={message.error}
message={message.message}
/>
<Paper sx={{ p: 1, overflowX: "scroll" }}>
{wishlist.value.length > 0 ? (
<Table>
<TableHead>
<TableRow>
{[
"ลำดับ",
"รูปภาพ",
"ชื่อสินค้า",
"รายละเอียด",
"ราคา",
"นำออกจากรายการ",
].map((label, idx) => (
<TableCell key={idx}>{label}</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{CartProduct.map(
(pdt, idx) =>
pdt && (
<TableRow key={idx}>
<TableCell>{idx + 1}</TableCell>
<TableCell>
<img
width={100}
src={pdt.image?.length ? pdt.image : "/empty.jpg"}
alt="รูปสินค้า"
/>
</TableCell>
<TableCell>{pdt.name}</TableCell>
<TableCell>
<div className="max-h-10 overflow-scroll">
{pdt.detail}
</div>
</TableCell>
<TableCell>
{pdt.discount > 0 ? (
<Box color={"orangered"}>
<del>${pdt.price}</del> $
{pdt.price - pdt.price * (pdt.discount / 100)}
</Box>
) : (
<Box color="orangered">${pdt.price}</Box>
)}
</TableCell>
<TableCell>
<Button
color="error"
onClick={() => removeFromCart(pdt.id)}
>
<Delete />
</Button>
</TableCell>
</TableRow>
)
)}
</TableBody>
</Table>
) : (
<div className="text-center">รายการว่างเปล่า</div>
)}
</Paper>
</Box>
</>
);
}
...@@ -20,6 +20,25 @@ export default function Home() { ...@@ -20,6 +20,25 @@ export default function Home() {
? products.filter((prod) => String(prod.name).includes(router.query.q)) ? products.filter((prod) => String(prod.name).includes(router.query.q))
: products.filter((prod) => Number(prod.stock) > 0); : products.filter((prod) => Number(prod.stock) > 0);
async function onCart(id, isRemove = false) {
if (!user.value?.token) {
setMessage({ message: "คุณยังไม่ได้เข้าสู่ระบบ", error: true });
setTimeout(() => {
setMessage({ message: "", error: true });
}, 2000);
return;
}
if (isRemove) {
} else {
let response = await axios.post(
"/api/u/cart",
{ id },
{ headers: { token: user.value.token } }
);
console.log(response.data);
}
}
async function onWishlist(id, isRemove = false) { async function onWishlist(id, isRemove = false) {
if (!user.value?.token) { if (!user.value?.token) {
setMessage({ message: "คุณยังไม่ได้เข้าสู่ระบบ", error: true }); setMessage({ message: "คุณยังไม่ได้เข้าสู่ระบบ", error: true });
...@@ -80,6 +99,7 @@ export default function Home() { ...@@ -80,6 +99,7 @@ export default function Home() {
).length ).length
} }
product={prod} product={prod}
cartHandler={() => onCart(prod.id)}
favHandler={() => favHandler={() =>
onWishlist( onWishlist(
prod.id, prod.id,
......
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