diff --git a/app/src/plugins/tm@_utils/useEmployeeTimeline.ts b/app/src/plugins/tm@_utils/useEmployeeTimeline.ts index 1a52daf..e26276f 100644 --- a/app/src/plugins/tm@_utils/useEmployeeTimeline.ts +++ b/app/src/plugins/tm@_utils/useEmployeeTimeline.ts @@ -1,89 +1,104 @@ -import { useQuery } from '@tanstack/vue-query' -import { computed, Ref, unref } from 'vue' -import axios from '@/plugins/w@custom/axios/models/axios' -import moment from 'moment' -import timelineUtils from '@/plugins/tm@dashboard/tasks/_utils/timeline.utils' +import { useQuery } from '@tanstack/vue-query'; +import { computed, Ref, unref } from 'vue'; +import axios from '@/plugins/w@custom/axios/models/axios'; +import moment from 'moment'; +import timelineUtils from '@/plugins/tm@dashboard/tasks/_utils/timeline.utils'; import { detectCollision, calculateTimeblockDuration, getCollisionSegments, type Timeblock, type CollisionInfo, -} from './timeblock.utils' +} from './timeblock.utils'; interface Employee { - id: number - name: string - surname: string - work_start: number - work_end: number + id: number; + name: string; + surname: string; + work_start: number; + work_end: number; } export function useEmployeeTimeline( employee: Ref, date: Ref, - currentTimeblock: Ref + currentTimeblock: Ref, ) { // Fetch employee's tasks for the selected date - const { data: tasksData, isLoading, error, refetch } = useQuery({ + const { + data: tasksData, + isLoading, + error, + refetch, + } = useQuery({ queryKey: computed(() => [ 'employee-timeline', unref(employee)?.id, unref(date) ? moment(unref(date)).format('YYYY-MM-DD') : null, ]), queryFn: async () => { - const emp = unref(employee) - const d = unref(date) + const emp = unref(employee); + const d = unref(date); if (!emp?.id || !d) { - return null + return null; } - const dateStr = moment(d).format('YYYY-MM-DD') + const dateStr = moment(d).format('YYYY-MM-DD'); const queryParams = new URLSearchParams({ start: dateStr, end: dateStr, employee_id: emp.id.toString(), - }).toString() + }).toString(); - const response = await axios.get_auth(`v1/subtasks?${queryParams}`) - return response + const response = await axios.get_auth(`v1/subtasks?${queryParams}`); + return response; }, enabled: computed(() => { - const emp = unref(employee) - const d = unref(date) - return !!(emp?.id && d) + const emp = unref(employee); + const d = unref(date); + return !!(emp?.id && d); }), - }) + }); // Generate timeline tasks from fetched data const timelineTasks = computed(() => { - const data = unref(tasksData) - const emp = unref(employee) - const d = unref(date) + const data = unref(tasksData); + const emp = unref(employee); + const d = unref(date); if (!data || !emp || !d) { - return [] + return []; } - const subtasks = [...(data.subtasks || []), ...(data.blockers || [])] - const dateObj = new Date(d) - const selectedDateStr = moment(d).format('YYYY-MM-DD') + const subtasks = [...(data.subtasks || []), ...(data.blockers || [])]; + const selectedDateStr = moment(d).format('YYYY-MM-DD'); try { // Process timeblocks directly instead of using timeline utils // which is designed for multi-day views - const tasks: any[] = [] + const tasks: any[] = []; subtasks.forEach((subtask) => { - if (!['blocker', 'adhoc', 'home_office', 'vacation', 'free_day', 'office365_blocker'].includes(subtask.type)) { + if ( + ![ + 'blocker', + 'adhoc', + 'home_office', + 'vacation', + 'free_day', + 'office365_blocker', + ].includes(subtask.type) + ) { subtask.timeblocks?.forEach((timeblock: any) => { - const timeblockDateStr = moment(timeblock.start).format('YYYY-MM-DD') + const timeblockDateStr = moment(timeblock.start).format( + 'YYYY-MM-DD', + ); // Only include timeblocks for the selected date if (timeblockDateStr === selectedDateStr) { - let type = 'subtask' - if (subtask.type === 'office365') type = 'office365' + let type = 'subtask'; + if (subtask.type === 'office365') type = 'office365'; tasks.push({ id: subtask.id, @@ -98,28 +113,28 @@ export function useEmployeeTimeline( _timeblock_is_finished: timeblock.is_finished, _real_start: new Date(timeblock.start), _real_end: new Date(timeblock.end), - }) + }); } - }) + }); } - }) + }); - return tasks + return tasks; } catch (error) { - console.error('Error generating timeline tasks:', error) - return [] + console.error('Error generating timeline tasks:', error); + return []; } - }) + }); // Calculate scheduled time for the day (in hours) const scheduledTime = computed(() => { - const tasks = unref(timelineTasks) - const d = unref(date) - const now = moment() + const tasks = unref(timelineTasks); + const d = unref(date); + const now = moment(); - if (!tasks || !d) return 0 + if (!tasks || !d) return 0; - let totalMinutes = 0 + let totalMinutes = 0; tasks.forEach((task) => { if ( @@ -127,64 +142,69 @@ export function useEmployeeTimeline( task.subtask?.is_finished || task.blocker?.is_finished ) { - return + return; } if (now.isAfter(moment(task._real_end))) { // Ignore elapsed tasks - return + return; } else if ( now.isAfter(moment(task._real_start)) && now.isBefore(moment(task._real_end)) ) { // Task in progress - totalMinutes += timelineUtils._getDifferenceInMinutes(task._real_end, new Date()) + totalMinutes += timelineUtils._getDifferenceInMinutes( + task._real_end, + new Date(), + ); } else { // Future task totalMinutes += timelineUtils._getDifferenceInMinutes( task._real_end, - task._real_start - ) + task._real_start, + ); } - }) + }); - return (totalMinutes / 60).toFixed(1) - }) + 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) - const scheduled = parseFloat(String(unref(scheduledTime))) + const emp = unref(employee); + const d = unref(date); + const scheduled = parseFloat(String(unref(scheduledTime))); - if (!emp || !d) return '0' + if (!emp || !d) return '0'; - const now = moment() - const dateObj = moment(d) - const dailyCapacityHours = emp.work_end - emp.work_start + const now = moment(); + const dateObj = moment(d); + const dailyCapacityHours = emp.work_end - emp.work_start; if (dateObj.isBefore(now, 'days')) { // Past date - return '0' + return '0'; } else if (dateObj.isSame(now, 'days')) { // Today - calculate remaining capacity - const elapsedMinutes = now.diff(now.clone().startOf('day'), 'minutes') + const elapsedMinutes = now.diff(now.clone().startOf('day'), 'minutes'); const workStart = - emp.work_start * 60 > elapsedMinutes ? emp.work_start : elapsedMinutes / 60 - const todayCapacityHours = emp.work_end - workStart - const free = todayCapacityHours - scheduled - return free < 0 ? '0' : free.toFixed(1) + emp.work_start * 60 > elapsedMinutes + ? emp.work_start + : elapsedMinutes / 60; + const todayCapacityHours = emp.work_end - workStart; + const free = todayCapacityHours - scheduled; + return free < 0 ? '0' : free.toFixed(1); } else { // Future date - const free = dailyCapacityHours - scheduled - return free < 0 ? '0' : free.toFixed(1) + const free = dailyCapacityHours - scheduled; + return free < 0 ? '0' : free.toFixed(1); } - }) + }); // Detect collisions with current timeblock const collision = computed(() => { - const timeblock = unref(currentTimeblock) - const tasks = unref(timelineTasks) + const timeblock = unref(currentTimeblock); + const tasks = unref(timelineTasks); if (!timeblock || !tasks) { return { @@ -192,30 +212,30 @@ export function useEmployeeTimeline( startCollides: false, endCollides: false, collidingTasks: [], - } + }; } - return detectCollision(timeblock, tasks) - }) + return detectCollision(timeblock, tasks); + }); // Get collision segments for timeline visualization const collisionSegments = computed(() => { - const timeblock = unref(currentTimeblock) - const tasks = unref(timelineTasks) + const timeblock = unref(currentTimeblock); + const tasks = unref(timelineTasks); if (!timeblock || !tasks) { - return [] + return []; } - return getCollisionSegments(timeblock, tasks) - }) + return getCollisionSegments(timeblock, tasks); + }); // Calculate current timeblock duration const timeblockDuration = computed(() => { - const timeblock = unref(currentTimeblock) - if (!timeblock) return 0 - return calculateTimeblockDuration(timeblock) - }) + const timeblock = unref(currentTimeblock); + if (!timeblock) return 0; + return calculateTimeblockDuration(timeblock); + }); return { // Query states @@ -232,6 +252,5 @@ export function useEmployeeTimeline( collision, collisionSegments, timeblockDuration, - } + }; } - diff --git a/app/src/plugins/tm@modal/task/_components/employees/a-employee-timeblock-timeline.vue b/app/src/plugins/tm@modal/task/_components/employees/a-employee-timeblock-timeline.vue index e5e3ed7..a9cf8e7 100644 --- a/app/src/plugins/tm@modal/task/_components/employees/a-employee-timeblock-timeline.vue +++ b/app/src/plugins/tm@modal/task/_components/employees/a-employee-timeblock-timeline.vue @@ -3,8 +3,8 @@
Načítavam...
-
-
+
+