Files
frontend/app/(main)/payment/page.tsx
T
TakahashiNguyen 877c7be84b
Release package / release (push) Failing after 8m34s
fix: cart connect to backend (#39)
Co-authored-by: TakahashiNg <83152264+TakahashiNguyen@users.noreply.github.com>
Reviewed-on: #39
2026-05-13 08:56:58 +00:00

162 lines
6.7 KiB
TypeScript

"use client";
import Button from "@/components/atoms/buttons/Button";
import PaymentSummaryCard from "@/components/molecules/cards/PaymentSummaryCard";
import ReviewModal from "@/components/organisms/modals/ReviewModal";
import { useAuth } from "@/lib/auth-context";
import { useCart } from "@/lib/cart-context";
import { useManager } from "@/lib/manager-context";
import { MenuItemEntity } from "@/lib/types";
import { useState } from "react";
export const formatPrice = (value?: number) =>
(value ?? 0).toLocaleString("vi-VN", { style: "currency", currency: "VND" });
export default function PaymentPage() {
const {
items,
totalPrice,
increaseQty,
decreaseQty,
removeFromCart,
setQuantity,
} = useCart();
const { user } = useAuth();
const { products } = useManager();
const findProduct = (id: string): MenuItemEntity =>
products.find((i) => i.id == id)!;
const [isReviewOpen, setIsReviewOpen] = useState(false);
const isCustomer = user?.role === "customer";
return (
<div>
<div className="mx-auto w-full max-w-screen-2xl px-4 py-6 md:px-6 md:py-8 lg:px-8">
<div className="flex flex-col gap-6 xl:flex-row">
<section className="min-w-0 flex-1">
<div className="bg-card overflow-hidden rounded-2xl border border-(--color-border-light)">
<div className="border-b border-(--color-border-light) px-4 py-3">
<h1 className="text-foreground text-lg font-bold md:text-xl">
Trang thanh toán
</h1>
</div>
{items?.length === 0 ? (
<div className="px-4 py-10 text-center text-(--color-text-muted)">
Chưa sản phẩm nào trong giỏ hàng.
</div>
) : (
<div className="overflow-x-auto">
<table className="w-full min-w-190 text-sm">
<thead>
<tr className="bg-(--color-border-light)/40 text-left">
<th scope="col" className="px-4 py-3 font-semibold">
Product name
</th>
<th scope="col" className="px-4 py-3 font-semibold">
Price
</th>
<th scope="col" className="px-4 py-3 font-semibold">
Description
</th>
<th scope="col" className="px-4 py-3 font-semibold">
Quantity
</th>
<th
scope="col"
className="px-4 py-3 text-right font-semibold"
>
Delete
</th>
</tr>
</thead>
<tbody>
{items?.map(
({
productId: id,
priceAtTimeOfAdding: price,
quantity,
}) => {
const { name, description } = findProduct(id);
return (
<tr
key={id}
className="border-t border-(--color-border-light)"
>
<td className="text-foreground px-4 py-3 font-medium">
{name}
</td>
<td className="px-4 py-3 font-semibold text-(--color-primary)">
{formatPrice(price)}
</td>
<td className="max-w-70 px-4 py-3 text-(--color-text-muted)">
<p className="line-clamp-2">{description}</p>
</td>
<td className="px-4 py-3">
<div className="flex items-center gap-2">
<button
onClick={() => decreaseQty(id)}
className="inline-flex h-8 w-8 items-center justify-center rounded-lg border border-(--color-border) hover:bg-(--color-border-light)"
aria-label={`Giảm số lượng ${name}`}
>
-
</button>
<input
type="number"
min={1}
value={quantity}
onChange={(e) =>
setQuantity(id, Number(e.target.value))
}
className="h-8 w-16 rounded-lg border border-(--color-border) bg-transparent text-center"
title="Nhập số lượng"
/>
<button
onClick={() => increaseQty(id)}
className="inline-flex h-8 w-8 items-center justify-center rounded-lg border border-(--color-border) hover:bg-(--color-border-light)"
aria-label={`Tăng số lượng ${name}`}
>
+
</button>
</div>
</td>
<td className="px-4 py-3 text-right">
<Button
onClick={() => removeFromCart(id)}
variant="danger"
size="md"
style="payment"
aria-label={`Xóa ${name} khỏi giỏ hàng`}
>
Delete product
</Button>
</td>
</tr>
);
},
)}
</tbody>
</table>
</div>
)}
</div>
</section>
<PaymentSummaryCard
totalPrice={totalPrice}
isCustomer={isCustomer}
backHref="/"
/>
</div>
</div>
<ReviewModal
isOpen={isReviewOpen}
onClose={() => setIsReviewOpen(false)}
/>
</div>
);
}