import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { createFileRoute, Link, useParams } from "@tanstack/react-router"; import { useState } from "react"; import { toast } from "sonner"; import { GiftSelector } from "@/components/registration/GiftSelector"; import { GuestList } from "@/components/registration/GuestList"; import { calculateDrinkCard, type GuestEntry, inputCls, parseGuests, } from "@/lib/registration"; import { orpc } from "@/utils/orpc"; export const Route = createFileRoute("/manage/$token")({ component: ManageRegistrationPage, }); // --------------------------------------------------------------------------- // Shared layout wrappers // --------------------------------------------------------------------------- function PageShell({ children }: { children: React.ReactNode }) { return (
{children}
); } function BackLink() { return ( ← Terug naar account ); } // --------------------------------------------------------------------------- // Payment status badges // --------------------------------------------------------------------------- function PaidBadge() { return (
Betaling ontvangen
); } function PendingBadge() { return (
Betaling in afwachting
); } function ExtraPaymentBadge({ amountCents }: { amountCents: number }) { const euros = amountCents / 100; return (
Extra betaling vereist — €{euros.toFixed(euros % 1 === 0 ? 0 : 2)}
); } // --------------------------------------------------------------------------- // Edit form (inline on the manage page) // --------------------------------------------------------------------------- interface EditFormProps { token: string; initialData: { firstName: string; lastName: string; email: string; phone: string | null; registrationType: string; artForm: string | null; experience: string | null; isOver16: boolean; extraQuestions: string | null; guests: string | null; paymentStatus: string | null; giftAmount: number | null; }; onCancel: () => void; onSaved: () => void; } function EditForm({ token, initialData, onCancel, onSaved }: EditFormProps) { // Narrow the string from DB to the valid union; fall back to "watcher" const initialType: "performer" | "watcher" = initialData.registrationType === "performer" ? "performer" : "watcher"; const [formData, setFormData] = useState({ firstName: initialData.firstName, lastName: initialData.lastName, email: initialData.email, phone: initialData.phone ?? "", registrationType: initialType, artForm: initialData.artForm ?? "", experience: initialData.experience ?? "", isOver16: initialData.isOver16, extraQuestions: initialData.extraQuestions ?? "", }); const [formGuests, setFormGuests] = useState( parseGuests(initialData.guests), ); const [giftAmount, setGiftAmount] = useState(initialData.giftAmount ?? 0); const updateMutation = useMutation({ ...orpc.updateRegistration.mutationOptions(), onSuccess: () => { toast.success("Inschrijving bijgewerkt!"); onSaved(); }, onError: (err) => { toast.error(`Opslaan mislukt: ${err.message}`); }, }); const isWatcher = formData.registrationType === "watcher"; const totalDrinkCard = isWatcher ? calculateDrinkCard(formGuests.length) : 0; const originalGuestCount = parseGuests(initialData.guests).length; const isPaid = initialData.paymentStatus === "paid" || initialData.paymentStatus === "extra_payment_pending"; const extraGuests = formGuests.length - originalGuestCount; function handleSubmit(e: React.FormEvent) { e.preventDefault(); const performer = formData.registrationType === "performer"; updateMutation.mutate({ token, firstName: formData.firstName.trim(), lastName: formData.lastName.trim(), email: formData.email.trim(), phone: formData.phone.trim() || undefined, registrationType: formData.registrationType, artForm: performer ? formData.artForm.trim() || undefined : undefined, experience: performer ? formData.experience.trim() || undefined : undefined, isOver16: performer ? formData.isOver16 : false, guests: performer ? [] : formGuests.map((g) => ({ firstName: g.firstName.trim(), lastName: g.lastName.trim(), email: g.email.trim() || undefined, phone: g.phone.trim() || undefined, })), extraQuestions: formData.extraQuestions.trim() || undefined, giftAmount, }); } return ( <>

Bewerk inschrijving

{/* Name */}
setFormData((p) => ({ ...p, firstName: e.target.value })) } className={inputCls(false)} />
setFormData((p) => ({ ...p, lastName: e.target.value })) } className={inputCls(false)} />
{/* Contact */}
setFormData((p) => ({ ...p, email: e.target.value })) } className={inputCls(false)} />
setFormData((p) => ({ ...p, phone: e.target.value })) } className={inputCls(false)} />
{/* Registration type toggle */}

Type inschrijving

{(["performer", "watcher"] as const).map((type) => (
{/* Performer fields */} {formData.registrationType === "performer" && (
setFormData((p) => ({ ...p, artForm: e.target.value })) } list="artFormSuggestions" className={inputCls(false)} />
setFormData((p) => ({ ...p, experience: e.target.value })) } list="experienceSuggestions" className={inputCls(false)} />