sumona-banerjeee 96cc1bb684 Added working-day-only calculation, Fixed leave logic so balance is deducted only on approval and pending requests are considered to prevent over-application.
Ensured consistent day calculation using stored days field and removed duplicate daysBetween logic.
Implemented working-day-only calculation, excluding weekends (Saturday & Sunday), and blocked invalid date selections.
Corrected handling of Unpaid leave so it does not affect leave balance.
Added routing and integrated Sonner notifications for login, manager actions, and employee leave submission.
2026-04-29 19:14:58 +05:30

146 lines
5.2 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 { CalendarDays, Loader2 } from "lucide-react";
import { ROUTES } from "@/lib/routes";
import { toast } from "sonner";
export default function LoginPage() {
const { login, user, isLoading } = useAuth();
const router = useRouter();
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [loading, setLoading] = useState(false);
useEffect(() => {
if (!isLoading && user) {
router.replace(user.role === "manager" ? ROUTES.manager : ROUTES.employee);
}
}, [user, isLoading, router]);
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (!username || !password) {
toast.error("Please enter username and password");
return;
}
setLoading(true);
const result = await login(username, password);
setLoading(false);
if (!result.ok) {
toast.error(result.error ?? "Login failed");
}
};
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>
<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>
);
}