"use client"; import { useState, useTransition } from "react"; import { useRouter } from "next/navigation"; import { PASSWORD_MIN_LENGTH, PASSWORD_POLICY_MESSAGE } from "@capakraken/shared"; import { createFirstAdmin } from "./actions.js"; export function SetupClient() { const router = useRouter(); const [name, setName] = useState(""); const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const [confirmPassword, setConfirmPassword] = useState(""); const [formError, setFormError] = useState(null); const [done, setDone] = useState(false); const [isPending, startTransition] = useTransition(); function handleSubmit(e: React.FormEvent) { e.preventDefault(); setFormError(null); if (password.length < PASSWORD_MIN_LENGTH) { setFormError(PASSWORD_POLICY_MESSAGE); return; } if (password !== confirmPassword) { setFormError("Passwords do not match."); return; } startTransition(async () => { const result = await createFirstAdmin({ name, email, password }); if ("success" in result) { setDone(true); router.push("/auth/signin?setup=done"); return; } if (result.error === "alreadySetup") { setFormError("Setup already completed. Redirecting…"); setTimeout(() => router.push("/auth/signin"), 2000); return; } if (result.error === "emailTaken") { setFormError("An account with this email already exists."); return; } if (result.error === "validation") { setFormError(result.message ?? "Validation error."); return; } }); } if (done) { return (

Admin account created

Redirecting to sign in…

); } return (

First-run setup

Create the initial administrator account for CapaKraken.

{formError && (
{formError}
)}
setName(e.target.value)} required placeholder="Your full name" className="w-full rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-900 px-3 py-2 text-sm text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-brand-400" />
setEmail(e.target.value)} required placeholder="admin@example.com" className="w-full rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-900 px-3 py-2 text-sm text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-brand-400" />
setPassword(e.target.value)} required minLength={PASSWORD_MIN_LENGTH} placeholder={`At least ${PASSWORD_MIN_LENGTH} characters`} className="w-full rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-900 px-3 py-2 text-sm text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-brand-400" />
setConfirmPassword(e.target.value)} required placeholder="Repeat your password" className="w-full rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-900 px-3 py-2 text-sm text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-brand-400" />
); }