import { useState, useEffect } from "react";
import { Eye, EyeOff, Sun, Moon, Monitor } from "lucide-react";
import { submitSystemLogin } from "../utils/requests";
interface LoginProps {
onLoginSuccess: () => void;
}
export default function Login({ onLoginSuccess }: LoginProps) {
const [authKey, setAuthKey] = useState("");
const [showPassword, setShowPassword] = useState(false);
const [error, setError] = useState("");
const [success, setSuccess] = useState(false);
const [loading, setLoading] = useState(false);
// Initialize theme from localStorage or system class list
const [theme, setTheme] = useState<"light" | "dark" | "system">(() => {
const saved = localStorage.getItem("liven-theme") as
| "light"
| "dark"
| "system"
| null;
return saved || "dark";
});
const [resolvedTheme, setResolvedTheme] = useState<"light" | "dark">("dark");
useEffect(() => {
localStorage.setItem("liven-theme", theme);
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
const updateTheme = () => {
let active: "light" | "dark" = "light";
if (theme === "system") {
active = mediaQuery.matches ? "dark" : "light";
} else {
active = theme;
}
setResolvedTheme(active);
if (active === "dark") {
document.documentElement.classList.add("dark");
} else {
document.documentElement.classList.remove("dark");
}
};
updateTheme();
if (theme === "system") {
mediaQuery.addEventListener("change", updateTheme);
return () => mediaQuery.removeEventListener("change", updateTheme);
}
}, [theme]);
const toggleTheme = () => {
setTheme((prev) => {
if (prev === "dark") return "light";
if (prev === "light") return "system";
return "dark"; // if currently system, go back to dark
});
};
const handleLogin = async (e: React.FormEvent) => {
e.preventDefault();
setError("");
setSuccess(false);
const trimmedKey = authKey.trim();
if (!trimmedKey) {
setError("Please enter your auth key.");
return;
}
try {
setLoading(true);
await submitSystemLogin(trimmedKey);
setSuccess(true);
setTimeout(() => {
onLoginSuccess();
}, 800);
} catch (err: any) {
console.error(err);
setError(err.message || "Authentication failed. Invalid auth key");
} finally {
setLoading(false);
}
};
return (
<div className="relative min-h-screen margin-2 flex flex-col items-center justify-center overflow-hidden font-sans transition-all duration-500 bg-body-bg text-text-main">
{/* Premium background gradient spheres and glows */}
{resolvedTheme === "dark" ? (
<>
<div className="absolute top-1/4 left-1/4 w-[500px] h-[500px] bg-primary/20 rounded-full blur-[130px] pointer-events-none" />
<div className="absolute bottom-1/4 right-1/4 w-[450px] h-[450px] bg-blue-950/20 rounded-full blur-[110px] pointer-events-none" />
</>
) : (
<>
<div className="absolute top-1/4 left-1/4 w-[500px] h-[500px] bg-accent/20 rounded-full blur-[130px] pointer-events-none" />
<div className="absolute bottom-1/4 right-1/4 w-[450px] h-[450px] bg-teal-50/50 rounded-full blur-[110px] pointer-events-none" />
</>
)}
{/* Subtle fine tech-mesh pattern overlay */}
<div
className={`absolute inset-0 bg-[linear-gradient(rgba(255,255,255,0.007)_1px,transparent_1px),linear-gradient(90deg,rgba(255,255,255,0.007)_1px,transparent_1px)] bg-[size:32px_32px] opacity-25 ${resolvedTheme === "light" && "invert bg-[linear-gradient(rgba(0,0,0,0.015)_1px,transparent_1px),linear-gradient(90deg,rgba(0,0,0,0.015)_1px,transparent_1px)]"}`}
/>
{/* Floating Theme Switcher */}
<div className="absolute top-6 right-6 z-20">
<button
type="button"
onClick={toggleTheme}
className={`p-3 rounded-2xl border transition-all duration-300 shadow-md ${
resolvedTheme === "dark"
? "bg-zinc-950/60 border-zinc-800 text-primary hover:bg-zinc-900 hover:border-primary/60"
: "bg-white/80 border-zinc-200/60 text-primary hover:bg-zinc-50 hover:border-primary-hover"
}`}
title={`Switch to ${theme === "dark" ? "Light" : theme === "light" ? "System" : "Dark"} Mode`}
>
{theme === "dark" ? (
<Sun className="w-5 h-5" />
) : theme === "light" ? (
<Moon className="w-5 h-5" />
) : (
<Monitor className="w-5 h-5" />
)}
</button>
</div>
{/* Logo and Title outside the card */}
<div className="relative z-10 text-center mb-6">
<div className="flex justify-center">
<img src={`/logo.svg`} alt="LivenDB Logo" className="w-20 h-20" />
<h1 className="text-5xl font-extrabold tracking-tight text-zinc-500 dark:text-zinc-200 mt-2">
LivenDB
</h1>
</div>
</div>
{/* Login glassmorphic card container */}
<div
className={`relative w-10/12 max-w-md mx-4 p-8 rounded-3xl border backdrop-blur-2xl shadow-2xl transition-all ${
resolvedTheme === "dark"
? "border-zinc-800 bg-zinc-900 shadow-primary/30"
: "border-primary/20 bg-white/90 shadow-primary/5"
}`}
>
{/* Action feedback notifications */}
{error && (
<div
className={`flex items-start gap-3 p-4 border rounded-2xl text-xs mb-6 animate-shake ${
resolvedTheme === "dark"
? "bg-red-950/30 border-red-500/20 text-red-200"
: "bg-red-50 border-red-200 text-red-800"
}`}
>
<span>{error}</span>
</div>
)}
{success && (
<div
className={`flex items-start gap-3 p-4 border rounded-2xl text-xs mb-6 animate-shake ${
resolvedTheme === "dark"
? "bg-emerald-950/30 border-emerald-500/20 text-emerald-200"
: "bg-emerald-50 border-emerald-200 text-emerald-800"
}`}
>
<span>Key Authenticated! Securing admin session...</span>
</div>
)}
<form onSubmit={handleLogin} className="space-y-6">
<div>
<label
className={`block text-[10px] font-bold uppercase tracking-wider mb-2 ${
resolvedTheme === "dark" ? "text-zinc-400" : "text-zinc-600"
}`}
>
ENTER AUTH KEY
</label>
<div className="relative">
<input
type={showPassword ? "text" : "password"}
value={authKey}
onChange={(e) => setAuthKey(e.target.value)}
className={`w-full pl-4 pr-11 py-3.5 font-mono text-xs rounded-2xl border focus:outline-none focus:outline-slate-600 transition-all duration-300 ${
resolvedTheme === "dark"
? "bg-zinc-950/50 border-zinc-800 text-zinc-100 placeholder-zinc-700"
: "bg-zinc-50 border-zinc-200 text-zinc-900 placeholder-zinc-400"
}`}
/>
<button
type="button"
onClick={() => setShowPassword(!showPassword)}
className={`absolute right-3.5 top-1/2 -translate-y-1/2 p-1 rounded-lg transition-colors ${
resolvedTheme === "dark"
? "text-zinc-600 hover:text-zinc-300"
: "text-zinc-400 hover:text-zinc-700"
}`}
>
{showPassword ? (
<EyeOff className="w-4.5 h-4.5" />
) : (
<Eye className="w-4.5 h-4.5" />
)}
</button>
</div>
</div>
{/* Submit Action Button */}
<button
type="submit"
disabled={loading || success}
className="w-full flex items-center justify-center gap-2 py-4 bg-primary hover:bg-primary-hover text-zinc-50 font-bold text-xs uppercase tracking-wider rounded-2xl shadow-lg hover:shadow-primary/10 focus:outline-none focus:ring-2 focus:ring-primary/30 disabled:opacity-50 disabled:cursor-not-allowed transition-all duration-300 active:scale-[0.98]"
>
{loading ? (
<span className="flex items-center gap-2">
<svg
className="animate-spin h-4 w-4 text-white"
fill="none"
viewBox="0 0 24 24"
>
<circle
className="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
strokeWidth="4"
/>
<path
className="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.14 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
/>
</svg>
<span>Verifying credentials...</span>
</span>
) : (
<>
<span>Sign In</span>
</>
)}
</button>
</form>
</div>
</div>
);
}