mirror of
https://bitbucket.org/studiotem/jandl-taskmanager-app.git
synced 2026-10-21 06:20:21 +00:00
refactor(task-modal): added support for multi-employees edit in z-task-modal to support new draft tasks editing
This commit is contained in:
1 parent
604dc4f988
commit
9266991335
3 files changed
+110
-19
No files matched your search
@@ -281,7 +281,7 @@ const otherTimeblocksForSameDate = computed(() => {
|
|||||||
// Skip current timeblock - compare by reference or by matching all key properties
|
// Skip current timeblock - compare by reference or by matching all key properties
|
||||||
if (
|
if (
|
||||||
tb === currentTimeblock ||
|
tb === currentTimeblock ||
|
||||||
(tb.employee_id === currentTimeblock.employee_id &&
|
(tb.employee_id == currentTimeblock.employee_id &&
|
||||||
tb.date === currentTimeblock.date &&
|
tb.date === currentTimeblock.date &&
|
||||||
tb.starts_at_time === currentTimeblock.starts_at_time &&
|
tb.starts_at_time === currentTimeblock.starts_at_time &&
|
||||||
tb.ends_at_time === currentTimeblock.ends_at_time &&
|
tb.ends_at_time === currentTimeblock.ends_at_time &&
|
||||||
|
|||||||
@@ -91,14 +91,14 @@ const setTimeblockRef = (el: any, index: number) => {
|
|||||||
const selectedEmployee = computed(() => {
|
const selectedEmployee = computed(() => {
|
||||||
if (!props.employeeData.id) return null;
|
if (!props.employeeData.id) return null;
|
||||||
const employees = store.getters['tm/enrichedEmployees'];
|
const employees = store.getters['tm/enrichedEmployees'];
|
||||||
return employees.find((emp: any) => emp.id === props.employeeData.id) || null;
|
return employees.find((emp: any) => emp.id == props.employeeData.id) || null;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Filter allTimeblocks to only include timeblocks for current employee
|
// Filter allTimeblocks to only include timeblocks for current employee
|
||||||
const allTimeblocksForCurrentEmployee = computed(() => {
|
const allTimeblocksForCurrentEmployee = computed(() => {
|
||||||
if (!props.employeeData.id) return [];
|
if (!props.employeeData.id) return [];
|
||||||
return props.allTimeblocks.filter(
|
return props.allTimeblocks.filter(
|
||||||
(tb) => tb.employee_id === props.employeeData.id,
|
(tb) => tb.employee_id == props.employeeData.id,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -95,9 +95,9 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Employee Assignment with Timeblocks -->
|
<!-- Employee Assignment with Timeblocks -->
|
||||||
<!-- Edit Mode: Single Employee -->
|
<!-- Edit Mode: Single Employee (for published subtasks) -->
|
||||||
<A-employee
|
<A-employee
|
||||||
v-if="subtask.id"
|
v-if="subtask.id && !isDraftWithMultipleEmployees"
|
||||||
v-model:employee-data="editModeEmployee"
|
v-model:employee-data="editModeEmployee"
|
||||||
:timeblocks="getEmployeeTimeblocks(subtask.employee_id)"
|
:timeblocks="getEmployeeTimeblocks(subtask.employee_id)"
|
||||||
:all-timeblocks="timeblocks"
|
:all-timeblocks="timeblocks"
|
||||||
@@ -112,7 +112,7 @@
|
|||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- Create Mode: Multiple Employees -->
|
<!-- Multi-Employee Mode (for new tasks and drafts with multiple employees) -->
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<A-employee
|
<A-employee
|
||||||
v-for="(employee, index) in subtask.employees"
|
v-for="(employee, index) in subtask.employees"
|
||||||
@@ -350,6 +350,13 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
isDraftWithMultipleEmployees() {
|
||||||
|
return (
|
||||||
|
this.subtask?.is_draft &&
|
||||||
|
Array.isArray(this.subtask?.employees) &&
|
||||||
|
this.subtask.employees.length > 0
|
||||||
|
);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
validations() {
|
validations() {
|
||||||
@@ -369,7 +376,7 @@ export default {
|
|||||||
// In edit mode: reassign timeblocks to new employee
|
// In edit mode: reassign timeblocks to new employee
|
||||||
if (this.subtask.id) {
|
if (this.subtask.id) {
|
||||||
this.timeblocks = this.timeblocks.map((tb) => {
|
this.timeblocks = this.timeblocks.map((tb) => {
|
||||||
if (tb.employee_id === oldValue) {
|
if (tb.employee_id == oldValue) {
|
||||||
return { ...tb, employee_id: value };
|
return { ...tb, employee_id: value };
|
||||||
}
|
}
|
||||||
return tb;
|
return tb;
|
||||||
@@ -377,7 +384,7 @@ export default {
|
|||||||
} else {
|
} else {
|
||||||
// In create mode: remove old employee's timeblocks
|
// In create mode: remove old employee's timeblocks
|
||||||
this.timeblocks = this.timeblocks.filter(
|
this.timeblocks = this.timeblocks.filter(
|
||||||
(tb) => tb.employee_id !== oldValue,
|
(tb) => tb.employee_id != oldValue,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -554,7 +561,7 @@ export default {
|
|||||||
// Helper: Get timeblocks for specific employee
|
// Helper: Get timeblocks for specific employee
|
||||||
getEmployeeTimeblocks(employeeId) {
|
getEmployeeTimeblocks(employeeId) {
|
||||||
if (!this.timeblocks) return [];
|
if (!this.timeblocks) return [];
|
||||||
return this.timeblocks.filter((tb) => tb.employee_id === employeeId);
|
return this.timeblocks.filter((tb) => tb.employee_id == employeeId);
|
||||||
},
|
},
|
||||||
|
|
||||||
updateEmployeeTimeblocks(updatedTimeblocks, employeeId) {
|
updateEmployeeTimeblocks(updatedTimeblocks, employeeId) {
|
||||||
@@ -565,7 +572,7 @@ export default {
|
|||||||
const deletedIds = this.timeblocks
|
const deletedIds = this.timeblocks
|
||||||
.filter(
|
.filter(
|
||||||
(tb) =>
|
(tb) =>
|
||||||
tb.employee_id === employeeId && tb.id && !updatedIds.has(tb.id),
|
tb.employee_id == employeeId && tb.id && !updatedIds.has(tb.id),
|
||||||
)
|
)
|
||||||
.map((tb) => tb.id)
|
.map((tb) => tb.id)
|
||||||
.filter((id) => !this.deletedTimeblockIds.includes(id));
|
.filter((id) => !this.deletedTimeblockIds.includes(id));
|
||||||
@@ -574,7 +581,7 @@ export default {
|
|||||||
|
|
||||||
// Replace timeblocks for this employee
|
// Replace timeblocks for this employee
|
||||||
const otherEmployeeTimeblocks = this.timeblocks.filter(
|
const otherEmployeeTimeblocks = this.timeblocks.filter(
|
||||||
(tb) => tb.employee_id !== employeeId,
|
(tb) => tb.employee_id != employeeId,
|
||||||
);
|
);
|
||||||
const updatedWithEmployeeId = updatedTimeblocks.map((tb) => ({
|
const updatedWithEmployeeId = updatedTimeblocks.map((tb) => ({
|
||||||
...tb,
|
...tb,
|
||||||
@@ -608,7 +615,7 @@ export default {
|
|||||||
|
|
||||||
// Get timeblocks for this employee
|
// Get timeblocks for this employee
|
||||||
const employeeTimeblocks = this.timeblocks.filter(
|
const employeeTimeblocks = this.timeblocks.filter(
|
||||||
(tb) => tb.employee_id === employeeId,
|
(tb) => tb.employee_id == employeeId,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (afterIndex === -1 || afterIndex >= employeeTimeblocks.length - 1) {
|
if (afterIndex === -1 || afterIndex >= employeeTimeblocks.length - 1) {
|
||||||
@@ -654,7 +661,7 @@ export default {
|
|||||||
if (this.subtask.employee_id) {
|
if (this.subtask.employee_id) {
|
||||||
// Remove all timeblocks for this employee
|
// Remove all timeblocks for this employee
|
||||||
this.timeblocks = this.timeblocks.filter(
|
this.timeblocks = this.timeblocks.filter(
|
||||||
(tb) => tb.employee_id !== this.subtask.employee_id,
|
(tb) => tb.employee_id != this.subtask.employee_id,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -670,7 +677,7 @@ export default {
|
|||||||
if (employee?.id) {
|
if (employee?.id) {
|
||||||
// Remove all timeblocks for this employee
|
// Remove all timeblocks for this employee
|
||||||
this.timeblocks = this.timeblocks.filter(
|
this.timeblocks = this.timeblocks.filter(
|
||||||
(tb) => tb.employee_id !== employee.id,
|
(tb) => tb.employee_id != employee.id,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -741,8 +748,59 @@ export default {
|
|||||||
// Store timeblocks in the component's timeblocks array
|
// Store timeblocks in the component's timeblocks array
|
||||||
this.timeblocks = convertedTimeblocks;
|
this.timeblocks = convertedTimeblocks;
|
||||||
|
|
||||||
// Ensure at least one timeblock exists for edit mode
|
// If draft with employees data, parse timeblocks for each employee
|
||||||
if (data.employee_id && this.timeblocks.length === 0) {
|
if (
|
||||||
|
data.is_draft &&
|
||||||
|
data.employees &&
|
||||||
|
Array.isArray(data.employees)
|
||||||
|
) {
|
||||||
|
const draftTimeblocks = [];
|
||||||
|
|
||||||
|
data.employees.forEach((employee) => {
|
||||||
|
if (employee.timeblocks && Array.isArray(employee.timeblocks)) {
|
||||||
|
employee.timeblocks.forEach((timeblock) => {
|
||||||
|
// Convert BE format to internal format
|
||||||
|
if (timeblock.start && timeblock.end) {
|
||||||
|
const startMoment = moment(
|
||||||
|
timeblock.start,
|
||||||
|
'YYYY-MM-DD HH:mm:ss',
|
||||||
|
);
|
||||||
|
const endMoment = moment(
|
||||||
|
timeblock.end,
|
||||||
|
'YYYY-MM-DD HH:mm:ss',
|
||||||
|
);
|
||||||
|
draftTimeblocks.push({
|
||||||
|
id: timeblock.id || null,
|
||||||
|
date: startMoment.toDate(),
|
||||||
|
starts_at_time: startMoment.format('HH:mm'),
|
||||||
|
ends_at_time: endMoment.format('HH:mm'),
|
||||||
|
is_finished: timeblock.is_finished || 0,
|
||||||
|
employee_id: employee.id, // Associate with employee
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Use draft timeblocks if they exist
|
||||||
|
if (draftTimeblocks.length > 0) {
|
||||||
|
this.timeblocks = draftTimeblocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure employees array has proper structure for editing
|
||||||
|
// Check if last employee is not empty, then add empty slot
|
||||||
|
const lastEmployee = data.employees[data.employees.length - 1];
|
||||||
|
if (lastEmployee && (lastEmployee.id || lastEmployee.duration)) {
|
||||||
|
data.employees.push({});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure at least one timeblock exists for edit mode (non-draft single employee)
|
||||||
|
if (
|
||||||
|
data.employee_id &&
|
||||||
|
!data.is_draft &&
|
||||||
|
this.timeblocks.length === 0
|
||||||
|
) {
|
||||||
this.addTimeblock(data.employee_id);
|
this.addTimeblock(data.employee_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -881,7 +939,7 @@ export default {
|
|||||||
timeblock.date &&
|
timeblock.date &&
|
||||||
timeblock.starts_at_time &&
|
timeblock.starts_at_time &&
|
||||||
timeblock.ends_at_time &&
|
timeblock.ends_at_time &&
|
||||||
timeblock.employee_id === this.subtask.employee_id,
|
timeblock.employee_id == this.subtask.employee_id,
|
||||||
) // Only send complete timeblocks for this employee
|
) // Only send complete timeblocks for this employee
|
||||||
.map((timeblock) => {
|
.map((timeblock) => {
|
||||||
const dateStr = moment(timeblock.date).format('YYYY-MM-DD');
|
const dateStr = moment(timeblock.date).format('YYYY-MM-DD');
|
||||||
@@ -895,6 +953,36 @@ export default {
|
|||||||
|
|
||||||
const payload = { ...this.subtask, timesheets, timeblocks };
|
const payload = { ...this.subtask, timesheets, timeblocks };
|
||||||
|
|
||||||
|
// For drafts with multiple employees, include employees array
|
||||||
|
if (this.subtask.is_draft && this.isDraftWithMultipleEmployees) {
|
||||||
|
const validEmployees = this.subtask.employees.filter(
|
||||||
|
(employee) => employee.id && employee.duration,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Assign timeblocks to each employee
|
||||||
|
validEmployees.forEach((employee) => {
|
||||||
|
employee.timeblocks = this.timeblocks
|
||||||
|
.filter(
|
||||||
|
(tb) =>
|
||||||
|
tb.employee_id == employee.id &&
|
||||||
|
tb.date &&
|
||||||
|
tb.starts_at_time &&
|
||||||
|
tb.ends_at_time,
|
||||||
|
)
|
||||||
|
.map((tb) => ({
|
||||||
|
start: `${moment(tb.date).format('YYYY-MM-DD')} ${
|
||||||
|
tb.starts_at_time
|
||||||
|
}:00`,
|
||||||
|
end: `${moment(tb.date).format('YYYY-MM-DD')} ${
|
||||||
|
tb.ends_at_time
|
||||||
|
}:00`,
|
||||||
|
id: tb.id || null,
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
payload.employees = validEmployees;
|
||||||
|
}
|
||||||
|
|
||||||
if (concept) {
|
if (concept) {
|
||||||
payload.is_draft = 1;
|
payload.is_draft = 1;
|
||||||
} else {
|
} else {
|
||||||
@@ -925,7 +1013,7 @@ export default {
|
|||||||
timeblock.date &&
|
timeblock.date &&
|
||||||
timeblock.starts_at_time &&
|
timeblock.starts_at_time &&
|
||||||
timeblock.ends_at_time &&
|
timeblock.ends_at_time &&
|
||||||
timeblock.employee_id === employee.id,
|
timeblock.employee_id == employee.id,
|
||||||
)
|
)
|
||||||
.map((timeblock) => {
|
.map((timeblock) => {
|
||||||
return {
|
return {
|
||||||
@@ -1002,7 +1090,10 @@ export default {
|
|||||||
|
|
||||||
_mergeDeadlineTimeDate() {
|
_mergeDeadlineTimeDate() {
|
||||||
// Override for concept tasks which may not have a deadline time set (check for invalid date)
|
// Override for concept tasks which may not have a deadline time set (check for invalid date)
|
||||||
if (isNaN(new Date(this.subtask.deadline).getTime())) {
|
if (
|
||||||
|
isNaN(new Date(this.subtask.deadline).getTime()) ||
|
||||||
|
!this.subtask._deadline_time
|
||||||
|
) {
|
||||||
this.subtask.deadline = null;
|
this.subtask.deadline = null;
|
||||||
} else {
|
} else {
|
||||||
const date = new Date(this.subtask.deadline);
|
const date = new Date(this.subtask.deadline);
|
||||||
|
|||||||
Reference in new issue
Block a user