"use client"; import { useEffect, useMemo, useState } from "react"; import { useRouter } from "next/navigation"; import { createClient } from "@/lib/supabase/client"; import { formatMessage } from "@/lib/i18n/shared"; import type { Dict } from "@/lib/i18n/shared"; import PasskeyManager from "@/components/PasskeyManager"; import { useDict } from "@/components/i18n/LocaleProvider"; function authErrorMessage(dict: Dict, message: string): string { if (/invalid login credentials/i.test(message)) return dict.account.wrongCurrentPassword; if (/should be at least/i.test(message)) return dict.account.passwordTooShort; if (/email.*already|already.*registered/i.test(message)) return dict.account.emailAlreadyUsed; return message; } export default function AccountManager({ role, initialFullName, initialEmail, initialPasswordAuthEnabled, }: { role: string; initialFullName: string; initialEmail: string; initialPasswordAuthEnabled: boolean; }) { const supabase = useMemo(() => createClient(), []); const router = useRouter(); const dict = useDict(); const roleLabel = role === "admin" ? dict.common.roleAdmin : dict.common.roleStaff; // Persönliche Daten const [fullName, setFullName] = useState(initialFullName); const [nameError, setNameError] = useState(null); const [nameInfo, setNameInfo] = useState(null); const [nameBusy, setNameBusy] = useState(false); // E-Mail-Adresse const [email, setEmail] = useState(initialEmail); const [emailError, setEmailError] = useState(null); const [emailInfo, setEmailInfo] = useState(null); const [emailBusy, setEmailBusy] = useState(false); // Passwort const [currentPassword, setCurrentPassword] = useState(""); const [newPassword, setNewPassword] = useState(""); const [newPasswordRepeat, setNewPasswordRepeat] = useState(""); const [pwError, setPwError] = useState(null); const [pwInfo, setPwInfo] = useState(null); const [pwBusy, setPwBusy] = useState(false); // Passwort-Anmeldung an/aus const [passwordAuthEnabled, setPasswordAuthEnabled] = useState( initialPasswordAuthEnabled ); const [passkeyCount, setPasskeyCount] = useState(null); const [authError, setAuthError] = useState(null); const [authInfo, setAuthInfo] = useState(null); const [authBusy, setAuthBusy] = useState(false); useEffect(() => { supabase.auth.passkey .list() .then(({ data }) => setPasskeyCount((data ?? []).length)); }, [supabase]); async function saveName(e: React.FormEvent) { e.preventDefault(); setNameError(null); setNameInfo(null); const name = fullName.trim(); if (!name) { setNameError(dict.account.nameRequired); return; } setNameBusy(true); const { error } = await supabase .from("profiles") .update({ full_name: name }) .eq("id", (await supabase.auth.getUser()).data.user?.id ?? ""); if (error) setNameError(formatMessage(dict.account.saveError, { message: error.message })); else { setNameInfo(dict.account.nameSaved); router.refresh(); } setNameBusy(false); } async function saveEmail(e: React.FormEvent) { e.preventDefault(); setEmailError(null); setEmailInfo(null); const next = email.trim(); if (!next || next === initialEmail) return; setEmailBusy(true); const { error } = await supabase.auth.updateUser({ email: next }); if (error) { setEmailError( formatMessage(dict.account.changeError, { message: authErrorMessage(dict, error.message), }) ); } else { setEmailInfo(dict.account.emailSent); } setEmailBusy(false); } async function savePassword(e: React.FormEvent) { e.preventDefault(); setPwError(null); setPwInfo(null); if (newPassword.length < 8) { setPwError(dict.account.passwordTooShort); return; } if (newPassword !== newPasswordRepeat) { setPwError(dict.account.passwordMismatch); return; } setPwBusy(true); // Zur Verifizierung: aktuelles Passwort gegenprüfen, bevor geändert wird. const { error: verifyError } = await supabase.auth.signInWithPassword({ email: initialEmail, password: currentPassword, }); if (verifyError) { setPwError(authErrorMessage(dict, verifyError.message)); setPwBusy(false); return; } const { error } = await supabase.auth.updateUser({ password: newPassword }); if (error) { setPwError( formatMessage(dict.account.changeError, { message: authErrorMessage(dict, error.message), }) ); } else { setPwInfo(dict.account.passwordChanged); setCurrentPassword(""); setNewPassword(""); setNewPasswordRepeat(""); } setPwBusy(false); } async function togglePasswordAuth() { setAuthError(null); setAuthInfo(null); const next = !passwordAuthEnabled; if (!next && (passkeyCount ?? 0) === 0) { setAuthError(dict.account.passwordAuthNeedsPasskey); return; } if (!next && !window.confirm(dict.account.confirmDisablePasswordAuth)) return; setAuthBusy(true); const { error } = await supabase .from("profiles") .update({ password_auth_enabled: next }) .eq("id", (await supabase.auth.getUser()).data.user?.id ?? ""); if (error) { setAuthError(formatMessage(dict.account.saveError, { message: error.message })); } else { setPasswordAuthEnabled(next); setAuthInfo( next ? dict.account.passwordAuthEnabled : dict.account.passwordAuthDisabled ); } setAuthBusy(false); } return (

{dict.account.title}

{initialEmail} – {roleLabel}

{dict.account.personalTitle}

setFullName(e.target.value)} required />
{nameError && (

{nameError}

)} {nameInfo &&

{nameInfo}

}

{dict.account.emailTitle}

setEmail(e.target.value)} required />
{emailError && (

{emailError}

)} {emailInfo &&

{emailInfo}

}

{dict.account.passwordTitle}

setCurrentPassword(e.target.value)} autoComplete="current-password" required />
setNewPassword(e.target.value)} autoComplete="new-password" minLength={8} required />
setNewPasswordRepeat(e.target.value)} autoComplete="new-password" minLength={8} required />
{pwError && (

{pwError}

)} {pwInfo &&

{pwInfo}

}

{dict.account.passwordAuthTitle}

{dict.account.passwordAuthHint}

{authError && (

{authError}

)} {authInfo &&

{authInfo}

}
); }