import React, { useEffect, useMemo, useState } from "react"; import { createRoot } from "react-dom/client"; import { AnimatePresence, motion } from "framer-motion"; import { Bell, Building2, Camera, CalendarDays, Check, ChevronRight, Clock3, CreditCard, Download, FileText, HeartPulse, Home, LogOut, MapPin, Menu, Plus, QrCode, Search, Settings, ShieldCheck, Users, X, } from "lucide-react"; import { BrowserRouter, Navigate, Route, Routes, useNavigate } from "react-router-dom"; import { Area, AreaChart, Bar, BarChart, CartesianGrid, ResponsiveContainer, Tooltip, XAxis, YAxis } from "recharts"; import "./index.css"; const API_BASE = import.meta.env.VITE_API_BASE || ""; const appVersion = "NeverLag Work v1.0.0"; const demoUsers = [ { label: "Super Admin", username: "super", password: "admin123" }, { label: "Company Admin / Boss", username: "boss", password: "boss123" }, { label: "Branch Manager", username: "manager", password: "manager123" }, { label: "Employee", username: "employee", password: "employee123" }, { label: "QR/Selfie Test Employee", username: "tester", password: "tester123" }, ]; const navByRole = { super_admin: [ ["Home", Home], ["Companies", Building2], ["Plans", CreditCard], ["Reports", FileText], ["More", Menu], ], boss: [ ["Home", Home], ["Branches", Building2], ["Employees", Users], ["Attendance", CalendarDays], ["Salary", CreditCard], ["More", Menu], ], branch_manager: [ ["Home", Home], ["Employees", Users], ["Attendance", CalendarDays], ["Salary", CreditCard], ["More", Menu], ], employee: [ ["Home", Home], ["Attendance", CalendarDays], ["Salary Slip", FileText], ["Notifications", Bell], ["Profile", Users], ], }; function getNavForRole(role, showBranchTools) { const nav = navByRole[role] || []; if (!showBranchTools) return nav.filter(([name]) => name !== "Branches"); return nav; } const statColors = { green: "bg-blue-50 text-primary", blue: "bg-blue-50 text-blue-700", orange: "bg-orange-50 text-orange-700", red: "bg-red-50 text-red-700", gray: "bg-slate-100 text-slate-600", }; function HeroIcon({ name, className = "h-6 w-6" }) { const paths = { speed: "M3.75 13.5a8.25 8.25 0 1 1 16.5 0c0 2.1-.78 4.02-2.07 5.48a.75.75 0 0 1-.56.25H6.38a.75.75 0 0 1-.56-.25A8.22 8.22 0 0 1 3.75 13.5Zm8.25 0 3.75-4.5", shield: "M12 3.75 5.25 6v5.08c0 4.18 2.8 7.84 6.75 8.92 3.95-1.08 6.75-4.74 6.75-8.92V6L12 3.75Z", cloud: "M6.75 18.75h10.5a4.5 4.5 0 0 0 .5-8.97 6 6 0 0 0-11.44-1.66A5.25 5.25 0 0 0 6.75 18.75Z", lock: "M7.5 10.5V8.25a4.5 4.5 0 0 1 9 0v2.25m-10.5 0h12a.75.75 0 0 1 .75.75v7.5a.75.75 0 0 1-.75.75h-12a.75.75 0 0 1-.75-.75v-7.5a.75.75 0 0 1 .75-.75Z", }; return ( ); } async function api(path, options = {}) { const token = sessionStorage.getItem("authToken"); const res = await fetch(`${API_BASE}${path}`, { method: options.method || "GET", headers: { "Content-Type": "application/json", ...(token ? { Authorization: `Bearer ${token}` } : {}), }, body: options.body ? JSON.stringify(options.body) : undefined, }); const data = await res.json().catch(() => ({})); if (!res.ok) throw new Error(data.error || "Data was not saved. Please check server/database connection."); return data; } function App() { return ( } /> } /> ); } function Login() { const navigate = useNavigate(); const [form, setForm] = useState({ username: "boss", password: "boss123" }); const [error, setError] = useState(""); const [loading, setLoading] = useState(false); async function submit(event) { event.preventDefault(); setLoading(true); setError(""); try { const data = await api("/api/auth/login", { method: "POST", body: form }); sessionStorage.setItem("authToken", data.token); sessionStorage.setItem("currentUser", JSON.stringify(data.user)); navigate("/"); } catch (err) { setError(err.message); } finally { setLoading(false); } } return (

NeverLag Work

Employee Attendance & Payroll SaaS

{[ ["Speed", "Live attendance flow", "speed"], ["Security", "GPS, selfie, QR checks", "lock"], ["Cloud", "Branch-ready SaaS", "cloud"], ].map(([title, meta, icon]) => (
{title} {meta}
))}

Login

Role is detected after login.

setForm({ ...form, username: value })} /> setForm({ ...form, password: value })} />
{error &&

{error}

} {loading ? "Signing in..." : "Login"}
{demoUsers.map((user) => ( ))}
); } function AnimatedField({ label, type = "text", value, onChange }) { return ( {label} onChange(event.target.value)} /> ); } function Shell() { const navigate = useNavigate(); const [user, setUser] = useState(() => safeJson(sessionStorage.getItem("currentUser"))); const [active, setActive] = useState("Home"); const [data, setData] = useState(null); const [toast, setToast] = useState(""); const [showNotifications, setShowNotifications] = useState(false); const showBranchTools = Boolean(data?.settings?.enableMultiBranch); const nav = getNavForRole(user?.role, showBranchTools); useEffect(() => { if (!sessionStorage.getItem("authToken")) navigate("/login"); }, [navigate]); useEffect(() => { if (!user) return; refresh().catch((err) => setToast(err.message)); }, [user]); useEffect(() => { if (active === "Branches" && !showBranchTools) setActive("Home"); }, [active, showBranchTools]); async function refresh() { const [me, attendance, slips, notifications, settings] = await Promise.all([ api("/api/auth/me"), api("/api/employee-attendance/today"), api("/api/employee-salary/slips"), api("/api/notifications"), ["boss", "branch_manager", "employee"].includes(user.role) ? api("/api/company/settings") : Promise.resolve({}), ]); setUser(me.user); sessionStorage.setItem("currentUser", JSON.stringify(me.user)); setData({ attendance, slips, notifications, settings }); } async function logout() { await api("/api/auth/logout", { method: "POST" }).catch(() => null); sessionStorage.removeItem("authToken"); sessionStorage.removeItem("currentUser"); navigate("/login"); } if (!user) return null; return (

Good morning, {user.name}

{active}

setShowNotifications(true)} whileTap={{ scale: 0.96 }} animate={data?.notifications?.unread ? { scale: [1, 1.08, 1] } : {}} className="relative min-h-11 min-w-11 rounded-full bg-white p-3 text-primary shadow-premium transition hover:-translate-y-0.5 hover:shadow-lift"> {data?.notifications?.unread > 0 && }
{renderPage({ user, active, setActive, data, refresh, setToast, showBranchTools })}
{toast && setToast("")} />} {showNotifications && setShowNotifications(false)} />}
); } function Brand() { return (
NeverLag Work Employee Attendance & Payroll SaaS
); } function NavButton({ name, Icon, active, onClick }) { return ( ); } function renderPage(props) { if (props.user.role === "employee") return ; if (["boss", "branch_manager"].includes(props.user.role)) return ; return ; } function EmployeePages({ user, active, data, refresh, setToast }) { if (active === "Attendance") return ; if (active === "Salary Slip") return ; if (active === "Notifications") return ; if (active === "Profile") return ; return ; } function BossPages({ active, data, refresh, setToast, setActive, showBranchTools }) { if (active === "Branches") return showBranchTools ? : ; if (active === "Employees") return ; if (active === "Attendance") return ; if (active === "Salary") return ; if (active === "More") return ; return ; } function SuperPages({ active, data }) { if (active === "Companies") return ; if (active === "Plans") return ; if (active === "Reports") return ; if (active === "More") return ; return ; } function EmployeeHome({ user, data, refresh, setToast }) { const today = data?.attendance?.rows?.[0]; const settings = data?.settings || {}; const checkedIn = Boolean(today?.checkInTime); const checkedOut = Boolean(today?.checkOutTime); const status = today?.status || "Absent"; const [selfie, setSelfie] = useState(""); const [qrToken, setQrToken] = useState(""); const [qrStatus, setQrStatus] = useState(""); const [showCamera, setShowCamera] = useState(false); const [showQrScanner, setShowQrScanner] = useState(false); const qrEnabled = Boolean(user?.username === "tester" || settings.enableQRAttendance || settings.qrRequiredOnCheckIn || settings.qrRequiredOnCheckOut); async function verifyQrToken(token = qrToken) { if (!token) { setToast("Please scan office QR code to continue."); return; } const verified = await api("/api/employee-attendance/verify-qr", { method: "POST", body: { qrToken: token } }); setQrToken(token); setQrStatus(`QR verified for branch ${verified.branchId}`); setToast("QR verified"); } async function action(kind) { try { if ((kind === "in" && settings.selfieRequiredOnCheckIn || kind === "out" && settings.selfieRequiredOnCheckOut) && !selfie) { setShowCamera(true); throw new Error("Selfie required but not captured"); } if ((kind === "in" && settings.qrRequiredOnCheckIn || kind === "out" && settings.qrRequiredOnCheckOut) && !qrToken) { throw new Error("Please scan office QR code to continue."); } let selfieUrl = ""; if (selfie) { const upload = await api("/api/uploads/selfie", { method: "POST", body: { dataUrl: selfie } }); selfieUrl = upload.url; } const position = await getLocation(); await api(`/api/employee-attendance/${kind === "in" ? "check-in" : "check-out"}`, { method: "POST", body: { latitude: position.lat, longitude: position.lng, qrToken, selfieUrl, deviceInfo: navigator.userAgent }, }); setSelfie(""); setQrToken(""); setQrStatus(""); setToast(kind === "in" ? "Check-in successful" : "Check-out successful"); await refresh(); } catch (err) { setToast(err.message); } } return (

Today status

{status}

{settings.selfieRequiredOnCheckIn || settings.selfieRequiredOnCheckOut ? : null} {settings.qrRequiredOnCheckIn || settings.qrRequiredOnCheckOut ? : null}
{qrEnabled &&
{ setQrToken(value); setQrStatus(""); }} />
{user?.username === "tester" && }
{qrStatus &&

{qrStatus}

}
} {(settings.selfieRequiredOnCheckIn || settings.selfieRequiredOnCheckOut) &&
{selfie && Captured selfie preview}
} action(checkedIn ? "out" : "in")} className={`mt-8 min-h-24 w-full rounded-full text-xl font-semibold shadow-lift transition hover:-translate-y-0.5 ${checkedOut ? "bg-slate-400 text-white" : checkedIn ? "bg-primary text-white hover:bg-[#74a2f7]" : "gradient-bg text-white shadow-glow"}`} > {checkedOut ? "Completed Today" : checkedIn ? "Check Out" : "Check In"}
{showCamera && setShowCamera(false)} onCapture={(image) => { setSelfie(image); setShowCamera(false); }} />} {showQrScanner && setShowQrScanner(false)} onScan={(token) => { setShowQrScanner(false); verifyQrToken(token).catch((err) => setToast(err.message)); }} />}
); } function BossHome({ data, setToast, setActive, refresh, showBranchTools }) { const [branches, setBranches] = useState([]); const [branchId, setBranchId] = useState(""); const [attendance, setAttendance] = useState(data?.attendance || {}); const stats = attendance?.dashboard || {}; useEffect(() => setAttendance(data?.attendance || {}), [data]); useEffect(() => { api("/api/branches").then(setBranches).catch((err) => setToast?.(err.message)); }, [setToast]); useEffect(() => { api(`/api/employee-attendance/today${branchId ? `?branchId=${branchId}` : ""}`) .then(setAttendance) .catch((err) => setToast?.(err.message)); }, [branchId, setToast]); return (
{showBranchTools && }
); } function AdvancedModuleShortcuts({ setActive, setToast, refresh, showBranchTools }) { async function enableDemoTest() { await api("/api/company/settings", { method: "PUT", body: { enableSelfieAttendance: true, selfieRequiredOnCheckIn: true, selfieRequiredOnCheckOut: false, enableQRAttendance: true, qrRequiredOnCheckIn: true, qrRequiredOnCheckOut: false, enableMultiBranch: true, }, }); setToast?.("QR + Selfie test mode enabled. Demo QR token: MAIN-OFFICE-DEMO-QR"); await refresh?.(); } const modules = [ ...(showBranchTools ? [["Branches", "Multiple offices, branch geofence, and branch status.", "Branches", Building2]] : []), ["Selfie Attendance", "Enable camera selfie rules from attendance settings.", "More", Camera], ["Attendance QR", "Generate, print, regenerate, and activate office QR codes.", "More", QrCode], ...(showBranchTools ? [["Branch Managers", "Create logins restricted to assigned branch data.", "More", Users]] : []), ["Premium Features", "Face Recognition and Biometric placeholders.", "More", ShieldCheck], ]; return (
{modules.map(([title, meta, target, Icon]) => ( ))}
); } function SuperHome({ data }) { const stats = data?.attendance?.dashboard || {}; return (
); } function StatGrid({ stats }) { return (
{stats.map(([label, value, color], index) => (

{label}

))}
); } function Counter({ value, className }) { const [shown, setShown] = useState(0); useEffect(() => { const numeric = Number(value) || 0; const id = setInterval(() => setShown((old) => (old >= numeric ? numeric : Math.min(numeric, old + Math.ceil(numeric / 12 || 1)))), 18); return () => clearInterval(id); }, [value]); return {shown}; } function AttendanceCards({ data, boss, refresh, setToast }) { const rows = data?.attendance?.rows || []; const [selectedMonth, setSelectedMonth] = useState(() => new Date().toISOString().slice(0, 7)); const [monthlyRows, setMonthlyRows] = useState(rows); const [filter, setFilter] = useState("All"); useEffect(() => setMonthlyRows(rows), [rows]); useEffect(() => { api(`/api/employee-attendance/monthly?month=${selectedMonth}`) .then(setMonthlyRows) .catch((err) => setToast?.(err.message)); }, [selectedMonth, setToast]); const filtered = filter === "All" ? monthlyRows : monthlyRows.filter((row) => attendanceFilterMatch(row, filter)); async function markLeave(row) { await api("/api/leaves/mark", { method: "POST", body: { employeeId: row.employeeId, date: row.date } }); setToast?.("Leave marked"); await refresh?.(); } async function correct(row) { const reason = window.prompt("Correction reason"); if (!reason) return; const status = window.prompt("New status: Present, Late, Half Day, Leave, Absent", row.status || "Present"); if (!status) return; await api(`/api/employee-attendance/${row.id || row._id}/manual-correction`, { method: "PUT", body: { status, reason } }); setToast?.("Attendance corrected"); await refresh?.(); } return (
{["All", "Present", "Absent", "Late", "Leave", "Checked Out", "Inside Office"].map((item) => ( ))}
setSelectedMonth(event.target.value)} className="min-h-11 rounded-full border border-line bg-white px-4 font-medium text-navy shadow-premium outline-none focus:ring-4 focus:ring-primary/20" />
{filtered.map((row, index) => (
{initials(row.employeeName || "Employee")}

{row.employeeName || "Employee"}

{row.department || "Department optional"}

{(row.checkInSelfieUrl || row.checkOutSelfieUrl) &&
{row.checkInSelfieUrl && } {row.checkOutSelfieUrl && }
} {boss &&
}
))} {!filtered.length && }
); } function AttendanceCalendar({ month, rows, filter, boss }) { const days = calendarDays(month); const recordsByDate = rows.reduce((map, row) => { const key = row.date; map[key] = map[key] || []; map[key].push(row); return map; }, {}); return (

Attendance Calendar

{new Date(`${month}-01T00:00:00`).toLocaleDateString([], { month: "long", year: "numeric" })}

{attendanceLegend().map((item) => {item.label})}
{["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"].map((day) =>
{day}
)}
{days.map((day, index) => { if (!day) return
; const dayRows = recordsByDate[day.date] || []; const cell = attendanceCell(day, dayRows, filter, boss); return (
{day.dayNumber} {cell.short}

{cell.title}

{cell.meta}

); })}
); } function calendarDays(month) { const [year, monthIndex] = month.split("-").map(Number); const first = new Date(year, monthIndex - 1, 1); const total = new Date(year, monthIndex, 0).getDate(); const blanks = Array.from({ length: first.getDay() }, () => null); const days = Array.from({ length: total }, (_, index) => { const dayNumber = index + 1; const date = `${month}-${String(dayNumber).padStart(2, "0")}`; return { date, dayNumber }; }); return [...blanks, ...days]; } function attendanceFilterMatch(row, filter) { if (filter === "All") return true; if (filter === "Checked Out") return Boolean(row.checkOutTime); if (filter === "Inside Office") return Boolean(row.checkInTime && !row.checkOutTime); return (row.status || "Absent") === filter; } function attendancePalette(status) { const normalized = status === "Half Day" ? "Late" : status; const palette = { Present: { short: "P", title: "Present", className: "border-emerald-200 bg-emerald-50 text-emerald-800", badgeClass: "bg-emerald-600 text-white", legendClass: "bg-emerald-50 text-emerald-700", dotClass: "bg-emerald-500" }, Absent: { short: "A", title: "Absent", className: "border-red-200 bg-red-50 text-red-800", badgeClass: "bg-red-600 text-white", legendClass: "bg-red-50 text-red-700", dotClass: "bg-red-500" }, Late: { short: "L", title: "Late", className: "border-amber-200 bg-amber-50 text-amber-800", badgeClass: "bg-amber-500 text-white", legendClass: "bg-amber-50 text-amber-700", dotClass: "bg-amber-500" }, Leave: { short: "LV", title: "Leave", className: "border-violet-200 bg-violet-50 text-violet-800", badgeClass: "bg-violet-600 text-white", legendClass: "bg-violet-50 text-violet-700", dotClass: "bg-violet-500" }, "Checked Out": { short: "OUT", title: "Checked Out", className: "border-sky-200 bg-sky-50 text-sky-800", badgeClass: "bg-sky-600 text-white", legendClass: "bg-sky-50 text-sky-700", dotClass: "bg-sky-500" }, "Inside Office": { short: "IN", title: "Inside Office", className: "border-blue-200 bg-blue-50 text-blue-800", badgeClass: "bg-primary text-white", legendClass: "bg-blue-50 text-blue-700", dotClass: "bg-primary" }, "No Record": { short: "-", title: "No Record", className: "border-line bg-white text-muted", badgeClass: "bg-surface text-muted", legendClass: "bg-slate-50 text-slate-600", dotClass: "bg-slate-300" }, }; return palette[normalized] || palette["No Record"]; } function attendanceCell(day, rows, filter, boss) { const todayKey = new Date().toISOString().slice(0, 10); if (!rows.length) { const isPastOrToday = day.date <= todayKey; const generatedStatus = !boss && isPastOrToday ? "Absent" : "No Record"; const palette = attendancePalette(generatedStatus); const hidden = filter !== "All" && filter !== generatedStatus; return { ...palette, className: `${palette.className} ${hidden ? "opacity-30" : ""}`, meta: generatedStatus === "Absent" ? "No check-in" : "No data yet" }; } const checkedOut = rows.filter((row) => row.checkOutTime).length; const inside = rows.filter((row) => row.checkInTime && !row.checkOutTime).length; const priority = rows.find((row) => row.status === "Leave") || rows.find((row) => row.status === "Late") || rows.find((row) => row.status === "Absent") || rows[0]; const status = checkedOut && rows.length === checkedOut ? "Checked Out" : inside && rows.length === inside ? "Inside Office" : priority.status || "Present"; const palette = attendancePalette(status); const hidden = filter !== "All" && !rows.some((row) => attendanceFilterMatch(row, filter)) && !(filter === status); return { ...palette, className: `${palette.className} ${hidden ? "opacity-30" : ""}`, title: boss ? `${rows.length} record${rows.length === 1 ? "" : "s"}` : palette.title, meta: boss ? `${checkedOut} out / ${inside} inside` : `${time(priority.checkInTime)} - ${time(priority.checkOutTime)}`, }; } function attendanceLegend() { return ["Present", "Absent", "Late", "Leave", "Checked Out", "Inside Office"].map((status) => ({ label: `${attendancePalette(status).short} ${status}`, ...attendancePalette(status) })); } function SelfieThumb({ label, src }) { return
{label}

{label}

; } function BranchFilter({ branches, value, onChange }) { if (!branches || branches.length <= 1) return null; return ( ); } function EmployeesPage({ setToast, showBranchTools }) { const [items, setItems] = useState([]); const [branches, setBranches] = useState([]); const [open, setOpen] = useState(false); const [editing, setEditing] = useState(null); async function load() { const [employees, branchRows] = await Promise.all([api("/api/employees"), api("/api/branches")]); setItems(employees); setBranches(branchRows); } useEffect(() => { load().catch((err) => setToast(err.message)); }, [setToast]); async function removeEmployee(employee) { await api(`/api/employees/${employee.id || employee._id}`, { method: "DELETE" }); setItems((old) => old.filter((item) => (item.id || item._id) !== (employee.id || employee._id))); setToast("Employee deleted"); } return (
{items.map((employee) => { setEditing(employee); setOpen(true); }} onDelete={() => removeEmployee(employee).catch((err) => setToast(err.message))} />)}
setOpen(true)} className="fixed bottom-24 right-5 z-30 flex h-16 w-16 items-center justify-center rounded-full bg-primary text-white shadow-lift transition hover:-translate-y-0.5 hover:bg-[#74a2f7] lg:bottom-8"> {open && { setOpen(false); setEditing(null); }} onSaved={(employee) => { setItems((old) => editing ? old.map((item) => (item.id || item._id) === (employee.id || employee._id) ? employee : item) : [employee, ...old]); }} setToast={setToast} />}
); } function EmployeeCard({ employee, onEdit, onDelete }) { return (
{initials(employee.name)}

{employee.name}

{employee.employeeCode} / {employee.mobile}

{employee.department || "Department optional"} / {employee.designation || "Designation optional"}

{employee.branchName || "Main Office"}

); } function EmployeeSheet({ initial, branches, showBranchTools, onClose, onSaved, setToast }) { const defaultBranchId = branches?.[0]?.id || branches?.[0]?._id || ""; const [form, setForm] = useState(() => initial ? { ...initial, branchId: initial.branchId || defaultBranchId, username: initial.username || "", password: "" } : { name: "", employeeCode: "", mobile: "", email: "", department: "", designation: "", joiningDate: "", salary: "", shift: "General", branchId: defaultBranchId, username: "", password: "", status: "Active" }); const [errors, setErrors] = useState({}); async function save(event) { event.preventDefault(); try { const id = initial?.id || initial?._id; const employee = await api(id ? `/api/employees/${id}` : "/api/employees", { method: id ? "PUT" : "POST", body: form }); onSaved(employee); onClose(); } catch (err) { setToast(err.message); setErrors({ form: err.message }); } } return (

{initial ? "Edit Employee" : "Add Employee"}

{Object.keys(form).filter((key) => showBranchTools || key !== "branchId").map((key) => key === "branchId" ? ( ) : ( ))}
{errors.form &&

{errors.form}

}
); } function SalaryPanel({ slips, refresh, setToast, showBranchTools }) { const [branches, setBranches] = useState([]); const [branchId, setBranchId] = useState(""); const [rows, setRows] = useState(slips); useEffect(() => setRows(slips), [slips]); useEffect(() => { api("/api/branches").then(setBranches).catch((err) => setToast(err.message)); }, [setToast]); useEffect(() => { api(`/api/employee-salary/slips${branchId ? `?branchId=${branchId}` : ""}`).then(setRows).catch((err) => setToast(err.message)); }, [branchId, setToast]); async function generate() { try { await api("/api/employee-salary/generate", { method: "POST", body: { branchId } }); setToast("Salary slip generated"); setRows(await api(`/api/employee-salary/slips${branchId ? `?branchId=${branchId}` : ""}`)); await refresh(); } catch (err) { setToast(err.message); } } async function toggleStatus(slip) { const next = slip.paymentStatus === "Paid" ? "Pending" : "Paid"; await api(`/api/employee-salary/slips/${slip.id || slip._id}/status`, { method: "PUT", body: { paymentStatus: next } }); setToast(`Salary slip marked ${next}`); await refresh(); } return (
{showBranchTools && }
); } function SalarySlips({ slips, onToggleStatus }) { return (
{slips.map((slip) => (

{slip.slipNumber}

{slip.month} {slip.year}

{onToggleStatus && }
))} {!slips.length && }
); } function Charts() { const weekly = [ { day: "Mon", present: 42 }, { day: "Tue", present: 45 }, { day: "Wed", present: 39 }, { day: "Thu", present: 48 }, { day: "Fri", present: 44 }, ]; const monthly = [ { name: "Present", value: 88 }, { name: "Absent", value: 12 }, ]; return (
); } function ChartCard({ title, children }) { return (

{title}

{children}
); } function CompaniesPage() { const [companies, setCompanies] = useState([]); const [bosses, setBosses] = useState([]); const [form, setForm] = useState({ name: "", bossName: "", bossUsername: "", bossPassword: "" }); const [message, setMessage] = useState(""); async function load() { const [companyRows, bossRows] = await Promise.all([api("/api/companies"), api("/api/company-admins")]); setCompanies(companyRows); setBosses(bossRows); } useEffect(() => { load().catch((err) => setMessage(err.message)); }, []); async function save(event) { event.preventDefault(); await api("/api/companies", { method: "POST", body: form }); setForm({ name: "", bossName: "", bossUsername: "", bossPassword: "" }); setMessage("Company and Boss login created"); await load(); } async function toggle(company) { await api(`/api/companies/${company.id || company._id}`, { method: "PUT", body: { status: company.status === "Active" ? "Inactive" : "Active" } }); await load(); } return (
{companies.map((company) => toggle(company)} className="min-h-11 rounded-2xl bg-slate-100 px-4 font-black">Toggle} />)}
{bosses.map((boss) => )}
setForm({ ...form, name: value })} required /> setForm({ ...form, bossName: value })} required /> setForm({ ...form, bossUsername: value })} required /> setForm({ ...form, bossPassword: value })} required /> {message &&

{message}

}
); } function PlansPage() { const [plans, setPlans] = useState([]); const [payments, setPayments] = useState([]); const [form, setForm] = useState({ name: "", price: "", employeeLimit: "" }); async function load() { const [planRows, paymentRows] = await Promise.all([api("/api/subscription-plans"), api("/api/payments")]); setPlans(planRows); setPayments(paymentRows); } useEffect(() => { load().catch(() => null); }, []); async function save(event) { event.preventDefault(); await api("/api/subscription-plans", { method: "POST", body: form }); setForm({ name: "", price: "", employeeLimit: "" }); await load(); } return (
{plans.map((plan) => )}
{payments.map((payment) => )} {!payments.length && }
setForm({ ...form, name: value })} required /> setForm({ ...form, price: value })} required /> setForm({ ...form, employeeLimit: value })} required />
); } function ReportsPage() { const [attendance, setAttendance] = useState([]); const [salary, setSalary] = useState([]); useEffect(() => { Promise.all([api("/api/reports/attendance"), api("/api/reports/salary")]).then(([a, s]) => { setAttendance(a); setSalary(s); }).catch(() => null); }, []); return (
); } function MorePanel({ superAdmin, showBranchTools }) { return superAdmin ? :
{showBranchTools && }
; } function BranchesPage({ setToast }) { const [branches, setBranches] = useState([]); const [form, setForm] = useState({ branchName: "", branchCode: "", address: "", city: "", state: "", pincode: "", contactPerson: "", mobile: "", email: "", latitude: "", longitude: "", geofenceRadius: "100", shiftStartTime: "09:00", shiftEndTime: "18:00", graceMinutes: "10", isMainBranch: false, status: "Active" }); async function load() { setBranches(await api("/api/branches")); } useEffect(() => { load().catch((err) => setToast(err.message)); }, [setToast]); async function save(event) { event.preventDefault(); await api("/api/branches", { method: "POST", body: form }); setToast("Branch saved"); setForm({ ...form, branchName: "", branchCode: "" }); await load(); } async function toggle(branch) { await api(`/api/branches/${branch.id || branch._id}`, { method: "PUT", body: { status: branch.status === "Active" ? "Inactive" : "Active" } }); await load(); } return (
{branches.map((branch) => toggle(branch)} className="min-h-11 rounded-2xl bg-slate-100 px-4 font-black">Toggle} />)}
{["branchName", "branchCode", "address", "city", "state", "pincode", "contactPerson", "mobile", "email", "latitude", "longitude", "geofenceRadius", "shiftStartTime", "shiftEndTime", "graceMinutes"].map((key) => setForm({ ...form, [key]: value })} required={["branchName", "branchCode", "latitude", "longitude", "geofenceRadius"].includes(key)} />)}
); } function AttendanceQrPanel() { const [branches, setBranches] = useState([]); const [qrs, setQrs] = useState([]); const [form, setForm] = useState({ qrLabel: "Office QR", branchId: "" }); const [token, setToken] = useState(""); async function load() { const [branchRows, qrRows] = await Promise.all([api("/api/branches"), api("/api/attendance-qr")]); setBranches(branchRows); setQrs(qrRows); setForm((old) => ({ ...old, branchId: old.branchId || branchRows[0]?.id || "" })); } useEffect(() => { load().catch(() => null); }, []); async function generate() { const qr = await api("/api/attendance-qr/generate", { method: "POST", body: form }); setToken(qr.qrToken); await load(); } async function regenerate(qr) { const next = await api("/api/attendance-qr/regenerate", { method: "POST", body: { id: qr.id || qr._id } }); setToken(next.qrToken); await load(); } async function toggleStatus(qr) { await api("/api/attendance-qr/status", { method: "POST", body: { id: qr.id || qr._id, isActive: !qr.isActive } }); await load(); } return (
setForm({ ...form, qrLabel: value })} />
{token &&
QR Token

{token}

}
{qrs.map((qr) => (branch.id || branch._id) === qr.branchId)?.branchName || ""}`} action={
} />)}
); } function BranchManagersPanel() { const [branches, setBranches] = useState([]); const [managers, setManagers] = useState([]); const [form, setForm] = useState({ name: "", mobile: "", email: "", branchId: "", username: "", password: "", status: "Active" }); async function load() { const [branchRows, managerRows] = await Promise.all([api("/api/branches"), api("/api/branch-managers")]); setBranches(branchRows); setManagers(managerRows); setForm((old) => ({ ...old, branchId: old.branchId || branchRows[0]?.id || "" })); } useEffect(() => { load().catch(() => null); }, []); async function save(event) { event.preventDefault(); await api("/api/branch-managers", { method: "POST", body: form }); setForm({ ...form, name: "", mobile: "", username: "", password: "" }); await load(); } return (
{["name", "mobile", "email", "username", "password"].map((key) => setForm({ ...form, [key]: value })} required={["name", "mobile", "username", "password"].includes(key)} />)}
{managers.map((manager) => )}
); } function PremiumFeaturesPanel() { function request(name) { window.alert(`${name} is a premium feature. Contact Super Admin to enable.`); } return (
request("Face Recognition")} className="min-h-11 rounded-2xl bg-primary px-4 font-black text-white">Request Activation} /> request("Biometric Device Integration")} className="min-h-11 rounded-2xl bg-primary px-4 font-black text-white">Request Activation} />
); } function Notifications({ notices }) { const [items, setItems] = useState(notices); useEffect(() => setItems(notices), [notices]); async function read(notice) { const id = notice.id || notice._id; await api(`/api/notifications/${id}/read`, { method: "PUT" }); setItems((old) => old.map((item) => (item.id || item._id) === id ? { ...item, read: true } : item)); } return
{items.map((notice) =>
{notice.message}

{timeAgo(notice.createdAt)} / {notice.read ? "Read" : "Unread"}

{!notice.read && }
)} {!items.length && }
; } function SelfieCapture({ onCapture, onClose }) { const videoRef = React.useRef(null); const streamRef = React.useRef(null); const [error, setError] = useState(""); useEffect(() => { navigator.mediaDevices?.getUserMedia({ video: true }) .then((stream) => { streamRef.current = stream; if (videoRef.current) videoRef.current.srcObject = stream; }) .catch(() => setError("Camera permission is required for selfie attendance.")); return () => streamRef.current?.getTracks().forEach((track) => track.stop()); }, []); function capture() { const video = videoRef.current; if (!video) return; const canvas = document.createElement("canvas"); canvas.width = video.videoWidth || 640; canvas.height = video.videoHeight || 480; canvas.getContext("2d").drawImage(video, 0, 0, canvas.width, canvas.height); onCapture(canvas.toDataURL("image/jpeg", 0.82)); } return (

Selfie Attendance

{error ?

{error}

:
); } function QrScanner({ onScan, onClose }) { const videoRef = React.useRef(null); const streamRef = React.useRef(null); const frameRef = React.useRef(null); const detectorRef = React.useRef(null); const [error, setError] = useState(""); useEffect(() => { let stopped = false; async function start() { if (!("BarcodeDetector" in window)) { setError("QR camera scanning is not supported in this browser. Enter the QR token manually."); return; } detectorRef.current = new window.BarcodeDetector({ formats: ["qr_code"] }); try { const stream = await navigator.mediaDevices?.getUserMedia({ video: { facingMode: "environment" } }); if (!stream) throw new Error("Camera permission is required to scan QR."); streamRef.current = stream; if (videoRef.current) { videoRef.current.srcObject = stream; await videoRef.current.play(); } const scan = async () => { if (stopped || !videoRef.current || !detectorRef.current) return; try { const codes = await detectorRef.current.detect(videoRef.current); const token = codes?.[0]?.rawValue; if (token) { onScan(token); return; } } catch { setError("Unable to read QR from camera. Try again or enter the token manually."); } frameRef.current = requestAnimationFrame(scan); }; frameRef.current = requestAnimationFrame(scan); } catch (err) { setError(err.message || "Camera permission is required to scan QR."); } } start(); return () => { stopped = true; if (frameRef.current) cancelAnimationFrame(frameRef.current); streamRef.current?.getTracks().forEach((track) => track.stop()); }; }, [onScan]); return (

Scan Office QR

{error ?

{error}

:
); } function NotificationDrawer({ notices, onClose }) { return (

Notifications

{notices.length} total

); } function Profile() { const [form, setForm] = useState({ currentPassword: "", newPassword: "" }); const [message, setMessage] = useState(""); async function save(event) { event.preventDefault(); await api("/api/profile/change-password", { method: "PUT", body: form }); setForm({ currentPassword: "", newPassword: "" }); setMessage("Password changed"); } return (
save(event).catch((err) => setMessage(err.message))} className="grid max-w-md gap-3"> setForm({ ...form, currentPassword: value })} required /> setForm({ ...form, newPassword: value })} required /> {message &&

{message}

}
); } function AdminTools() { const [health, setHealth] = useState(null); const [backups, setBackups] = useState([]); const [message, setMessage] = useState(""); const [secret, setSecret] = useState("demo-secret"); async function load() { const [healthRows, backupRows] = await Promise.all([api("/api/system/health"), api("/api/backups")]); setHealth(healthRows); setBackups(backupRows); } useEffect(() => { load().catch((err) => setMessage(err.message)); }, []); async function backup() { await api("/api/backups/manual", { method: "POST" }); setMessage("Manual backup created"); await load(); } async function restore(id) { await api("/api/backups/restore", { method: "POST", body: { backupId: id, setupSecret: secret, confirmation: "RESTORE DATA" } }); setMessage("Backup restored"); await load(); } async function freshReset() { await api("/api/system/fresh-reset", { method: "POST", body: { setupSecret: secret, confirmation: "DELETE ALL DATA" } }); setMessage("Fresh Reset complete. Login again if session was cleared."); } return (
{health?.checks?.map((check) => ) || }
{backups.map((item) => restore(item.id || item._id)} className="min-h-11 rounded-2xl bg-slate-100 px-4 font-black">Restore} />)} {message &&

{message}

}
); } function CompanySettingsPanel() { const [settings, setSettings] = useState(null); const [message, setMessage] = useState(""); useEffect(() => { api("/api/company/settings").then(setSettings).catch((err) => setMessage(err.message)); }, []); if (!settings) return ; async function save(event) { event.preventDefault(); const saved = await api("/api/company/settings", { method: "PUT", body: settings }); setSettings(saved); setMessage("Settings saved"); } return (
save(event).catch((err) => setMessage(err.message))} className="grid gap-3 md:grid-cols-2"> {["companyName", "officeName", "latitude", "longitude", "radius", "shiftStart", "shiftEnd", "graceMinutes", "fullDayHours", "halfDayHours", "weeklyOff"].map((key) => ( setSettings({ ...settings, [key]: value })} /> ))} {[ ["enableSelfieAttendance", "Enable Selfie Attendance"], ["selfieRequiredOnCheckIn", "Selfie Required On Check In"], ["selfieRequiredOnCheckOut", "Selfie Required On Check Out"], ["enableQRAttendance", "Enable QR Attendance"], ["qrRequiredOnCheckIn", "QR Required On Check In"], ["qrRequiredOnCheckOut", "QR Required On Check Out"], ["enableMultiBranch", "Enable Multiple Branches"], ["allowAnyBranchCheckIn", "Allow Any Branch Check In"], ["faceRecognitionEnabled", "Face Recognition Enabled"], ["biometricIntegrationEnabled", "Biometric Integration Enabled"], ].map(([key, label]) => ( ))} {message &&

{message}

}
); } function Panel({ title, children }) { return

{title}

{children}
; } function RowCard({ title, meta, action }) { return
{title}

{meta}

{action}
; } function Input({ label, value, onChange, type = "text", required = false }) { return ; } function ReportCard({ title, rows, kinds, fileName }) { return (
{kinds.map((kind) => )}
); } function exportCsv(fileName, rows) { const safeRows = rows.length ? rows : [{ message: "No records" }]; const headers = Object.keys(safeRows[0]); const csv = [headers.join(","), ...safeRows.map((row) => headers.map((key) => `"${String(row[key] ?? "").replaceAll('"', '""')}"`).join(","))].join("\n"); const url = URL.createObjectURL(new Blob([csv], { type: "text/csv" })); const link = document.createElement("a"); link.href = url; link.download = fileName; link.click(); URL.revokeObjectURL(url); } async function downloadSalaryPdf(slip) { try { const id = slip.id || slip._id; const token = sessionStorage.getItem("authToken"); const response = await fetch(`${API_BASE}/api/employee-salary/slips/${id}/download`, { headers: token ? { Authorization: `Bearer ${token}` } : {}, }); if (!response.ok) { const text = await response.text(); throw new Error(text || "Unable to download PDF"); } const blob = await response.blob(); const url = URL.createObjectURL(blob); const link = document.createElement("a"); link.href = url; link.download = `${slip.slipNumber || "salary-slip"}.pdf`; link.click(); URL.revokeObjectURL(url); } catch (error) { window.alert(error.message || "Unable to download PDF"); } } function HeroGreeting({ title, subtitle }) { return

{subtitle}

{title}

; } function Info({ label, value }) { return

{label}

{value || "-"}
; } function StatusBadge({ status }) { const color = status === "Present" || status === "Paid" ? "green" : status === "Late" || status === "Pending" ? "orange" : status === "Absent" ? "red" : "blue"; return {status}; } function Toast({ message, onClose }) { useEffect(() => { const id = setTimeout(onClose, 3200); return () => clearTimeout(id); }, [onClose]); return {message}; } function EmptyState({ text }) { return
{text}
; } function safeJson(value) { try { return value ? JSON.parse(value) : null; } catch { return null; } } function time(value) { return value ? new Date(value).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" }) : "-"; } function timeAgo(value) { if (!value) return ""; const minutes = Math.max(1, Math.round((Date.now() - new Date(value).getTime()) / 60000)); return `${minutes} min ago`; } function initials(name) { return String(name || "Employee").split(" ").map((item) => item[0]).join("").slice(0, 2).toUpperCase(); } function getLocation() { return new Promise((resolve, reject) => { if (!navigator.geolocation) return reject(new Error("GPS Required")); navigator.geolocation.getCurrentPosition( (position) => resolve({ lat: position.coords.latitude, lng: position.coords.longitude }), () => reject(new Error("GPS permission is required.")) ); }); } createRoot(document.getElementById("root")).render();