"use client"; import { useState } from "react"; import { authClient } from "@/lib/auth-client"; import { useRouter } from "next/navigation"; import Link from "next/link"; const socialProviders = [ { id: "google", name: "Google", subtitle: "Platzhalter", icon: "G", }, { id: "apple", name: "Apple", subtitle: "Platzhalter", icon: "", }, ]; const MIN_USERNAME_LENGTH = 3; const MAX_USERNAME_LENGTH = 30; const MAX_USERNAME_ATTEMPTS = 8; function normalizeUsername(value: string) { return value .trim() .toLowerCase() .normalize("NFKD") .replace(/[\u0300-\u036f]/g, "") .replace(/[^a-z0-9._]+/g, ".") .replace(/\.{2,}/g, ".") .replace(/^[_\.]+|[_\.]+$/g, ""); } function truncateWithSuffix(base: string, suffix = "") { const allowedBaseLength = Math.max(MIN_USERNAME_LENGTH, MAX_USERNAME_LENGTH - suffix.length); const safeBase = base.slice(0, allowedBaseLength); return `${safeBase}${suffix}`.slice(0, MAX_USERNAME_LENGTH); } function fallbackUsernameFromInput(name: string, email: string) { const emailLocalPart = email.split("@")[0] ?? ""; const fromName = normalizeUsername(name); const fromEmail = normalizeUsername(emailLocalPart); const candidate = fromName || fromEmail || "user"; if (candidate.length >= MIN_USERNAME_LENGTH) { return candidate.slice(0, MAX_USERNAME_LENGTH); } return truncateWithSuffix(`${candidate}user`); } async function isUsernameAvailable(username: string) { try { const result = await authClient.isUsernameAvailable({ username }); if (result.error) { return null; } return result.data?.available === true; } catch { return null; } } async function getAvailableUsername(base: string) { const normalizedBase = normalizeUsername(base); const seeded = normalizedBase.length >= MIN_USERNAME_LENGTH ? normalizedBase : truncateWithSuffix(`${normalizedBase || "user"}user`); for (let attempt = 0; attempt < MAX_USERNAME_ATTEMPTS; attempt += 1) { const suffix = attempt === 0 ? "" : `.${Math.floor(100 + Math.random() * 900)}`; const candidate = truncateWithSuffix(seeded, suffix); const available = await isUsernameAvailable(candidate); if (available === true) { return candidate; } if (available === null) { return candidate; } } return truncateWithSuffix(seeded, `.${Date.now().toString().slice(-4)}`); } function toGermanAuthError(message?: string) { if (!message) { return "Registrierung fehlgeschlagen. Bitte versuche es erneut."; } const normalized = message.toLowerCase(); if (normalized.includes("email") && normalized.includes("already")) { return "Diese E-Mail-Adresse wird bereits verwendet."; } if (normalized.includes("username") && normalized.includes("already")) { return "Dieser Username ist bereits vergeben."; } if (normalized.includes("password")) { return "Das Passwort erfüllt die Anforderungen nicht."; } if (normalized.includes("invalid username")) { return "Der Username enthält ungültige Zeichen."; } return "Registrierung fehlgeschlagen. Bitte prüfe deine Eingaben."; } export default function SignUpPage() { const router = useRouter(); const [name, setName] = useState(""); const [email, setEmail] = useState(""); const [username, setUsername] = useState(""); const [generateUsername, setGenerateUsername] = useState(true); const [password, setPassword] = useState(""); const [error, setError] = useState(""); const [socialMessage, setSocialMessage] = useState(""); const [success, setSuccess] = useState(false); const [loading, setLoading] = useState(false); const handleSignUp = async (e: React.FormEvent) => { e.preventDefault(); setError(""); setSocialMessage(""); setLoading(true); try { const trimmedUsername = username.trim(); let finalUsername: string | undefined; if (trimmedUsername) { const normalizedInput = normalizeUsername(trimmedUsername); if (normalizedInput.length < MIN_USERNAME_LENGTH) { setError("Dein Username ist zu kurz (mindestens 3 Zeichen)."); return; } const availability = await isUsernameAvailable(normalizedInput); if (availability === false) { setError("Dieser Username ist bereits vergeben."); return; } finalUsername = normalizedInput; } else if (generateUsername) { const generatedBase = fallbackUsernameFromInput(name, email); finalUsername = await getAvailableUsername(generatedBase); } const result = await authClient.signUp.email({ email, password, name, username: finalUsername, }); if (result.error) { setError(toGermanAuthError(result.error.message)); } else { setSuccess(true); } } catch { setError("Ein unerwarteter Fehler ist aufgetreten"); } finally { setLoading(false); } }; const handleSocialPlaceholder = (provider: string) => { setError(""); setSocialMessage(`${provider}-Signup ist aktuell als Platzhalter eingebunden.`); }; if (success) { return (
Wir haben dir eine E-Mail an {email} geschickt. Klicke auf den Link, um dein Konto zu aktivieren.
Erstelle dein LemonSpace-Konto
Bereits ein Konto?{" "} Anmelden