mirror of
https://bitbucket.org/studiotem/jandl-taskmanager-app.git
synced 2026-10-21 14:29:34 +00:00
feat(timeline): add support for calculating local timeblock durations and update employee timeblock handling in modal
This commit is contained in:
1 parent
03974b1b99
commit
1b7cea85bf
3 files changed
+75
-26
No files matched your search
@@ -23,6 +23,7 @@ export function useEmployeeTimeline(
|
|||||||
employee: Ref<Employee | null>,
|
employee: Ref<Employee | null>,
|
||||||
date: Ref<Date | string | null>,
|
date: Ref<Date | string | null>,
|
||||||
currentTimeblock: Ref<Timeblock | null>,
|
currentTimeblock: Ref<Timeblock | null>,
|
||||||
|
otherLocalTimeblocks?: Ref<Timeblock[]>,
|
||||||
) {
|
) {
|
||||||
// Fetch employee's tasks for the selected date
|
// Fetch employee's tasks for the selected date
|
||||||
const {
|
const {
|
||||||
@@ -193,9 +194,27 @@ export function useEmployeeTimeline(
|
|||||||
|
|
||||||
if (!emp || !d) return '0';
|
if (!emp || !d) return '0';
|
||||||
|
|
||||||
|
// Calculate duration of other local unsaved timeblocks for the same date
|
||||||
|
let localTimeblocksHours = 0;
|
||||||
|
if (otherLocalTimeblocks) {
|
||||||
|
const localTbs = unref(otherLocalTimeblocks) || [];
|
||||||
|
localTbs.forEach((tb) => {
|
||||||
|
// Only count timeblocks with complete time data
|
||||||
|
if (tb.starts_at_time && tb.ends_at_time) {
|
||||||
|
localTimeblocksHours += calculateTimeblockDuration(tb);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also include the current timeblock if it has both start and end times
|
||||||
|
const currentTb = unref(currentTimeblock);
|
||||||
|
if (currentTb?.starts_at_time && currentTb?.ends_at_time) {
|
||||||
|
localTimeblocksHours += calculateTimeblockDuration(currentTb);
|
||||||
|
}
|
||||||
|
|
||||||
const dailyCapacityHours = emp.work_end - emp.work_start;
|
const dailyCapacityHours = emp.work_end - emp.work_start;
|
||||||
|
|
||||||
return (dailyCapacityHours - scheduled).toFixed(1);
|
return (dailyCapacityHours - scheduled - localTimeblocksHours).toFixed(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Detect collisions with current timeblock
|
// Detect collisions with current timeblock
|
||||||
|
|||||||
@@ -215,6 +215,29 @@ const employeeRef = computed(() => props.employee);
|
|||||||
const dateRef = computed(() => props.modelValue.date);
|
const dateRef = computed(() => props.modelValue.date);
|
||||||
const timeblockRef = computed(() => props.modelValue);
|
const timeblockRef = computed(() => props.modelValue);
|
||||||
|
|
||||||
|
// Get other timeblocks for the same date (excluding current one)
|
||||||
|
// This includes timeblocks from both the current employee and other employees
|
||||||
|
const otherTimeblocksForSameDate = computed(() => {
|
||||||
|
if (!props.modelValue.date) return [];
|
||||||
|
|
||||||
|
const currentDate = moment(props.modelValue.date).format('YYYY-MM-DD');
|
||||||
|
|
||||||
|
// Use allEmployeeTimeblocks which contains timeblocks for this specific employee
|
||||||
|
// Filter out the current timeblock by comparing index directly
|
||||||
|
return props.allEmployeeTimeblocks.filter((tb, index) => {
|
||||||
|
// Skip current timeblock by index
|
||||||
|
if (index === props.currentIndex) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Must have required fields
|
||||||
|
if (!tb.date || !tb.starts_at_time || !tb.ends_at_time) return false;
|
||||||
|
|
||||||
|
// Must be the same date
|
||||||
|
return moment(tb.date).format('YYYY-MM-DD') === currentDate;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// Use timeline composable
|
// Use timeline composable
|
||||||
const {
|
const {
|
||||||
isLoading,
|
isLoading,
|
||||||
@@ -223,7 +246,12 @@ const {
|
|||||||
freeTime: _freeTime,
|
freeTime: _freeTime,
|
||||||
timeblockDuration,
|
timeblockDuration,
|
||||||
refetch,
|
refetch,
|
||||||
} = useEmployeeTimeline(employeeRef, dateRef, timeblockRef);
|
} = useEmployeeTimeline(
|
||||||
|
employeeRef,
|
||||||
|
dateRef,
|
||||||
|
timeblockRef,
|
||||||
|
otherTimeblocksForSameDate,
|
||||||
|
);
|
||||||
|
|
||||||
// Force refetch when date changes
|
// Force refetch when date changes
|
||||||
watch(
|
watch(
|
||||||
@@ -264,29 +292,6 @@ const collisionSegments = computed(() => {
|
|||||||
return getCollisionSegmentsUtil(props.modelValue, scheduledBlocks.value);
|
return getCollisionSegmentsUtil(props.modelValue, scheduledBlocks.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Get other timeblocks for the same date (excluding current one)
|
|
||||||
// This includes timeblocks from both the current employee and other employees
|
|
||||||
const otherTimeblocksForSameDate = computed(() => {
|
|
||||||
if (!props.modelValue.date) return [];
|
|
||||||
|
|
||||||
const currentDate = moment(props.modelValue.date).format('YYYY-MM-DD');
|
|
||||||
|
|
||||||
// Use allEmployeeTimeblocks which contains timeblocks for this specific employee
|
|
||||||
// Filter out the current timeblock by comparing index directly
|
|
||||||
return props.allEmployeeTimeblocks.filter((tb, index) => {
|
|
||||||
// Skip current timeblock by index
|
|
||||||
if (index === props.currentIndex) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Must have required fields
|
|
||||||
if (!tb.date || !tb.starts_at_time || !tb.ends_at_time) return false;
|
|
||||||
|
|
||||||
// Must be the same date
|
|
||||||
return moment(tb.date).format('YYYY-MM-DD') === currentDate;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Get current timeblock range
|
// Get current timeblock range
|
||||||
const currentTimeblockRange = computed(() => {
|
const currentTimeblockRange = computed(() => {
|
||||||
const { start, end } = timeblockToDateRange(props.modelValue);
|
const { start, end } = timeblockToDateRange(props.modelValue);
|
||||||
|
|||||||
@@ -922,12 +922,37 @@ export default {
|
|||||||
const employee = this.enrichedEmployees.find(
|
const employee = this.enrichedEmployees.find(
|
||||||
(employee) => employee.id == subtask.employee_id,
|
(employee) => employee.id == subtask.employee_id,
|
||||||
);
|
);
|
||||||
this.subtask.employees = [employee];
|
|
||||||
|
// Get current logged-in user
|
||||||
|
const currentUserId = this.$store.getters['auth/user']?.id;
|
||||||
|
const isCurrentUser = currentUserId === subtask.employee_id;
|
||||||
|
|
||||||
|
// If the clicked employee is different from current user, add current user first as empty slot
|
||||||
|
if (!isCurrentUser) {
|
||||||
|
this.subtask.employees = [
|
||||||
|
{ id: currentUserId, duration: null }, // Empty current user slot
|
||||||
|
employee, // The clicked employee with data
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
// Same user or no current user, just add the clicked employee
|
||||||
|
this.subtask.employees = [employee];
|
||||||
|
}
|
||||||
|
|
||||||
this.subtask.deadline = subtask.deadline;
|
this.subtask.deadline = subtask.deadline;
|
||||||
this.subtask._deadline_time = subtask._deadline_time;
|
this.subtask._deadline_time = subtask._deadline_time;
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.timeblocks = [
|
this.timeblocks = [
|
||||||
|
...(!isCurrentUser
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
date: new Date(subtask.deadline),
|
||||||
|
starts_at_time: subtask._deadline_time,
|
||||||
|
ends_at_time: null,
|
||||||
|
employee_id: currentUserId,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: []),
|
||||||
{
|
{
|
||||||
date: new Date(subtask.deadline),
|
date: new Date(subtask.deadline),
|
||||||
starts_at_time: subtask._deadline_time,
|
starts_at_time: subtask._deadline_time,
|
||||||
|
|||||||
Reference in new issue
Block a user