import { useState } from "react"; import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { z } from "zod"; import { useParams, useLocation, useSearch, Link } from "wouter"; import { useLanguage } from "../contexts/LanguageContext"; import { useGetRequest, useDonateToRequest, getListRequestsQueryKey, getListPublishedRequestsQueryKey, getGetRequestQueryKey, } from "@workspace/api-client-react"; import { useQueryClient } from "@tanstack/react-query"; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"; import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; import { Card, CardContent } from "@/components/ui/card"; import { Checkbox } from "@/components/ui/checkbox"; import { CheckCircle, Heart, Gift, ShoppingCart, Check } from "lucide-react"; import { Skeleton } from "@/components/ui/skeleton"; import { getNeedImage } from "../lib/needImages"; const RIYAL = "﷼"; const PRESETS = [100, 50, 10]; 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 Donate() { const { t } = useLanguage(); const params = useParams<{ id: string }>(); const search = useSearch(); const [, setLocation] = useLocation(); const queryClient = useQueryClient(); const initialAmount = (() => { const a = Number(new URLSearchParams(search).get("amount")); return Number.isFinite(a) && a > 0 ? String(a) : ""; })(); const [step, setStep] = useState<1 | 2>(1); const [amount, setAmount] = useState(initialAmount); const [amountError, setAmountError] = useState(false); const [onBehalf, setOnBehalf] = useState(false); const [onBehalfName, setOnBehalfName] = useState(""); const [donated, setDonated] = useState(false); const { data: request, isLoading } = useGetRequest(params.id || "", { query: { enabled: !!params.id, queryKey: getGetRequestQueryKey(params.id || "") }, }); const donateMutation = useDonateToRequest(); const form = useForm({ resolver: zodResolver(schema), defaultValues: { donorName: "", donorPhone: "", donorEmail: "" }, }); if (isLoading) { return (
); } if (!request) { return (
{t.donate.caseNotFound}
); } const progress = Math.min( 100, request.requestedAmount > 0 ? Math.round((request.collectedAmount / request.requestedAmount) * 100) : 0 ); const remaining = Math.max(0, request.requestedAmount - request.collectedAmount); if (donated) { return (

{t.common.success}

{t.donate.successMessage}

{request.caseId}

); } const goToPayment = () => { const amt = Number(amount); if (!Number.isFinite(amt) || amt <= 0) { setAmountError(true); return; } // Never let a single donation exceed the remaining target. if (amt > remaining) { setAmount(String(remaining)); } setAmountError(false); setStep(2); }; const onSubmit = (data: FormData) => { donateMutation.mutate( { id: params.id || "", data: { donorName: data.donorName, donorPhone: data.donorPhone, donorEmail: data.donorEmail || null, amount: Number(amount), }, }, { onSuccess: () => { queryClient.invalidateQueries({ queryKey: getListRequestsQueryKey() }); queryClient.invalidateQueries({ queryKey: getListPublishedRequestsQueryKey() }); queryClient.invalidateQueries({ queryKey: getGetRequestQueryKey(params.id || "") }); setDonated(true); }, } ); }; const StepIndicator = () => (
{/* Step 1 - Details */}
= 1 ? "bg-primary text-primary-foreground border-primary" : "bg-background text-muted-foreground border-border" }`}> {step > 1 ? : "1"}
= 1 ? "text-primary" : "text-muted-foreground"}`}> {t.donate.stepDetails}
= 2 ? "bg-primary" : "bg-border"}`} /> {/* Step 2 - Payment */}
= 2 ? "bg-primary text-primary-foreground border-primary" : "bg-background text-muted-foreground border-border" }`}> 2
= 2 ? "text-primary" : "text-muted-foreground"}`}> {t.donate.stepPayment}
); const DetailsPanel = () => (

{t.donate.detailsTitle}

{request.description}
{progress}%
{t.needTypes[request.needType as keyof typeof t.needTypes] || t.opportunities.generalProjects}

{request.description}

{request.caseId}

{t.opportunities.remainingShort}

{RIYAL} {remaining.toLocaleString()}

{t.opportunities.collectedShort}

{RIYAL} {request.collectedAmount.toLocaleString()}

); return (

{t.donate.title}

{/* Details panel (right in RTL) */} {/* Form panel (left in RTL) */} {step === 1 ? (

{t.donate.amountTitle}

{/* Presets */}
{PRESETS.map((p) => ( ))}
{/* Custom amount */}
{RIYAL} { setAmount(e.target.value); setAmountError(false); }} placeholder={t.donate.customAmount} className="ps-8" data-testid="input-customAmount" />
{/* On behalf checkbox */}
{onBehalf && ( setOnBehalfName(e.target.value)} placeholder={t.donate.onBehalfName} className="mt-3" data-testid="input-onBehalfName" /> )}
{amountError && (

{t.donate.selectAmountError}

)}
) : (

{t.donate.paymentTitle}

{t.donate.amount} {RIYAL} {Number(amount).toLocaleString()}
( {t.donate.donorName} )} /> ( {t.donate.donorPhone} )} /> ( {t.donate.donorEmail} )} />
)}
); }