"use client" import { useState, useEffect } from "react" import { useParams } from "next/navigation" import { AmountStep } from "./steps/amount-step" import { PaymentStep } from "./steps/payment-step" import { IdentityStep } from "./steps/identity-step" import { ConfirmationStep } from "./steps/confirmation-step" import { BankInstructionsStep } from "./steps/bank-instructions-step" import { CardPaymentStep } from "./steps/card-payment-step" import { DirectDebitStep } from "./steps/direct-debit-step" export type Rail = "bank" | "gocardless" | "card" export interface PledgeData { amountPence: number rail: Rail donorName: string donorEmail: string donorPhone: string giftAid: boolean } interface EventInfo { id: string name: string organizationName: string qrSourceId: string | null qrSourceLabel: string | null } // Steps: // 0 = Amount // 1 = Payment method // 2 = Identity (for bank transfer) // 3 = Bank instructions // 4 = Confirmation (card, DD) // 5 = Card payment step // 7 = Direct Debit step export default function PledgePage() { const params = useParams() const token = params.token as string const [step, setStep] = useState(0) const [eventInfo, setEventInfo] = useState(null) const [pledgeData, setPledgeData] = useState({ amountPence: 0, rail: "bank", donorName: "", donorEmail: "", donorPhone: "", giftAid: false, }) const [pledgeResult, setPledgeResult] = useState<{ id: string reference: string bankDetails?: { bankName: string sortCode: string accountNo: string accountName: string } } | null>(null) const [loading, setLoading] = useState(true) const [error, setError] = useState("") useEffect(() => { fetch(`/api/qr/${token}`) .then((r) => r.json()) .then((data) => { if (data.error) setError(data.error) else setEventInfo(data) setLoading(false) }) .catch(() => { setError("Unable to load pledge page") setLoading(false) }) fetch("/api/analytics", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ eventType: "pledge_start", metadata: { token } }), }).catch(() => {}) }, [token]) const handleAmountSelected = (amountPence: number) => { setPledgeData((d) => ({ ...d, amountPence })) setStep(1) } const handleRailSelected = (rail: Rail) => { setPledgeData((d) => ({ ...d, rail })) const railStepMap: Record = { bank: 2, card: 5, gocardless: 7, } setStep(railStepMap[rail]) } const submitPledge = async (identity: { donorName: string; donorEmail: string; donorPhone: string; giftAid: boolean }) => { const finalData = { ...pledgeData, ...identity } setPledgeData(finalData) try { const res = await fetch("/api/pledges", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ ...finalData, eventId: eventInfo?.id, qrSourceId: eventInfo?.qrSourceId, }), }) const result = await res.json() if (result.error) { setError(result.error); return } setPledgeResult(result) setStep(finalData.rail === "bank" ? 3 : 4) } catch { setError("Something went wrong. Please try again.") } } if (loading) { return (
Loading...
) } if (error) { return (
😔

Something went wrong

{error}

) } const shareUrl = eventInfo?.qrSourceId ? `${typeof window !== "undefined" ? window.location.origin : ""}/p/${token}` : undefined const steps: Record = { 0: , 1: , 2: , 3: pledgeResult && , 4: pledgeResult && , 5: , 7: , } const backableSteps = new Set([1, 2, 5, 7]) const getBackStep = (s: number): number => { if (s === 5 || s === 7) return 1 return s - 1 } const progressPercent = step >= 3 ? 100 : step >= 2 ? 66 : step >= 1 ? 33 : 10 return (

{eventInfo?.organizationName}

{eventInfo?.qrSourceLabel || ""}

{steps[step]}
{backableSteps.has(step) && (
)}
) }