mirror of
https://bitbucket.org/studiotem/jandl-taskmanager-app.git
synced 2026-10-21 06:20:21 +00:00
137 lines
4.0 KiB
Vue
137 lines
4.0 KiB
Vue
<template>
|
|
<A-mastertask-name
|
|
:id="subtask.master_task_id"
|
|
:name="subtask._master_task.name"
|
|
:color="subtask._master_task.color"
|
|
@close-modal="$emit('close-modal')"
|
|
/>
|
|
<A-mastertask-status :is-finished="subtask.is_finished" />
|
|
<A-task-deadline :subtask="subtask" />
|
|
<Z-created-by :employee-id="subtask.created_by" />
|
|
|
|
<!-- Loop through normalized employees -->
|
|
<div
|
|
v-for="(employeeData, index) in normalizedEmployees"
|
|
:key="`employee-${employeeData.id || index}`"
|
|
:class="{
|
|
'employee-section': hasMultipleEmployees,
|
|
'border-top': hasMultipleEmployees,
|
|
'border-bottom':
|
|
hasMultipleEmployees && index === normalizedEmployees.length - 1,
|
|
}"
|
|
>
|
|
<A-task-assigned-employee :employee="employeeData._employee" />
|
|
<A-task-planned-time :hours="employeeData.duration" />
|
|
<A-task-timeblocks
|
|
:timeblocks="employeeData.timeblocks"
|
|
:subtask="{
|
|
...subtask,
|
|
employee_id: employeeData.id,
|
|
timeblocks: employeeData.timeblocks,
|
|
}"
|
|
@update-subtask="$emit('update-subtask', $event)"
|
|
/>
|
|
</div>
|
|
|
|
<!-- Remaining/spent time only for single employee (not in multi-employee drafts) -->
|
|
<template v-if="!hasMultipleEmployees">
|
|
<A-task-remaining-time :hours="subtask.duration - subtask.spent_time" />
|
|
<A-task-spent-time :hours="subtask.spent_time" :subtask="subtask" />
|
|
</template>
|
|
|
|
<A-task-description
|
|
:description="subtask.description"
|
|
:mastertask-description="subtask.master_task_description"
|
|
/>
|
|
<Z-files :files="subtask.files" />
|
|
</template>
|
|
|
|
<script>
|
|
import AMastertaskName from './_components/a-mastertask-name.vue';
|
|
import AMastertaskStatus from './_components/a-mastertask-status.vue';
|
|
import ATaskTimeblocks from './_components/a-task-timeblocks.vue';
|
|
import ZCreatedBy from '../../_components/read-only/z-created-by.vue';
|
|
import ATaskAssignedEmployee from './_components/a-task-assigned-employee.vue';
|
|
import ATaskPlannedTime from './_components/a-task-planned-time.vue';
|
|
import ATaskSpentTime from './_components/a-task-spent-time.vue';
|
|
import ATaskRemainingTime from './_components/a-task-remaining-time.vue';
|
|
import ATaskDeadline from './_components/a-task-deadline.vue';
|
|
import ATaskDescription from './_components/a-task-description.vue';
|
|
import ZFiles from '@/plugins/tm@modal/_components/read-only/z-files.vue';
|
|
import { mapGetters } from 'vuex';
|
|
|
|
export default {
|
|
components: {
|
|
ZFiles,
|
|
AMastertaskName,
|
|
AMastertaskStatus,
|
|
ATaskTimeblocks,
|
|
ZCreatedBy,
|
|
ATaskAssignedEmployee,
|
|
ATaskPlannedTime,
|
|
ATaskSpentTime,
|
|
ATaskRemainingTime,
|
|
ATaskDescription,
|
|
ATaskDeadline,
|
|
},
|
|
|
|
props: {
|
|
subtask: {
|
|
type: Object,
|
|
required: true,
|
|
},
|
|
},
|
|
emits: ['close-modal', 'update-subtask'],
|
|
|
|
computed: {
|
|
...mapGetters('tm', ['enrichedEmployees']),
|
|
|
|
normalizedEmployees() {
|
|
// Drafts always have employees array
|
|
if (this.subtask.is_draft) {
|
|
return this.subtask.employees
|
|
.filter((emp) => emp.id) // Filter out empty employee slots
|
|
.map((emp) => ({
|
|
id: emp.id,
|
|
duration: emp.duration || 0,
|
|
timeblocks: emp.timeblocks || [],
|
|
_employee: this.enrichedEmployees.find((e) => e.id == emp.id) || {},
|
|
}));
|
|
}
|
|
|
|
// Published subtask - single employee format
|
|
return [
|
|
{
|
|
id: this.subtask.employee_id,
|
|
duration: this.subtask.duration,
|
|
timeblocks: this.subtask.timeblocks || [],
|
|
_employee: this.subtask._employee,
|
|
},
|
|
];
|
|
},
|
|
|
|
hasMultipleEmployees() {
|
|
// For drafts, always use multi-employee styling (even with 1 employee)
|
|
if (this.subtask.is_draft) {
|
|
return true;
|
|
}
|
|
// For published subtasks, check actual count
|
|
return this.normalizedEmployees.length > 1;
|
|
},
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style lang="sass" scoped>
|
|
.employee-section
|
|
margin: 16px 0
|
|
|
|
.border-top
|
|
border-top: 1px solid rgba(0, 0, 0, 0.12)
|
|
padding-top: 16px
|
|
|
|
.border-bottom
|
|
border-bottom: 1px solid rgba(0, 0, 0, 0.12)
|
|
padding-bottom: 16px
|
|
</style>
|