diff --git a/app/src/plugins/tm@_utils/useEmployeeTimeline.ts b/app/src/plugins/tm@_utils/useEmployeeTimeline.ts index e4754ca..103724d 100644 --- a/app/src/plugins/tm@_utils/useEmployeeTimeline.ts +++ b/app/src/plugins/tm@_utils/useEmployeeTimeline.ts @@ -62,17 +62,60 @@ export function useEmployeeTimeline( }), }); + const { + data: conceptTasksData, + isLoading: conceptTasksLoading, + error: conceptTasksError, + refetch: conceptTasksRefetch, + } = useQuery({ + queryKey: computed(() => [ + 'concept-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); + + if (!emp?.id || !d) { + return null; + } + + const dateStr = moment(d).format('YYYY-MM-DD'); + const queryParams = new URLSearchParams({ + start: dateStr, + end: dateStr, + employee_id: emp.id.toString(), + type: 'draft', + }).toString(); + + 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); + }), + }); + // Generate timeline tasks from fetched data const timelineTasks = computed(() => { const data = unref(tasksData); + const conceptData = unref(conceptTasksData); const emp = unref(employee); const d = unref(date); - if (!data || !emp || !d) { + if (!data || !conceptData || !emp || !d) { return []; } - const subtasks = [...(data.subtasks || []), ...(data.blockers || [])]; + const subtasks = [ + ...(data.subtasks || []), + ...(data.blockers || []), + ...(conceptData.subtasks || []), + ]; + const selectedDateStr = moment(d).format('YYYY-MM-DD'); try { @@ -108,6 +151,7 @@ export function useEmployeeTimeline( date: new Date(subtask.start), project_code: null, subtask: subtask, + is_draft: !!subtask.is_draft, blocker: subtask, type, _timeblock_id: null, @@ -138,6 +182,7 @@ export function useEmployeeTimeline( date: new Date(timeblock.start), project_code: subtask.project_code, subtask: subtask, + is_draft: !!subtask.is_draft, blocker: undefined, type, _timeblock_id: timeblock.id, @@ -259,6 +304,10 @@ export function useEmployeeTimeline( error, refetch, + conceptTasksLoading, + conceptTasksError, + conceptTasksRefetch, + // Timeline data timelineTasks, scheduledTime, 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 2b0a1fb..cee1995 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 @@ -64,6 +64,7 @@ 'free_day', 'office365_blocker', ].includes(task.type), + 'scheduled-block--concept': task.is_draft === true, }" :style="{ left: `${getTimePosition(task._real_start)}px`, @@ -213,6 +214,7 @@ interface TimelineTask { subtask?: { title: string }; blocker?: { type: string }; type?: string; + is_draft?: boolean; } interface CollisionSegment { @@ -883,6 +885,9 @@ defineExpose({ border: 1px solid rgb(156, 0, 28) opacity: 0.7 + &--concept + background: repeating-linear-gradient(135deg, transparent, transparent 10px, rgba(127, 57, 251, 0.3) 10px, rgba(127, 57, 251, 0.3) 20px) + .other-timeblock position: absolute top: 5px 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 b716a7f..b3b4e09 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 @@ -242,6 +242,7 @@ const { freeTime: _freeTime, timeblockDuration, refetch, + conceptTasksRefetch, } = useEmployeeTimeline( employeeRef, dateRef, @@ -255,10 +256,16 @@ watch( () => { if (props.modelValue.date && props.employee?.id) { refetch(); + conceptTasksRefetch(); } }, ); +onMounted(() => { + refetch(); + conceptTasksRefetch(); +}); + // All tasks from timelineTasks are already filtered for the selected date // Filter out timeblocks that are being edited or deleted locally const scheduledBlocks = computed(() => {