mirror of
https://bitbucket.org/studiotem/jandl-taskmanager-app.git
synced 2026-10-21 14:29:34 +00:00
refactor(timeline): updated modal for adding timeblock to correctly display other (draft) timeblocks when editing subtask draft
This commit is contained in:
1 parent
9f2db65481
commit
c5672c94f2
5 files changed
+110
-50
No files matched your search
@@ -25,7 +25,7 @@ export function useEmployeeTimeline(
|
||||
currentTimeblock: Ref<Timeblock | null>,
|
||||
otherLocalTimeblocks?: Ref<Timeblock[]>,
|
||||
editingBlockerId?: Ref<number | null>,
|
||||
showDraftTasks?: Ref<boolean>,
|
||||
draftTimeblocks?: Ref<Timeblock[]>,
|
||||
) {
|
||||
// Fetch employee's tasks for the selected date
|
||||
const {
|
||||
@@ -64,61 +64,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);
|
||||
// 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;
|
||||
}
|
||||
// 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 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);
|
||||
}),
|
||||
});
|
||||
// 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 conceptData = unref(conceptTasksData);
|
||||
const emp = unref(employee);
|
||||
const d = unref(date);
|
||||
const excludeBlockerId = editingBlockerId ? unref(editingBlockerId) : null;
|
||||
const includeDrafts = showDraftTasks ? unref(showDraftTasks) : false;
|
||||
const draftTbs = draftTimeblocks ? unref(draftTimeblocks) : [];
|
||||
|
||||
if (!data || !conceptData || !emp || !d) {
|
||||
if (!data || !emp || !d) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const subtasks = [
|
||||
...(data.subtasks || []),
|
||||
...(data.blockers || []),
|
||||
// Only include concept tasks if showDraftTasks is true
|
||||
...(includeDrafts ? (conceptData.subtasks || []) : []),
|
||||
// ...(conceptData.subtasks || []),
|
||||
];
|
||||
|
||||
const selectedDateStr = moment(d).format('YYYY-MM-DD');
|
||||
@@ -221,6 +220,39 @@ export function useEmployeeTimeline(
|
||||
}
|
||||
});
|
||||
|
||||
// Process draft timeblocks from other employees in the same draft subtask
|
||||
draftTbs.forEach((timeblock: any) => {
|
||||
// Skip if timeblock doesn't have required fields
|
||||
if (!timeblock.start || !timeblock.end) {
|
||||
return;
|
||||
}
|
||||
|
||||
const timeblockDateStr = moment(timeblock.start).format('YYYY-MM-DD');
|
||||
|
||||
// Only include timeblocks for the selected date
|
||||
if (timeblockDateStr === selectedDateStr) {
|
||||
const task = {
|
||||
id: null, // Draft timeblock doesn't have a subtask ID
|
||||
start: new Date(timeblock.start),
|
||||
end: new Date(timeblock.end),
|
||||
master_task: null,
|
||||
date: new Date(timeblock.start),
|
||||
project_code: null,
|
||||
subtask: null,
|
||||
is_draft: true,
|
||||
blocker: undefined,
|
||||
type: 'draft_timeblock',
|
||||
_timeblock_id: timeblock.id || null,
|
||||
_timeblock_is_finished: timeblock.is_finished || false,
|
||||
_real_start: new Date(timeblock.start),
|
||||
_real_end: new Date(timeblock.end),
|
||||
_employee_id: timeblock.employee_id,
|
||||
};
|
||||
|
||||
tasks.push(task);
|
||||
}
|
||||
});
|
||||
|
||||
return tasks;
|
||||
} catch (error) {
|
||||
console.error('Error generating timeline tasks:', error);
|
||||
@@ -328,9 +360,9 @@ export function useEmployeeTimeline(
|
||||
error,
|
||||
refetch,
|
||||
|
||||
conceptTasksLoading,
|
||||
conceptTasksError,
|
||||
conceptTasksRefetch,
|
||||
// conceptTasksLoading,
|
||||
// conceptTasksError,
|
||||
// conceptTasksRefetch,
|
||||
|
||||
// Timeline data
|
||||
timelineTasks,
|
||||
|
||||
@@ -117,7 +117,7 @@
|
||||
:employee="employee"
|
||||
:deletable="false"
|
||||
:index="0"
|
||||
:show-draft-tasks="!!subtask.is_draft"
|
||||
:draft-timeblocks="draftTimeblocks"
|
||||
/>
|
||||
</v-card-text>
|
||||
|
||||
@@ -215,6 +215,11 @@ export default {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
|
||||
isDraft: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
emits: ['update-subtask'],
|
||||
|
||||
@@ -261,6 +266,26 @@ export default {
|
||||
);
|
||||
},
|
||||
|
||||
// Get draft timeblocks for the current employee in backend format for timeline
|
||||
draftTimeblocks() {
|
||||
if (!this.isDraft) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Convert timeblocks from internal format to backend format for timeline
|
||||
return this.timeblocks
|
||||
.filter((tb) => tb.date && tb.starts_at_time && tb.ends_at_time)
|
||||
.map((tb) => {
|
||||
const dateStr = moment(tb.date).format('YYYY-MM-DD');
|
||||
return {
|
||||
...tb,
|
||||
start: `${dateStr} ${tb.starts_at_time}:00`,
|
||||
end: `${dateStr} ${tb.ends_at_time}:00`,
|
||||
employee_id: this.subtask.employee_id,
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
// Hour width based on screen size
|
||||
hourWidth() {
|
||||
return window.innerWidth <= 768
|
||||
|
||||
@@ -77,7 +77,7 @@ interface Props {
|
||||
currentIndex?: number;
|
||||
deletable?: boolean;
|
||||
index?: number;
|
||||
showDraftTasks?: boolean; // Whether to show draft/concept tasks on timeline
|
||||
draftTimeblocks?: TimeblockData[]; // Draft timeblocks from all employees in draft subtask
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
@@ -88,7 +88,7 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
currentIndex: 0,
|
||||
deletable: false,
|
||||
index: 0,
|
||||
showDraftTasks: false,
|
||||
draftTimeblocks: () => [],
|
||||
});
|
||||
|
||||
const emit = defineEmits<{
|
||||
@@ -240,7 +240,7 @@ const otherTimeblocksForSameDate = computed(() => {
|
||||
|
||||
// Use timeline composable
|
||||
const editingBlockerIdRef = computed(() => props.editingBlockerId);
|
||||
const showDraftTasksRef = computed(() => props.showDraftTasks);
|
||||
const draftTimeblocksRef = computed(() => props.draftTimeblocks);
|
||||
|
||||
const {
|
||||
isLoading,
|
||||
@@ -249,14 +249,13 @@ const {
|
||||
freeTime: _freeTime,
|
||||
timeblockDuration,
|
||||
refetch,
|
||||
conceptTasksRefetch,
|
||||
} = useEmployeeTimeline(
|
||||
employeeRef,
|
||||
dateRef,
|
||||
timeblockRef,
|
||||
otherTimeblocksForSameDate,
|
||||
editingBlockerIdRef,
|
||||
showDraftTasksRef,
|
||||
draftTimeblocksRef,
|
||||
);
|
||||
|
||||
// Force refetch when date changes
|
||||
@@ -265,14 +264,14 @@ watch(
|
||||
() => {
|
||||
if (props.modelValue.date && props.employee?.id) {
|
||||
refetch();
|
||||
conceptTasksRefetch();
|
||||
// conceptTasksRefetch();
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
refetch();
|
||||
conceptTasksRefetch();
|
||||
// conceptTasksRefetch();
|
||||
});
|
||||
|
||||
// All tasks from timelineTasks are already filtered for the selected date
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
:all-employee-timeblocks="timeblocks"
|
||||
:all-timeblocks="allTimeblocksForCurrentEmployee"
|
||||
:deleted-timeblock-ids="deletedTimeblockIds"
|
||||
:draft-timeblocks="draftTimeblocks"
|
||||
:current-index="index"
|
||||
:deletable="timeblocks.length > 1"
|
||||
:index="index"
|
||||
@@ -46,6 +47,7 @@ interface Props {
|
||||
timeblocks?: TimeblockData[];
|
||||
allTimeblocks?: TimeblockData[]; // All timeblocks from all employees
|
||||
deletedTimeblockIds?: number[]; // IDs of saved timeblocks that have been deleted
|
||||
draftTimeblocks?: TimeblockData[]; // Draft timeblocks from all employees in draft subtask
|
||||
customFilter?: CustomFilterFunction;
|
||||
hasBackground?: boolean;
|
||||
required?: boolean;
|
||||
@@ -55,6 +57,7 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
timeblocks: () => [],
|
||||
allTimeblocks: () => [],
|
||||
deletedTimeblockIds: () => [],
|
||||
draftTimeblocks: () => [],
|
||||
customFilter: undefined,
|
||||
hasBackground: true,
|
||||
required: false,
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
<A-task-planned-time :hours="employeeData.duration" />
|
||||
<A-task-timeblocks
|
||||
:timeblocks="employeeData.timeblocks"
|
||||
:is-draft="!!subtask.is_draft"
|
||||
:subtask="{
|
||||
...subtask,
|
||||
employee_id: employeeData.id,
|
||||
|
||||
Reference in new issue
Block a user