"use client" import type React from "react" import { Button } from "@/components/ui/button" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" import { Input } from "@/components/ui/input" import { Label } from "@/components/ui/label" import { Textarea } from "@/components/ui/textarea" import { Checkbox } from "@/components/ui/checkbox" import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group" import Link from "next/link" import { useState } from "react" import { EVENT_SHORT, EVENT_FULL_NAME, EVENT_DATES, EVENT_LOCATION, PRICING_TIERS, PROCESSING_FEE_PERCENT, ACCOMMODATION_VENUES, ACCOMMODATION_MAP, ACCOMMODATION_NIGHTS, LINKS, } from "@/lib/event.config" // Determine current tier client-side function getClientTier() { const now = new Date().toISOString().slice(0, 10) return PRICING_TIERS.find((t) => now < t.cutoff) ?? PRICING_TIERS[PRICING_TIERS.length - 1] } export default function RegisterPage() { const [step, setStep] = useState<"form" | "payment">("form") const [isSubmitting, setIsSubmitting] = useState(false) const [includeAccommodation, setIncludeAccommodation] = useState(true) const [wantFood, setWantFood] = useState(false) const [selectedVenueKey, setSelectedVenueKey] = useState(ACCOMMODATION_VENUES[0]?.key || "") const [accommodationType, setAccommodationType] = useState( ACCOMMODATION_VENUES[0]?.options[0]?.id || "" ) const [formData, setFormData] = useState({ name: "", email: "", contact: "", contributions: "", expectations: "", howHeard: "", dietary: [] as string[], dietaryOther: "", crewConsent: "", }) const tier = getClientTier() const baseTicketPrice = tier.price const accommodationPrice = ACCOMMODATION_MAP[accommodationType]?.price ?? 0 const subtotalPrice = baseTicketPrice + (includeAccommodation ? accommodationPrice : 0) const processingFee = Math.round(subtotalPrice * PROCESSING_FEE_PERCENT * 100) / 100 const totalPrice = subtotalPrice + processingFee const handleSubmit = async (e: React.FormEvent) => { e.preventDefault() // Validate required fields if ( !formData.name || !formData.email || !formData.contact || !formData.contributions || !formData.expectations || !formData.crewConsent ) { alert("Please fill in all required fields") return } setIsSubmitting(true) try { // Submit registration to Google Sheet first const dietaryString = formData.dietary.join(", ") + (formData.dietaryOther ? `, ${formData.dietaryOther}` : "") const response = await fetch("/api/register", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ name: formData.name, email: formData.email, contact: formData.contact, contributions: formData.contributions, expectations: formData.expectations, howHeard: formData.howHeard, dietary: dietaryString, crewConsent: formData.crewConsent, wantFood, }), }) if (!response.ok) { throw new Error("Failed to record registration") } // Proceed to payment step setStep("payment") } catch (error) { console.error("Registration error:", error) alert("There was an error recording your registration. Please try again.") } finally { setIsSubmitting(false) } } const handleDietaryChange = (value: string, checked: boolean) => { setFormData((prev) => ({ ...prev, dietary: checked ? [...prev.dietary, value] : prev.dietary.filter((item) => item !== value), })) } // Pricing summary line const pricingSummary = PRICING_TIERS.map( (t) => `€${t.price} ${t.label}${t === tier ? " (current)" : ""}` ).join(" · ") if (step === "payment") { return (
{/* Header */}
{EVENT_SHORT}

Complete Your Registration

Choose your payment method

Event Registration {pricingSummary}
{/* Ticket */}
{EVENT_SHORT} Ticket
{pricingSummary}
€{baseTicketPrice.toFixed(2)}
{/* Accommodation */}
setIncludeAccommodation(checked as boolean)} className="mt-1" />
{includeAccommodation && ( €{accommodationPrice.toFixed(2)} )}
{includeAccommodation ? (
{/* Venue selection */} { setSelectedVenueKey(value) const venue = ACCOMMODATION_VENUES.find((v) => v.key === value) if (venue?.options[0]) { setAccommodationType(venue.options[0].id) } }} className="space-y-2" > {ACCOMMODATION_VENUES.map((venue) => (
))}
{/* Sub-options for selected venue */} {ACCOMMODATION_VENUES.filter((v) => v.key === selectedVenueKey).map((venue) => (

{venue.description}

{venue.options.map((opt) => (
))}
))}
) : (

I'll arrange my own accommodation

)}
{includeAccommodation && (

We'll follow up closer to the event to confirm room assignments and accommodation details.

)} {/* Food */}
setWantFood(checked as boolean)} className="mt-1" />

More details and costs will be shared soon — checking this box registers your interest so we can plan accordingly. Your dietary preferences from step 1 have been noted.

{/* Processing fee */}
Payment processing fee ({(PROCESSING_FEE_PERCENT * 100).toFixed(0)}%)
€{processingFee.toFixed(2)}
{/* Total */}
Total Amount
Ticket{includeAccommodation ? " + accommodation" : ""}
€{totalPrice.toFixed(2)}
{/* Payment Methods */}
Payment Options Choose your preferred payment method

You'll be redirected to Mollie's secure checkout where you can pay by credit card, SEPA bank transfer, iDEAL, PayPal, or other methods.

All payments are processed securely through Mollie. You'll receive a confirmation email after successful payment.

{/* Simplified Footer */}
) } return (
{/* Header */}
{EVENT_SHORT}

Register for {EVENT_SHORT}

{EVENT_DATES} · {EVENT_LOCATION}

Registration Form Tell us about yourself and what you'd like to bring to {EVENT_SHORT}
{/* Name */}
setFormData({ ...formData, name: e.target.value })} />
{/* Email */}
setFormData({ ...formData, email: e.target.value })} />

We'll send your registration confirmation and event updates here.

{/* Contact */}
setFormData({ ...formData, contact: e.target.value })} />
{/* Contributions */}