fix(task-edit): fixed free time calculation

This commit is contained in:
Matej Glasnák committed 2026-02-03 04:18:40 +01:00
1 parent 68e7c0d785
commit c9772400bd
2 files changed
+37 -9

No files matched your search

@@ -26,6 +26,7 @@ export function useEmployeeTimeline(
otherLocalTimeblocks?: Ref<Timeblock[]>,
editingBlockerId?: Ref<number | null>,
draftTimeblocks?: Ref<Timeblock[]>,
allEditingTimeblockIds?: Ref<number[]>,
) {
// Fetch employee's tasks for the selected date
const {
@@ -267,6 +268,11 @@ export function useEmployeeTimeline(
if (!tasks || !d) return 0;
// Get IDs of timeblocks being edited locally to exclude them from scheduled time
const editingTimeblockIds = allEditingTimeblockIds
? new Set(unref(allEditingTimeblockIds).filter((id) => id != null))
: new Set();
let totalMinutes = 0;
tasks.forEach((task) => {
@@ -278,6 +284,11 @@ export function useEmployeeTimeline(
return;
}
// Skip timeblocks that are being edited locally to avoid double-counting
if (task._timeblock_id && editingTimeblockIds.has(task._timeblock_id)) {
return;
}
totalMinutes += timelineUtils._getDifferenceInMinutes(
task._real_end,
task._real_start,
@@ -287,14 +298,10 @@ export function useEmployeeTimeline(
return (totalMinutes / 60).toFixed(1);
});
// Calculate free/unscheduled time for the day (in hours)
const freeTime = computed(() => {
const emp = unref(employee);
const d = unref(date);
// Calculate total planned time including local edits (for display purposes)
const totalPlannedTime = computed(() => {
const scheduled = parseFloat(String(unref(scheduledTime)));
if (!emp || !d) return '0';
// Calculate duration of other local unsaved timeblocks for the same date
let localTimeblocksHours = 0;
if (otherLocalTimeblocks) {
@@ -313,9 +320,20 @@ export function useEmployeeTimeline(
localTimeblocksHours += calculateTimeblockDuration(currentTb);
}
return (scheduled + localTimeblocksHours).toFixed(1);
});
// Calculate free/unscheduled time for the day (in hours)
const freeTime = computed(() => {
const emp = unref(employee);
const d = unref(date);
const totalPlanned = parseFloat(String(unref(totalPlannedTime)));
if (!emp || !d) return '0';
const dailyCapacityHours = emp.work_end - emp.work_start;
return (dailyCapacityHours - scheduled - localTimeblocksHours).toFixed(1);
return (dailyCapacityHours - totalPlanned).toFixed(1);
});
// Detect collisions with current timeblock
@@ -367,6 +385,7 @@ export function useEmployeeTimeline(
// Timeline data
timelineTasks,
scheduledTime,
totalPlannedTime,
freeTime,
// Collision detection
@@ -14,7 +14,7 @@
:has-start-time-error="hasStartTimeError"
:has-end-time-error="hasEndTimeError"
:end-time-error-message="endTimeErrorMessage"
:planned-time="_scheduledTime"
:planned-time="_totalPlannedTime"
:free-time="_freeTime"
:employee="employee"
:index="index"
@@ -238,6 +238,13 @@ const otherTimeblocksForSameDate = computed(() => {
});
});
// Get all timeblock IDs being edited locally for this employee (to exclude from server scheduled time)
const allEditingTimeblockIds = computed(() => {
return props.allEmployeeTimeblocks
.filter((tb) => tb.id != null)
.map((tb) => tb.id) as number[];
});
// Use timeline composable
const editingBlockerIdRef = computed(() => props.editingBlockerId);
const draftTimeblocksRef = computed(() => props.draftTimeblocks);
@@ -246,6 +253,7 @@ const {
isLoading,
timelineTasks,
scheduledTime: _scheduledTime,
totalPlannedTime: _totalPlannedTime,
freeTime: _freeTime,
timeblockDuration,
refetch,
@@ -256,6 +264,7 @@ const {
otherTimeblocksForSameDate,
editingBlockerIdRef,
draftTimeblocksRef,
allEditingTimeblockIds,
);
// Force refetch when date changes