import React, { useState } from "react"; import { Button, Form } from "react-bootstrap"; import { useForm } from "react-hook-form"; import { ContinueButton, FormItem } from "../components/atoms"; import { StagerComponent } from "../components/stager"; import { Summary } from "../components/summary"; import { FormSchema, currencyCodeToSymbol } from "../schema"; import { get as getEnv } from "../env"; const membershipToDonationTiers = (membership: string): Array => { switch (membership) { case "suggested": case "standard": return [25, 50, 100, 500]; case "lowWaged": return [4, 8]; case "unwaged": case "student": return [3, 6]; default: return [25, 50, 100, 500]; } }; export const DonationPage: StagerComponent = ({ data, onCompleted }) => { const donationTiers = data.membership ? membershipToDonationTiers(data.membership) : [5, 10, 15, 20]; const supporterMode = Boolean(getEnv("DONATION_SUPPORTER_MODE")); const oneOffAvailable = Boolean(getEnv("USE_STRIPE")) && !Boolean(getEnv("STRIPE_DIRECT_DEBIT_ONLY")); const membershipPlans = (getEnv("MEMBERSHIP_PLANS") as any[]) || []; const supporterTiers: number[] = membershipPlans.map((p) => Number(p.amount)).filter((n) => n > 0); const supporterCurrency: string = membershipPlans[0]?.currency || "GBP"; const defaultSupporterTier = supporterTiers[0] ?? 0; const [isMonthly, setIsMonthly] = useState(true); const [selectedTier, setSelectedTier] = useState(defaultSupporterTier); const form = useForm({ defaultValues: { donationAmount: supporterMode ? defaultSupporterTier : donationTiers[1], recurDonation: supporterMode ? true : false, ...data } }); const selectedDonationAmount = form.watch("donationAmount"); const otherDonationAmount = form.watch("otherDonationAmount"); const handleSubmit = form.handleSubmit((formData) => { if (supporterMode) { const amount = (formData.otherDonationAmount != null && formData.otherDonationAmount !== "") ? Number(formData.otherDonationAmount) : selectedTier; delete formData.otherDonationAmount; // Find the plan whose amount matches the selected tier. // The plan price IS the donation — no separate donationAmount item should be created. const matchingPlan = membershipPlans.find((p: any) => Number(p.amount) === amount); const fallbackPlan = membershipPlans.find((p: any) => p.allowCustomAmount) ?? membershipPlans[0]; const resolvedPlan = matchingPlan ?? fallbackPlan; onCompleted({ ...formData, membership: resolvedPlan?.value ?? formData.membership, ...(!matchingPlan ? { customMembershipAmount: amount } : {}), // Recurring: plan price IS the donation — no separate donationAmount item needed // One-off: no subscription is created, so pass the amount for the PaymentIntent donationAmount: isMonthly ? 0 : amount, recurDonation: isMonthly, // One-off payments require card — override any stale directDebit from session ...(!isMonthly ? { paymentMethod: "creditCard" } : {}), }); return; } if (formData.otherDonationAmount !== "" && formData.otherDonationAmount != null) { formData.donationAmount = formData.otherDonationAmount; delete formData.otherDonationAmount; } onCompleted(formData); }); if (supporterMode && supporterTiers.length === 0) { return (
No donation amounts configured.

Add membership plans to this block in the WordPress editor. Their amounts will be used as the donation tiers shown to supporters.

); } if (supporterMode) { const currencySymbol = currencyCodeToSymbol(supporterCurrency); const activeAmount = (otherDonationAmount != null && otherDonationAmount !== "") ? Number(otherDonationAmount) : selectedTier; const ctaLabel = activeAmount > 0 ? (isMonthly ? `Donate ${currencySymbol}${activeAmount}/month` : `Donate ${currencySymbol}${activeAmount} now`) : (isMonthly ? "Donate monthly" : "Donate now"); return (

Support us

{!oneOffAvailable && (

One-off donations are not available with Direct Debit. To make a one-off donation, please contact us.

)}
{supporterTiers.map((tier) => ( ))}
); } return (

Can you chip in?

We rely on our members' generosity to build our movement, particularly as we look ahead to the next General Election and the work that needs to be done to gain more MPs.

Many of our members top up their membership, which forms a vital part of our income. We'd be very grateful if you would consider doing the same.

{donationTiers.map((donationTierAmount) => ( ))}
{ form.setValue("donationAmount", 0); }} text="Not right now" /> ); };