"use client"; import { useState, useEffect, useCallback } from "react"; import { Clock, Plus, Calendar, Check, X, AlertTriangle } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { fetchEmployees } from "@/lib/supabase/employees-actions"; import { getUserPermissions } from "@/lib/supabase/rbac-actions"; import PageSkeleton from "./PageSkeleton"; export default function TimesheetPage() { const [loading, setLoading] = useState(true); const [canManage, setCanManage] = useState(false); const [employees, setEmployees] = useState([]); const [timesheets, setTimesheets] = useState([]); const [weekStart, setWeekStart] = useState(() => { const d = new Date(); const day = d.getDay(); d.setDate(d.getDate() - (day === 0 ? 6 : day - 1)); return d.toISOString().split("T")[0]; }); const [showAddForm, setShowAddForm] = useState(false); const [selectedEmployee, setSelectedEmployee] = useState(""); const [selectedDate, setSelectedDate] = useState(""); const [hours, setHours] = useState(""); const [notes, setNotes] = useState(""); const [status, setStatus] = useState<"work" | "leave" | "sick">("work"); const [saving, setSaving] = useState(false); useEffect(() => { let cancelled = false; Promise.all([ fetchEmployees().catch(() => []), getUserPermissions().catch(() => ({ orgRole: "employee" })), ]) .then(([emps, perms]) => { if (!cancelled) { setEmployees(emps); setCanManage(perms.orgRole === "owner" || perms.orgRole === "admin"); } }) .catch(() => {}) .finally(() => { if (!cancelled) setLoading(false); }); return () => { cancelled = true; }; }, []); const weekDays = Array.from({ length: 5 }, (_, i) => { const d = new Date(weekStart + "T00:00:00"); d.setDate(d.getDate() + i); return { date: d.toISOString().split("T")[0], day: d.toLocaleDateString("en-AU", { weekday: "short" }), dayNum: d.getDate(), }; }); const handleAdd = async () => { if (!selectedEmployee || !selectedDate || !hours) return; setSaving(true); // Stub: In a real app, save to timesheets table setTimesheets((prev) => [...prev, { id: Date.now().toString(), employee_id: selectedEmployee, date: selectedDate, hours: parseFloat(hours), notes, status, created_at: new Date().toISOString(), }]); setShowAddForm(false); setSelectedEmployee(""); setSelectedDate(""); setHours(""); setNotes(""); setStatus("work"); setSaving(false); }; if (loading) return ; return (
{/* Header */}

Timesheets

Track work hours and time off

setWeekStart(e.target.value)} className="border border-gray-200 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-teal-300" /> {canManage && ( )}
{/* Add Timesheet Modal */} {showAddForm && (
setShowAddForm(false)}>
e.stopPropagation()}>

Log Hours

setSelectedDate(e.target.value)} className="mt-1 w-full border border-gray-200 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-teal-300" />
setHours(e.target.value)} className="mt-1 w-full border border-gray-200 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-teal-300" placeholder="8" />
{(["work", "leave", "sick"] as const).map((s) => ( ))}