diff --git a/app/src/plugins/tm@_utils/useEmployeeTimeline.ts b/app/src/plugins/tm@_utils/useEmployeeTimeline.ts index bb91144..a237918 100644 --- a/app/src/plugins/tm@_utils/useEmployeeTimeline.ts +++ b/app/src/plugins/tm@_utils/useEmployeeTimeline.ts @@ -1,5 +1,5 @@ import { useQuery } from '@tanstack/vue-query'; -import { computed, Ref, unref, watch } from 'vue'; +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'; @@ -80,8 +80,12 @@ export function useEmployeeTimeline( const tasks: any[] = []; subtasks.forEach((subtask) => { + // Check if this is a blocker/adhoc/etc with direct start/end fields (no timeblocks array) if ( - ![ + !subtask.timeblocks && + subtask.start && + subtask.end && + [ 'blocker', 'adhoc', 'home_office', @@ -90,6 +94,31 @@ export function useEmployeeTimeline( 'office365_blocker', ].includes(subtask.type) ) { + const blockerDateStr = moment(subtask.start).format('YYYY-MM-DD'); + + if (blockerDateStr === selectedDateStr) { + const type = subtask.type; + + const task = { + id: subtask.id, + start: new Date(subtask.start), + end: new Date(subtask.end), + master_task: null, + date: new Date(subtask.start), + project_code: null, + subtask: subtask, + blocker: subtask, + type, + _timeblock_id: null, + _timeblock_is_finished: subtask.is_finished || false, + _real_start: new Date(subtask.start), + _real_end: new Date(subtask.end), + }; + + tasks.push(task); + } + } else { + // Process regular subtasks with timeblocks array subtask.timeblocks?.forEach((timeblock: any) => { const timeblockDateStr = moment(timeblock.start).format( 'YYYY-MM-DD', @@ -100,7 +129,7 @@ export function useEmployeeTimeline( let type = 'subtask'; if (subtask.type === 'office365') type = 'office365'; - tasks.push({ + const task = { id: subtask.id, start: new Date(timeblock.start), end: new Date(timeblock.end), @@ -108,12 +137,15 @@ export function useEmployeeTimeline( date: new Date(timeblock.start), project_code: subtask.project_code, subtask: subtask, + blocker: undefined, type, _timeblock_id: timeblock.id, _timeblock_is_finished: timeblock.is_finished, _real_start: new Date(timeblock.start), _real_end: new Date(timeblock.end), - }); + }; + + tasks.push(task); } }); } @@ -202,22 +234,6 @@ export function useEmployeeTimeline( return calculateTimeblockDuration(timeblock); }); - watch( - scheduledTime, - (newVal) => { - console.log('scheduledTime', newVal); - }, - { immediate: true }, - ); - - watch( - freeTime, - (newVal) => { - console.log('freeTime', newVal); - }, - { immediate: true }, - ); - return { // Query states isLoading, diff --git a/app/src/plugins/tm@modal/task/_components/_components/a-task-timeblocks.vue b/app/src/plugins/tm@modal/task/_components/_components/a-task-timeblocks.vue index 2b916fc..6626b5f 100644 --- a/app/src/plugins/tm@modal/task/_components/_components/a-task-timeblocks.vue +++ b/app/src/plugins/tm@modal/task/_components/_components/a-task-timeblocks.vue @@ -23,36 +23,62 @@
- -

+ +

+ {{ formatTimeblockStart(timeblock) }} - + {{ formatTimeblockEnd(timeblock) }} +

+ +
+ + +
- {{ formatTimeblockStart(timeblock) }} - - {{ formatTimeblockEnd(timeblock) }} -

- + +
@@ -60,12 +86,12 @@ - -
+ +

Pridať dátum

- - + + - - - + - Potvrdiť + + + Potvrdiť + +
@@ -155,17 +153,22 @@ - 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 0b4e732..0a9a73e 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 @@ -46,6 +46,9 @@ v-for="(task, index) in scheduledBlocks" :key="`task-${index}`" class="scheduled-block" + :class="{ + 'scheduled-block--blocker': ['blocker', 'adhoc', 'home_office', 'vacation', 'free_day', 'office365_blocker'].includes(task.type) + }" :style="{ left: `${getTimePosition(task._real_start)}px`, width: `${getTimeWidth(task._real_start, task._real_end)}px`, @@ -255,6 +258,11 @@ defineExpose({ border-radius: 2px z-index: 2 + &--blocker + background: rgb(176, 0, 32) + border: 1px solid rgb(156, 0, 28) + opacity: 0.7 + .other-timeblock position: absolute top: 5px @@ -297,4 +305,12 @@ defineExpose({ color: white text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3) pointer-events: none + +.timeline-loading + height: 60px + display: flex + align-items: center + justify-content: center + font-size: 14px + opacity: 0.5 diff --git a/app/src/plugins/tm@modal/task/_components/employees/a-employee-timeblock.vue b/app/src/plugins/tm@modal/task/_components/employees/a-employee-timeblock.vue index c8bcd5b..d70f223 100644 --- a/app/src/plugins/tm@modal/task/_components/employees/a-employee-timeblock.vue +++ b/app/src/plugins/tm@modal/task/_components/employees/a-employee-timeblock.vue @@ -240,14 +240,15 @@ const scheduledBlocks = computed(() => { // Combine IDs that should be filtered: edited locally or deleted const hiddenTimeblockIds = new Set([ // Timeblock IDs being edited locally - ...props.allTimeblocks.filter(tb => tb.id).map(tb => tb.id), + ...props.allTimeblocks.filter((tb) => tb.id).map((tb) => tb.id), // Timeblock IDs that have been deleted - ...(props.deletedTimeblockIds || []) + ...(props.deletedTimeblockIds || []), ]); // Filter out tasks whose timeblock IDs should be hidden - return timelineTasks.value.filter(task => - !task._timeblock_id || !hiddenTimeblockIds.has(task._timeblock_id) + return timelineTasks.value.filter( + (task) => + !task._timeblock_id || !hiddenTimeblockIds.has(task._timeblock_id), ); }); @@ -271,18 +272,21 @@ const otherTimeblocksForSameDate = computed(() => { const currentTimeblock = props.modelValue; // Use allTimeblocks if available (includes all employees), otherwise fall back to current employee only - const timeblocksToCheck = props.allTimeblocks.length > 0 - ? props.allTimeblocks - : props.allEmployeeTimeblocks; + const timeblocksToCheck = + props.allTimeblocks.length > 0 + ? props.allTimeblocks + : props.allEmployeeTimeblocks; - return timeblocksToCheck.filter(tb => { + return timeblocksToCheck.filter((tb) => { // Skip current timeblock - compare by reference or by matching all key properties - if (tb === currentTimeblock || - (tb.employee_id === currentTimeblock.employee_id && - tb.date === currentTimeblock.date && - tb.starts_at_time === currentTimeblock.starts_at_time && - tb.ends_at_time === currentTimeblock.ends_at_time && - tb.id === currentTimeblock.id)) { + if ( + tb === currentTimeblock || + (tb.employee_id === currentTimeblock.employee_id && + tb.date === currentTimeblock.date && + tb.starts_at_time === currentTimeblock.starts_at_time && + tb.ends_at_time === currentTimeblock.ends_at_time && + tb.id === currentTimeblock.id) + ) { return false; } @@ -353,7 +357,7 @@ watch(isLoading, (newIsLoading, oldIsLoading) => { nextTick(() => { setTimeout(() => { centerTimeline(); - }, 100); // Small delay to ensure DOM is fully rendered + }, 0); // Small delay to ensure DOM is fully rendered }); } });