Files
calvana/pledge-now-pay-later/src/app/p/[token]/steps/identity-step.tsx
Omair Saleh 0236867c88 feat: remove FPX, add UK charity persona features
- Remove FPX payment rail entirely (Malaysian, not UK)
- Add volunteer portal (/v/[code]) with live pledge tracking
- Add public event page (/e/[slug]) with progress bar + social proof
- Add fundraiser leaderboard (/dashboard/events/[id]/leaderboard)
- Add WhatsApp share buttons on confirmation, bank instructions, volunteer view
- Enhanced Gift Aid UX with +25% bonus display and HMRC declaration text
- Gift Aid report export (HMRC-ready CSV filter)
- Volunteer view link + WhatsApp share on QR code cards
- Updated home page: 4 personas, 3 UK payment rails, 8 features
- Public event API endpoint with privacy-safe donor name truncation
- Volunteer API with stats, conversion rate, auto-refresh
2026-03-03 03:47:18 +08:00

162 lines
5.6 KiB
TypeScript

"use client"
import { useState } from "react"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { Gift, Shield } from "lucide-react"
interface Props {
onSubmit: (data: {
donorName: string
donorEmail: string
donorPhone: string
giftAid: boolean
}) => void
amount: number
}
export function IdentityStep({ onSubmit, amount }: Props) {
const [name, setName] = useState("")
const [email, setEmail] = useState("")
const [phone, setPhone] = useState("")
const [giftAid, setGiftAid] = useState(false)
const [submitting, setSubmitting] = useState(false)
const hasContact = email.includes("@") || phone.length >= 10
const isValid = hasContact
const giftAidBonus = Math.round(amount * 0.25)
const handleSubmit = async () => {
if (!isValid) return
setSubmitting(true)
try {
await onSubmit({ donorName: name, donorEmail: email, donorPhone: phone, giftAid })
} catch {
setSubmitting(false)
}
}
return (
<div className="max-w-md mx-auto pt-4 space-y-6">
<div className="text-center space-y-2">
<h1 className="text-2xl font-extrabold text-gray-900">
Almost there!
</h1>
<p className="text-muted-foreground">
We need a way to send you payment details
</p>
</div>
<div className="space-y-4">
<div className="space-y-2">
<Label htmlFor="name">Full Name <span className="text-muted-foreground font-normal">(for Gift Aid)</span></Label>
<Input
id="name"
placeholder="Your full name"
value={name}
onChange={(e) => setName(e.target.value)}
autoComplete="name"
/>
</div>
<div className="space-y-2">
<Label htmlFor="email">Email</Label>
<Input
id="email"
type="email"
placeholder="your@email.com"
value={email}
onChange={(e) => setEmail(e.target.value)}
autoComplete="email"
inputMode="email"
/>
<p className="text-xs text-muted-foreground">
We&apos;ll send your payment instructions and receipt here
</p>
</div>
<div className="relative flex items-center">
<div className="flex-grow border-t border-gray-200" />
<span className="flex-shrink mx-3 text-xs text-muted-foreground">or</span>
<div className="flex-grow border-t border-gray-200" />
</div>
<div className="space-y-2">
<Label htmlFor="phone">Mobile Number</Label>
<Input
id="phone"
type="tel"
placeholder="07700 900000"
value={phone}
onChange={(e) => setPhone(e.target.value)}
autoComplete="tel"
inputMode="tel"
/>
<p className="text-xs text-muted-foreground">
We can send reminders via SMS if you prefer
</p>
</div>
{/* Gift Aid — prominent UK-specific */}
<div
onClick={() => setGiftAid(!giftAid)}
className={`rounded-2xl border-2 p-5 cursor-pointer transition-all ${
giftAid
? "border-success-green bg-success-green/5 shadow-md shadow-success-green/10"
: "border-gray-200 bg-white hover:border-success-green/50"
}`}
>
<div className="flex items-start gap-4">
<div className={`rounded-xl p-2.5 ${giftAid ? "bg-success-green/10" : "bg-gray-100"}`}>
<Gift className={`h-6 w-6 ${giftAid ? "text-success-green" : "text-gray-400"}`} />
</div>
<div className="flex-1">
<div className="flex items-center gap-2">
<input
type="checkbox"
checked={giftAid}
onChange={() => {}}
className="h-5 w-5 rounded border-gray-300 text-success-green focus:ring-success-green"
/>
<span className="font-bold text-gray-900">Add Gift Aid</span>
{giftAid && (
<span className="text-xs font-bold px-2 py-0.5 rounded-full bg-success-green text-white">
+£{(giftAidBonus / 100).toFixed(0)} free
</span>
)}
</div>
<p className="text-sm text-muted-foreground mt-1">
Boost your £{(amount / 100).toFixed(0)} pledge to{" "}
<span className="font-bold text-success-green">£{((amount + giftAidBonus) / 100).toFixed(0)}</span> at no extra cost.
HMRC adds 25% the charity claims it back.
</p>
{giftAid && (
<p className="text-xs text-muted-foreground mt-2 italic">
I confirm I am a UK taxpayer and understand that if I pay less Income Tax and/or
Capital Gains Tax than the amount of Gift Aid claimed on all my donations in that
tax year it is my responsibility to pay any difference.
</p>
)}
</div>
</div>
</div>
</div>
<Button
size="xl"
className="w-full"
disabled={!isValid || submitting}
onClick={handleSubmit}
>
{submitting ? "Submitting..." : "Complete Pledge ✓"}
</Button>
<div className="flex items-center justify-center gap-2 text-xs text-muted-foreground">
<Shield className="h-3 w-3" />
<span>Your data is kept secure and only used for this pledge</span>
</div>
</div>
)
}