"use client"; import { useEffect, useState } from "react"; import Image from "next/image"; import Link from "next/link"; import router from "next/router"; interface EventContent { registrationEnabled: boolean; visitorOnly: boolean; volunteerAreas: string; } const normalizeSsn = (value: string) => value.replace(/[\s\-+]/g, "").replace(/\D/g, ""); const hasValidSsnLength = (value: string) => value.length === 10 || value.length === 12; const isValidEmail = (value: string) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value); const normalizeMobileNumber = (value: string) => { const digitsOnly = value.replace(/\D/g, ""); if (digitsOnly.startsWith("0046")) return `0${digitsOnly.slice(4)}`; if (digitsOnly.startsWith("46")) return `0${digitsOnly.slice(2)}`; if (digitsOnly.startsWith("7")) return `0${digitsOnly}`; return digitsOnly; }; const isValidMobileNumber = (value: string) => /^07\d{8}$/.test(normalizeMobileNumber(value)); export default function RegisterPage() { const [content, setContent] = useState(null); const [formData, setFormData] = useState({ firstName: "", surName: "", grade: "", phoneNumber: "", email: "", guardianName: "", guardianPhoneNumber: "", guardianEmail: "", isVisitor: false, hasApprovedGdpr: false, friends: "", specialDiet: "", ssn: "", }); const [isSubmitting, setIsSubmitting] = useState(false); const [message, setMessage] = useState({ type: "", text: "" }); const [fieldErrors, setFieldErrors] = useState>({}); const [showBecomeMemberCta, setShowBecomeMemberCta] = useState(false); useEffect(() => { fetch("/api/Content") .then((res) => res.json()) .then((data) => { setContent(data); if (data.visitorOnly) { setFormData((prev) => ({ ...prev, isVisitor: true })); } }) .catch((err) => console.error("Failed to fetch content", err)); }, []); if (content && !content.registrationEnabled) { return (

Registreringen är stängd

Vi tar tyvärr inte emot fler anmälningar just nu.

Gå tillbaka till startsidan
); } const handleInputChange = ( e: React.ChangeEvent< HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement >, ) => { const { name, value, type } = e.target; const val = type === "checkbox" ? (e.target as HTMLInputElement).checked : value; setFormData((prev) => ({ ...prev, [name]: val, })); setFieldErrors((prev) => ({ ...prev, [name]: "", })); }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); const normalizedSsn = normalizeSsn(formData.ssn); const trimmedFirstName = formData.firstName.trim(); const trimmedSurName = formData.surName.trim(); const trimmedGrade = formData.grade.trim(); const trimmedPhoneNumber = formData.phoneNumber.trim(); const trimmedGuardianName = formData.guardianName.trim(); const trimmedGuardianPhone = formData.guardianPhoneNumber.trim(); const trimmedGuardianEmail = formData.guardianEmail.trim(); const normalizedPhoneNumber = normalizeMobileNumber(trimmedPhoneNumber); const normalizedGuardianPhone = normalizeMobileNumber(trimmedGuardianPhone); const nextFieldErrors: Record = {}; if (!normalizedSsn) { nextFieldErrors.ssn = "Personnummer krävs för registrering."; } else if (!hasValidSsnLength(normalizedSsn)) { nextFieldErrors.ssn = "Personnummer måste vara 10 eller 12 siffror."; } if (!trimmedFirstName) nextFieldErrors.firstName = "Förnamn är obligatoriskt."; if (!trimmedSurName) nextFieldErrors.surName = "Efternamn är obligatoriskt."; if (!trimmedGrade) nextFieldErrors.grade = "Årskurs är obligatorisk."; if (!trimmedGuardianName) nextFieldErrors.guardianName = "Vårdnadshavares namn är obligatoriskt."; if (!trimmedGuardianPhone) nextFieldErrors.guardianPhoneNumber = "Vårdnadshavares Mobilnummer är obligatoriskt."; if (!trimmedGuardianEmail) nextFieldErrors.guardianEmail = "Vårdnadshavares e-post är obligatorisk."; if (trimmedPhoneNumber && !isValidMobileNumber(trimmedPhoneNumber)) { nextFieldErrors.phoneNumber = "Mobilnummer måste vara ett giltigt svenskt mobilnummer."; } if (trimmedGuardianPhone && !isValidMobileNumber(trimmedGuardianPhone)) { nextFieldErrors.guardianPhoneNumber = "Vårdnadshavares Mobilnummer måste vara ett giltigt svenskt mobilnummer."; } if (trimmedGuardianEmail && !isValidEmail(trimmedGuardianEmail)) { nextFieldErrors.guardianEmail = "Vårdnadshavarens e-postadress är ogiltig."; } if (formData.email.trim() && !isValidEmail(formData.email.trim())) { nextFieldErrors.email = "Din e-postadress är ogiltig."; } if (Object.keys(nextFieldErrors).length > 0) { setFieldErrors(nextFieldErrors); setMessage({ type: "error", text: "Kontrollera markerade fält och försök igen.", }); return; } setFieldErrors({}); setShowBecomeMemberCta(false); setIsSubmitting(true); setMessage({ type: "info", text: "Behandlar din anmälan..." }); try { // Returns Ok (200) if NOT registered, Conflict (409) if registered const checkRes = await fetch( `/api/Registration/registered/${normalizedSsn}`, ); if (checkRes.status === 409) { setMessage({ type: "error", text: "Detta personnummer är redan registrerat för LAN:et.", }); setIsSubmitting(false); return; } // Returns 200 (Ok) if member, 404 (NotFound) if not const validateRes = await fetch( `/api/Registration/register/${normalizedSsn}`, ); const isMember = validateRes.ok; const { ssn, ...participantData } = formData; const finalPayload = { ...participantData, firstName: trimmedFirstName, surName: trimmedSurName, grade: trimmedGrade, phoneNumber: normalizedPhoneNumber, email: formData.email.trim(), guardianName: trimmedGuardianName, guardianPhoneNumber: normalizedGuardianPhone, guardianEmail: trimmedGuardianEmail, friends: formData.friends.trim(), specialDiet: formData.specialDiet.trim(), isMember: isMember, }; const response = await fetch("/api/Participant/register", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(finalPayload), }); if (response.ok) { setMessage({ type: "success", text: "Registreringen är klar! Du är nu anmäld till LAN:et.", }); setShowBecomeMemberCta(!isMember); await fetch(`/api/Registration/register/${normalizedSsn}`, { method: "POST", }); } else { const errorData = await response.json(); setMessage({ type: "error", text: errorData.message || "Registreringen misslyckades.", }); } } catch (error) { console.error("Registration error:", error); setMessage({ type: "error", text: "Ett anslutningsfel uppstod. Kontrollera internet och försök igen.", }); } finally { setIsSubmitting(false); } }; return (
vBytes

LAN-registrering

Vänligen fyll i detta formulär för att anmäla dig till lanet.

{fieldErrors.ssn && (

{fieldErrors.ssn}

)}

Används endast för att kolla om du redan är medlem eller inte. Sparas ej.

{fieldErrors.firstName && (

{fieldErrors.firstName}

)}
{fieldErrors.surName && (

{fieldErrors.surName}

)}
{fieldErrors.grade && (

{fieldErrors.grade}

)}
{fieldErrors.phoneNumber && (

{fieldErrors.phoneNumber}

)}
{fieldErrors.email && (

{fieldErrors.email}

)}

Vårdnadshavares Information

{fieldErrors.guardianName && (

{fieldErrors.guardianName}

)}
{fieldErrors.guardianPhoneNumber && (

{fieldErrors.guardianPhoneNumber}

)}
{fieldErrors.guardianEmail && (

{fieldErrors.guardianEmail}

)}

Ytterligare uppgifter