This commit is contained in:
jason
2026-04-20 15:49:01 -05:00
parent 381a31d607
commit b98837a72c
46 changed files with 8883 additions and 37 deletions
+95
View File
@@ -0,0 +1,95 @@
"use client";
import { useState } from "react";
import { useRouter } from "next/navigation";
import Link from "next/link";
export default function AdminLoginPage() {
const router = useRouter();
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState<string | null>(null);
const [busy, setBusy] = useState(false);
async function onSubmit(e: React.FormEvent) {
e.preventDefault();
setError(null);
setBusy(true);
try {
const res = await fetch("/api/auth/admin/login", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ email, password }),
});
const data = await res.json().catch(() => ({}));
if (!res.ok) {
setError(data.error ?? "Sign-in failed");
return;
}
router.push(data.redirect ?? "/admin");
router.refresh();
} catch {
setError("Network error");
} finally {
setBusy(false);
}
}
return (
<main className="min-h-dvh flex items-center justify-center p-6 bg-slate-50">
<form
onSubmit={onSubmit}
className="w-full max-w-sm space-y-5 bg-white rounded-2xl border border-slate-200 p-6 shadow-sm"
>
<div>
<h1 className="text-2xl font-semibold">Admin sign-in</h1>
<p className="text-slate-500 text-sm mt-1">Use your email and password.</p>
</div>
<label className="block">
<span className="block text-sm font-medium text-slate-700 mb-1">Email</span>
<input
type="email"
autoComplete="email"
required
value={email}
onChange={(e) => setEmail(e.target.value)}
className="w-full rounded-lg border border-slate-300 px-3 py-2 text-base outline-none focus:border-slate-900 focus:ring-2 focus:ring-slate-200"
/>
</label>
<label className="block">
<span className="block text-sm font-medium text-slate-700 mb-1">Password</span>
<input
type="password"
autoComplete="current-password"
required
value={password}
onChange={(e) => setPassword(e.target.value)}
className="w-full rounded-lg border border-slate-300 px-3 py-2 text-base outline-none focus:border-slate-900 focus:ring-2 focus:ring-slate-200"
/>
</label>
{error && (
<p className="text-sm text-red-600 bg-red-50 border border-red-200 rounded-md px-3 py-2">
{error}
</p>
)}
<button
type="submit"
disabled={busy}
className="w-full rounded-lg bg-slate-900 text-white py-2.5 font-medium disabled:opacity-60 hover:bg-slate-800 transition"
>
{busy ? "Signing in…" : "Sign in"}
</button>
<div className="text-center">
<Link href="/login" className="text-sm text-slate-500 hover:text-slate-900">
Back
</Link>
</div>
</form>
</main>
);
}