From 240155d1f63101f7d04d58aa4043ae0bcc034596 Mon Sep 17 00:00:00 2001
From: Thanh Quy - wolf <524H0124@student.tdtu.edu.vn>
Date: Sat, 4 Apr 2026 02:02:23 +0700
Subject: [PATCH] =?UTF-8?q?=C4=90=C3=B3ng=20g=C3=B3i=20code=20=E1=BB=9F=20?=
=?UTF-8?q?payment=20page?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/(main)/payment/page.tsx | 90 ++++--------------
components/atoms/buttons/Button.tsx | 6 +-
components/atoms/buttons/Button.types.ts | 1 +
components/molecules/cards/Card.types.ts | 7 ++
.../molecules/cards/PaymentSummaryCard.tsx | 91 +++++++++++++++++++
components/organisms/modals/ReviewModal.tsx | 2 +-
6 files changed, 122 insertions(+), 75 deletions(-)
create mode 100644 components/molecules/cards/PaymentSummaryCard.tsx
diff --git a/app/(main)/payment/page.tsx b/app/(main)/payment/page.tsx
index feca381..febe020 100644
--- a/app/(main)/payment/page.tsx
+++ b/app/(main)/payment/page.tsx
@@ -1,9 +1,10 @@
"use client";
-import { ReviewModal } from "@/components/organisms/modals";
+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 Link from "next/link";
import { useState } from "react";
const formatPrice = (value: number) =>
@@ -23,15 +24,8 @@ export default function PaymentPage() {
const [isReviewOpen, setIsReviewOpen] = useState(false);
const isCustomer = user?.role === "customer";
- const handlePayment = () => {
- // UI-only: open review modal after "payment"
- if (isCustomer) {
- setIsReviewOpen(true);
- }
- };
-
return (
- <>
+
@@ -81,7 +75,7 @@ export default function PaymentPage() {
- removeFromCart(item.id)}
- className="inline-flex items-center justify-center gap-2 rounded-lg bg-red-500 px-3 py-2 text-white transition-colors hover:bg-red-600"
+ variant="danger"
+ size="md"
>
-
-
- Xóa sản phẩm
-
-
+ Xóa sản phẩm
+
|
))}
@@ -125,59 +117,11 @@ export default function PaymentPage() {
-
+
@@ -185,6 +129,6 @@ export default function PaymentPage() {
isOpen={isReviewOpen}
onClose={() => setIsReviewOpen(false)}
/>
- >
+
);
}
diff --git a/components/atoms/buttons/Button.tsx b/components/atoms/buttons/Button.tsx
index 12ded1f..d83b579 100644
--- a/components/atoms/buttons/Button.tsx
+++ b/components/atoms/buttons/Button.tsx
@@ -10,10 +10,14 @@ export default function Button({
disabled = false,
children,
className = "",
+ payment = false,
...props
}: ButtonProps) {
const baseStyles =
"font-semibold rounded-lg transition-colors disabled:opacity-50 disabled:cursor-not-allowed inline-flex items-center justify-center gap-1.5";
+// h-8 w-8
+ const paymentStyles =
+ "inline-flex cursor-pointer items-center justify-center gap-2 rounded-xl transition-colors";
const variants = {
primary:
@@ -34,7 +38,7 @@ export default function Button({
return (
diff --git a/components/atoms/buttons/Button.types.ts b/components/atoms/buttons/Button.types.ts
index 5fd69cd..476d8b0 100644
--- a/components/atoms/buttons/Button.types.ts
+++ b/components/atoms/buttons/Button.types.ts
@@ -8,4 +8,5 @@ export interface ButtonProps extends ButtonHTMLAttributes {
disabled?: boolean;
children: React.ReactNode;
className?: string;
+ payment?: boolean;
}
diff --git a/components/molecules/cards/Card.types.ts b/components/molecules/cards/Card.types.ts
index d55835a..0211080 100644
--- a/components/molecules/cards/Card.types.ts
+++ b/components/molecules/cards/Card.types.ts
@@ -16,3 +16,10 @@ export interface ShopCardProps {
image: string;
onClick?: () => void;
}
+
+export interface PaymentSummaryCardProps {
+ totalPrice: number;
+ isCustomer: boolean;
+ backHref: string;
+ onPay?: () => void;
+}
diff --git a/components/molecules/cards/PaymentSummaryCard.tsx b/components/molecules/cards/PaymentSummaryCard.tsx
new file mode 100644
index 0000000..d0fdaf4
--- /dev/null
+++ b/components/molecules/cards/PaymentSummaryCard.tsx
@@ -0,0 +1,91 @@
+import Button from "@/components/atoms/buttons/Button";
+import Link from "next/link";
+
+import { ReviewModal } from "@/components/organisms/modals";
+import { useState } from "react";
+
+import type { PaymentSummaryCardProps } from "./Card.types";
+
+const formatPrice = (value: number) =>
+ value.toLocaleString("vi-VN", { style: "currency", currency: "VND" });
+
+export default function PaymentSummaryCard({
+ totalPrice,
+ isCustomer = false,
+ backHref,
+}: PaymentSummaryCardProps) {
+
+ const [isReviewOpen, setIsReviewOpen] = useState(false);
+ const handlePayment = () => {
+ // UI-only: open review modal after "payment"
+ if (isCustomer) {
+ setIsReviewOpen(true);
+ }
+};
+ return (
+
+ );
+}
diff --git a/components/organisms/modals/ReviewModal.tsx b/components/organisms/modals/ReviewModal.tsx
index e770875..a1e8c0a 100644
--- a/components/organisms/modals/ReviewModal.tsx
+++ b/components/organisms/modals/ReviewModal.tsx
@@ -1,6 +1,6 @@
"use client";
-import { Button, Caption, Heading, Text, Textarea } from "@/components/atoms";
+import { Button, Heading, Text, Textarea } from "@/components/atoms";
import { useState } from "react";
import type { ReviewModalProps } from "./Modal.types";