Files
lms-sb/src/app/(auth)/login/login-form.tsx
T
admins a5e7b20699 Add forgot-password and reset-password flow
Users can now request a password reset link via email. Better Auth
sendResetPassword callback sends a branded email via Resend. Login
page shows success notice after password is set.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-07 11:04:06 +05:00

109 lines
3.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
import { useState } from "react";
import { useRouter } from "next/navigation";
import Link from "next/link";
import { signIn, authClient } from "@/lib/auth-client";
export function LoginForm() {
const router = useRouter();
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState("");
const [loading, setLoading] = useState(false);
async function handleSubmit(e: React.FormEvent) {
e.preventDefault();
setError("");
setLoading(true);
const result = await signIn.email({ email, password });
if (result.error) {
setError("Неверный email или пароль");
setLoading(false);
return;
}
const session = await authClient.getSession();
const role = session.data?.user?.role;
if (role === "admin") {
router.push("/admin/dashboard");
} else if (role === "curator") {
router.push("/curator/dashboard");
} else {
router.push("/dashboard");
}
router.refresh();
}
return (
<form onSubmit={handleSubmit} className="space-y-5">
<div className="space-y-1.5">
<label className="block text-xs uppercase tracking-widest font-bold" style={{ color: "var(--muted-foreground)" }}>
Email
</label>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
className="w-full px-3 py-2 text-sm bg-transparent"
style={{
border: "2px solid var(--border)",
color: "var(--foreground)",
fontFamily: "var(--font-sans)",
outline: "none",
}}
onFocus={(e) => (e.target.style.borderColor = "var(--foreground)")}
onBlur={(e) => (e.target.style.borderColor = "var(--border)")}
placeholder="you@example.com"
/>
</div>
<div className="space-y-1.5">
<label className="block text-xs uppercase tracking-widest font-bold" style={{ color: "var(--muted-foreground)" }}>
Пароль
</label>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
className="w-full px-3 py-2 text-sm bg-transparent"
style={{
border: "2px solid var(--border)",
color: "var(--foreground)",
fontFamily: "var(--font-sans)",
outline: "none",
}}
onFocus={(e) => (e.target.style.borderColor = "var(--foreground)")}
onBlur={(e) => (e.target.style.borderColor = "var(--border)")}
placeholder="••••••••"
/>
</div>
{error && (
<p className="text-sm" style={{ color: "var(--destructive)" }}>
{error}
</p>
)}
<button
type="submit"
disabled={loading}
className="btn-aubade w-full justify-center"
style={loading ? { opacity: 0.6, cursor: "not-allowed" } : undefined}
>
{loading ? "Вход..." : "Войти"}
</button>
<div className="flex items-center justify-between text-xs" style={{ color: "var(--muted-foreground)" }}>
<Link href="/forgot-password" className="underline" style={{ color: "var(--muted-foreground)" }}>
Забыли пароль?
</Link>
<Link href="/register" className="underline" style={{ color: "var(--foreground)" }}>
Зарегистрироваться
</Link>
</div>
</form>
);
}