Leave_Management_System/lib/leavesStore.ts
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

149 lines
4.6 KiB
TypeScript

export interface LeaveRequest {
id: number;
userId: number;
userName?: string;
type: "Sick" | "Casual" | "Annual" | "Unpaid";
fromDate: string;
toDate: string;
reason: string;
status: "Pending" | "Approved" | "Rejected";
appliedAt: string;
}
export interface UserRecord {
id: number;
username: string;
name: string;
role: "employee" | "manager";
leaveBalance?: number;
}
const LEAVES_KEY = "lms_leaves";
const USERS_KEY = "lms_users";
// Seed from JSON on first load
async function seedIfNeeded() {
if (typeof window === "undefined") return;
if (!localStorage.getItem(LEAVES_KEY)) {
const mod = await import("@/data/leaves.json");
const raw = mod.default ?? mod;
const leaves = Array.isArray(raw) ? raw : ((raw as any).leaves ?? []);
localStorage.setItem(LEAVES_KEY, JSON.stringify(leaves));
}
if (!localStorage.getItem(USERS_KEY)) {
const mod = await import("@/data/users.json");
const raw = mod.default ?? mod;
const users = Array.isArray(raw) ? raw : ((raw as any).users ?? []);
localStorage.setItem(USERS_KEY, JSON.stringify(users));
}
}
export async function getLeaves(): Promise<LeaveRequest[]> {
await seedIfNeeded();
const raw = localStorage.getItem(LEAVES_KEY) ?? "[]";
const leaves: LeaveRequest[] = JSON.parse(raw);
// Attach userName from users
const users = getUsers();
return leaves.map((l) => {
const u = users.find((u) => u.id === l.userId);
return { ...l, userName: u?.name ?? "Unknown" };
});
}
export function getUsers(): UserRecord[] {
const raw = localStorage.getItem(USERS_KEY) ?? "[]";
return JSON.parse(raw);
}
export async function getLeavesForUser(userId: number): Promise<LeaveRequest[]> {
const all = await getLeaves();
return all.filter((l) => l.userId === userId);
}
export async function applyLeave(
userId: number,
data: { type: LeaveRequest["type"]; fromDate: string; toDate: string; reason: string }
): Promise<{ ok: boolean; error?: string }> {
await seedIfNeeded();
// Calculate days
const from = new Date(data.fromDate);
const to = new Date(data.toDate);
const days = Math.ceil((to.getTime() - from.getTime()) / 86400000) + 1;
// Check balance
const users = getUsers();
const user = users.find((u) => u.id === userId);
if (!user) return { ok: false, error: "User not found" };
if ((user.leaveBalance ?? 0) < days)
return { ok: false, error: `Insufficient balance. You have ${user.leaveBalance} days left.` };
const leaves: LeaveRequest[] = JSON.parse(localStorage.getItem(LEAVES_KEY) ?? "[]");
const newLeave: LeaveRequest = {
id: Date.now(),
userId,
type: data.type,
fromDate: data.fromDate,
toDate: data.toDate,
reason: data.reason,
status: "Pending",
appliedAt: new Date().toISOString().split("T")[0],
};
leaves.push(newLeave);
localStorage.setItem(LEAVES_KEY, JSON.stringify(leaves));
return { ok: true };
}
export async function updateLeaveStatus(
leaveId: number,
status: "Approved" | "Rejected"
): Promise<void> {
await seedIfNeeded();
const leaves: LeaveRequest[] = JSON.parse(localStorage.getItem(LEAVES_KEY) ?? "[]");
const idx = leaves.findIndex((l) => l.id === leaveId);
if (idx === -1) return;
const leave = leaves[idx];
const wasApproved = leave.status === "Approved";
leaves[idx] = { ...leave, status };
localStorage.setItem(LEAVES_KEY, JSON.stringify(leaves));
// Adjust balance
const users = getUsers();
const user = users.find((u) => u.id === leave.userId);
if (!user || user.role !== "employee") return;
const from = new Date(leave.fromDate);
const to = new Date(leave.toDate);
const days = Math.ceil((to.getTime() - from.getTime()) / 86400000) + 1;
if (status === "Approved" && !wasApproved) {
user.leaveBalance = (user.leaveBalance ?? 0) - days;
} else if (status === "Rejected" && wasApproved) {
user.leaveBalance = (user.leaveBalance ?? 0) + days;
}
localStorage.setItem(USERS_KEY, JSON.stringify(users));
// Also update session user if it's the same person
const sessionUser = localStorage.getItem("lms_user");
if (sessionUser) {
const su = JSON.parse(sessionUser);
if (su.id === user.id) {
su.leaveBalance = user.leaveBalance;
localStorage.setItem("lms_user", JSON.stringify(su));
}
}
}
export function getUserBalance(userId: number): number {
const users = getUsers();
const u = users.find((u) => u.id === userId);
return u?.leaveBalance ?? 0;
}
export function daysBetween(from: string, to: string): number {
const f = new Date(from);
const t = new Date(to);
return Math.ceil((t.getTime() - f.getTime()) / 86400000) + 1;
}