"use client";
import { useState, type FormEvent } from "react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { parseAuthIdentity, type AuthIdentity } from "@/lib/auth/types";
type LoginScreenProps = {
onAuthenticated: (token: string, user: AuthIdentity) => void;
};
type LoginResponse = {
token: string;
user: AuthIdentity;
};
export function LoginScreen({ onAuthenticated }: LoginScreenProps) {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [isSubmitting, setIsSubmitting] = useState(false);
const [error, setError] = useState("");
async function handleSubmit(event: FormEvent<HTMLFormElement>) {
event.preventDefault();
if (!email.trim() || !password.trim() || isSubmitting) {
return;
}
setIsSubmitting(true);
setError("");
try {
const response = await fetch("/api/auth/login", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email, password }),
});
if (!response.ok) {
throw new Error("Login failed");
}
const payload = parseLoginResponse(await response.json());
if (!payload) {
throw new Error("Invalid login response");
}
onAuthenticated(payload.token, payload.user);
} catch {
setError("Не удалось войти. Проверьте логин и пароль.");
} finally {
setIsSubmitting(false);
}
}
return (
<main className="flex min-h-screen items-center justify-center bg-muted/30 p-6">
<section className="w-full max-w-sm rounded-lg border bg-background p-8 shadow-sm">
<p className="mb-6 text-sm font-medium text-muted-foreground">
AI Control Center
</p>
<h1 className="text-2xl font-semibold">Вход</h1>
<form className="mt-6 space-y-4" onSubmit={handleSubmit}>
<div className="space-y-2">
<label className="text-sm font-medium" htmlFor="email">
Логин или почта
</label>
<Input
autoComplete="username"
id="email"
onChange={(event) => setEmail(event.target.value)}
type="text"
value={email}
/>
</div>
<div className="space-y-2">
<label className="text-sm font-medium" htmlFor="password">
Пароль
</label>
<Input
autoComplete="current-password"
id="password"
onChange={(event) => setPassword(event.target.value)}
type="password"
value={password}
/>
</div>
<p aria-live="polite" className="min-h-5 text-sm text-destructive">
{error}
</p>
<Button
className="w-full"
disabled={!email.trim() || !password.trim() || isSubmitting}
type="submit"
>
{isSubmitting ? "Выполняем вход…" : "Продолжить"}
</Button>
</form>
</section>
</main>
);
}
function parseLoginResponse(value: unknown): LoginResponse | null {
if (
typeof value !== "object" ||
value === null ||
!("token" in value) ||
typeof value.token !== "string" ||
!value.token ||
!("user" in value)
) {
return null;
}
const user = parseAuthIdentity(value.user);
return user ? { token: value.token, user } : null;
}