sumona-banerjeee c5946ce95e first commit for the leave management system. built a Leave Management System with role-based access:
Employees can apply for leave and track balance, status, and history.
Managers can view all requests and approve/reject them.
Login with separate dashboards for employees and managers with the dummy json.
Tables with filters (All, Pending, Approved, Rejected) for easy management.
2026-04-29 11:22:14 +05:30

157 lines
5.8 KiB
TypeScript

"use client";
import { useState, useEffect } from "react";
import { useRouter } from "next/navigation";
import { useAuth } from "@/context/AuthContext";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Alert, AlertDescription } from "@/components/ui/alert";
import { CalendarDays, AlertCircle, Loader2 } from "lucide-react";
export default function LoginPage() {
const { login, user, isLoading } = useAuth();
const router = useRouter();
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState("");
const [loading, setLoading] = useState(false);
useEffect(() => {
if (!isLoading && user) {
router.replace(user.role === "manager" ? "/manager" : "/employee");
}
}, [user, isLoading, router]);
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (!username || !password) {
setError("Please enter username and password");
return;
}
setLoading(true);
setError("");
const result = await login(username, password);
setLoading(false);
if (!result.ok) {
setError(result.error ?? "Login failed");
} else if (result.ok) {
// redirect handled by useEffect
}
};
if (isLoading) return null;
return (
<main className="min-h-screen flex items-center justify-center p-4" style={{ background: "var(--surface-base)" }}>
{/* Decorative blobs */}
<div
className="fixed top-0 left-0 w-96 h-96 rounded-full pointer-events-none"
style={{
background: "radial-gradient(circle, var(--brand-200) 0%, transparent 70%)",
opacity: 0.4,
transform: "translate(-30%, -30%)",
}}
/>
<div
className="fixed bottom-0 right-0 w-80 h-80 rounded-full pointer-events-none"
style={{
background: "radial-gradient(circle, var(--brand-300) 0%, transparent 70%)",
opacity: 0.3,
transform: "translate(30%, 30%)",
}}
/>
<div className="w-full max-w-md relative z-10">
{/* Logo */}
<div className="flex flex-col items-center mb-8">
<div
className="w-14 h-14 rounded-2xl flex items-center justify-center mb-4"
style={{ background: "linear-gradient(135deg, var(--brand-600), var(--brand-400))", boxShadow: "0 8px 24px -4px rgb(99 102 241 / 0.35)" }}
>
<CalendarDays className="w-7 h-7" style={{ color: "var(--text-on-brand)" }} />
</div>
<h1 className="text-2xl font-bold tracking-tight" style={{ color: "var(--text-primary)" }}>
LeaveFlow
</h1>
</div>
<Card
style={{
border: "1px solid var(--surface-border)",
boxShadow: "var(--shadow-modal)",
background: "var(--surface-card)",
borderRadius: "var(--radius-lg)",
}}
>
<CardHeader className="pb-4">
<CardTitle className="text-lg" style={{ color: "var(--text-primary)" }}>
Sign in to your account
</CardTitle>
</CardHeader>
<CardContent>
<form onSubmit={handleSubmit} className="space-y-4">
<div className="space-y-1.5">
<Label htmlFor="username" style={{ color: "var(--text-secondary)", fontSize: "0.8125rem", fontWeight: 500 }}>
Username
</Label>
<Input
id="username"
value={username}
onChange={(e) => setUsername(e.target.value)}
placeholder="e.g. emp1"
autoComplete="username"
style={{ borderColor: "var(--surface-border)", borderRadius: "var(--radius-sm)" }}
/>
</div>
<div className="space-y-1.5">
<Label htmlFor="password" style={{ color: "var(--text-secondary)", fontSize: "0.8125rem", fontWeight: 500 }}>
Password
</Label>
<Input
id="password"
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="••••••••"
autoComplete="current-password"
style={{ borderColor: "var(--surface-border)", borderRadius: "var(--radius-sm)" }}
/>
</div>
{error && (
<Alert style={{ borderColor: "var(--color-danger-border)", background: "var(--color-danger-bg)", borderRadius: "var(--radius-sm)" }}>
<AlertCircle className="h-4 w-4" style={{ color: "var(--color-danger)" }} />
<AlertDescription style={{ color: "var(--color-danger)" }}>{error}</AlertDescription>
</Alert>
)}
<Button
type="submit"
className="w-full font-semibold"
disabled={loading}
style={{
background: "linear-gradient(135deg, var(--brand-600), var(--brand-500))",
borderRadius: "var(--radius-sm)",
boxShadow: "0 4px 12px -2px rgb(99 102 241 / 0.3)",
border: "none",
}}
>
{loading ? (
<>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
Signing in
</>
) : (
"Sign In"
)}
</Button>
</form>
</CardContent>
</Card>
</div>
</main>
);
}