Fix error when deleting time entries from the timesheet

Update the timesheet detail page to correctly handle the deletion of time entries by ensuring that entries with zero hours are included in the save operation when they have been modified.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 55837015-10e9-4be9-b857-7f5e6be73772
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 5d5b4df6-50de-4be5-a63e-d635e929441e
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/1cc377db-7ea0-49f2-97ce-c3e87e0228cc/55837015-10e9-4be9-b857-7f5e6be73772/9KCnXCa
Replit-Helium-Checkpoint-Created: true
This commit is contained in:
SylvainP1 2026-04-14 08:48:24 +00:00
parent b454523241
commit 0b0385df95
2 changed files with 8 additions and 3 deletions

View File

@ -58,10 +58,10 @@ export default function TimesheetDetailPage() {
const deleteLine = useDeleteTimesheetLine();
const upsertEntries = useUpsertTimeEntries();
// Local state for optimistic updates
const [localEntries, setLocalEntries] = useState<Record<string, number>>({});
const [isAddingLine, setIsAddingLine] = useState(false);
const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);
const dirtyKeysRef = useRef<Set<string>>(new Set());
const { data: projects } = useListProjects({ query: { queryKey: getListProjectsQueryKey() } });
@ -78,6 +78,7 @@ export default function TimesheetDetailPage() {
});
setLocalEntries(initial);
setHasUnsavedChanges(false);
dirtyKeysRef.current.clear();
}
}, [timesheet]);
@ -114,10 +115,11 @@ export default function TimesheetDetailPage() {
const entries = localEntriesRef.current;
const entriesToSave: LocalEntry[] = [];
const dirty = dirtyKeysRef.current;
Object.entries(entries).forEach(([key, hours]) => {
const lineIdStr = key.split("-")[0];
const fullDate = key.substring(lineIdStr.length + 1);
if (hours > 0) {
if (hours > 0 || dirty.has(key)) {
entriesToSave.push({
timesheetLineId: parseInt(lineIdStr),
date: fullDate,
@ -134,6 +136,7 @@ export default function TimesheetDetailPage() {
onSuccess: () => {
setSaveStatus("saved");
setHasUnsavedChanges(false);
dirtyKeysRef.current.clear();
queryClient.invalidateQueries({ queryKey: getGetTimesheetQueryKey(timesheetId) });
setTimeout(() => setSaveStatus("idle"), 2000);
},
@ -148,6 +151,7 @@ export default function TimesheetDetailPage() {
const key = `${lineId}-${dateStr}`;
setLocalEntries(prev => ({ ...prev, [key]: hours }));
setHasUnsavedChanges(true);
dirtyKeysRef.current.add(key);
if (saveTimerRef.current) clearTimeout(saveTimerRef.current);
saveTimerRef.current = setTimeout(() => doSave(), 800);
@ -181,11 +185,12 @@ export default function TimesheetDetailPage() {
if (hasUnsavedChanges) {
const entries = localEntriesRef.current;
const dirty = dirtyKeysRef.current;
const entriesToSave: LocalEntry[] = [];
Object.entries(entries).forEach(([key, hours]) => {
const lineIdStr = key.split("-")[0];
const fullDate = key.substring(lineIdStr.length + 1);
if (hours > 0) {
if (hours > 0 || dirty.has(key)) {
entriesToSave.push({ timesheetLineId: parseInt(lineIdStr), date: fullDate, hours });
}
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB