import { useState } from "react"; import { useLocation, Link } from "wouter"; import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { z } from "zod"; import { useLanguage } from "../contexts/LanguageContext"; import { useCart } from "../contexts/CartContext"; import { useDonateToRequest, getListRequestsQueryKey, getListPublishedRequestsQueryKey, } from "@workspace/api-client-react"; import { useQueryClient } from "@tanstack/react-query"; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { ShoppingCart, Trash2, ChevronLeft, ChevronRight, CheckCircle, Heart } from "lucide-react"; import { getNeedImage } from "../lib/needImages"; import { Riyal } from "@/components/Riyal"; import { Reveal } from "../components/Reveal"; import leafPattern from "@assets/right-snapel-2_1780688632733.svg"; const schema = z.object({ donorName: z.string().min(2), donorPhone: z.string().min(10), donorEmail: z.string().email().optional().or(z.literal("")), }); type FormData = z.infer; export default function Cart() { const { t, dir } = useLanguage(); const [, setLocation] = useLocation(); const queryClient = useQueryClient(); const { items, removeItem, updateAmount, total, clear } = useCart(); const donateMutation = useDonateToRequest(); const [step, setStep] = useState<"cart" | "payment">("cart"); const [amountError, setAmountError] = useState(false); const [submitError, setSubmitError] = useState(false); const [done, setDone] = useState(false); const form = useForm({ resolver: zodResolver(schema), defaultValues: { donorName: "", donorPhone: "", donorEmail: "" }, }); const Chevron = dir === "rtl" ? ChevronLeft : ChevronRight; const goToPayment = () => { if (items.length === 0) return; if (!items.every((i) => i.amount > 0)) { setAmountError(true); return; } setAmountError(false); setStep("payment"); }; const onSubmit = async (data: FormData) => { // Re-validate amounts at submit time in case the user edited a value // back to zero after entering the payment step. if (!items.every((i) => i.amount > 0)) { setSubmitError(false); setStep("cart"); setAmountError(true); return; } setSubmitError(false); let failed = false; try { for (const item of items) { await donateMutation.mutateAsync({ id: item.id, data: { donorName: data.donorName, donorPhone: data.donorPhone, donorEmail: data.donorEmail || null, amount: item.amount, }, }); removeItem(item.id); } } catch { failed = true; setSubmitError(true); } finally { // Always refresh request data: even on partial failure, the donations // that did succeed have already changed server state. queryClient.invalidateQueries({ queryKey: getListRequestsQueryKey() }); queryClient.invalidateQueries({ queryKey: getListPublishedRequestsQueryKey() }); } if (!failed) { clear(); setDone(true); } }; // Success screen after a completed multi-item donation if (done) { return (

{t.common.success}

{t.cart.successMessage}

); } return (
{/* Decorative leaf background */}
{/* Breadcrumb */}

{t.cart.title}

{items.length === 0 ? (

{t.cart.empty}

{t.cart.emptyHint}

) : (
{/* Items list */}
{items.map((item) => { const progress = Math.min( 100, item.requestedAmount > 0 ? Math.round((item.collectedAmount / item.requestedAmount) * 100) : 0 ); return (
{/* Image + progress */}
{item.description}
{progress}%
{/* Content */}
{t.needTypes[item.needType as keyof typeof t.needTypes] || t.opportunities.generalProjects}

{item.description}

0 ? item.amount : ""} onChange={(e) => { updateAmount(item.id, Number(e.target.value)); setAmountError(false); }} placeholder={t.cart.amountLabel} className="ps-8" data-testid={`input-amount-${item.id}`} />
); })}
{/* Summary / checkout panel */}
{t.cart.itemsCount} {items.length}
{t.cart.total} {total.toLocaleString()}
{step === "cart" ? ( <> {amountError && (

{t.cart.amountRequired}

)} ) : (

{t.donate.paymentTitle}

( {t.donate.donorName} )} /> ( {t.donate.donorPhone} )} /> ( {t.donate.donorEmail} )} /> {submitError && (

{t.common.error}

)}
)}
)}
); }