fix(z-task-modal): ensure employee array checks in draft handling and improve timeblock update logic

This commit is contained in:
Matej Glasnák committed 2026-01-08 02:41:33 +01:00
1 parent 7a5f354912
commit 857a0aaa7e
4 files changed
+34 -17

No files matched your search

@@ -15,12 +15,12 @@ const MOBILE_BREAKPOINT = 768;
const SIZE_PRESETS = { const SIZE_PRESETS = {
small: { small: {
width: 600, width: 600,
height: 'fit-content', height: 'auto',
maxWidth: 600, maxWidth: 600,
}, },
medium: { medium: {
width: 900, width: 900,
height: 'fit-content', height: 'auto',
maxWidth: 900, maxWidth: 900,
}, },
large: { large: {
@@ -28,11 +28,7 @@
/> />
<!-- Timeline Visualization --> <!-- Timeline Visualization -->
<div <div v-if="modelValue.date && employee" class="timeline-wrapper">
v-if="modelValue.date && employee"
:class="{ 'timeline-wrapper--finished': modelValue.is_finished }"
class="timeline-wrapper"
>
<a-employee-timeblock-timeline <a-employee-timeblock-timeline
ref="timelineRef" ref="timelineRef"
:is-loading="isLoading" :is-loading="isLoading"
@@ -436,10 +432,22 @@ const handleTimeblockUpdated = (payload: {
starts_at_time: string; starts_at_time: string;
ends_at_time: string; ends_at_time: string;
}) => { }) => {
const { starts_at_time } = payload;
let { ends_at_time } = payload;
// Fix accidental same start/end time by adding 1 hour to end
if (starts_at_time === ends_at_time) {
const [hours, minutes] = starts_at_time.split(':').map(Number);
const newEndHour = (hours + 1) % 24; // Wrap around at midnight
ends_at_time = `${String(newEndHour).padStart(2, '0')}:${String(
minutes,
).padStart(2, '0')}`;
}
emit('update:modelValue', { emit('update:modelValue', {
...props.modelValue, ...props.modelValue,
starts_at_time: payload.starts_at_time, starts_at_time,
ends_at_time: payload.ends_at_time, ends_at_time,
}); });
// Trigger validation after timeline update // Trigger validation after timeline update
@@ -88,7 +88,7 @@ export default {
normalizedEmployees() { normalizedEmployees() {
// Drafts always have employees array // Drafts always have employees array
if (this.subtask.is_draft) { if (this.subtask.is_draft && Array.isArray(this.subtask.employees)) {
return this.subtask.employees return this.subtask.employees
.filter((emp) => emp.id) // Filter out empty employee slots .filter((emp) => emp.id) // Filter out empty employee slots
.map((emp) => ({ .map((emp) => ({
+16 -7
View File
@@ -563,16 +563,20 @@ export default {
// New subtask with multiple employees support // New subtask with multiple employees support
// Hide employees that are already selected in any slot // Hide employees that are already selected in any slot
// The v-autocomplete will still display the currently selected employee // The v-autocomplete will still display the currently selected employee
const isAlreadySelected = this.subtask.employees.some( const isAlreadySelected =
(emp) => emp.id && Number(emp.id) === employeeId, Array.isArray(this.subtask.employees) &&
); this.subtask.employees.some(
(emp) => emp.id && Number(emp.id) === employeeId,
);
return shouldShowItem && !isAlreadySelected; return shouldShowItem && !isAlreadySelected;
} else if (this.subtask.is_draft) { } else if (this.subtask.is_draft) {
// Edit draft subtask with multiple employees support // Edit draft subtask with multiple employees support
// Hide employees that are already selected in any slot // Hide employees that are already selected in any slot
const isAlreadySelected = this.subtask.employees.some( const isAlreadySelected =
(emp) => emp.id && Number(emp.id) === employeeId, Array.isArray(this.subtask.employees) &&
); this.subtask.employees.some(
(emp) => emp.id && Number(emp.id) === employeeId,
);
return shouldShowItem && !isAlreadySelected; return shouldShowItem && !isAlreadySelected;
} else { } else {
// Saved standard subtask, allow "re-select" for better UX // Saved standard subtask, allow "re-select" for better UX
@@ -734,7 +738,10 @@ export default {
this.pendingRemoveEmployeeId = undefined; this.pendingRemoveEmployeeId = undefined;
} }
// Handle create mode (multiple employees removal) // Handle create mode (multiple employees removal)
else if (this.pendingRemoveEmployeeIndex !== undefined) { else if (
this.pendingRemoveEmployeeIndex !== undefined &&
Array.isArray(this.subtask.employees)
) {
const employee = const employee =
this.subtask.employees[this.pendingRemoveEmployeeIndex]; this.subtask.employees[this.pendingRemoveEmployeeIndex];
if (employee?.id) { if (employee?.id) {
@@ -1184,6 +1191,8 @@ export default {
// Filter employees based on whether it's a concept/draft or published task // Filter employees based on whether it's a concept/draft or published task
// For concepts: only require id (duration can be null/0) // For concepts: only require id (duration can be null/0)
// For published tasks: require both id and duration // For published tasks: require both id and duration
if (!Array.isArray(employees)) return [];
return employees.filter((employee) => { return employees.filter((employee) => {
if (isConcept) { if (isConcept) {
return employee.id; // Only require ID for concepts/drafts return employee.id; // Only require ID for concepts/drafts