"use client"; import { useRouter } from "next/navigation"; import { useState } from "react"; import { PasswordInput } from "@/components/password-input"; import { Button, Card, Field, Notice, TextInput } from "@/components/ui"; import { ApiError, apiJson } from "@/lib/api-client"; function useSubmit() { const router = useRouter(); const [pending, setPending] = useState(false); const [error, setError] = useState(null); const submit = async (json: unknown) => { setPending(true); setError(null); try { await apiJson("/api/auth", { method: "POST", json }); // refresh() ist hier entscheidend: Kopfbereich und Startseite werden // serverseitig je nach Anmeldung unterschiedlich gerendert, und ohne // Verwerfen des Zwischenspeichers käme die Seite von vor der Anmeldung. router.replace("/"); router.refresh(); } catch (caught) { setError( caught instanceof ApiError ? caught.message : "Die Anmeldung ist fehlgeschlagen.", ); setPending(false); } }; return { submit, pending, error, router }; } export function LoginForm() { const { submit, pending, error } = useSubmit(); const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); return (
{ event.preventDefault(); void submit({ action: "login", email, password }); }} > {error ? {error} : null} setEmail(event.target.value)} /> setPassword(event.target.value)} />
); } export function SetupForm({ minLength }: { minLength: number }) { const { submit, pending, error } = useSubmit(); const [email, setEmail] = useState(""); const [name, setName] = useState(""); const [password, setPassword] = useState(""); const [repeat, setRepeat] = useState(""); const mismatch = repeat.length > 0 && password !== repeat; return (
{ event.preventDefault(); if (mismatch) return; void submit({ action: "setup", email, name, password }); }} > {error ? {error} : null} setName(event.target.value)} /> setEmail(event.target.value)} /> setPassword(event.target.value)} /> setRepeat(event.target.value)} />
); } export function LogoutButton() { const router = useRouter(); const [pending, setPending] = useState(false); return ( ); }