"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" 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 [accommodationVenue, setAccommodationVenue] = useState<"commons-hub" | "herrnhof">("commons-hub") const [accommodationType, setAccommodationType] = useState("ch-multi") const [formData, setFormData] = useState({ name: "", email: "", contact: "", contributions: "", expectations: "", howHeard: "", dietary: [] as string[], dietaryOther: "", crewConsent: "", }) // Dynamic pricing tiers const pricingTiers = [ { label: "Early bird", price: 80, cutoff: "2026-03-31" }, { label: "Regular", price: 120, cutoff: "2026-07-01" }, { label: "Late", price: 150, cutoff: "2099-12-31" }, ] const now = new Date().toISOString().slice(0, 10) const currentTier = pricingTiers.find((t) => now < t.cutoff) ?? pricingTiers[pricingTiers.length - 1] const baseTicketPrice = currentTier.price const accommodationPrices: Record = { "ch-multi": { label: "Bed in shared room (Commons Hub)", price: 279.30 }, "ch-double": { label: "Bed in double room (Commons Hub)", price: 356.30 }, "hh-single": { label: "Single room (Herrnhof)", price: 665 }, "hh-double-separate": { label: "Double room, separate beds (Herrnhof)", price: 420 }, "hh-double-shared": { label: "Double room, shared double bed (Herrnhof)", price: 350 }, "hh-triple": { label: "Triple room, one single + one shared double bed (Herrnhof)", price: 350 }, "hh-daybed": { label: "Daybed or extra bed in living room (Herrnhof)", price: 280 }, } const accommodationPrice = accommodationPrices[accommodationType]?.price ?? 0 const subtotalPrice = baseTicketPrice + (includeAccommodation ? accommodationPrice : 0) const processingFee = Math.round(subtotalPrice * 0.02 * 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), })) } if (step === "payment") { return (
{/* Header */}
CCG

Complete Your Registration

Choose your payment method

Event Registration {currentTier.label} pricing — €{currentTier.price}
{/* Ticket */}
CCG 2026 Ticket
{pricingTiers.map((t, i) => ( {i > 0 ? " · " : ""}€{t.price} {t.label}{t === currentTier ? " (current)" : ""} ))}
CCA members: Bring two newcomers, get a free ticket!
€{baseTicketPrice.toFixed(2)}
{/* Accommodation */}
setIncludeAccommodation(checked as boolean)} className="mt-1" />
{includeAccommodation && ( €{accommodationPrice.toFixed(2)} )}
{includeAccommodation ? (
{/* Venue selection */} { const venue = value as "commons-hub" | "herrnhof" setAccommodationVenue(venue) setAccommodationType(venue === "commons-hub" ? "ch-multi" : "hh-single") }} className="space-y-2" >
{/* Sub-options per venue */} {accommodationVenue === "commons-hub" ? (

30 beds on-site at the main venue. Basic, communal accommodation.

) : (

Historic 19th-century mansion with newly renovated apartments, sauna, and river swimming platform. Prices per person for 7 nights (incl. city tax & VAT).

For whole-apartment quotes, contact{" "} office@commons-hub.at.

)}
) : (

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" />

We are exploring co-producing our own meals as a community. 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 (2%)
€{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.

{/* Footer */}

CCG 2026

Crypto Commons Gathering
August 16-23, 2026

Links

  • Register to Attend
  • Gallery
  • About CCG 2026
  • Directions
  • Financial Transparency

Community

  • Join the CCG26 Telegram
  • Join the Crypto Commons Association Telegram

Partners

  • Commons Hub
  • Crypto Commons Association
  • Sponsorships

This website is under Creative Commons license. Built with solidarity for the commons.

) } return (
{/* Header */}
CCG

Register for CCG 2026

August 16-23, 2026 at the Commons Hub in Austria

Registration Form Tell us about yourself and what you'd like to bring to CCG
{/* 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 */}