feat: unlock/reopen timesheet button in admin detail modal

This commit is contained in:
BizzleBot
2026-03-05 14:02:48 +00:00
parent 8c49fe1ec8
commit 9952d873c7
+20 -1
View File
@@ -517,6 +517,17 @@ function Reports() {
}).catch(console.error).finally(() => setLoading(false)); }).catch(console.error).finally(() => setLoading(false));
}, []); }, []);
async function unlockTimesheet(id) {
if (!confirm('Unlock this timesheet so the employee can edit it?')) return;
try {
await api.put(`/admin/timesheets/${id}/reopen`);
setTimesheets((prev) => prev.map((t) => t.id === id ? { ...t, status: 'draft' } : t));
if (selectedTs?.id === id) setSelectedTs((prev) => ({ ...prev, status: 'draft' }));
} catch (err) {
alert(err.response?.data?.error || 'Failed to unlock timesheet');
}
}
async function applyFilters() { async function applyFilters() {
setLoading(true); setLoading(true);
try { try {
@@ -647,9 +658,17 @@ function Reports() {
<X size={20} /> <X size={20} />
</button> </button>
</div> </div>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2 flex-wrap">
<StatusBadge status={selectedTs.status} /> <StatusBadge status={selectedTs.status} />
<span className="text-sm text-gray-500">{fmtDate(selectedTs.weekStart)} — {fmtDate(selectedTs.weekEnd)}</span> <span className="text-sm text-gray-500">{fmtDate(selectedTs.weekStart)} — {fmtDate(selectedTs.weekEnd)}</span>
{(selectedTs.status === 'submitted' || selectedTs.status === 'approved') && (
<button
onClick={() => unlockTimesheet(selectedTs.id)}
className="ml-auto flex items-center gap-1.5 px-3 py-1.5 rounded-lg bg-amber-50 dark:bg-amber-500/10 text-amber-600 dark:text-amber-400 text-xs font-semibold hover:bg-amber-100 dark:hover:bg-amber-500/20 transition-all"
>
🔓 Unlock for Editing
</button>
)}
</div> </div>
{detailLoading ? ( {detailLoading ? (