import { useMutation } from "@tanstack/react-query"; import { useState } from "react"; import { toast } from "sonner"; import { inputCls, validateEmail, validatePhone, validateTextField, } from "@/lib/registration"; import { orpc } from "@/utils/orpc"; import { GiftSelector } from "./GiftSelector"; interface PerformerErrors { firstName?: string; lastName?: string; email?: string; phone?: string; artForm?: string; isOver16?: string; } interface Props { onBack: () => void; onSuccess: (token: string, email: string, name: string) => void; prefillFirstName?: string; prefillLastName?: string; prefillEmail?: string; isLoggedIn?: boolean; } export function PerformerForm({ onBack, onSuccess, prefillFirstName = "", prefillLastName = "", prefillEmail = "", isLoggedIn = false, }: Props) { const [data, setData] = useState({ firstName: prefillFirstName, lastName: prefillLastName, email: prefillEmail, phone: "", artForm: "", experience: "", isOver16: false, extraQuestions: "", }); const [giftAmount, setGiftAmount] = useState(0); const [errors, setErrors] = useState({}); const [touched, setTouched] = useState>({}); const submitMutation = useMutation({ ...orpc.submitRegistration.mutationOptions(), onSuccess: (result) => { if (result.managementToken) onSuccess( result.managementToken, data.email.trim(), `${data.firstName.trim()} ${data.lastName.trim()}`.trim(), ); }, onError: (error) => { toast.error(`Er is iets misgegaan: ${error.message}`); }, }); function validate(): boolean { const errs: PerformerErrors = { firstName: validateTextField(data.firstName, true, "Voornaam"), lastName: validateTextField(data.lastName, true, "Achternaam"), email: validateEmail(data.email), phone: validatePhone(data.phone), artForm: !data.artForm.trim() ? "Kunstvorm is verplicht" : undefined, isOver16: !data.isOver16 ? "Je moet 16 jaar of ouder zijn om op te treden" : undefined, }; setErrors(errs); setTouched({ firstName: true, lastName: true, email: true, phone: true, artForm: true, isOver16: true, }); return !Object.values(errs).some(Boolean); } function handleChange( e: React.ChangeEvent, ) { const { name, value, type } = e.target; const newValue = type === "checkbox" ? (e.target as HTMLInputElement).checked : value; setData((prev) => ({ ...prev, [name]: newValue })); if (type !== "checkbox" && touched[name]) { const fieldError: Record = { firstName: validateTextField( name === "firstName" ? value : data.firstName, true, "Voornaam", ), lastName: validateTextField( name === "lastName" ? value : data.lastName, true, "Achternaam", ), email: validateEmail(name === "email" ? value : data.email), phone: validatePhone(name === "phone" ? value : data.phone), artForm: name === "artForm" && !value.trim() ? "Kunstvorm is verplicht" : undefined, }; setErrors((prev) => ({ ...prev, [name]: fieldError[name] })); } } function handleBlur( e: React.FocusEvent, ) { const { name, value } = e.target; setTouched((prev) => ({ ...prev, [name]: true })); const errMap: Record = { firstName: validateTextField(value, true, "Voornaam"), lastName: validateTextField(value, true, "Achternaam"), email: validateEmail(value), phone: validatePhone(value), artForm: !value.trim() ? "Kunstvorm is verplicht" : undefined, }; setErrors((prev) => ({ ...prev, [name]: errMap[name] })); } function handleSubmit(e: React.FormEvent) { e.preventDefault(); if (!validate()) { toast.error("Controleer je invoer"); return; } submitMutation.mutate({ firstName: data.firstName.trim(), lastName: data.lastName.trim(), email: data.email.trim(), phone: data.phone.trim() || undefined, registrationType: "performer", artForm: data.artForm.trim() || undefined, experience: data.experience.trim() || undefined, isOver16: data.isOver16, extraQuestions: data.extraQuestions.trim() || undefined, giftAmount, }); } return (
{/* Back + type header */}
Ik wil optreden
{/* Name row */}
{touched.firstName && errors.firstName && ( {errors.firstName} )}
{touched.lastName && errors.lastName && ( {errors.lastName} )}
{/* Contact row */}
{touched.email && errors.email && ( {errors.email} )}
{touched.phone && errors.phone && ( {errors.phone} )}
{/* Performer-specific fields */}

Optreden details

{touched.artForm && errors.artForm && ( {errors.artForm} )}
{/* Age confirmation */}
{/* Extra questions */}