winofy-front/src/components/customer/checkout-payment.tsx
2026-09-02 10:40:48 +03:30

110 lines
4.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"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<PaymentMethod>("wallet");
const [error, setError] = useState<string | null>(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 (
<div className="flex flex-col gap-6 pb-44">
<section className="flex flex-col gap-3">
<h2 className="text-[15px] font-bold leading-none text-foreground">روش پرداخت</h2>
{PAYMENT_OPTIONS.map((option) => {
const selected = method === option.value;
return (
<label
key={option.value}
className={`flex cursor-pointer items-center justify-between rounded-2xl border p-4 ${selected ? "border-primary-action" : "border-gray-200"}`}
>
<input
type="radio"
name="payment"
checked={selected}
onChange={() => setMethod(option.value)}
className="sr-only"
/>
{/* DOM order intentionally mirrors the screenshot's left→right layout — see
the inherited dir="rtl" note on the /cart page. No wallet balance line:
Winofy's API has no wallet-balance endpoint — that's a Gooyal-side
feature (see the wallet.wallet:get_balance OAuth scope) with no
documented endpoint available here, so it isn't faked. */}
<span className="text-[14px] font-bold leading-none text-foreground">{option.label}</span>
<span
className={`flex h-5 w-5 shrink-0 items-center justify-center rounded-full border-2 ${selected ? "border-primary-action" : "border-gray-300"}`}
>
{selected && <span className="h-2.5 w-2.5 rounded-full bg-primary-action" />}
</span>
</label>
);
})}
</section>
{error && <p className="text-end text-sm text-error">{error}</p>}
<div className="fixed inset-x-0 bottom-0 z-10 mx-auto flex w-full max-w-md flex-col gap-3 bg-white px-4 pt-4 pb-6 shadow-[0_-4px_15px_0_rgba(0,0,0,0.102)]">
<div className="flex items-center justify-between text-[13px] text-gray-600">
<span>
{group.items.length.toLocaleString("fa-IR")} کالا از {group.store.name}
</span>
<span>{payable.toLocaleString("fa-IR")} تومان</span>
</div>
<div className="flex items-center justify-between mb-2">
<span className="text-[14px] font-semibold leading-none text-foreground">جمع کل</span>
<span className="text-[16px] font-bold leading-none text-foreground">
{payable.toLocaleString("fa-IR")} تومان
</span>
</div>
<button
type="button"
onClick={handlePay}
disabled={isPending}
className="w-full rounded-2xl bg-primary-action py-4 text-[15px] font-bold text-white disabled:opacity-40"
>
{isPending ? "در حال ثبت سفارش..." : `پرداخت ${payable.toLocaleString("fa-IR")} تومان`}
</button>
</div>
</div>
);
}