diff --git a/src/app/(customer)/(shop)/checkout/[store]/confirm/page.tsx b/src/app/(customer)/(shop)/checkout/[store]/confirm/page.tsx new file mode 100644 index 0000000..9411ca7 --- /dev/null +++ b/src/app/(customer)/(shop)/checkout/[store]/confirm/page.tsx @@ -0,0 +1,35 @@ +import Link from "next/link"; +import { notFound } from "next/navigation"; +import { ArrowRight } from "lucide-react"; +import { getCart } from "@/lib/api/cart"; +import { getAddresses } from "@/lib/api/addresses"; +import { requireSession } from "@/lib/auth/session"; +import { CheckoutPayment } from "@/components/customer/checkout-payment"; + +export default async function ConfirmPaymentPage({ params }: PageProps<"/checkout/[store]/confirm">) { + const { store } = await params; + await requireSession(`/checkout/${store}/confirm`); + + const [cart, addresses] = await Promise.all([ + getCart(), + // Known gap (FRONTEND_GUIDE.md §7): addresses GET can 403 on the current OAuth + // scope — fall back to empty rather than crashing this page over it. + getAddresses().catch(() => []), + ]); + const group = cart.groups.find((g) => g.store.uuid === store); + if (!group) notFound(); + + return ( +
+ {/* Same header pattern as /cart and /checkout/[store]. */} +
+ + + +

تأیید و پرداخت

+
+ + +
+ ); +} diff --git a/src/components/customer/checkout-payment.tsx b/src/components/customer/checkout-payment.tsx new file mode 100644 index 0000000..d61de45 --- /dev/null +++ b/src/components/customer/checkout-payment.tsx @@ -0,0 +1,110 @@ +"use client"; + +import { useState, useTransition } from "react"; +import { useRouter } from "next/navigation"; +import { submitCheckout } from "@/lib/api/checkout"; +import type { Address, CartGroup, PaymentMethod } from "@/types/api"; + +/** Exact labels per the OpenAPI PaymentMethodEnum description ("(آنلاین)" added to match the screenshot). */ +const PAYMENT_OPTIONS: { value: PaymentMethod; label: string }[] = [ + { value: "wallet", label: "کیف پول وینسو" }, + { value: "online", label: "درگاه بانکی (آنلاین)" }, + { value: "cash_on_delivery", label: "پرداخت در محل" }, +]; + +export function CheckoutPayment({ group, addresses }: { group: CartGroup; addresses: Address[] }) { + const router = useRouter(); + const [method, setMethod] = useState("wallet"); + const [error, setError] = useState(null); + const [isPending, startTransition] = useTransition(); + + // Pickup flow — no delivery fee, matches the fulfillment screen's "دریافت حضوری" total. + const payable = group.items_subtotal; + + function handlePay() { + setError(null); + const addressUuid = addresses.find((a) => a.is_default)?.uuid ?? addresses[0]?.uuid; + if (!addressUuid) { + setError("برای ثبت سفارش ابتدا یک آدرس اضافه کنید."); + return; + } + startTransition(async () => { + // submitCheckout processes the whole cart at once (splits into per-store orders + // server-side), not just this store — see PageProps note on the confirm page. + const result = await submitCheckout({ + address_uuid: addressUuid, + delivery_type: "express", + scheduled_at: null, + payment_method: method, + notes: "", + }); + if (result.ok) { + router.push(`/order-groups/${result.data.uuid}`); + } else { + setError(result.message); + } + }); + } + + return ( +
+
+

روش پرداخت

+ + {PAYMENT_OPTIONS.map((option) => { + const selected = method === option.value; + return ( + + ); + })} +
+ + {error &&

{error}

} + +
+
+ + {group.items.length.toLocaleString("fa-IR")} کالا از {group.store.name} + + {payable.toLocaleString("fa-IR")} تومان +
+
+ جمع کل + + {payable.toLocaleString("fa-IR")} تومان + +
+ +
+
+ ); +}