import { useState } from "react"; import { Loader, Lock, User } from "lucide-react"; import { api, ApiError } from "../../api/client.js"; interface Props { onSuccess: (username: string) => void; } export function LoginScreen({ onSuccess }: Props) { const [username, setUsername] = useState(""); const [password, setPassword] = useState(""); const [error, setError] = useState(null); const [busy, setBusy] = useState(false); async function submit(e: React.SubmitEvent) { e.preventDefault(); if (busy) return; setBusy(true); setError(null); try { const res = await api.login(username, password); onSuccess(res.username); } catch (err) { if (err instanceof ApiError && err.status === 401) { setError("Invalid username or password."); } else if (err instanceof ApiError && err.status === 429) { setError( "Too many failed attempts. Please wait a moment and try again.", ); } else { setError(err instanceof Error ? err.message : "Login failed."); } } finally { setBusy(false); } } return (
NVCurve

NVCurve

Sign in to continue

setUsername(e.target.value)} className="w-full bg-zinc-950 border border-zinc-700 rounded-lg pl-9 pr-3 py-2 text-sm text-zinc-100 placeholder-zinc-600 focus:outline-none focus:border-violet-500 focus:ring-1 focus:ring-violet-500/40" placeholder="username" />
setPassword(e.target.value)} className="w-full bg-zinc-950 border border-zinc-700 rounded-lg pl-9 pr-3 py-2 text-sm text-zinc-100 placeholder-zinc-600 focus:outline-none focus:border-violet-500 focus:ring-1 focus:ring-violet-500/40" placeholder="••••••••" />
{error && (
{error}
)}

Sessions last 24 hours, then you will be asked to sign in again.

); }