diff --git a/app/dist/js/index.js b/app/dist/js/index.js index ad80a9a..4dc770b 100644 --- a/app/dist/js/index.js +++ b/app/dist/js/index.js @@ -455,7 +455,7 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var cor /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.array.push.js */ \"./node_modules/core-js/modules/es.array.push.js\");\n/* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_es_json_stringify_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/es.json.stringify.js */ \"./node_modules/core-js/modules/es.json.stringify.js\");\n/* harmony import */ var core_js_modules_es_json_stringify_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_json_stringify_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var core_js_modules_esnext_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! core-js/modules/esnext.iterator.constructor.js */ \"./node_modules/core-js/modules/esnext.iterator.constructor.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var core_js_modules_esnext_iterator_filter_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! core-js/modules/esnext.iterator.filter.js */ \"./node_modules/core-js/modules/esnext.iterator.filter.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_filter_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_filter_js__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var core_js_modules_esnext_iterator_find_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! core-js/modules/esnext.iterator.find.js */ \"./node_modules/core-js/modules/esnext.iterator.find.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_find_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_find_js__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var core_js_modules_esnext_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! core-js/modules/esnext.iterator.for-each.js */ \"./node_modules/core-js/modules/esnext.iterator.for-each.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_5__);\n/* harmony import */ var core_js_modules_esnext_iterator_map_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! core-js/modules/esnext.iterator.map.js */ \"./node_modules/core-js/modules/esnext.iterator.map.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_map_js__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_map_js__WEBPACK_IMPORTED_MODULE_6__);\n/* harmony import */ var _plugins_tm_utils_tm_utils__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @/plugins/tm@_utils/tm.utils */ \"./src/plugins/tm@_utils/tm.utils.ts\");\n/* harmony import */ var moment__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! moment */ \"./node_modules/moment/moment.js\");\n/* harmony import */ var moment__WEBPACK_IMPORTED_MODULE_8___default = /*#__PURE__*/__webpack_require__.n(moment__WEBPACK_IMPORTED_MODULE_8__);\n/* harmony import */ var _plugins_tm_modal_mixins_modal_mixin__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @/plugins/tm@modal/_mixins/modal.mixin */ \"./src/plugins/tm@modal/_mixins/modal.mixin.ts\");\n/* harmony import */ var vuex__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! vuex */ \"./node_modules/vuex/dist/vuex.esm-bundler.js\");\n/* harmony import */ var _employees_a_employee_timeblock_vue__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../employees/a-employee-timeblock.vue */ \"./src/plugins/tm@modal/task/_components/employees/a-employee-timeblock.vue\");\n/* harmony import */ var _plugins_tm_utils_timeblock_utils__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! @/plugins/tm@_utils/timeblock.utils */ \"./src/plugins/tm@_utils/timeblock.utils.ts\");\n/* harmony import */ var _plugins_tm_modal_components_a_reset_size_button_vue__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! @/plugins/tm@modal/_components/a-reset-size-button.vue */ \"./src/plugins/tm@modal/_components/a-reset-size-button.vue\");\n/* harmony import */ var _plugins_tm_modal_components_a_close_button_vue__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! @/plugins/tm@modal/_components/a-close-button.vue */ \"./src/plugins/tm@modal/_components/a-close-button.vue\");\n/* harmony import */ var _plugins_tm_modal_components_a_resize_handle_vue__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! @/plugins/tm@modal/_components/a-resize-handle.vue */ \"./src/plugins/tm@modal/_components/a-resize-handle.vue\");\n/* provided dependency */ var console = __webpack_require__(/*! ./node_modules/console-browserify/index.js */ \"./node_modules/console-browserify/index.js\");\n\n\n\n\n\n\n\n\n\n\n\n\n// import AEmployeeTimeblockTimeline from '../employees/a-employee-timeblock-timeline.vue';\n\n\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n components: {\n AEmployeeTimeblock: _employees_a_employee_timeblock_vue__WEBPACK_IMPORTED_MODULE_11__[\"default\"],\n // AEmployeeTimeblockTimeline,\n AResetSizeButton: _plugins_tm_modal_components_a_reset_size_button_vue__WEBPACK_IMPORTED_MODULE_13__[\"default\"],\n ACloseButton: _plugins_tm_modal_components_a_close_button_vue__WEBPACK_IMPORTED_MODULE_14__[\"default\"],\n AResizeHandle: _plugins_tm_modal_components_a_resize_handle_vue__WEBPACK_IMPORTED_MODULE_15__[\"default\"]\n },\n mixins: [_plugins_tm_modal_mixins_modal_mixin__WEBPACK_IMPORTED_MODULE_9__[\"default\"]],\n props: {\n timeblocks: {\n type: Array,\n required: true\n },\n subtask: {\n type: Object,\n required: true\n }\n },\n emits: ['update-subtask'],\n data() {\n return {\n tmUtils: _plugins_tm_utils_tm_utils__WEBPACK_IMPORTED_MODULE_7__[\"default\"],\n showModal: false,\n visible: false,\n // New timeblock for modal (used by a-employee-timeblock component)\n newTimeblock: {\n id: null,\n date: new Date(),\n starts_at_time: null,\n ends_at_time: null,\n employee_id: null\n },\n // Timeline constants\n START_HOUR: 0,\n END_HOUR: 24,\n HOUR_WIDTH: 60,\n HOUR_WIDTH_MOBILE: 50,\n // Existing timeblocks timeline data\n existingTimeblocksData: {},\n // { [index]: { tasks: [], loading: false } }\n modalName: 'a-task-timeblocks-modal',\n modalSize: 'medium'\n };\n },\n computed: {\n ...(0,vuex__WEBPACK_IMPORTED_MODULE_10__.mapGetters)('tm', ['mastertasks', 'enrichedEmployees']),\n isOffice365Task() {\n return this.subtask.type == 'office365';\n },\n // Get employee data from subtask\n employee() {\n if (!this.subtask?.employee_id) return null;\n return this.subtask._employee || this.enrichedEmployees.find(emp => emp.id === this.subtask.employee_id);\n },\n // Hour width based on screen size\n hourWidth() {\n return window.innerWidth <= 768 ? this.HOUR_WIDTH_MOBILE : this.HOUR_WIDTH;\n },\n // Computed property to trigger reactivity when existingTimeblocksData changes\n existingTimeblocksDataReactive() {\n // This forces Vue to track changes to existingTimeblocksData\n return {\n ...this.existingTimeblocksData\n };\n }\n },\n watch: {\n // Watch for timeblocks changes\n timeblocks: {\n handler() {\n // Refetch timeline data for all timeblocks when they change\n this.$nextTick(() => {\n this.fetchAllTimelinesData();\n });\n },\n deep: true\n },\n // Watch for employee changes\n 'employee.id': {\n handler(newId) {\n if (newId) {\n this.fetchAllTimelinesData();\n }\n }\n },\n // Watch for modal opening - set employee_id and reset to today\n showModal: {\n handler(isOpen) {\n if (isOpen) {\n this.newTimeblock = {\n id: null,\n date: new Date(),\n starts_at_time: null,\n ends_at_time: null,\n employee_id: this.employee?.id || null\n };\n }\n }\n }\n },\n mounted() {\n // Fetch timeline data on mount\n if (this.employee?.id) {\n this.fetchAllTimelinesData();\n }\n },\n methods: {\n // Submit timeblock from employee timeblock component\n async submitFromEmployeeTimeblock() {\n // Validate using the employee timeblock component's validation\n const isValid = await this.$refs.employeeTimeblockRef?.validate();\n if (!isValid) {\n return;\n }\n\n // The newTimeblock data is already reactive and updated by the component\n await this.submit();\n },\n // Methods for existing timeblocks timeline\n getTimelineLoadingState(index) {\n const reactiveData = this.existingTimeblocksDataReactive;\n return reactiveData[index]?.loading || false;\n },\n getScheduledBlocksForTimeblock(index) {\n // Use the reactive computed property to ensure Vue tracks changes\n const reactiveData = this.existingTimeblocksDataReactive;\n const tasks = reactiveData[index]?.tasks || [];\n const currentTimeblock = this.timeblocks[index];\n\n // Filter out the current timeblock from scheduled blocks\n return tasks.filter(task => !task._timeblock_id || !currentTimeblock.id || task._timeblock_id !== currentTimeblock.id);\n },\n getOtherTimeblocksForTimeblock(timeblock, currentIndex) {\n if (!timeblock.date) return [];\n const selectedDate = moment__WEBPACK_IMPORTED_MODULE_8___default()(timeblock.date).format('YYYY-MM-DD');\n return this.timeblocks.filter((tb, idx) => {\n // Skip current timeblock\n if (idx === currentIndex) return false;\n if (!tb.date || !tb.starts_at_time || !tb.ends_at_time) return false;\n const tbDate = moment__WEBPACK_IMPORTED_MODULE_8___default()(tb.date).format('YYYY-MM-DD');\n return tbDate === selectedDate;\n });\n },\n getTimeblockRange(timeblock) {\n const {\n start,\n end\n } = (0,_plugins_tm_utils_timeblock_utils__WEBPACK_IMPORTED_MODULE_12__.timeblockToDateRange)(timeblock);\n return {\n start,\n end\n };\n },\n getCollisionForTimeblock(timeblock, index) {\n const scheduledBlocks = this.getScheduledBlocksForTimeblock(index);\n return (0,_plugins_tm_utils_timeblock_utils__WEBPACK_IMPORTED_MODULE_12__.detectCollision)(timeblock, scheduledBlocks);\n },\n getCollisionSegmentsForTimeblock(timeblock, index) {\n const scheduledBlocks = this.getScheduledBlocksForTimeblock(index);\n return (0,_plugins_tm_utils_timeblock_utils__WEBPACK_IMPORTED_MODULE_12__.getCollisionSegments)(timeblock, scheduledBlocks);\n },\n calculateDuration(timeblock) {\n return (0,_plugins_tm_utils_timeblock_utils__WEBPACK_IMPORTED_MODULE_12__.calculateTimeblockDuration)(timeblock);\n },\n async fetchTimelineDataForTimeblock(index) {\n const timeblock = this.timeblocks[index];\n if (!this.employee?.id || !timeblock.date) {\n this.existingTimeblocksData = {\n ...this.existingTimeblocksData,\n [index]: {\n tasks: [],\n loading: false\n }\n };\n return;\n }\n this.existingTimeblocksData = {\n ...this.existingTimeblocksData,\n [index]: {\n tasks: this.existingTimeblocksData[index]?.tasks || [],\n loading: true\n }\n };\n try {\n const dateStr = moment__WEBPACK_IMPORTED_MODULE_8___default()(timeblock.date).format('YYYY-MM-DD');\n const queryParams = new URLSearchParams({\n start: dateStr,\n end: dateStr,\n employee_id: this.employee.id.toString()\n }).toString();\n const response = await this.$axios.get_auth(`v1/subtasks?${queryParams}`);\n const subtasks = [...(response.subtasks || []), ...(response.blockers || [])];\n const tasks = [];\n subtasks.forEach(subtask => {\n // Check if this is a blocker/adhoc/etc with direct start/end fields (no timeblocks array)\n if (!subtask.timeblocks && subtask.start && subtask.end && ['blocker', 'adhoc', 'home_office', 'vacation', 'free_day', 'office365_blocker'].includes(subtask.type)) {\n const blockerDateStr = moment__WEBPACK_IMPORTED_MODULE_8___default()(subtask.start).format('YYYY-MM-DD');\n if (blockerDateStr === dateStr) {\n const type = subtask.type;\n tasks.push({\n id: subtask.id,\n start: new Date(subtask.start),\n end: new Date(subtask.end),\n master_task: null,\n date: new Date(subtask.start),\n project_code: null,\n subtask: subtask,\n blocker: subtask,\n type,\n _timeblock_id: null,\n _timeblock_is_finished: subtask.is_finished || false,\n _real_start: new Date(subtask.start),\n _real_end: new Date(subtask.end)\n });\n }\n } else {\n // Process regular subtasks with timeblocks array\n subtask.timeblocks?.forEach(tb => {\n const timeblockDateStr = moment__WEBPACK_IMPORTED_MODULE_8___default()(tb.start).format('YYYY-MM-DD');\n if (timeblockDateStr === dateStr) {\n let type = 'subtask';\n if (subtask.type === 'office365') type = 'office365';\n tasks.push({\n id: subtask.id,\n start: new Date(tb.start),\n end: new Date(tb.end),\n master_task: subtask.master_task,\n date: new Date(tb.start),\n project_code: subtask.project_code,\n subtask: subtask,\n blocker: undefined,\n type,\n _timeblock_id: tb.id,\n _timeblock_is_finished: tb.is_finished,\n _real_start: new Date(tb.start),\n _real_end: new Date(tb.end)\n });\n }\n });\n }\n });\n this.existingTimeblocksData = {\n ...this.existingTimeblocksData,\n [index]: {\n tasks,\n loading: false\n }\n };\n } catch (error) {\n console.error('Error fetching timeline data for timeblock:', error);\n this.existingTimeblocksData = {\n ...this.existingTimeblocksData,\n [index]: {\n tasks: [],\n loading: false\n }\n };\n }\n },\n // Fetch timeline data for all existing timeblocks\n async fetchAllTimelinesData() {\n if (!this.employee?.id) return;\n const promises = this.timeblocks.map((_, index) => this.fetchTimelineDataForTimeblock(index));\n await Promise.all(promises);\n },\n formatTimeblockStart(timeblock) {\n // Handle internal format with date and time fields\n if (timeblock.date && timeblock.starts_at_time) {\n const dateStr = moment__WEBPACK_IMPORTED_MODULE_8___default()(timeblock.date).format('DD.MM.yyyy');\n return `${dateStr}, ${timeblock.starts_at_time}`;\n }\n // Fallback to backend format\n if (timeblock.start) {\n return _plugins_tm_utils_tm_utils__WEBPACK_IMPORTED_MODULE_7__[\"default\"].formatDateTime(timeblock.start);\n }\n return '';\n },\n formatTimeblockEnd(timeblock) {\n // Handle internal format with date and time fields\n if (timeblock.date && timeblock.ends_at_time) {\n return timeblock.ends_at_time;\n }\n // Fallback to backend format\n if (timeblock.end) {\n return _plugins_tm_utils_tm_utils__WEBPACK_IMPORTED_MODULE_7__[\"default\"].formatDateTime(timeblock.end);\n }\n return '';\n },\n async submit() {\n const subtask = JSON.parse(JSON.stringify(this.subtask));\n if (!subtask?.timeblocks) {\n subtask.timeblocks = [];\n }\n if (!subtask?.timesheets) {\n subtask.timesheets = [];\n }\n if (!subtask?.is_finished) {\n subtask.is_finished = 0;\n }\n\n // Add timeblock in internal format from newTimeblock\n subtask.timeblocks.push({\n id: null,\n date: this.newTimeblock.date,\n starts_at_time: this.newTimeblock.starts_at_time,\n ends_at_time: this.newTimeblock.ends_at_time,\n is_finished: 0\n });\n if (subtask.deadline) subtask.deadline = _plugins_tm_utils_tm_utils__WEBPACK_IMPORTED_MODULE_7__[\"default\"].formatDateTimeForBackend(this._mergeDeadlineTimeDate());\n const isAfterDeadline = this.isAfterDeadline();\n if (isAfterDeadline) {\n this.visible = true;\n } else {\n if (!subtask.id) {\n this.$emit('update-unfinished-subtask', subtask);\n this.closeModal();\n } else {\n this._update(subtask);\n }\n }\n },\n async confirmSubmit() {\n const subtask = JSON.parse(JSON.stringify(this.subtask));\n if (!subtask?.timeblocks) {\n subtask.timeblocks = [];\n }\n if (!subtask?.timesheets) {\n subtask.timesheets = [];\n }\n if (!subtask?.is_finished) {\n subtask.is_finished = 0;\n }\n\n // Add timeblock in internal format from newTimeblock\n subtask.timeblocks.push({\n id: null,\n date: this.newTimeblock.date,\n starts_at_time: this.newTimeblock.starts_at_time,\n ends_at_time: this.newTimeblock.ends_at_time,\n is_finished: 0\n });\n if (subtask.deadline) subtask.deadline = _plugins_tm_utils_tm_utils__WEBPACK_IMPORTED_MODULE_7__[\"default\"].formatDateTimeForBackend(this._mergeDeadlineTimeDate());\n if (!subtask.id) {\n this.$emit('update-unfinished-subtask', subtask);\n this.closeModal();\n return;\n }\n this.visible = false;\n this._update(subtask);\n },\n async toggleTimeblockIsFinished(originalTimeblock) {\n // TODO: Pridat odpracovany cas modal?\n const subtask = JSON.parse(JSON.stringify(this.subtask));\n const timeblock = JSON.parse(JSON.stringify(originalTimeblock));\n timeblock.is_finished = timeblock.is_finished == 1 ? 0 : 1;\n try {\n // Convert timeblock to backend format before sending\n const timeblockForBackend = {\n id: timeblock.id,\n is_finished: timeblock.is_finished\n };\n\n // If timeblock is in internal format, convert it\n if (timeblock.date) {\n const dateStr = moment__WEBPACK_IMPORTED_MODULE_8___default()(timeblock.date).format('YYYY-MM-DD');\n timeblockForBackend.start = `${dateStr} ${timeblock.starts_at_time}:00`;\n timeblockForBackend.end = `${dateStr} ${timeblock.ends_at_time}:00`;\n } else {\n // Already in backend format\n timeblockForBackend.start = timeblock.start;\n timeblockForBackend.end = timeblock.end;\n }\n const {\n data: newTimeblock\n } = await this.$axios.put_auth(`v1/timeblocks/${timeblock.id}`, timeblockForBackend);\n\n // Convert returned timeblock from backend format to internal format\n const startMoment = moment__WEBPACK_IMPORTED_MODULE_8___default()(newTimeblock.start, 'YYYY-MM-DD HH:mm:ss');\n const endMoment = moment__WEBPACK_IMPORTED_MODULE_8___default()(newTimeblock.end, 'YYYY-MM-DD HH:mm:ss');\n const convertedTimeblock = {\n id: newTimeblock.id,\n date: startMoment.toDate(),\n starts_at_time: startMoment.format('HH:mm'),\n ends_at_time: endMoment.format('HH:mm'),\n is_finished: newTimeblock.is_finished\n };\n subtask.timeblocks = subtask.timeblocks.map(originalTimeblock => {\n if (originalTimeblock.id == convertedTimeblock.id) return convertedTimeblock;\n return originalTimeblock;\n });\n this.$events.emit('on-subtask-edited', subtask);\n this.$emit('update-subtask', subtask);\n if (timeblock.is_finished) this.$events.emit('show-task-add-time-modal', {\n subtask\n });\n } catch (error) {\n this.$toast.error(error.message || error);\n }\n },\n async deleteTimeblock({\n id\n }) {\n const subtask = JSON.parse(JSON.stringify(this.subtask));\n subtask.timeblocks = subtask.timeblocks.filter(timeblock => timeblock.id != id);\n if (subtask.deadline) subtask.deadline = _plugins_tm_utils_tm_utils__WEBPACK_IMPORTED_MODULE_7__[\"default\"].formatDateTimeForBackend(this._mergeDeadlineTimeDate());\n this._update(subtask);\n },\n deleteTimeblockWithoutId(_index) {\n this.$emit('delete-timeblock');\n },\n async _update(data) {\n try {\n const timesheets = data.timesheets.map(timesheet => {\n delete timesheet.employee_name;\n return timesheet;\n });\n\n // Convert timeblocks from internal format to BE format\n const timeblocks = (data.timeblocks || []).filter(timeblock => {\n // Filter timeblocks that have either old format (date) or new format (start)\n return timeblock.date || timeblock.start;\n }).map(timeblock => {\n // If already in BE format (has start field), return as is\n if (timeblock.start && !timeblock.date) {\n return {\n id: timeblock.id || null,\n start: timeblock.start,\n end: timeblock.end,\n is_finished: timeblock.is_finished || 0\n };\n }\n\n // Convert from internal format to BE format\n const dateStr = moment__WEBPACK_IMPORTED_MODULE_8___default()(timeblock.date).format('YYYY-MM-DD');\n return {\n id: timeblock.id || null,\n start: `${dateStr} ${timeblock.starts_at_time}:00`,\n end: `${dateStr} ${timeblock.ends_at_time}:00`,\n is_finished: timeblock.is_finished || 0\n };\n });\n const {\n subtask\n } = await this.$axios.put_auth(`v1/subtasks/${data.id}`, {\n ...data,\n timesheets,\n timeblocks\n });\n this.closeModal();\n this.$events.emit('on-subtask-edited', subtask);\n } catch (error) {\n this.$toast.error(error.message || error);\n }\n },\n isAfterDeadline() {\n const deadline = this.getDeadline(this.subtask);\n if (!deadline) return;\n const mDate = moment__WEBPACK_IMPORTED_MODULE_8___default()(this.newTimeblock.date);\n const mDeadline = moment__WEBPACK_IMPORTED_MODULE_8___default()(deadline);\n const [hours, minutes] = this.newTimeblock.ends_at_time.split(':').map(Number);\n mDate.hours(hours);\n mDate.minutes(minutes);\n return mDate.isAfter(mDeadline);\n },\n getDeadline(subtask) {\n if (subtask?.deadline) return subtask.deadline;\n return subtask.master_task_deadline;\n },\n _mergeDeadlineTimeDate() {\n const date = new Date(this.subtask.deadline);\n const timeParts = this.subtask._deadline_time.split(':');\n date.setHours(parseInt(timeParts[0]));\n date.setMinutes(parseInt(timeParts[1]));\n return date;\n },\n closeModal() {\n // Reset newTimeblock\n this.newTimeblock = {\n id: null,\n date: new Date(),\n starts_at_time: null,\n ends_at_time: null,\n employee_id: this.employee?.id || null\n };\n this.showModal = false;\n }\n }\n});\n\n//# sourceURL=webpack://jandl/./src/plugins/tm@modal/task/_components/_components/a-task-timeblocks.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}"); +eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.array.push.js */ \"./node_modules/core-js/modules/es.array.push.js\");\n/* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_es_json_stringify_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/es.json.stringify.js */ \"./node_modules/core-js/modules/es.json.stringify.js\");\n/* harmony import */ var core_js_modules_es_json_stringify_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_json_stringify_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var core_js_modules_esnext_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! core-js/modules/esnext.iterator.constructor.js */ \"./node_modules/core-js/modules/esnext.iterator.constructor.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var core_js_modules_esnext_iterator_filter_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! core-js/modules/esnext.iterator.filter.js */ \"./node_modules/core-js/modules/esnext.iterator.filter.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_filter_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_filter_js__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var core_js_modules_esnext_iterator_find_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! core-js/modules/esnext.iterator.find.js */ \"./node_modules/core-js/modules/esnext.iterator.find.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_find_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_find_js__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var core_js_modules_esnext_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! core-js/modules/esnext.iterator.for-each.js */ \"./node_modules/core-js/modules/esnext.iterator.for-each.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_5__);\n/* harmony import */ var core_js_modules_esnext_iterator_map_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! core-js/modules/esnext.iterator.map.js */ \"./node_modules/core-js/modules/esnext.iterator.map.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_map_js__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_map_js__WEBPACK_IMPORTED_MODULE_6__);\n/* harmony import */ var core_js_modules_esnext_iterator_some_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! core-js/modules/esnext.iterator.some.js */ \"./node_modules/core-js/modules/esnext.iterator.some.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_some_js__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_some_js__WEBPACK_IMPORTED_MODULE_7__);\n/* harmony import */ var _plugins_tm_utils_tm_utils__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @/plugins/tm@_utils/tm.utils */ \"./src/plugins/tm@_utils/tm.utils.ts\");\n/* harmony import */ var moment__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! moment */ \"./node_modules/moment/moment.js\");\n/* harmony import */ var moment__WEBPACK_IMPORTED_MODULE_9___default = /*#__PURE__*/__webpack_require__.n(moment__WEBPACK_IMPORTED_MODULE_9__);\n/* harmony import */ var _plugins_tm_modal_mixins_modal_mixin__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @/plugins/tm@modal/_mixins/modal.mixin */ \"./src/plugins/tm@modal/_mixins/modal.mixin.ts\");\n/* harmony import */ var vuex__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! vuex */ \"./node_modules/vuex/dist/vuex.esm-bundler.js\");\n/* harmony import */ var _employees_a_employee_timeblock_vue__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../employees/a-employee-timeblock.vue */ \"./src/plugins/tm@modal/task/_components/employees/a-employee-timeblock.vue\");\n/* harmony import */ var _plugins_tm_utils_timeblock_utils__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! @/plugins/tm@_utils/timeblock.utils */ \"./src/plugins/tm@_utils/timeblock.utils.ts\");\n/* harmony import */ var _plugins_tm_modal_components_a_reset_size_button_vue__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! @/plugins/tm@modal/_components/a-reset-size-button.vue */ \"./src/plugins/tm@modal/_components/a-reset-size-button.vue\");\n/* harmony import */ var _plugins_tm_modal_components_a_close_button_vue__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! @/plugins/tm@modal/_components/a-close-button.vue */ \"./src/plugins/tm@modal/_components/a-close-button.vue\");\n/* harmony import */ var _plugins_tm_modal_components_a_resize_handle_vue__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! @/plugins/tm@modal/_components/a-resize-handle.vue */ \"./src/plugins/tm@modal/_components/a-resize-handle.vue\");\n/* provided dependency */ var console = __webpack_require__(/*! ./node_modules/console-browserify/index.js */ \"./node_modules/console-browserify/index.js\");\n\n\n\n\n\n\n\n\n\n\n\n\n\n// import AEmployeeTimeblockTimeline from '../employees/a-employee-timeblock-timeline.vue';\n\n\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n components: {\n AEmployeeTimeblock: _employees_a_employee_timeblock_vue__WEBPACK_IMPORTED_MODULE_12__[\"default\"],\n // AEmployeeTimeblockTimeline,\n AResetSizeButton: _plugins_tm_modal_components_a_reset_size_button_vue__WEBPACK_IMPORTED_MODULE_14__[\"default\"],\n ACloseButton: _plugins_tm_modal_components_a_close_button_vue__WEBPACK_IMPORTED_MODULE_15__[\"default\"],\n AResizeHandle: _plugins_tm_modal_components_a_resize_handle_vue__WEBPACK_IMPORTED_MODULE_16__[\"default\"]\n },\n mixins: [_plugins_tm_modal_mixins_modal_mixin__WEBPACK_IMPORTED_MODULE_10__[\"default\"]],\n props: {\n timeblocks: {\n type: Array,\n required: true\n },\n subtask: {\n type: Object,\n required: true\n }\n },\n emits: ['update-subtask'],\n data() {\n return {\n tmUtils: _plugins_tm_utils_tm_utils__WEBPACK_IMPORTED_MODULE_8__[\"default\"],\n showModal: false,\n visible: false,\n // New timeblock for modal (used by a-employee-timeblock component)\n newTimeblock: {\n id: null,\n date: new Date(),\n starts_at_time: null,\n ends_at_time: null,\n employee_id: null\n },\n // Timeline constants\n START_HOUR: 0,\n END_HOUR: 24,\n HOUR_WIDTH: 60,\n HOUR_WIDTH_MOBILE: 50,\n // Existing timeblocks timeline data\n existingTimeblocksData: {},\n // { [index]: { tasks: [], loading: false } }\n modalName: 'a-task-timeblocks-modal',\n modalSize: 'medium'\n };\n },\n computed: {\n ...(0,vuex__WEBPACK_IMPORTED_MODULE_11__.mapGetters)('tm', ['mastertasks', 'enrichedEmployees']),\n isOffice365Task() {\n return this.subtask.type == 'office365';\n },\n // Get employee data from subtask\n employee() {\n if (!this.subtask?.employee_id) return null;\n return this.subtask._employee || this.enrichedEmployees.find(emp => emp.id === this.subtask.employee_id);\n },\n // Hour width based on screen size\n hourWidth() {\n return window.innerWidth <= 768 ? this.HOUR_WIDTH_MOBILE : this.HOUR_WIDTH;\n },\n // Computed property to trigger reactivity when existingTimeblocksData changes\n existingTimeblocksDataReactive() {\n // This forces Vue to track changes to existingTimeblocksData\n return {\n ...this.existingTimeblocksData\n };\n }\n },\n watch: {\n // Watch for timeblocks changes\n timeblocks: {\n handler() {\n // Refetch timeline data for all timeblocks when they change\n this.$nextTick(() => {\n this.fetchAllTimelinesData();\n });\n },\n deep: true\n },\n // Watch for employee changes\n 'employee.id': {\n handler(newId) {\n if (newId) {\n this.fetchAllTimelinesData();\n }\n }\n },\n // Watch for modal opening - set employee_id and reset to today\n showModal: {\n handler(isOpen) {\n if (isOpen) {\n this.newTimeblock = {\n id: null,\n date: new Date(),\n starts_at_time: null,\n ends_at_time: null,\n employee_id: this.employee?.id || null\n };\n }\n }\n }\n },\n mounted() {\n // Fetch timeline data on mount\n if (this.employee?.id) {\n this.fetchAllTimelinesData();\n }\n },\n methods: {\n // Submit timeblock from employee timeblock component\n async submitFromEmployeeTimeblock() {\n // Validate using the employee timeblock component's validation\n const isValid = await this.$refs.employeeTimeblockRef?.validate();\n if (!isValid) {\n return;\n }\n\n // The newTimeblock data is already reactive and updated by the component\n await this.submit();\n },\n // Methods for existing timeblocks timeline\n getTimelineLoadingState(index) {\n const reactiveData = this.existingTimeblocksDataReactive;\n return reactiveData[index]?.loading || false;\n },\n getScheduledBlocksForTimeblock(index) {\n // Use the reactive computed property to ensure Vue tracks changes\n const reactiveData = this.existingTimeblocksDataReactive;\n const tasks = reactiveData[index]?.tasks || [];\n const currentTimeblock = this.timeblocks[index];\n\n // Filter out the current timeblock from scheduled blocks\n return tasks.filter(task => !task._timeblock_id || !currentTimeblock.id || task._timeblock_id !== currentTimeblock.id);\n },\n getOtherTimeblocksForTimeblock(timeblock, currentIndex) {\n if (!timeblock.date) return [];\n const selectedDate = moment__WEBPACK_IMPORTED_MODULE_9___default()(timeblock.date).format('YYYY-MM-DD');\n return this.timeblocks.filter((tb, idx) => {\n // Skip current timeblock\n if (idx === currentIndex) return false;\n if (!tb.date || !tb.starts_at_time || !tb.ends_at_time) return false;\n const tbDate = moment__WEBPACK_IMPORTED_MODULE_9___default()(tb.date).format('YYYY-MM-DD');\n return tbDate === selectedDate;\n });\n },\n getTimeblockRange(timeblock) {\n const {\n start,\n end\n } = (0,_plugins_tm_utils_timeblock_utils__WEBPACK_IMPORTED_MODULE_13__.timeblockToDateRange)(timeblock);\n return {\n start,\n end\n };\n },\n getCollisionForTimeblock(timeblock, index) {\n const scheduledBlocks = this.getScheduledBlocksForTimeblock(index);\n return (0,_plugins_tm_utils_timeblock_utils__WEBPACK_IMPORTED_MODULE_13__.detectCollision)(timeblock, scheduledBlocks);\n },\n getCollisionSegmentsForTimeblock(timeblock, index) {\n const scheduledBlocks = this.getScheduledBlocksForTimeblock(index);\n return (0,_plugins_tm_utils_timeblock_utils__WEBPACK_IMPORTED_MODULE_13__.getCollisionSegments)(timeblock, scheduledBlocks);\n },\n calculateDuration(timeblock) {\n return (0,_plugins_tm_utils_timeblock_utils__WEBPACK_IMPORTED_MODULE_13__.calculateTimeblockDuration)(timeblock);\n },\n async fetchTimelineDataForTimeblock(index) {\n const timeblock = this.timeblocks[index];\n if (!this.employee?.id || !timeblock.date) {\n this.existingTimeblocksData = {\n ...this.existingTimeblocksData,\n [index]: {\n tasks: [],\n loading: false\n }\n };\n return;\n }\n this.existingTimeblocksData = {\n ...this.existingTimeblocksData,\n [index]: {\n tasks: this.existingTimeblocksData[index]?.tasks || [],\n loading: true\n }\n };\n try {\n const dateStr = moment__WEBPACK_IMPORTED_MODULE_9___default()(timeblock.date).format('YYYY-MM-DD');\n const queryParams = new URLSearchParams({\n start: dateStr,\n end: dateStr,\n employee_id: this.employee.id.toString()\n }).toString();\n const response = await this.$axios.get_auth(`v1/subtasks?${queryParams}`);\n const subtasks = [...(response.subtasks || []), ...(response.blockers || [])];\n const tasks = [];\n subtasks.forEach(subtask => {\n // Check if this is a blocker/adhoc/etc with direct start/end fields (no timeblocks array)\n if (!subtask.timeblocks && subtask.start && subtask.end && ['blocker', 'adhoc', 'home_office', 'vacation', 'free_day', 'office365_blocker'].includes(subtask.type)) {\n const blockerDateStr = moment__WEBPACK_IMPORTED_MODULE_9___default()(subtask.start).format('YYYY-MM-DD');\n if (blockerDateStr === dateStr) {\n const type = subtask.type;\n tasks.push({\n id: subtask.id,\n start: new Date(subtask.start),\n end: new Date(subtask.end),\n master_task: null,\n date: new Date(subtask.start),\n project_code: null,\n subtask: subtask,\n blocker: subtask,\n type,\n _timeblock_id: null,\n _timeblock_is_finished: subtask.is_finished || false,\n _real_start: new Date(subtask.start),\n _real_end: new Date(subtask.end)\n });\n }\n } else {\n // Process regular subtasks with timeblocks array\n subtask.timeblocks?.forEach(tb => {\n const timeblockDateStr = moment__WEBPACK_IMPORTED_MODULE_9___default()(tb.start).format('YYYY-MM-DD');\n if (timeblockDateStr === dateStr) {\n let type = 'subtask';\n if (subtask.type === 'office365') type = 'office365';\n tasks.push({\n id: subtask.id,\n start: new Date(tb.start),\n end: new Date(tb.end),\n master_task: subtask.master_task,\n date: new Date(tb.start),\n project_code: subtask.project_code,\n subtask: subtask,\n blocker: undefined,\n type,\n _timeblock_id: tb.id,\n _timeblock_is_finished: tb.is_finished,\n _real_start: new Date(tb.start),\n _real_end: new Date(tb.end)\n });\n }\n });\n }\n });\n this.existingTimeblocksData = {\n ...this.existingTimeblocksData,\n [index]: {\n tasks,\n loading: false\n }\n };\n } catch (error) {\n console.error('Error fetching timeline data for timeblock:', error);\n this.existingTimeblocksData = {\n ...this.existingTimeblocksData,\n [index]: {\n tasks: [],\n loading: false\n }\n };\n }\n },\n // Fetch timeline data for all existing timeblocks\n async fetchAllTimelinesData() {\n if (!this.employee?.id) return;\n const promises = this.timeblocks.map((_, index) => this.fetchTimelineDataForTimeblock(index));\n await Promise.all(promises);\n },\n formatTimeblockStart(timeblock) {\n // Handle internal format with date and time fields\n if (timeblock.date && timeblock.starts_at_time) {\n const dateStr = moment__WEBPACK_IMPORTED_MODULE_9___default()(timeblock.date).format('DD.MM.yyyy');\n return `${dateStr}, ${timeblock.starts_at_time}`;\n }\n // Fallback to backend format\n if (timeblock.start) {\n return _plugins_tm_utils_tm_utils__WEBPACK_IMPORTED_MODULE_8__[\"default\"].formatDateTime(timeblock.start);\n }\n return '';\n },\n formatTimeblockEnd(timeblock) {\n // Handle internal format with date and time fields\n if (timeblock.date && timeblock.ends_at_time) {\n return timeblock.ends_at_time;\n }\n // Fallback to backend format\n if (timeblock.end) {\n return _plugins_tm_utils_tm_utils__WEBPACK_IMPORTED_MODULE_8__[\"default\"].formatDateTime(timeblock.end);\n }\n return '';\n },\n async submit() {\n const subtask = JSON.parse(JSON.stringify(this.subtask));\n if (!subtask?.timeblocks) {\n subtask.timeblocks = [];\n }\n if (!subtask?.timesheets) {\n subtask.timesheets = [];\n }\n if (!subtask?.is_finished) {\n subtask.is_finished = 0;\n }\n const newTimeblockData = {\n id: null,\n date: this.newTimeblock.date,\n starts_at_time: this.newTimeblock.starts_at_time,\n ends_at_time: this.newTimeblock.ends_at_time,\n is_finished: 0\n };\n\n // For drafts with employees array, add to the correct employee's timeblocks\n if (subtask.is_draft && Array.isArray(subtask.employees)) {\n const employeeIndex = subtask.employees.findIndex(emp => emp.id == this.subtask.employee_id);\n if (employeeIndex !== -1) {\n if (!subtask.employees[employeeIndex].timeblocks) {\n subtask.employees[employeeIndex].timeblocks = [];\n }\n subtask.employees[employeeIndex].timeblocks.push(newTimeblockData);\n }\n } else {\n // For published subtasks, add to root timeblocks\n subtask.timeblocks.push(newTimeblockData);\n }\n if (subtask.deadline) subtask.deadline = _plugins_tm_utils_tm_utils__WEBPACK_IMPORTED_MODULE_8__[\"default\"].formatDateTimeForBackend(this._mergeDeadlineTimeDate());\n const isAfterDeadline = this.isAfterDeadline();\n if (isAfterDeadline) {\n this.visible = true;\n } else {\n if (!subtask.id) {\n this.$emit('update-unfinished-subtask', subtask);\n this.closeModal();\n } else {\n this._update(subtask);\n }\n }\n },\n async confirmSubmit() {\n const subtask = JSON.parse(JSON.stringify(this.subtask));\n if (!subtask?.timeblocks) {\n subtask.timeblocks = [];\n }\n if (!subtask?.timesheets) {\n subtask.timesheets = [];\n }\n if (!subtask?.is_finished) {\n subtask.is_finished = 0;\n }\n const newTimeblockData = {\n id: null,\n date: this.newTimeblock.date,\n starts_at_time: this.newTimeblock.starts_at_time,\n ends_at_time: this.newTimeblock.ends_at_time,\n is_finished: 0\n };\n\n // For drafts with employees array, add to the correct employee's timeblocks\n if (subtask.is_draft && Array.isArray(subtask.employees)) {\n const employeeIndex = subtask.employees.findIndex(emp => emp.id == this.subtask.employee_id);\n if (employeeIndex !== -1) {\n if (!subtask.employees[employeeIndex].timeblocks) {\n subtask.employees[employeeIndex].timeblocks = [];\n }\n subtask.employees[employeeIndex].timeblocks.push(newTimeblockData);\n }\n } else {\n // For published subtasks, add to root timeblocks\n subtask.timeblocks.push(newTimeblockData);\n }\n if (subtask.deadline) subtask.deadline = _plugins_tm_utils_tm_utils__WEBPACK_IMPORTED_MODULE_8__[\"default\"].formatDateTimeForBackend(this._mergeDeadlineTimeDate());\n if (!subtask.id) {\n this.$emit('update-unfinished-subtask', subtask);\n this.closeModal();\n return;\n }\n this.visible = false;\n this._update(subtask);\n },\n async toggleTimeblockIsFinished(originalTimeblock, _index) {\n // Only works for published subtasks with saved timeblocks\n if (!originalTimeblock.id) {\n return;\n }\n const subtask = JSON.parse(JSON.stringify(this.subtask));\n const timeblock = JSON.parse(JSON.stringify(originalTimeblock));\n timeblock.is_finished = timeblock.is_finished == 1 ? 0 : 1;\n try {\n // Convert timeblock to backend format before sending\n const timeblockForBackend = {\n id: timeblock.id,\n is_finished: timeblock.is_finished\n };\n\n // If timeblock is in internal format, convert it\n if (timeblock.date) {\n const dateStr = moment__WEBPACK_IMPORTED_MODULE_9___default()(timeblock.date).format('YYYY-MM-DD');\n timeblockForBackend.start = `${dateStr} ${timeblock.starts_at_time}:00`;\n timeblockForBackend.end = `${dateStr} ${timeblock.ends_at_time}:00`;\n } else {\n // Already in backend format\n timeblockForBackend.start = timeblock.start;\n timeblockForBackend.end = timeblock.end;\n }\n const {\n data: newTimeblock\n } = await this.$axios.put_auth(`v1/timeblocks/${timeblock.id}`, timeblockForBackend);\n\n // Convert returned timeblock from backend format to internal format\n const startMoment = moment__WEBPACK_IMPORTED_MODULE_9___default()(newTimeblock.start, 'YYYY-MM-DD HH:mm:ss');\n const endMoment = moment__WEBPACK_IMPORTED_MODULE_9___default()(newTimeblock.end, 'YYYY-MM-DD HH:mm:ss');\n const convertedTimeblock = {\n id: newTimeblock.id,\n date: startMoment.toDate(),\n starts_at_time: startMoment.format('HH:mm'),\n ends_at_time: endMoment.format('HH:mm'),\n is_finished: newTimeblock.is_finished\n };\n\n // Update timeblock in correct location (employee's array for drafts, root for published)\n if (subtask.is_draft && Array.isArray(subtask.employees)) {\n const employeeIndex = subtask.employees.findIndex(emp => emp.id == this.subtask.employee_id);\n if (employeeIndex !== -1) {\n subtask.employees[employeeIndex].timeblocks = subtask.employees[employeeIndex].timeblocks.map(tb => {\n if (tb.id == convertedTimeblock.id) return convertedTimeblock;\n return tb;\n });\n }\n } else {\n subtask.timeblocks = subtask.timeblocks.map(tb => {\n if (tb.id == convertedTimeblock.id) return convertedTimeblock;\n return tb;\n });\n }\n this.$events.emit('on-subtask-edited', subtask);\n this.$emit('update-subtask', subtask);\n if (timeblock.is_finished) this.$events.emit('show-task-add-time-modal', {\n subtask\n });\n } catch (error) {\n this.$toast.error(error.message || error);\n }\n },\n async deleteTimeblock({\n id\n }) {\n const subtask = JSON.parse(JSON.stringify(this.subtask));\n\n // Remove timeblock from correct location (employee's array for drafts, root for published)\n if (subtask.is_draft && Array.isArray(subtask.employees)) {\n // Find which employee this timeblock belongs to by searching through all employees\n let found = false;\n subtask.employees = subtask.employees.map(emp => {\n if (!emp.timeblocks) return emp;\n\n // Check if this employee has the timeblock\n const hasTimeblock = emp.timeblocks.some(tb => tb.id == id);\n if (hasTimeblock) {\n found = true;\n return {\n ...emp,\n timeblocks: emp.timeblocks.filter(tb => tb.id != id)\n };\n }\n return emp;\n });\n if (!found) {\n console.warn('Timeblock not found in any employee', id);\n }\n } else {\n subtask.timeblocks = subtask.timeblocks.filter(timeblock => timeblock.id != id);\n }\n if (subtask.deadline) subtask.deadline = _plugins_tm_utils_tm_utils__WEBPACK_IMPORTED_MODULE_8__[\"default\"].formatDateTimeForBackend(this._mergeDeadlineTimeDate());\n this._update(subtask);\n },\n async deleteTimeblockByIndex(index) {\n const subtask = JSON.parse(JSON.stringify(this.subtask));\n\n // Remove timeblock by index from correct location\n if (subtask.is_draft && Array.isArray(subtask.employees)) {\n const employeeIndex = subtask.employees.findIndex(emp => emp.id == this.subtask.employee_id);\n if (employeeIndex !== -1 && subtask.employees[employeeIndex].timeblocks) {\n subtask.employees[employeeIndex].timeblocks.splice(index, 1);\n }\n } else {\n subtask.timeblocks.splice(index, 1);\n }\n if (subtask.deadline) subtask.deadline = _plugins_tm_utils_tm_utils__WEBPACK_IMPORTED_MODULE_8__[\"default\"].formatDateTimeForBackend(this._mergeDeadlineTimeDate());\n if (!subtask.id) {\n this.$emit('update-unfinished-subtask', subtask);\n } else {\n this._update(subtask);\n }\n },\n async _update(data) {\n try {\n const timesheets = data.timesheets.map(timesheet => {\n delete timesheet.employee_name;\n return timesheet;\n });\n const payload = {\n ...data,\n timesheets\n };\n\n // For drafts with employees array, properly structure the employees with their timeblocks\n if (data.is_draft && Array.isArray(data.employees)) {\n const validEmployees = data.employees.filter(emp => emp.id).map(emp => ({\n id: emp.id,\n duration: emp.duration,\n // Convert employee timeblocks to BE format\n timeblocks: (emp.timeblocks || []).filter(tb => tb.date || tb.start).map(tb => {\n if (tb.start && !tb.date) {\n return {\n id: tb.id || null,\n start: tb.start,\n end: tb.end,\n is_finished: tb.is_finished || 0\n };\n }\n const dateStr = moment__WEBPACK_IMPORTED_MODULE_9___default()(tb.date).format('YYYY-MM-DD');\n return {\n id: tb.id || null,\n start: `${dateStr} ${tb.starts_at_time}:00`,\n end: `${dateStr} ${tb.ends_at_time}:00`,\n is_finished: tb.is_finished || 0\n };\n })\n }));\n payload.employees = validEmployees;\n // For drafts, don't send root-level timeblocks\n delete payload.timeblocks;\n } else {\n // For published subtasks, convert and send root-level timeblocks\n const timeblocks = (data.timeblocks || []).filter(timeblock => {\n // Filter timeblocks that have either old format (date) or new format (start)\n return timeblock.date || timeblock.start;\n }).map(timeblock => {\n // If already in BE format (has start field), return as is\n if (timeblock.start && !timeblock.date) {\n return {\n id: timeblock.id || null,\n start: timeblock.start,\n end: timeblock.end,\n is_finished: timeblock.is_finished || 0\n };\n }\n\n // Convert from internal format to BE format\n const dateStr = moment__WEBPACK_IMPORTED_MODULE_9___default()(timeblock.date).format('YYYY-MM-DD');\n return {\n id: timeblock.id || null,\n start: `${dateStr} ${timeblock.starts_at_time}:00`,\n end: `${dateStr} ${timeblock.ends_at_time}:00`,\n is_finished: timeblock.is_finished || 0\n };\n });\n payload.timeblocks = timeblocks;\n }\n\n // Remove UI-only enriched fields\n delete payload._created_by;\n delete payload._employee;\n delete payload._master_task;\n delete payload._deadline_time;\n const {\n subtask\n } = await this.$axios.put_auth(`v1/subtasks/${data.id}`, payload);\n this.closeModal();\n this.$events.emit('on-subtask-edited', subtask);\n } catch (error) {\n this.$toast.error(error.message || error);\n }\n },\n isAfterDeadline() {\n const deadline = this.getDeadline(this.subtask);\n if (!deadline) return;\n const mDate = moment__WEBPACK_IMPORTED_MODULE_9___default()(this.newTimeblock.date);\n const mDeadline = moment__WEBPACK_IMPORTED_MODULE_9___default()(deadline);\n const [hours, minutes] = this.newTimeblock.ends_at_time.split(':').map(Number);\n mDate.hours(hours);\n mDate.minutes(minutes);\n return mDate.isAfter(mDeadline);\n },\n getDeadline(subtask) {\n if (subtask?.deadline) return subtask.deadline;\n return subtask.master_task_deadline;\n },\n _mergeDeadlineTimeDate() {\n const date = new Date(this.subtask.deadline);\n const timeParts = this.subtask._deadline_time.split(':');\n date.setHours(parseInt(timeParts[0]));\n date.setMinutes(parseInt(timeParts[1]));\n return date;\n },\n closeModal() {\n // Reset newTimeblock\n this.newTimeblock = {\n id: null,\n date: new Date(),\n starts_at_time: null,\n ends_at_time: null,\n employee_id: this.employee?.id || null\n };\n this.showModal = false;\n }\n }\n});\n\n//# sourceURL=webpack://jandl/./src/plugins/tm@modal/task/_components/_components/a-task-timeblocks.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}"); /***/ }), @@ -466,7 +466,7 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var cor /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_esnext_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/esnext.iterator.constructor.js */ \"./node_modules/core-js/modules/esnext.iterator.constructor.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_esnext_iterator_filter_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/esnext.iterator.filter.js */ \"./node_modules/core-js/modules/esnext.iterator.filter.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_filter_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_filter_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var core_js_modules_esnext_iterator_find_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! core-js/modules/esnext.iterator.find.js */ \"./node_modules/core-js/modules/esnext.iterator.find.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_find_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_find_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var core_js_modules_esnext_iterator_map_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! core-js/modules/esnext.iterator.map.js */ \"./node_modules/core-js/modules/esnext.iterator.map.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_map_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_map_js__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var _components_a_mastertask_name_vue__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./_components/a-mastertask-name.vue */ \"./src/plugins/tm@modal/task/_components/_components/a-mastertask-name.vue\");\n/* harmony import */ var _components_a_mastertask_status_vue__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./_components/a-mastertask-status.vue */ \"./src/plugins/tm@modal/task/_components/_components/a-mastertask-status.vue\");\n/* harmony import */ var _components_a_task_timeblocks_vue__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./_components/a-task-timeblocks.vue */ \"./src/plugins/tm@modal/task/_components/_components/a-task-timeblocks.vue\");\n/* harmony import */ var _components_read_only_z_created_by_vue__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../_components/read-only/z-created-by.vue */ \"./src/plugins/tm@modal/_components/read-only/z-created-by.vue\");\n/* harmony import */ var _components_a_task_assigned_employee_vue__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./_components/a-task-assigned-employee.vue */ \"./src/plugins/tm@modal/task/_components/_components/a-task-assigned-employee.vue\");\n/* harmony import */ var _components_a_task_planned_time_vue__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./_components/a-task-planned-time.vue */ \"./src/plugins/tm@modal/task/_components/_components/a-task-planned-time.vue\");\n/* harmony import */ var _components_a_task_spent_time_vue__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./_components/a-task-spent-time.vue */ \"./src/plugins/tm@modal/task/_components/_components/a-task-spent-time.vue\");\n/* harmony import */ var _components_a_task_remaining_time_vue__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./_components/a-task-remaining-time.vue */ \"./src/plugins/tm@modal/task/_components/_components/a-task-remaining-time.vue\");\n/* harmony import */ var _components_a_task_deadline_vue__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./_components/a-task-deadline.vue */ \"./src/plugins/tm@modal/task/_components/_components/a-task-deadline.vue\");\n/* harmony import */ var _components_a_task_description_vue__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./_components/a-task-description.vue */ \"./src/plugins/tm@modal/task/_components/_components/a-task-description.vue\");\n/* harmony import */ var _plugins_tm_modal_components_read_only_z_files_vue__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! @/plugins/tm@modal/_components/read-only/z-files.vue */ \"./src/plugins/tm@modal/_components/read-only/z-files.vue\");\n/* harmony import */ var vuex__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! vuex */ \"./node_modules/vuex/dist/vuex.esm-bundler.js\");\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n components: {\n ZFiles: _plugins_tm_modal_components_read_only_z_files_vue__WEBPACK_IMPORTED_MODULE_14__[\"default\"],\n AMastertaskName: _components_a_mastertask_name_vue__WEBPACK_IMPORTED_MODULE_4__[\"default\"],\n AMastertaskStatus: _components_a_mastertask_status_vue__WEBPACK_IMPORTED_MODULE_5__[\"default\"],\n ATaskTimeblocks: _components_a_task_timeblocks_vue__WEBPACK_IMPORTED_MODULE_6__[\"default\"],\n ZCreatedBy: _components_read_only_z_created_by_vue__WEBPACK_IMPORTED_MODULE_7__[\"default\"],\n ATaskAssignedEmployee: _components_a_task_assigned_employee_vue__WEBPACK_IMPORTED_MODULE_8__[\"default\"],\n ATaskPlannedTime: _components_a_task_planned_time_vue__WEBPACK_IMPORTED_MODULE_9__[\"default\"],\n ATaskSpentTime: _components_a_task_spent_time_vue__WEBPACK_IMPORTED_MODULE_10__[\"default\"],\n ATaskRemainingTime: _components_a_task_remaining_time_vue__WEBPACK_IMPORTED_MODULE_11__[\"default\"],\n ATaskDescription: _components_a_task_description_vue__WEBPACK_IMPORTED_MODULE_13__[\"default\"],\n ATaskDeadline: _components_a_task_deadline_vue__WEBPACK_IMPORTED_MODULE_12__[\"default\"]\n },\n props: {\n subtask: {\n type: Object,\n required: true\n }\n },\n emits: ['close-modal', 'update-subtask'],\n computed: {\n ...(0,vuex__WEBPACK_IMPORTED_MODULE_15__.mapGetters)('tm', ['enrichedEmployees']),\n normalizedEmployees() {\n // Draft with multiple employees\n if (this.subtask.is_draft && Array.isArray(this.subtask.employees)) {\n return this.subtask.employees.filter(emp => emp.id) // Filter out empty employee slots\n .map(emp => ({\n id: emp.id,\n duration: emp.duration || 0,\n timeblocks: emp.timeblocks || [],\n _employee: this.enrichedEmployees.find(e => e.id == emp.id) || {}\n }));\n }\n\n // Single employee (published subtask)\n return [{\n id: this.subtask.employee_id,\n duration: this.subtask.duration,\n timeblocks: this.subtask.timeblocks || [],\n _employee: this.subtask._employee\n }];\n },\n hasMultipleEmployees() {\n return this.normalizedEmployees.length > 1;\n }\n }\n});\n\n//# sourceURL=webpack://jandl/./src/plugins/tm@modal/task/_components/z-task-readonly-info.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}"); +eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_esnext_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/esnext.iterator.constructor.js */ \"./node_modules/core-js/modules/esnext.iterator.constructor.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_esnext_iterator_filter_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/esnext.iterator.filter.js */ \"./node_modules/core-js/modules/esnext.iterator.filter.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_filter_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_filter_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var core_js_modules_esnext_iterator_find_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! core-js/modules/esnext.iterator.find.js */ \"./node_modules/core-js/modules/esnext.iterator.find.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_find_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_find_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var core_js_modules_esnext_iterator_map_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! core-js/modules/esnext.iterator.map.js */ \"./node_modules/core-js/modules/esnext.iterator.map.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_map_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_map_js__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var _components_a_mastertask_name_vue__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./_components/a-mastertask-name.vue */ \"./src/plugins/tm@modal/task/_components/_components/a-mastertask-name.vue\");\n/* harmony import */ var _components_a_mastertask_status_vue__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./_components/a-mastertask-status.vue */ \"./src/plugins/tm@modal/task/_components/_components/a-mastertask-status.vue\");\n/* harmony import */ var _components_a_task_timeblocks_vue__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./_components/a-task-timeblocks.vue */ \"./src/plugins/tm@modal/task/_components/_components/a-task-timeblocks.vue\");\n/* harmony import */ var _components_read_only_z_created_by_vue__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../_components/read-only/z-created-by.vue */ \"./src/plugins/tm@modal/_components/read-only/z-created-by.vue\");\n/* harmony import */ var _components_a_task_assigned_employee_vue__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./_components/a-task-assigned-employee.vue */ \"./src/plugins/tm@modal/task/_components/_components/a-task-assigned-employee.vue\");\n/* harmony import */ var _components_a_task_planned_time_vue__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./_components/a-task-planned-time.vue */ \"./src/plugins/tm@modal/task/_components/_components/a-task-planned-time.vue\");\n/* harmony import */ var _components_a_task_spent_time_vue__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./_components/a-task-spent-time.vue */ \"./src/plugins/tm@modal/task/_components/_components/a-task-spent-time.vue\");\n/* harmony import */ var _components_a_task_remaining_time_vue__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./_components/a-task-remaining-time.vue */ \"./src/plugins/tm@modal/task/_components/_components/a-task-remaining-time.vue\");\n/* harmony import */ var _components_a_task_deadline_vue__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./_components/a-task-deadline.vue */ \"./src/plugins/tm@modal/task/_components/_components/a-task-deadline.vue\");\n/* harmony import */ var _components_a_task_description_vue__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./_components/a-task-description.vue */ \"./src/plugins/tm@modal/task/_components/_components/a-task-description.vue\");\n/* harmony import */ var _plugins_tm_modal_components_read_only_z_files_vue__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! @/plugins/tm@modal/_components/read-only/z-files.vue */ \"./src/plugins/tm@modal/_components/read-only/z-files.vue\");\n/* harmony import */ var vuex__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! vuex */ \"./node_modules/vuex/dist/vuex.esm-bundler.js\");\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n components: {\n ZFiles: _plugins_tm_modal_components_read_only_z_files_vue__WEBPACK_IMPORTED_MODULE_14__[\"default\"],\n AMastertaskName: _components_a_mastertask_name_vue__WEBPACK_IMPORTED_MODULE_4__[\"default\"],\n AMastertaskStatus: _components_a_mastertask_status_vue__WEBPACK_IMPORTED_MODULE_5__[\"default\"],\n ATaskTimeblocks: _components_a_task_timeblocks_vue__WEBPACK_IMPORTED_MODULE_6__[\"default\"],\n ZCreatedBy: _components_read_only_z_created_by_vue__WEBPACK_IMPORTED_MODULE_7__[\"default\"],\n ATaskAssignedEmployee: _components_a_task_assigned_employee_vue__WEBPACK_IMPORTED_MODULE_8__[\"default\"],\n ATaskPlannedTime: _components_a_task_planned_time_vue__WEBPACK_IMPORTED_MODULE_9__[\"default\"],\n ATaskSpentTime: _components_a_task_spent_time_vue__WEBPACK_IMPORTED_MODULE_10__[\"default\"],\n ATaskRemainingTime: _components_a_task_remaining_time_vue__WEBPACK_IMPORTED_MODULE_11__[\"default\"],\n ATaskDescription: _components_a_task_description_vue__WEBPACK_IMPORTED_MODULE_13__[\"default\"],\n ATaskDeadline: _components_a_task_deadline_vue__WEBPACK_IMPORTED_MODULE_12__[\"default\"]\n },\n props: {\n subtask: {\n type: Object,\n required: true\n }\n },\n emits: ['close-modal', 'update-subtask'],\n computed: {\n ...(0,vuex__WEBPACK_IMPORTED_MODULE_15__.mapGetters)('tm', ['enrichedEmployees']),\n normalizedEmployees() {\n // Drafts always have employees array\n if (this.subtask.is_draft && Array.isArray(this.subtask.employees)) {\n return this.subtask.employees.filter(emp => emp.id) // Filter out empty employee slots\n .map(emp => ({\n id: emp.id,\n duration: emp.duration || 0,\n timeblocks: emp.timeblocks || [],\n _employee: this.enrichedEmployees.find(e => e.id == emp.id) || {}\n }));\n }\n\n // Published subtask - single employee format\n return [{\n id: this.subtask.employee_id,\n duration: this.subtask.duration,\n timeblocks: this.subtask.timeblocks || [],\n _employee: this.subtask._employee\n }];\n },\n hasMultipleEmployees() {\n // For drafts, always use multi-employee styling (even with 1 employee)\n if (this.subtask.is_draft) {\n return true;\n }\n // For published subtasks, check actual count\n return this.normalizedEmployees.length > 1;\n }\n }\n});\n\n//# sourceURL=webpack://jandl/./src/plugins/tm@modal/task/_components/z-task-readonly-info.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}"); /***/ }), @@ -532,7 +532,7 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _pl /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.array.push.js */ \"./node_modules/core-js/modules/es.array.push.js\");\n/* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_esnext_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/esnext.iterator.constructor.js */ \"./node_modules/core-js/modules/esnext.iterator.constructor.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var core_js_modules_esnext_iterator_filter_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! core-js/modules/esnext.iterator.filter.js */ \"./node_modules/core-js/modules/esnext.iterator.filter.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_filter_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_filter_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var core_js_modules_esnext_iterator_map_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! core-js/modules/esnext.iterator.map.js */ \"./node_modules/core-js/modules/esnext.iterator.map.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_map_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_map_js__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var _plugins_lib_auth_utils_error_utils__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @/plugins/lib@auth/_utils/error.utils */ \"./src/plugins/lib@auth/_utils/error.utils.ts\");\n/* harmony import */ var _vuelidate_core__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @vuelidate/core */ \"./node_modules/@vuelidate/core/dist/index.esm.js\");\n/* harmony import */ var _vuelidate_validators__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @vuelidate/validators */ \"./node_modules/@vuelidate/validators/dist/index.esm.js\");\n/* harmony import */ var _plugins_tm_modal_mixins_modal_mixin__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @/plugins/tm@modal/_mixins/modal.mixin */ \"./src/plugins/tm@modal/_mixins/modal.mixin.ts\");\n/* harmony import */ var _plugins_tm_utils_tm_utils__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @/plugins/tm@_utils/tm.utils */ \"./src/plugins/tm@_utils/tm.utils.ts\");\n/* harmony import */ var moment__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! moment */ \"./node_modules/moment/moment.js\");\n/* harmony import */ var moment__WEBPACK_IMPORTED_MODULE_9___default = /*#__PURE__*/__webpack_require__.n(moment__WEBPACK_IMPORTED_MODULE_9__);\n/* harmony import */ var _plugins_tm_modal_components_a_resize_handle_vue__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @/plugins/tm@modal/_components/a-resize-handle.vue */ \"./src/plugins/tm@modal/_components/a-resize-handle.vue\");\n/* harmony import */ var _plugins_tm_modal_components_a_reset_size_button_vue__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! @/plugins/tm@modal/_components/a-reset-size-button.vue */ \"./src/plugins/tm@modal/_components/a-reset-size-button.vue\");\n/* harmony import */ var _plugins_tm_modal_components_a_close_button_vue__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! @/plugins/tm@modal/_components/a-close-button.vue */ \"./src/plugins/tm@modal/_components/a-close-button.vue\");\n\n\n\n\n\n\n\n\n\n\n\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n components: {\n AResizeHandle: _plugins_tm_modal_components_a_resize_handle_vue__WEBPACK_IMPORTED_MODULE_10__[\"default\"],\n AResetSizeButton: _plugins_tm_modal_components_a_reset_size_button_vue__WEBPACK_IMPORTED_MODULE_11__[\"default\"],\n ACloseButton: _plugins_tm_modal_components_a_close_button_vue__WEBPACK_IMPORTED_MODULE_12__[\"default\"]\n },\n mixins: [_plugins_tm_modal_mixins_modal_mixin__WEBPACK_IMPORTED_MODULE_7__[\"default\"]],\n emits: ['close', 'on-subtask-edited'],\n data() {\n return {\n v$: (0,_vuelidate_core__WEBPACK_IMPORTED_MODULE_5__[\"default\"])(),\n errorUtils: _plugins_lib_auth_utils_error_utils__WEBPACK_IMPORTED_MODULE_4__[\"default\"],\n visible: false,\n subtask: null,\n form: {\n hours: null\n },\n modalName: 'z-task-add-time-modal',\n modalSize: 'medium'\n };\n },\n validations() {\n return {\n form: {\n hours: {\n required: _vuelidate_validators__WEBPACK_IMPORTED_MODULE_6__.required,\n numeric: _vuelidate_validators__WEBPACK_IMPORTED_MODULE_6__.numeric,\n minValue: (0,_vuelidate_validators__WEBPACK_IMPORTED_MODULE_6__.minValue)(0.1)\n }\n }\n };\n },\n methods: {\n async showModal({\n subtask\n }) {\n this.subtask = subtask;\n this.visible = true;\n this.form.hours = null;\n this.$nextTick(() => this.v$.$reset());\n },\n async submit() {\n if (!(await this.v$.$validate())) return;\n if (this.subtask.deadline) this.subtask.deadline = _plugins_tm_utils_tm_utils__WEBPACK_IMPORTED_MODULE_8__[\"default\"].formatDateTimeForBackend(this.subtask.deadline);\n this.subtask.timesheets.push({\n id: null,\n employee_id: this.subtask.employee_id,\n time: typeof this.form.hours == 'string' ? parseFloat(this.form.hours) : this.form.hours\n });\n const timesheets = this.subtask.timesheets.map(timesheet => {\n delete timesheet.employee_name;\n return timesheet;\n });\n\n // Convert timeblocks from internal format to BE format\n const timeblocks = (this.subtask.timeblocks || []).filter(timeblock => {\n // Filter timeblocks that have either old format (date) or new format (start)\n return timeblock.date || timeblock.start;\n }).map(timeblock => {\n // If already in BE format (has start field), return as is\n if (timeblock.start && !timeblock.date) {\n return {\n id: timeblock.id || null,\n start: timeblock.start,\n end: timeblock.end,\n is_finished: timeblock.is_finished || 0\n };\n }\n\n // Convert from internal format to BE format\n const dateStr = moment__WEBPACK_IMPORTED_MODULE_9___default()(timeblock.date).format('YYYY-MM-DD');\n return {\n id: timeblock.id || null,\n start: `${dateStr} ${timeblock.starts_at_time}:00`,\n end: `${dateStr} ${timeblock.ends_at_time}:00`,\n is_finished: timeblock.is_finished || 0\n };\n });\n const payload = {\n ...this.subtask,\n timesheets,\n timeblocks\n };\n try {\n const {\n subtask\n } = await this.$axios.put_auth(`v1/subtasks/${this.subtask.id}`, payload);\n this.closeModal();\n this.$events.emit('on-subtask-edited', subtask);\n } catch (error) {\n this.$toast.error(error.message || error);\n }\n },\n closeModal() {\n this.visible = false;\n this.v$.$reset();\n }\n }\n});\n\n//# sourceURL=webpack://jandl/./src/plugins/tm@modal/task/z-task-add-time-modal.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}"); +eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.array.push.js */ \"./node_modules/core-js/modules/es.array.push.js\");\n/* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_esnext_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/esnext.iterator.constructor.js */ \"./node_modules/core-js/modules/esnext.iterator.constructor.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var core_js_modules_esnext_iterator_filter_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! core-js/modules/esnext.iterator.filter.js */ \"./node_modules/core-js/modules/esnext.iterator.filter.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_filter_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_filter_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var core_js_modules_esnext_iterator_map_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! core-js/modules/esnext.iterator.map.js */ \"./node_modules/core-js/modules/esnext.iterator.map.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_map_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_map_js__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var _plugins_lib_auth_utils_error_utils__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @/plugins/lib@auth/_utils/error.utils */ \"./src/plugins/lib@auth/_utils/error.utils.ts\");\n/* harmony import */ var _vuelidate_core__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @vuelidate/core */ \"./node_modules/@vuelidate/core/dist/index.esm.js\");\n/* harmony import */ var _vuelidate_validators__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @vuelidate/validators */ \"./node_modules/@vuelidate/validators/dist/index.esm.js\");\n/* harmony import */ var _plugins_tm_modal_mixins_modal_mixin__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @/plugins/tm@modal/_mixins/modal.mixin */ \"./src/plugins/tm@modal/_mixins/modal.mixin.ts\");\n/* harmony import */ var _plugins_tm_utils_tm_utils__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @/plugins/tm@_utils/tm.utils */ \"./src/plugins/tm@_utils/tm.utils.ts\");\n/* harmony import */ var moment__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! moment */ \"./node_modules/moment/moment.js\");\n/* harmony import */ var moment__WEBPACK_IMPORTED_MODULE_9___default = /*#__PURE__*/__webpack_require__.n(moment__WEBPACK_IMPORTED_MODULE_9__);\n/* harmony import */ var _plugins_tm_modal_components_a_resize_handle_vue__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @/plugins/tm@modal/_components/a-resize-handle.vue */ \"./src/plugins/tm@modal/_components/a-resize-handle.vue\");\n/* harmony import */ var _plugins_tm_modal_components_a_reset_size_button_vue__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! @/plugins/tm@modal/_components/a-reset-size-button.vue */ \"./src/plugins/tm@modal/_components/a-reset-size-button.vue\");\n/* harmony import */ var _plugins_tm_modal_components_a_close_button_vue__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! @/plugins/tm@modal/_components/a-close-button.vue */ \"./src/plugins/tm@modal/_components/a-close-button.vue\");\n\n\n\n\n\n\n\n\n\n\n\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n components: {\n AResizeHandle: _plugins_tm_modal_components_a_resize_handle_vue__WEBPACK_IMPORTED_MODULE_10__[\"default\"],\n AResetSizeButton: _plugins_tm_modal_components_a_reset_size_button_vue__WEBPACK_IMPORTED_MODULE_11__[\"default\"],\n ACloseButton: _plugins_tm_modal_components_a_close_button_vue__WEBPACK_IMPORTED_MODULE_12__[\"default\"]\n },\n mixins: [_plugins_tm_modal_mixins_modal_mixin__WEBPACK_IMPORTED_MODULE_7__[\"default\"]],\n emits: ['close', 'on-subtask-edited'],\n data() {\n return {\n v$: (0,_vuelidate_core__WEBPACK_IMPORTED_MODULE_5__[\"default\"])(),\n errorUtils: _plugins_lib_auth_utils_error_utils__WEBPACK_IMPORTED_MODULE_4__[\"default\"],\n visible: false,\n subtask: null,\n form: {\n hours: null\n },\n modalName: 'z-task-add-time-modal',\n modalSize: 'medium'\n };\n },\n validations() {\n return {\n form: {\n hours: {\n required: _vuelidate_validators__WEBPACK_IMPORTED_MODULE_6__.required,\n numeric: _vuelidate_validators__WEBPACK_IMPORTED_MODULE_6__.numeric,\n minValue: (0,_vuelidate_validators__WEBPACK_IMPORTED_MODULE_6__.minValue)(0.1)\n }\n }\n };\n },\n methods: {\n async showModal({\n subtask\n }) {\n // Prevent using this modal for drafts - they should be edited instead\n if (subtask.is_draft) {\n this.$toast.info('Pre koncepty použite režim úprav');\n return;\n }\n this.subtask = subtask;\n this.visible = true;\n this.form.hours = null;\n this.$nextTick(() => this.v$.$reset());\n },\n async submit() {\n if (!(await this.v$.$validate())) return;\n if (this.subtask.deadline) this.subtask.deadline = _plugins_tm_utils_tm_utils__WEBPACK_IMPORTED_MODULE_8__[\"default\"].formatDateTimeForBackend(this.subtask.deadline);\n this.subtask.timesheets.push({\n id: null,\n employee_id: this.subtask.employee_id,\n time: typeof this.form.hours == 'string' ? parseFloat(this.form.hours) : this.form.hours\n });\n const timesheets = this.subtask.timesheets.map(timesheet => {\n delete timesheet.employee_name;\n return timesheet;\n });\n\n // Convert timeblocks from internal format to BE format\n const timeblocks = (this.subtask.timeblocks || []).filter(timeblock => {\n // Filter timeblocks that have either old format (date) or new format (start)\n return timeblock.date || timeblock.start;\n }).map(timeblock => {\n // If already in BE format (has start field), return as is\n if (timeblock.start && !timeblock.date) {\n return {\n id: timeblock.id || null,\n start: timeblock.start,\n end: timeblock.end,\n is_finished: timeblock.is_finished || 0\n };\n }\n\n // Convert from internal format to BE format\n const dateStr = moment__WEBPACK_IMPORTED_MODULE_9___default()(timeblock.date).format('YYYY-MM-DD');\n return {\n id: timeblock.id || null,\n start: `${dateStr} ${timeblock.starts_at_time}:00`,\n end: `${dateStr} ${timeblock.ends_at_time}:00`,\n is_finished: timeblock.is_finished || 0\n };\n });\n const payload = {\n ...this.subtask,\n timesheets,\n timeblocks\n };\n try {\n const {\n subtask\n } = await this.$axios.put_auth(`v1/subtasks/${this.subtask.id}`, payload);\n this.closeModal();\n this.$events.emit('on-subtask-edited', subtask);\n } catch (error) {\n this.$toast.error(error.message || error);\n }\n },\n closeModal() {\n this.visible = false;\n this.v$.$reset();\n }\n }\n});\n\n//# sourceURL=webpack://jandl/./src/plugins/tm@modal/task/z-task-add-time-modal.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}"); /***/ }), @@ -543,7 +543,7 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var cor /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.array.push.js */ \"./node_modules/core-js/modules/es.array.push.js\");\n/* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_es_json_stringify_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/es.json.stringify.js */ \"./node_modules/core-js/modules/es.json.stringify.js\");\n/* harmony import */ var core_js_modules_es_json_stringify_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_json_stringify_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var core_js_modules_esnext_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! core-js/modules/esnext.iterator.constructor.js */ \"./node_modules/core-js/modules/esnext.iterator.constructor.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var core_js_modules_esnext_iterator_filter_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! core-js/modules/esnext.iterator.filter.js */ \"./node_modules/core-js/modules/esnext.iterator.filter.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_filter_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_filter_js__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var core_js_modules_esnext_iterator_find_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! core-js/modules/esnext.iterator.find.js */ \"./node_modules/core-js/modules/esnext.iterator.find.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_find_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_find_js__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var core_js_modules_esnext_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! core-js/modules/esnext.iterator.for-each.js */ \"./node_modules/core-js/modules/esnext.iterator.for-each.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_5__);\n/* harmony import */ var core_js_modules_esnext_iterator_map_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! core-js/modules/esnext.iterator.map.js */ \"./node_modules/core-js/modules/esnext.iterator.map.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_map_js__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_map_js__WEBPACK_IMPORTED_MODULE_6__);\n/* harmony import */ var core_js_modules_esnext_iterator_some_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! core-js/modules/esnext.iterator.some.js */ \"./node_modules/core-js/modules/esnext.iterator.some.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_some_js__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_some_js__WEBPACK_IMPORTED_MODULE_7__);\n/* harmony import */ var _plugins_tm_components_z_datepicker_vue__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @/plugins/tm@_components/z-datepicker.vue */ \"./src/plugins/tm@_components/z-datepicker.vue\");\n/* harmony import */ var _plugins_tm_components_z_files_upload_vue__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @/plugins/tm@_components/z-files-upload.vue */ \"./src/plugins/tm@_components/z-files-upload.vue\");\n/* harmony import */ var _vuelidate_core__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @vuelidate/core */ \"./node_modules/@vuelidate/core/dist/index.esm.js\");\n/* harmony import */ var _vuelidate_validators__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! @vuelidate/validators */ \"./node_modules/@vuelidate/validators/dist/index.esm.js\");\n/* harmony import */ var _plugins_lib_auth_utils_error_utils__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! @/plugins/lib@auth/_utils/error.utils */ \"./src/plugins/lib@auth/_utils/error.utils.ts\");\n/* harmony import */ var _vueup_vue_quill__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! @vueup/vue-quill */ \"./node_modules/@vueup/vue-quill/dist/vue-quill.esm-bundler.js\");\n/* harmony import */ var _master_task_mixins_selects_mixin__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ../master-task/_mixins/selects.mixin */ \"./src/plugins/tm@modal/master-task/_mixins/selects.mixin.ts\");\n/* harmony import */ var _plugins_tm_utils_tm_utils__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! @/plugins/tm@_utils/tm.utils */ \"./src/plugins/tm@_utils/tm.utils.ts\");\n/* harmony import */ var moment__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! moment */ \"./node_modules/moment/moment.js\");\n/* harmony import */ var moment__WEBPACK_IMPORTED_MODULE_16___default = /*#__PURE__*/__webpack_require__.n(moment__WEBPACK_IMPORTED_MODULE_16__);\n/* harmony import */ var _vueup_vue_quill_dist_vue_quill_snow_css__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! @vueup/vue-quill/dist/vue-quill.snow.css */ \"./node_modules/@vueup/vue-quill/dist/vue-quill.snow.css\");\n/* harmony import */ var _vueup_vue_quill_dist_vue_quill_snow_css__WEBPACK_IMPORTED_MODULE_17___default = /*#__PURE__*/__webpack_require__.n(_vueup_vue_quill_dist_vue_quill_snow_css__WEBPACK_IMPORTED_MODULE_17__);\n/* harmony import */ var _plugins_tm_mixins_autocomplete_mixin__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! @/plugins/tm@_mixins/autocomplete.mixin */ \"./src/plugins/tm@_mixins/autocomplete.mixin.ts\");\n/* harmony import */ var _components_z_task_readonly_info_vue__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ./_components/z-task-readonly-info.vue */ \"./src/plugins/tm@modal/task/_components/z-task-readonly-info.vue\");\n/* harmony import */ var _components_employees_a_employee_vue__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ./_components/employees/a-employee.vue */ \"./src/plugins/tm@modal/task/_components/employees/a-employee.vue\");\n/* harmony import */ var vuex__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! vuex */ \"./node_modules/vuex/dist/vuex.esm-bundler.js\");\n/* harmony import */ var _plugins_tm_modal_mixins_modal_mixin__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! @/plugins/tm@modal/_mixins/modal.mixin */ \"./src/plugins/tm@modal/_mixins/modal.mixin.ts\");\n/* harmony import */ var _plugins_tm_modal_components_a_resize_handle_vue__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! @/plugins/tm@modal/_components/a-resize-handle.vue */ \"./src/plugins/tm@modal/_components/a-resize-handle.vue\");\n/* harmony import */ var _plugins_tm_modal_components_a_reset_size_button_vue__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! @/plugins/tm@modal/_components/a-reset-size-button.vue */ \"./src/plugins/tm@modal/_components/a-reset-size-button.vue\");\n/* harmony import */ var _plugins_tm_modal_components_a_close_button_vue__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! @/plugins/tm@modal/_components/a-close-button.vue */ \"./src/plugins/tm@modal/_components/a-close-button.vue\");\n/* harmony import */ var _z_remove_employee_modal_vue__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! ./z-remove-employee-modal.vue */ \"./src/plugins/tm@modal/task/z-remove-employee-modal.vue\");\n/* harmony import */ var _z_remove_timeblock_modal_vue__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(/*! ./z-remove-timeblock-modal.vue */ \"./src/plugins/tm@modal/task/z-remove-timeblock-modal.vue\");\n/* provided dependency */ var console = __webpack_require__(/*! ./node_modules/console-browserify/index.js */ \"./node_modules/console-browserify/index.js\");\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n components: {\n ZTaskReadonlyInfo: _components_z_task_readonly_info_vue__WEBPACK_IMPORTED_MODULE_19__[\"default\"],\n AEmployee: _components_employees_a_employee_vue__WEBPACK_IMPORTED_MODULE_20__[\"default\"],\n ZFilesUpload: _plugins_tm_components_z_files_upload_vue__WEBPACK_IMPORTED_MODULE_9__[\"default\"],\n ZDatepicker: _plugins_tm_components_z_datepicker_vue__WEBPACK_IMPORTED_MODULE_8__[\"default\"],\n // ATaskTimeblocks,\n QuillEditor: _vueup_vue_quill__WEBPACK_IMPORTED_MODULE_13__.QuillEditor,\n AResizeHandle: _plugins_tm_modal_components_a_resize_handle_vue__WEBPACK_IMPORTED_MODULE_23__[\"default\"],\n AResetSizeButton: _plugins_tm_modal_components_a_reset_size_button_vue__WEBPACK_IMPORTED_MODULE_24__[\"default\"],\n ACloseButton: _plugins_tm_modal_components_a_close_button_vue__WEBPACK_IMPORTED_MODULE_25__[\"default\"],\n ZRemoveEmployeeModal: _z_remove_employee_modal_vue__WEBPACK_IMPORTED_MODULE_26__[\"default\"],\n ZRemoveTimeblockModal: _z_remove_timeblock_modal_vue__WEBPACK_IMPORTED_MODULE_27__[\"default\"]\n },\n mixins: [_master_task_mixins_selects_mixin__WEBPACK_IMPORTED_MODULE_14__[\"default\"], _plugins_tm_mixins_autocomplete_mixin__WEBPACK_IMPORTED_MODULE_18__[\"default\"], _plugins_tm_modal_mixins_modal_mixin__WEBPACK_IMPORTED_MODULE_22__[\"default\"]],\n emits: ['close', 'refresh'],\n data() {\n return {\n tmUtils: _plugins_tm_utils_tm_utils__WEBPACK_IMPORTED_MODULE_15__[\"default\"],\n editMode: false,\n visible: false,\n subtask: null,\n isSaving: false,\n errorUtils: _plugins_lib_auth_utils_error_utils__WEBPACK_IMPORTED_MODULE_12__[\"default\"],\n v$: (0,_vuelidate_core__WEBPACK_IMPORTED_MODULE_10__[\"default\"])(),\n showDatePicker: false,\n selectedNewDate: [],\n timeblocks: [],\n deletedTimeblockIds: [],\n // Track IDs of saved timeblocks that have been deleted\n wasFormValidationTriggered: false,\n modalName: 'z-task-modal',\n modalSize: 'large',\n employeeRefs: [],\n pendingRemoveEmployeeId: undefined,\n pendingRemoveEmployeeIndex: undefined\n };\n },\n computed: {\n ...(0,vuex__WEBPACK_IMPORTED_MODULE_21__.mapGetters)('tm', ['mastertasks', 'enrichedEmployees']),\n enrichedMastertasks() {\n return this.mastertasks.map(mastertask => ({\n ...mastertask,\n _fullName: `${mastertask.name} [${mastertask.project_code}]`\n }));\n },\n editModeEmployee: {\n get() {\n return {\n id: this.subtask?.employee_id || null,\n duration: this.subtask?.duration || null\n };\n },\n set(value) {\n if (this.subtask) {\n this.subtask.employee_id = value.id;\n this.subtask.duration = value.duration;\n }\n }\n },\n isDraftWithMultipleEmployees() {\n return this.subtask?.is_draft && Array.isArray(this.subtask?.employees) && this.subtask.employees.length > 0;\n }\n },\n validations() {\n return {\n subtask: {\n master_task_id: {\n required: _vuelidate_validators__WEBPACK_IMPORTED_MODULE_11__.required\n },\n deadline: {\n required: _vuelidate_validators__WEBPACK_IMPORTED_MODULE_11__.required\n },\n _deadline_time: {\n required: _vuelidate_validators__WEBPACK_IMPORTED_MODULE_11__.required\n }\n }\n };\n },\n watch: {\n 'subtask.employee_id'(value, oldValue) {\n if (!value || !oldValue) return;\n\n // In edit mode: reassign timeblocks to new employee\n if (this.subtask.id) {\n this.timeblocks = this.timeblocks.map(tb => {\n if (tb.employee_id == oldValue) {\n return {\n ...tb,\n employee_id: value\n };\n }\n return tb;\n });\n } else {\n // In create mode: remove old employee's timeblocks\n this.timeblocks = this.timeblocks.filter(tb => tb.employee_id != oldValue);\n }\n this.subtask._employee = this.enrichedEmployees.find(employee => employee.id == this.subtask.employee_id);\n },\n 'subtask.employees': {\n handler() {\n if (!this.subtask?.employees) return;\n const lastEmployee = this.subtask.employees[this.subtask.employees.length - 1];\n if (lastEmployee?.id || lastEmployee?.duration) this.subtask.employees.push({});\n },\n deep: true\n },\n 'subtask.master_task_id'(value) {\n if (!value) return;\n this.subtask._master_task = this.mastertasks.find(mastertask => mastertask.id == this.subtask.master_task_id);\n this.subtask.project_code = this.subtask._master_task?.project_code || null;\n },\n editMode() {\n this.$nextTick(() => {\n this.$refs['description']?.setHTML(this.subtask.description || '');\n });\n },\n subtask: {\n handler(val) {\n if (this.editMode && !this.subtask?.id) {\n const employees = val?.employees?.filter(employee => employee?.id || employee?.duration) || [{}];\n const subtaskData = {\n ...val,\n employees: employees && employees.length > 0 ? employees : [{}]\n };\n localStorage.setItem('subtaskData', JSON.stringify(subtaskData));\n }\n },\n deep: true\n },\n timeblocks: {\n handler(val) {\n if (this.editMode && !this.subtask?.id) {\n // Save timeblocks to localStorage for new tasks\n localStorage.setItem('subtaskTimeblocks', JSON.stringify(val));\n }\n },\n deep: true\n }\n },\n mounted() {\n // Handle remove timeblock modal\n this.$events.on('show-remove-timeblock-modal', ({\n onConfirm\n }) => {\n this.$refs.removeTimeblockModal.showModal({\n onConfirm\n });\n });\n this.$events.on('add-timeblock', timeblock => {\n if (!this.subtask) return;\n if (!this.subtask.timeblocks) {\n this.subtask.timeblocks = [];\n }\n if (!this.subtask.timesheets) {\n this.subtask.timesheets = [];\n }\n if (!this.subtask.is_finished) {\n this.subtask.is_finished = 0;\n }\n this.subtask.timeblocks.push(timeblock);\n });\n this.$events.on('on-subtask-edited', subtask => {\n if (subtask?.id !== this.subtask?.id) return;\n const data = JSON.parse(JSON.stringify(subtask));\n const splittedDeadline = data.deadline?.split(' ') || [];\n data.deadline = splittedDeadline[0];\n data._deadline_time = splittedDeadline[1];\n\n // Convert BE format timeblocks to internal format\n const convertedTimeblocks = [];\n if (data.timeblocks && data.timeblocks.length > 0) {\n data.timeblocks.forEach(timeblock => {\n // If already in internal format, keep as is\n if (timeblock.date) {\n convertedTimeblocks.push({\n ...timeblock,\n employee_id: data.employee_id // Add employee_id\n });\n return;\n }\n\n // Convert from BE format to internal format\n if (timeblock.start && timeblock.end) {\n const startMoment = moment__WEBPACK_IMPORTED_MODULE_16___default()(timeblock.start, 'YYYY-MM-DD HH:mm:ss');\n const endMoment = moment__WEBPACK_IMPORTED_MODULE_16___default()(timeblock.end, 'YYYY-MM-DD HH:mm:ss');\n convertedTimeblocks.push({\n id: timeblock.id || null,\n date: startMoment.toDate(),\n starts_at_time: startMoment.format('HH:mm'),\n ends_at_time: endMoment.format('HH:mm'),\n is_finished: timeblock.is_finished || 0,\n employee_id: data.employee_id // Add employee_id\n });\n }\n });\n }\n // Store in component's timeblocks array\n this.timeblocks = convertedTimeblocks;\n this.subtask = this._enrichTask(data);\n\n // TODO: Remove? riesil som neodstranovanie jedineho zanamu v trvani a odpracovanom case\n this.$forceUpdate();\n });\n this.$events.on('on-subtask-deleted', subtask => {\n if (subtask?.id == this.subtask?.id) this.closeModal();\n });\n },\n methods: {\n customFilterWithEmployeeFilter(item, input, itemObject) {\n const shouldShowItem = this.customFilter(item, input);\n if (!shouldShowItem) return false;\n if (!itemObject?.value) return false;\n const employeeId = itemObject.value;\n if (!this.subtask.id) {\n // New subtask with multiple employees support or edit of draft with multiple employees\n return shouldShowItem && !this.timeblocks.some(tb => tb.employee_id === employeeId);\n } else if (this.subtask.is_draft) {\n // Edit draft subtask with multiple employees support\n return shouldShowItem && !this.subtask.employees.some(employee => Number(employee.id) === employeeId);\n } else {\n // Saved standard subtask, allow \"re-select\" for better UX\n return shouldShowItem;\n }\n },\n toggleEditMode() {\n if (this.subtask.type == 'office365') return this.$events.emit('show-unable-to-edit-office-task-modal', {\n mode: 'edit'\n });\n this.editMode = !this.editMode;\n },\n // Set refs for employee components in create mode\n setEmployeeRef(el, index) {\n if (el) {\n this.employeeRefs[index] = el;\n }\n },\n openDatepicker(ref) {\n this.$refs[ref].openMenu();\n },\n // Helper: Get employee by ID\n getEmployeeById(employeeId) {\n return this.enrichedEmployees.find(emp => emp.id === employeeId);\n },\n // Helper: Get employee full name\n getEmployeeFullName(employeeId) {\n const employee = this.getEmployeeById(employeeId);\n return employee ? `${employee.name} ${employee.surname}` : '';\n },\n // Helper: Get enriched employee data by ID\n getEnrichedEmployee(employeeId) {\n return this.enrichedEmployees.find(emp => emp.id === employeeId) || {};\n },\n // Helper: Get valid employees (with id and duration) in create mode\n getValidEmployees() {\n if (!this.subtask?.employees) return [];\n return this.subtask.employees.filter(emp => emp.id && emp.duration);\n },\n // Helper: Get timeblocks for specific employee\n getEmployeeTimeblocks(employeeId) {\n if (!this.timeblocks) return [];\n return this.timeblocks.filter(tb => tb.employee_id == employeeId);\n },\n updateEmployeeTimeblocks(updatedTimeblocks, employeeId) {\n // Track deleted timeblocks (saved timeblocks that are no longer in the updated list)\n const updatedIds = new Set(updatedTimeblocks.filter(tb => tb.id).map(tb => tb.id));\n const deletedIds = this.timeblocks.filter(tb => tb.employee_id == employeeId && tb.id && !updatedIds.has(tb.id)).map(tb => tb.id).filter(id => !this.deletedTimeblockIds.includes(id));\n this.deletedTimeblockIds.push(...deletedIds);\n\n // Replace timeblocks for this employee\n const otherEmployeeTimeblocks = this.timeblocks.filter(tb => tb.employee_id != employeeId);\n const updatedWithEmployeeId = updatedTimeblocks.map(tb => ({\n ...tb,\n employee_id: employeeId\n }));\n this.timeblocks = [...otherEmployeeTimeblocks, ...updatedWithEmployeeId];\n },\n updateTimeblock(val, index, employeeId) {\n const employeeTimeblocks = this.getEmployeeTimeblocks(employeeId);\n const timeblock = employeeTimeblocks[index];\n if (!timeblock) return;\n\n // Find the actual index in the full timeblocks array\n const actualIndex = this.timeblocks.indexOf(timeblock);\n if (actualIndex !== -1) {\n this.timeblocks[actualIndex] = {\n ...val,\n employee_id: employeeId\n };\n }\n },\n addTimeblock(employeeId, afterIndex = -1) {\n const newTimeblock = {\n date: new Date(),\n // Preset to current day\n starts_at_time: null,\n ends_at_time: null,\n employee_id: employeeId\n };\n\n // Get timeblocks for this employee\n const employeeTimeblocks = this.timeblocks.filter(tb => tb.employee_id == employeeId);\n if (afterIndex === -1 || afterIndex >= employeeTimeblocks.length - 1) {\n // Add at the end\n this.timeblocks.push(newTimeblock);\n } else {\n // Find the position in the full timeblocks array\n const timeblockToInsertAfter = employeeTimeblocks[afterIndex];\n const insertPosition = this.timeblocks.indexOf(timeblockToInsertAfter) + 1;\n this.timeblocks.splice(insertPosition, 0, newTimeblock);\n }\n },\n removeTimeblock(index, employeeId) {\n const employeeTimeblocks = this.getEmployeeTimeblocks(employeeId);\n const timeblock = employeeTimeblocks[index];\n if (!timeblock) return;\n\n // Find the actual index in the full timeblocks array\n const actualIndex = this.timeblocks.indexOf(timeblock);\n if (actualIndex !== -1) {\n this.timeblocks.splice(actualIndex, 1);\n }\n },\n // Handle remove employee - also removes their timeblocks\n handleRemoveEmployee() {\n this.pendingRemoveEmployeeId = this.subtask.employee_id;\n this.$refs.removeEmployeeModal.showModal();\n },\n removeEmployeeAtIndex(index) {\n this.pendingRemoveEmployeeIndex = index;\n this.$refs.removeEmployeeModal.showModal();\n },\n confirmRemoveEmployee() {\n // Handle edit mode (single employee removal)\n if (this.pendingRemoveEmployeeId !== undefined) {\n if (this.subtask.employee_id) {\n // Remove all timeblocks for this employee\n this.timeblocks = this.timeblocks.filter(tb => tb.employee_id != this.subtask.employee_id);\n }\n\n // Clear employee data in edit mode\n this.subtask.employee_id = null;\n this.subtask.duration = null;\n this.pendingRemoveEmployeeId = undefined;\n }\n // Handle create mode (multiple employees removal)\n else if (this.pendingRemoveEmployeeIndex !== undefined) {\n const employee = this.subtask.employees[this.pendingRemoveEmployeeIndex];\n if (employee?.id) {\n // Remove all timeblocks for this employee\n this.timeblocks = this.timeblocks.filter(tb => tb.employee_id != employee.id);\n }\n\n // Remove employee from array\n this.subtask.employees.splice(this.pendingRemoveEmployeeIndex, 1);\n this.pendingRemoveEmployeeIndex = undefined;\n }\n },\n async showModal({\n subtask,\n editMode = false,\n mastertask = {}\n }) {\n this.isSaving = false;\n this.subtask = null;\n this.wasFormValidationTriggered = false; // Reset validation trigger\n\n // CRITICAL: Prevent v-dialog autofocus BEFORE modal opens\n this.preventInputFocus = true;\n this.visible = true;\n this.timeblocks = [];\n this.deletedTimeblockIds = []; // Reset deleted timeblock IDs\n this.employeeRefs = [];\n this.$nextTick(() => {\n this.v$.$reset();\n\n // Reset after modal is fully rendered and v-dialog autofocus has been blocked\n setTimeout(() => {\n this.preventInputFocus = false;\n }, 300);\n });\n try {\n if (subtask?.id) {\n const data = await this.$axios.get_auth_data(`v1/subtasks/${subtask.id}`);\n\n // Convert BE format timeblocks to internal format\n const convertedTimeblocks = [];\n if (data.timeblocks && data.timeblocks.length > 0) {\n data.timeblocks.forEach(timeblock => {\n // If already in internal format, keep as is\n if (timeblock.date) {\n convertedTimeblocks.push({\n ...timeblock,\n employee_id: data.employee_id // Add employee_id for edit mode\n });\n return;\n }\n\n // Convert from BE format to internal format\n if (timeblock.start && timeblock.end) {\n const startMoment = moment__WEBPACK_IMPORTED_MODULE_16___default()(timeblock.start, 'YYYY-MM-DD HH:mm:ss');\n const endMoment = moment__WEBPACK_IMPORTED_MODULE_16___default()(timeblock.end, 'YYYY-MM-DD HH:mm:ss');\n convertedTimeblocks.push({\n id: timeblock.id || null,\n date: startMoment.toDate(),\n starts_at_time: startMoment.format('HH:mm'),\n ends_at_time: endMoment.format('HH:mm'),\n is_finished: timeblock.is_finished || 0,\n employee_id: data.employee_id // Add employee_id for edit mode\n });\n }\n });\n }\n // Store timeblocks in the component's timeblocks array\n this.timeblocks = convertedTimeblocks;\n\n // If draft with employees data, parse timeblocks for each employee\n if (data.is_draft && data.employees && Array.isArray(data.employees)) {\n const draftTimeblocks = [];\n data.employees.forEach(employee => {\n if (employee.timeblocks && Array.isArray(employee.timeblocks)) {\n employee.timeblocks.forEach(timeblock => {\n // Convert BE format to internal format\n if (timeblock.start && timeblock.end) {\n const startMoment = moment__WEBPACK_IMPORTED_MODULE_16___default()(timeblock.start, 'YYYY-MM-DD HH:mm:ss');\n const endMoment = moment__WEBPACK_IMPORTED_MODULE_16___default()(timeblock.end, 'YYYY-MM-DD HH:mm:ss');\n draftTimeblocks.push({\n id: timeblock.id || null,\n date: startMoment.toDate(),\n starts_at_time: startMoment.format('HH:mm'),\n ends_at_time: endMoment.format('HH:mm'),\n is_finished: timeblock.is_finished || 0,\n employee_id: employee.id // Associate with employee\n });\n }\n });\n }\n });\n\n // Use draft timeblocks if they exist\n if (draftTimeblocks.length > 0) {\n this.timeblocks = draftTimeblocks;\n }\n\n // Ensure employees array has proper structure for editing\n // Check if last employee is not empty, then add empty slot\n const lastEmployee = data.employees[data.employees.length - 1];\n if (lastEmployee && (lastEmployee.id || lastEmployee.duration)) {\n data.employees.push({});\n }\n }\n\n // Ensure at least one timeblock exists for edit mode (non-draft single employee)\n if (data.employee_id && !data.is_draft && this.timeblocks.length === 0) {\n this.addTimeblock(data.employee_id);\n }\n if (!data.deadline) {\n this.editMode = editMode || !data.id;\n return this.subtask = this._enrichTask(data);\n }\n const splittedDeadline = data.deadline.split(' ');\n data.deadline = splittedDeadline[0];\n data._deadline_time = splittedDeadline[1];\n this.subtask = this._enrichTask(data);\n } else {\n const savedSubtask = localStorage.getItem('subtaskData');\n const savedTimeblocks = localStorage.getItem('subtaskTimeblocks');\n try {\n if (savedSubtask) {\n const parsedSubtask = JSON.parse(savedSubtask);\n this.subtask = parsedSubtask;\n // If the parsed result is not an object, reset to default\n if (typeof this.subtask !== 'object' || this.subtask === null) {\n throw new Error('Parsed subtask is not an object');\n }\n\n // Load timeblocks from localStorage if they exist\n if (savedTimeblocks) {\n try {\n let parsedTimeblocks = JSON.parse(savedTimeblocks);\n\n // Filter out timeblocks that are not valid\n parsedTimeblocks = parsedTimeblocks.filter(tb => tb.employee_id && tb.starts_at_time && tb.ends_at_time);\n if (Array.isArray(parsedTimeblocks)) {\n this.timeblocks = parsedTimeblocks.map(tb => ({\n ...tb,\n date: tb.date ? new Date(tb.date) : null\n }));\n } else {\n this.timeblocks = [];\n }\n } catch (e) {\n console.error('Error parsing saved timeblocks:', e);\n this.timeblocks = [];\n }\n }\n this.$nextTick(() => {\n this.$refs['description']?.setHTML(this.subtask.description || '');\n });\n } else {\n throw new Error('subtaskData is null or undefined');\n }\n } catch (error) {\n // Initialize with current logged-in employee\n const currentUserId = this.$store.getters['auth/user']?.id;\n const currentEmployee = currentUserId ? this.enrichedEmployees.find(emp => emp.id === currentUserId) : null;\n this.subtask = {\n master_task: mastertask,\n employees: currentEmployee ? [{\n id: currentEmployee.id,\n duration: null\n }] : [{}],\n _deadline_time: '17:00'\n };\n\n // Add a timeblock for the current user if they exist\n if (currentUserId) {\n this.addTimeblock(currentUserId);\n }\n }\n if (subtask?.deadline && subtask._deadline_time && subtask.employee_id) {\n const employee = this.enrichedEmployees.find(employee => employee.id == subtask.employee_id);\n this.subtask.employees = [employee];\n this.subtask.deadline = subtask.deadline;\n this.subtask._deadline_time = subtask._deadline_time;\n setTimeout(() => {\n this.timeblocks = [{\n date: new Date(subtask.deadline),\n starts_at_time: subtask._deadline_time,\n ends_at_time: null,\n employee_id: subtask.employee_id\n }];\n }, 500);\n }\n if (subtask?.master_task_id && subtask?.project_code) {\n this.subtask.master_task_id = subtask.master_task_id;\n this.subtask.project_code = subtask.project_code;\n }\n }\n this.editMode = editMode || !this.subtask.id;\n } catch (error) {\n this.$toast.error(this.$parseError(error));\n }\n },\n deleteTimeblock(i) {\n this.subtask.timeblocks.splice(i, 1);\n },\n closeModal() {\n this.visible = false;\n this.$router.replace({\n name: this.$route.name\n });\n },\n async validate(concept = false) {\n if (concept === false) {\n const employeesValid = await this._validateEmployees();\n const timeblocksValid = await this._validateTimeblocks();\n if (!(await this.v$.$validate())) return;\n if (!employeesValid || !timeblocksValid) return;\n return true;\n } else {\n this.v$.subtask.master_task_id.$touch();\n return this.v$.subtask.master_task_id.$errors.length === 0;\n }\n },\n async save(concept = false) {\n this.v$.$reset();\n this.wasFormValidationTriggered = true;\n if (!(await this.validate(concept))) return;\n this.subtask.description = this.$refs['description'].getHTML();\n this._mergeDeadlineTimeDate();\n try {\n this.isSaving = true;\n\n // Concept tasks may not have a deadline time set\n this.subtask.deadline = this.subtask.deadline ? moment__WEBPACK_IMPORTED_MODULE_16___default()(this.subtask.deadline).format('YYYY-MM-DD HH:mm:SS') : null;\n if (this.subtask?.id) {\n const timesheets = this.subtask.timesheets.map(timesheet => {\n delete timesheet.employee_name;\n return timesheet;\n });\n\n // Convert timeblocks from internal format to BE format for update\n // Filter out completely empty timeblocks AND timeblocks without all required fields\n const timeblocks = this.timeblocks.filter(timeblock => timeblock.date && timeblock.starts_at_time && timeblock.ends_at_time && timeblock.employee_id == this.subtask.employee_id) // Only send complete timeblocks for this employee\n .map(timeblock => {\n const dateStr = moment__WEBPACK_IMPORTED_MODULE_16___default()(timeblock.date).format('YYYY-MM-DD');\n return {\n id: timeblock.id || null,\n start: `${dateStr} ${timeblock.starts_at_time}:00`,\n end: `${dateStr} ${timeblock.ends_at_time}:00`,\n is_finished: timeblock.is_finished || 0\n };\n });\n const payload = {\n ...this.subtask,\n timesheets,\n timeblocks\n };\n\n // For drafts with multiple employees, include employees array\n if (this.subtask.is_draft && this.isDraftWithMultipleEmployees) {\n const validEmployees = this.subtask.employees.filter(employee => employee.id && employee.duration);\n\n // Assign timeblocks to each employee\n validEmployees.forEach(employee => {\n employee.timeblocks = this.timeblocks.filter(tb => tb.employee_id == employee.id && tb.date && tb.starts_at_time && tb.ends_at_time).map(tb => ({\n start: `${moment__WEBPACK_IMPORTED_MODULE_16___default()(tb.date).format('YYYY-MM-DD')} ${tb.starts_at_time}:00`,\n end: `${moment__WEBPACK_IMPORTED_MODULE_16___default()(tb.date).format('YYYY-MM-DD')} ${tb.ends_at_time}:00`,\n id: tb.id || null\n }));\n });\n payload.employees = validEmployees;\n }\n if (concept) {\n payload.is_draft = 1;\n } else {\n payload.is_draft = 0;\n }\n const {\n subtask\n } = await this.$axios.patch_auth_form(`v1/subtasks/${this.subtask.id}`, payload);\n localStorage.removeItem('subtaskData');\n localStorage.removeItem('subtaskTimeblocks');\n this.$store.commit('tm/update_subtask', subtask);\n this.$events.emit('on-subtask-edited', this.subtask);\n } else {\n // Filter out employees that don't have both id and duration\n const validEmployees = this.subtask.employees.filter(employee => employee.id && employee.duration);\n\n // Assign timeblocks to each employee based on employee_id\n // Filter out empty/incomplete timeblocks - only send fully filled timeblocks\n validEmployees.forEach(employee => {\n employee.timeblocks = this.timeblocks.filter(timeblock => timeblock.date && timeblock.starts_at_time && timeblock.ends_at_time && timeblock.employee_id == employee.id).map(timeblock => {\n return {\n start: `${moment__WEBPACK_IMPORTED_MODULE_16___default()(timeblock.date).format('YYYY-MM-DD')} ${timeblock.starts_at_time}:00`,\n end: `${moment__WEBPACK_IMPORTED_MODULE_16___default()(timeblock.date).format('YYYY-MM-DD')} ${timeblock.ends_at_time}:00`,\n id: null\n };\n });\n });\n const subtaskCopy = {\n ...this.subtask,\n employees: validEmployees\n };\n if (concept) {\n subtaskCopy.is_draft = true;\n subtaskCopy.employees = subtaskCopy.employees?.length > 0 ? subtaskCopy.employees : [{\n id: this.$store.getters['auth/user']?.id,\n duration: 0\n }];\n }\n delete subtaskCopy._master_task;\n const {\n subtasks\n } = await this.$axios.post_auth(`v1/mastertasks/${this.subtask.master_task_id}/subtasks`, subtaskCopy);\n localStorage.removeItem('subtaskData');\n localStorage.removeItem('subtaskTimeblocks');\n this.subtask.id = subtasks[0].id;\n subtasks.forEach(subtask => {\n this.$store.commit('tm/update_subtask', subtask);\n this.$events.emit('on-subtask-edited', this.subtask);\n });\n this.$events.emit('task-created');\n this.$events.emit('close-both-modals');\n }\n this.closeModal();\n } catch (error) {\n console.log('error', error);\n this.$toast.error(this.$parseError(error));\n } finally {\n this.isSaving = false;\n }\n },\n openDeleteTaskModal(subtask) {\n if (subtask.type == 'office365') return this.$events.emit('show-unable-to-edit-office-task-modal', {\n mode: 'delete'\n });\n this.$events.emit('show-delete-task-modal', {\n subtask\n });\n },\n showCompleteTaskModal() {\n this.$events.emit('show-complete-task-modal', {\n subtask: this.subtask\n });\n if (this.subtask.deadline) this.subtask.deadline = _plugins_tm_utils_tm_utils__WEBPACK_IMPORTED_MODULE_15__[\"default\"].formatDateTimeForBackend(this.subtask.deadline);\n },\n filesUploaded(files) {\n this.subtask.files = files;\n },\n updateSubtask(subtask) {\n this.subtask = subtask;\n },\n _mergeDeadlineTimeDate() {\n // Override for concept tasks which may not have a deadline time set (check for invalid date)\n if (isNaN(new Date(this.subtask.deadline).getTime()) || !this.subtask._deadline_time) {\n this.subtask.deadline = null;\n } else {\n const date = new Date(this.subtask.deadline);\n const timeParts = this.subtask._deadline_time.split(':');\n date.setHours(parseInt(timeParts[0]));\n date.setMinutes(parseInt(timeParts[1]));\n this.subtask.deadline = date;\n }\n },\n async _validateEmployees() {\n if (this.subtask.id && !this.subtask.is_draft) {\n // For existing subtasks, at least one employee is required\n const hasEmployee = !!(this.subtask.employee_id && this.subtask.duration);\n return hasEmployee;\n } else {\n let valid = true;\n\n // Validate ALL employee component refs (this will show errors on inputs)\n for (let i = 0; i < this.employeeRefs.length; i++) {\n const employeeRef = this.employeeRefs[i];\n\n // Validate employees that have any data (partial or complete)\n if (employeeRef && typeof employeeRef.validate === 'function') {\n if (!(await employeeRef.validate())) {\n valid = false;\n }\n }\n }\n return valid;\n }\n },\n async _validateTimeblocks() {\n // Date alone is valid. Validation only applies if start OR end time is filled.\n // If start OR end is filled, then ALL fields (date, start, end) are required.\n let valid = true;\n for (const timeblock of this.timeblocks) {\n const hasStart = !!timeblock.starts_at_time;\n const hasEnd = !!timeblock.ends_at_time;\n const hasAnyTime = hasStart || hasEnd;\n\n // If no time data (start/end), timeblock is valid (date alone is OK)\n if (!hasAnyTime) {\n continue;\n }\n\n // If start OR end is filled, ALL fields are required\n const hasDate = !!timeblock.date;\n if (!hasDate || !hasStart || !hasEnd) {\n valid = false;\n break;\n }\n\n // Validate that end time is after start time\n const dateStr = moment__WEBPACK_IMPORTED_MODULE_16___default()(timeblock.date).format('YYYY-MM-DD');\n const start = moment__WEBPACK_IMPORTED_MODULE_16___default()(`${dateStr} ${timeblock.starts_at_time}`, 'YYYY-MM-DD HH:mm');\n const end = moment__WEBPACK_IMPORTED_MODULE_16___default()(`${dateStr} ${timeblock.ends_at_time}`, 'YYYY-MM-DD HH:mm');\n if (end.isSameOrBefore(start)) {\n valid = false;\n break;\n }\n }\n return valid;\n },\n _enrichTask(subtask) {\n return {\n ...subtask,\n _created_by: this.enrichedEmployees.find(employee => employee.id == subtask.created_by),\n _employee: this.enrichedEmployees.find(employee => employee.id == subtask.employee_id),\n _master_task: this.mastertasks.find(mastertask => mastertask.id == subtask.master_task_id)\n };\n }\n }\n});\n\n//# sourceURL=webpack://jandl/./src/plugins/tm@modal/task/z-task-modal.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}"); +eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.array.push.js */ \"./node_modules/core-js/modules/es.array.push.js\");\n/* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_es_json_stringify_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/es.json.stringify.js */ \"./node_modules/core-js/modules/es.json.stringify.js\");\n/* harmony import */ var core_js_modules_es_json_stringify_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_json_stringify_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var core_js_modules_esnext_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! core-js/modules/esnext.iterator.constructor.js */ \"./node_modules/core-js/modules/esnext.iterator.constructor.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var core_js_modules_esnext_iterator_filter_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! core-js/modules/esnext.iterator.filter.js */ \"./node_modules/core-js/modules/esnext.iterator.filter.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_filter_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_filter_js__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var core_js_modules_esnext_iterator_find_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! core-js/modules/esnext.iterator.find.js */ \"./node_modules/core-js/modules/esnext.iterator.find.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_find_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_find_js__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var core_js_modules_esnext_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! core-js/modules/esnext.iterator.for-each.js */ \"./node_modules/core-js/modules/esnext.iterator.for-each.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_5__);\n/* harmony import */ var core_js_modules_esnext_iterator_map_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! core-js/modules/esnext.iterator.map.js */ \"./node_modules/core-js/modules/esnext.iterator.map.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_map_js__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_map_js__WEBPACK_IMPORTED_MODULE_6__);\n/* harmony import */ var core_js_modules_esnext_iterator_some_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! core-js/modules/esnext.iterator.some.js */ \"./node_modules/core-js/modules/esnext.iterator.some.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_some_js__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_some_js__WEBPACK_IMPORTED_MODULE_7__);\n/* harmony import */ var _plugins_tm_components_z_datepicker_vue__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @/plugins/tm@_components/z-datepicker.vue */ \"./src/plugins/tm@_components/z-datepicker.vue\");\n/* harmony import */ var _plugins_tm_components_z_files_upload_vue__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @/plugins/tm@_components/z-files-upload.vue */ \"./src/plugins/tm@_components/z-files-upload.vue\");\n/* harmony import */ var _vuelidate_core__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @vuelidate/core */ \"./node_modules/@vuelidate/core/dist/index.esm.js\");\n/* harmony import */ var _vuelidate_validators__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! @vuelidate/validators */ \"./node_modules/@vuelidate/validators/dist/index.esm.js\");\n/* harmony import */ var _plugins_lib_auth_utils_error_utils__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! @/plugins/lib@auth/_utils/error.utils */ \"./src/plugins/lib@auth/_utils/error.utils.ts\");\n/* harmony import */ var _vueup_vue_quill__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! @vueup/vue-quill */ \"./node_modules/@vueup/vue-quill/dist/vue-quill.esm-bundler.js\");\n/* harmony import */ var _master_task_mixins_selects_mixin__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ../master-task/_mixins/selects.mixin */ \"./src/plugins/tm@modal/master-task/_mixins/selects.mixin.ts\");\n/* harmony import */ var _plugins_tm_utils_tm_utils__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! @/plugins/tm@_utils/tm.utils */ \"./src/plugins/tm@_utils/tm.utils.ts\");\n/* harmony import */ var moment__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! moment */ \"./node_modules/moment/moment.js\");\n/* harmony import */ var moment__WEBPACK_IMPORTED_MODULE_16___default = /*#__PURE__*/__webpack_require__.n(moment__WEBPACK_IMPORTED_MODULE_16__);\n/* harmony import */ var _vueup_vue_quill_dist_vue_quill_snow_css__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! @vueup/vue-quill/dist/vue-quill.snow.css */ \"./node_modules/@vueup/vue-quill/dist/vue-quill.snow.css\");\n/* harmony import */ var _vueup_vue_quill_dist_vue_quill_snow_css__WEBPACK_IMPORTED_MODULE_17___default = /*#__PURE__*/__webpack_require__.n(_vueup_vue_quill_dist_vue_quill_snow_css__WEBPACK_IMPORTED_MODULE_17__);\n/* harmony import */ var _plugins_tm_mixins_autocomplete_mixin__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! @/plugins/tm@_mixins/autocomplete.mixin */ \"./src/plugins/tm@_mixins/autocomplete.mixin.ts\");\n/* harmony import */ var _components_z_task_readonly_info_vue__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ./_components/z-task-readonly-info.vue */ \"./src/plugins/tm@modal/task/_components/z-task-readonly-info.vue\");\n/* harmony import */ var _components_employees_a_employee_vue__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ./_components/employees/a-employee.vue */ \"./src/plugins/tm@modal/task/_components/employees/a-employee.vue\");\n/* harmony import */ var vuex__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! vuex */ \"./node_modules/vuex/dist/vuex.esm-bundler.js\");\n/* harmony import */ var _plugins_tm_modal_mixins_modal_mixin__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! @/plugins/tm@modal/_mixins/modal.mixin */ \"./src/plugins/tm@modal/_mixins/modal.mixin.ts\");\n/* harmony import */ var _plugins_tm_modal_components_a_resize_handle_vue__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! @/plugins/tm@modal/_components/a-resize-handle.vue */ \"./src/plugins/tm@modal/_components/a-resize-handle.vue\");\n/* harmony import */ var _plugins_tm_modal_components_a_reset_size_button_vue__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! @/plugins/tm@modal/_components/a-reset-size-button.vue */ \"./src/plugins/tm@modal/_components/a-reset-size-button.vue\");\n/* harmony import */ var _plugins_tm_modal_components_a_close_button_vue__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! @/plugins/tm@modal/_components/a-close-button.vue */ \"./src/plugins/tm@modal/_components/a-close-button.vue\");\n/* harmony import */ var _z_remove_employee_modal_vue__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! ./z-remove-employee-modal.vue */ \"./src/plugins/tm@modal/task/z-remove-employee-modal.vue\");\n/* harmony import */ var _z_remove_timeblock_modal_vue__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(/*! ./z-remove-timeblock-modal.vue */ \"./src/plugins/tm@modal/task/z-remove-timeblock-modal.vue\");\n/* provided dependency */ var console = __webpack_require__(/*! ./node_modules/console-browserify/index.js */ \"./node_modules/console-browserify/index.js\");\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n components: {\n ZTaskReadonlyInfo: _components_z_task_readonly_info_vue__WEBPACK_IMPORTED_MODULE_19__[\"default\"],\n AEmployee: _components_employees_a_employee_vue__WEBPACK_IMPORTED_MODULE_20__[\"default\"],\n ZFilesUpload: _plugins_tm_components_z_files_upload_vue__WEBPACK_IMPORTED_MODULE_9__[\"default\"],\n ZDatepicker: _plugins_tm_components_z_datepicker_vue__WEBPACK_IMPORTED_MODULE_8__[\"default\"],\n // ATaskTimeblocks,\n QuillEditor: _vueup_vue_quill__WEBPACK_IMPORTED_MODULE_13__.QuillEditor,\n AResizeHandle: _plugins_tm_modal_components_a_resize_handle_vue__WEBPACK_IMPORTED_MODULE_23__[\"default\"],\n AResetSizeButton: _plugins_tm_modal_components_a_reset_size_button_vue__WEBPACK_IMPORTED_MODULE_24__[\"default\"],\n ACloseButton: _plugins_tm_modal_components_a_close_button_vue__WEBPACK_IMPORTED_MODULE_25__[\"default\"],\n ZRemoveEmployeeModal: _z_remove_employee_modal_vue__WEBPACK_IMPORTED_MODULE_26__[\"default\"],\n ZRemoveTimeblockModal: _z_remove_timeblock_modal_vue__WEBPACK_IMPORTED_MODULE_27__[\"default\"]\n },\n mixins: [_master_task_mixins_selects_mixin__WEBPACK_IMPORTED_MODULE_14__[\"default\"], _plugins_tm_mixins_autocomplete_mixin__WEBPACK_IMPORTED_MODULE_18__[\"default\"], _plugins_tm_modal_mixins_modal_mixin__WEBPACK_IMPORTED_MODULE_22__[\"default\"]],\n emits: ['close', 'refresh'],\n data() {\n return {\n tmUtils: _plugins_tm_utils_tm_utils__WEBPACK_IMPORTED_MODULE_15__[\"default\"],\n editMode: false,\n visible: false,\n subtask: null,\n isSaving: false,\n errorUtils: _plugins_lib_auth_utils_error_utils__WEBPACK_IMPORTED_MODULE_12__[\"default\"],\n v$: (0,_vuelidate_core__WEBPACK_IMPORTED_MODULE_10__[\"default\"])(),\n showDatePicker: false,\n selectedNewDate: [],\n timeblocks: [],\n deletedTimeblockIds: [],\n // Track IDs of saved timeblocks that have been deleted\n wasFormValidationTriggered: false,\n modalName: 'z-task-modal',\n modalSize: 'large',\n employeeRefs: [],\n pendingRemoveEmployeeId: undefined,\n pendingRemoveEmployeeIndex: undefined\n };\n },\n computed: {\n ...(0,vuex__WEBPACK_IMPORTED_MODULE_21__.mapGetters)('tm', ['mastertasks', 'enrichedEmployees']),\n enrichedMastertasks() {\n return this.mastertasks.map(mastertask => ({\n ...mastertask,\n _fullName: `${mastertask.name} [${mastertask.project_code}]`\n }));\n },\n editModeEmployee: {\n get() {\n return {\n id: this.subtask?.employee_id || null,\n duration: this.subtask?.duration || null\n };\n },\n set(value) {\n if (this.subtask) {\n this.subtask.employee_id = value.id;\n this.subtask.duration = value.duration;\n }\n }\n },\n isDraftWithMultipleEmployees() {\n return this.subtask?.is_draft && Array.isArray(this.subtask?.employees) && this.subtask.employees.length > 0;\n }\n },\n validations() {\n return {\n subtask: {\n master_task_id: {\n required: _vuelidate_validators__WEBPACK_IMPORTED_MODULE_11__.required\n },\n deadline: {\n required: _vuelidate_validators__WEBPACK_IMPORTED_MODULE_11__.required\n },\n _deadline_time: {\n required: _vuelidate_validators__WEBPACK_IMPORTED_MODULE_11__.required\n }\n }\n };\n },\n watch: {\n 'subtask.employee_id'(value, oldValue) {\n if (!value || !oldValue) return;\n\n // In edit mode: reassign timeblocks to new employee\n if (this.subtask.id) {\n this.timeblocks = this.timeblocks.map(tb => {\n if (tb.employee_id == oldValue) {\n return {\n ...tb,\n employee_id: value\n };\n }\n return tb;\n });\n } else {\n // In create mode: remove old employee's timeblocks\n this.timeblocks = this.timeblocks.filter(tb => tb.employee_id != oldValue);\n }\n this.subtask._employee = this.enrichedEmployees.find(employee => employee.id == this.subtask.employee_id);\n },\n 'subtask.employees': {\n handler() {\n if (!this.subtask?.employees) return;\n const lastEmployee = this.subtask.employees[this.subtask.employees.length - 1];\n if (lastEmployee?.id || lastEmployee?.duration) this.subtask.employees.push({});\n },\n deep: true\n },\n 'subtask.master_task_id'(value) {\n if (!value) return;\n this.subtask._master_task = this.mastertasks.find(mastertask => mastertask.id == this.subtask.master_task_id);\n this.subtask.project_code = this.subtask._master_task?.project_code || null;\n },\n editMode() {\n this.$nextTick(() => {\n this.$refs['description']?.setHTML(this.subtask.description || '');\n });\n },\n subtask: {\n handler(val) {\n if (this.editMode && !this.subtask?.id) {\n const employees = val?.employees?.filter(employee => employee?.id || employee?.duration) || [{}];\n const subtaskData = {\n ...val,\n employees: employees && employees.length > 0 ? employees : [{}]\n };\n localStorage.setItem('subtaskData', JSON.stringify(subtaskData));\n }\n },\n deep: true\n },\n timeblocks: {\n handler(val) {\n if (this.editMode && !this.subtask?.id) {\n // Save timeblocks to localStorage for new tasks\n localStorage.setItem('subtaskTimeblocks', JSON.stringify(val));\n }\n },\n deep: true\n }\n },\n mounted() {\n // Handle remove timeblock modal\n this.$events.on('show-remove-timeblock-modal', ({\n onConfirm\n }) => {\n this.$refs.removeTimeblockModal.showModal({\n onConfirm\n });\n });\n this.$events.on('add-timeblock', timeblock => {\n if (!this.subtask) return;\n if (!this.subtask.timeblocks) {\n this.subtask.timeblocks = [];\n }\n if (!this.subtask.timesheets) {\n this.subtask.timesheets = [];\n }\n if (!this.subtask.is_finished) {\n this.subtask.is_finished = 0;\n }\n this.subtask.timeblocks.push(timeblock);\n });\n this.$events.on('on-subtask-edited', subtask => {\n if (subtask?.id !== this.subtask?.id) return;\n const data = JSON.parse(JSON.stringify(subtask));\n const splittedDeadline = data.deadline?.split(' ') || [];\n data.deadline = splittedDeadline[0];\n data._deadline_time = splittedDeadline[1];\n\n // Convert BE format timeblocks to internal format\n if (data.is_draft && Array.isArray(data.employees)) {\n // Handle draft subtasks with employees array\n const allDraftTimeblocks = [];\n data.employees = data.employees.map(emp => {\n const convertedTimeblocks = (emp.timeblocks || []).map(tb => this._convertTimeblockToInternal(tb, emp.id)).filter(Boolean);\n\n // Add to flat array for edit mode\n allDraftTimeblocks.push(...convertedTimeblocks);\n return {\n ...emp,\n timeblocks: convertedTimeblocks\n };\n });\n\n // Update flat timeblocks array for edit mode\n this.timeblocks = allDraftTimeblocks;\n } else {\n // Handle published subtasks with root-level timeblocks\n this.timeblocks = (data.timeblocks || []).map(tb => this._convertTimeblockToInternal(tb, data.employee_id)).filter(Boolean);\n }\n this.subtask = this._enrichTask(data);\n\n // TODO: Remove? riesil som neodstranovanie jedineho zanamu v trvani a odpracovanom case\n this.$forceUpdate();\n });\n this.$events.on('on-subtask-deleted', subtask => {\n if (subtask?.id == this.subtask?.id) this.closeModal();\n });\n },\n methods: {\n /**\n * Convert a timeblock from backend format to internal format\n * @param {Object} timeblock - Timeblock in BE format (start/end) or internal format (date/times)\n * @param {Number} employeeId - Employee ID to associate with the timeblock\n * @returns {Object} Timeblock in internal format\n */\n _convertTimeblockToInternal(timeblock, employeeId) {\n // If already in internal format, return as is\n if (timeblock.date) {\n return {\n ...timeblock,\n employee_id: employeeId\n };\n }\n\n // Convert from BE format to internal format\n if (timeblock.start && timeblock.end) {\n const startMoment = moment__WEBPACK_IMPORTED_MODULE_16___default()(timeblock.start, 'YYYY-MM-DD HH:mm:ss');\n const endMoment = moment__WEBPACK_IMPORTED_MODULE_16___default()(timeblock.end, 'YYYY-MM-DD HH:mm:ss');\n return {\n id: timeblock.id || null,\n date: startMoment.toDate(),\n starts_at_time: startMoment.format('HH:mm'),\n ends_at_time: endMoment.format('HH:mm'),\n is_finished: timeblock.is_finished || 0,\n employee_id: employeeId\n };\n }\n return null;\n },\n customFilterWithEmployeeFilter(item, input, itemObject) {\n const shouldShowItem = this.customFilter(item, input);\n if (!shouldShowItem) return false;\n if (!itemObject?.value) return false;\n const employeeId = itemObject.value;\n if (!this.subtask.id) {\n // New subtask with multiple employees support\n // Hide employees that are already selected in any slot\n // The v-autocomplete will still display the currently selected employee\n const isAlreadySelected = Array.isArray(this.subtask.employees) && this.subtask.employees.some(emp => emp.id && Number(emp.id) === employeeId);\n return shouldShowItem && !isAlreadySelected;\n } else if (this.subtask.is_draft) {\n // Edit draft subtask with multiple employees support\n // Hide employees that are already selected in any slot\n const isAlreadySelected = Array.isArray(this.subtask.employees) && this.subtask.employees.some(emp => emp.id && Number(emp.id) === employeeId);\n return shouldShowItem && !isAlreadySelected;\n } else {\n // Saved standard subtask, allow \"re-select\" for better UX\n return shouldShowItem;\n }\n },\n toggleEditMode() {\n if (this.subtask.type == 'office365') return this.$events.emit('show-unable-to-edit-office-task-modal', {\n mode: 'edit'\n });\n this.editMode = !this.editMode;\n },\n // Set refs for employee components in create mode\n setEmployeeRef(el, index) {\n if (el) {\n this.employeeRefs[index] = el;\n }\n },\n openDatepicker(ref) {\n this.$refs[ref].openMenu();\n },\n // Helper: Get employee by ID\n getEmployeeById(employeeId) {\n return this.enrichedEmployees.find(emp => emp.id === employeeId);\n },\n // Helper: Get employee full name\n getEmployeeFullName(employeeId) {\n const employee = this.getEmployeeById(employeeId);\n return employee ? `${employee.name} ${employee.surname}` : '';\n },\n // Helper: Get enriched employee data by ID\n getEnrichedEmployee(employeeId) {\n return this.enrichedEmployees.find(emp => emp.id === employeeId) || {};\n },\n // Helper: Get valid employees (with id and duration) in create mode\n getValidEmployees() {\n if (!this.subtask?.employees) return [];\n return this.subtask.employees.filter(emp => emp.id && emp.duration);\n },\n // Helper: Get timeblocks for specific employee\n getEmployeeTimeblocks(employeeId) {\n if (!this.timeblocks) return [];\n return this.timeblocks.filter(tb => tb.employee_id == employeeId);\n },\n updateEmployeeTimeblocks(updatedTimeblocks, employeeId) {\n // Track deleted timeblocks (saved timeblocks that are no longer in the updated list)\n const updatedIds = new Set(updatedTimeblocks.filter(tb => tb.id).map(tb => tb.id));\n const deletedIds = this.timeblocks.filter(tb => tb.employee_id == employeeId && tb.id && !updatedIds.has(tb.id)).map(tb => tb.id).filter(id => !this.deletedTimeblockIds.includes(id));\n this.deletedTimeblockIds.push(...deletedIds);\n\n // Replace timeblocks for this employee\n const otherEmployeeTimeblocks = this.timeblocks.filter(tb => tb.employee_id != employeeId);\n const updatedWithEmployeeId = updatedTimeblocks.map(tb => ({\n ...tb,\n employee_id: employeeId\n }));\n this.timeblocks = [...otherEmployeeTimeblocks, ...updatedWithEmployeeId];\n },\n updateTimeblock(val, index, employeeId) {\n const employeeTimeblocks = this.getEmployeeTimeblocks(employeeId);\n const timeblock = employeeTimeblocks[index];\n if (!timeblock) return;\n\n // Find the actual index in the full timeblocks array\n const actualIndex = this.timeblocks.indexOf(timeblock);\n if (actualIndex !== -1) {\n this.timeblocks[actualIndex] = {\n ...val,\n employee_id: employeeId\n };\n }\n },\n addTimeblock(employeeId, afterIndex = -1) {\n const newTimeblock = {\n date: new Date(),\n // Preset to current day\n starts_at_time: null,\n ends_at_time: null,\n employee_id: employeeId\n };\n\n // Get timeblocks for this employee\n const employeeTimeblocks = this.timeblocks.filter(tb => tb.employee_id == employeeId);\n if (afterIndex === -1 || afterIndex >= employeeTimeblocks.length - 1) {\n // Add at the end\n this.timeblocks.push(newTimeblock);\n } else {\n // Find the position in the full timeblocks array\n const timeblockToInsertAfter = employeeTimeblocks[afterIndex];\n const insertPosition = this.timeblocks.indexOf(timeblockToInsertAfter) + 1;\n this.timeblocks.splice(insertPosition, 0, newTimeblock);\n }\n },\n removeTimeblock(index, employeeId) {\n const employeeTimeblocks = this.getEmployeeTimeblocks(employeeId);\n const timeblock = employeeTimeblocks[index];\n if (!timeblock) return;\n\n // Find the actual index in the full timeblocks array\n const actualIndex = this.timeblocks.indexOf(timeblock);\n if (actualIndex !== -1) {\n this.timeblocks.splice(actualIndex, 1);\n }\n },\n // Handle remove employee - also removes their timeblocks\n handleRemoveEmployee() {\n this.pendingRemoveEmployeeId = this.subtask.employee_id;\n this.$refs.removeEmployeeModal.showModal();\n },\n removeEmployeeAtIndex(index) {\n this.pendingRemoveEmployeeIndex = index;\n this.$refs.removeEmployeeModal.showModal();\n },\n confirmRemoveEmployee() {\n // Handle edit mode (single employee removal)\n if (this.pendingRemoveEmployeeId !== undefined) {\n if (this.subtask.employee_id) {\n // Remove all timeblocks for this employee\n this.timeblocks = this.timeblocks.filter(tb => tb.employee_id != this.subtask.employee_id);\n }\n\n // Clear employee data in edit mode\n this.subtask.employee_id = null;\n this.subtask.duration = null;\n this.pendingRemoveEmployeeId = undefined;\n }\n // Handle create mode (multiple employees removal)\n else if (this.pendingRemoveEmployeeIndex !== undefined && Array.isArray(this.subtask.employees)) {\n const employee = this.subtask.employees[this.pendingRemoveEmployeeIndex];\n if (employee?.id) {\n // Remove all timeblocks for this employee\n this.timeblocks = this.timeblocks.filter(tb => tb.employee_id != employee.id);\n }\n\n // Remove employee from array\n this.subtask.employees.splice(this.pendingRemoveEmployeeIndex, 1);\n this.pendingRemoveEmployeeIndex = undefined;\n }\n },\n async showModal({\n subtask,\n editMode = false,\n mastertask = {}\n }) {\n this.isSaving = false;\n this.subtask = null;\n this.wasFormValidationTriggered = false; // Reset validation trigger\n\n // CRITICAL: Prevent v-dialog autofocus BEFORE modal opens\n this.preventInputFocus = true;\n this.visible = true;\n this.timeblocks = [];\n this.deletedTimeblockIds = []; // Reset deleted timeblock IDs\n this.employeeRefs = [];\n this.$nextTick(() => {\n this.v$.$reset();\n\n // Reset after modal is fully rendered and v-dialog autofocus has been blocked\n setTimeout(() => {\n this.preventInputFocus = false;\n }, 300);\n });\n try {\n if (subtask?.id) {\n const data = await this.$axios.get_auth_data(`v1/subtasks/${subtask.id}`);\n\n // Convert BE format timeblocks to internal format\n if (data.is_draft && data.employees && Array.isArray(data.employees)) {\n // Handle draft subtasks with employees array\n const draftTimeblocks = [];\n data.employees = data.employees.map(employee => {\n const convertedTimeblocks = (employee.timeblocks || []).map(tb => this._convertTimeblockToInternal(tb, employee.id)).filter(Boolean);\n draftTimeblocks.push(...convertedTimeblocks);\n return {\n ...employee,\n timeblocks: convertedTimeblocks\n };\n });\n this.timeblocks = draftTimeblocks;\n\n // Ensure employees array has proper structure for editing\n const lastEmployee = data.employees[data.employees.length - 1];\n if (lastEmployee && (lastEmployee.id || lastEmployee.duration)) {\n data.employees.push({});\n }\n } else {\n // Handle published subtasks with root-level timeblocks\n this.timeblocks = (data.timeblocks || []).map(tb => this._convertTimeblockToInternal(tb, data.employee_id)).filter(Boolean);\n }\n\n // Ensure at least one timeblock exists for edit mode (non-draft single employee)\n if (data.employee_id && !data.is_draft && this.timeblocks.length === 0) {\n this.addTimeblock(data.employee_id);\n }\n if (!data.deadline) {\n this.editMode = editMode || !data.id;\n return this.subtask = this._enrichTask(data);\n }\n const splittedDeadline = data.deadline.split(' ');\n data.deadline = splittedDeadline[0];\n data._deadline_time = splittedDeadline[1];\n this.subtask = this._enrichTask(data);\n } else {\n const savedSubtask = localStorage.getItem('subtaskData');\n const savedTimeblocks = localStorage.getItem('subtaskTimeblocks');\n try {\n if (savedSubtask) {\n const parsedSubtask = JSON.parse(savedSubtask);\n this.subtask = parsedSubtask;\n // If the parsed result is not an object, reset to default\n if (typeof this.subtask !== 'object' || this.subtask === null) {\n throw new Error('Parsed subtask is not an object');\n }\n\n // Load timeblocks from localStorage if they exist\n if (savedTimeblocks) {\n try {\n let parsedTimeblocks = JSON.parse(savedTimeblocks);\n\n // Filter out timeblocks that are not valid\n parsedTimeblocks = parsedTimeblocks.filter(tb => tb.employee_id && tb.starts_at_time && tb.ends_at_time);\n if (Array.isArray(parsedTimeblocks)) {\n this.timeblocks = parsedTimeblocks.map(tb => ({\n ...tb,\n date: tb.date ? new Date(tb.date) : null\n }));\n } else {\n this.timeblocks = [];\n }\n } catch (e) {\n console.error('Error parsing saved timeblocks:', e);\n this.timeblocks = [];\n }\n }\n this.$nextTick(() => {\n this.$refs['description']?.setHTML(this.subtask.description || '');\n });\n } else {\n throw new Error('subtaskData is null or undefined');\n }\n } catch (error) {\n // Initialize with current logged-in employee\n const currentUserId = this.$store.getters['auth/user']?.id;\n const currentEmployee = currentUserId ? this.enrichedEmployees.find(emp => emp.id === currentUserId) : null;\n this.subtask = {\n master_task: mastertask,\n employees: currentEmployee ? [{\n id: currentEmployee.id,\n duration: null\n }] : [{}],\n _deadline_time: '17:00'\n };\n\n // Add a timeblock for the current user if they exist\n if (currentUserId) {\n this.addTimeblock(currentUserId);\n }\n }\n if (subtask?.deadline && subtask._deadline_time && subtask.employee_id) {\n const employee = this.enrichedEmployees.find(employee => employee.id == subtask.employee_id);\n\n // Get current logged-in user\n const currentUserId = this.$store.getters['auth/user']?.id;\n const isCurrentUser = currentUserId === subtask.employee_id;\n\n // If the clicked employee is different from current user, add current user first as empty slot\n if (!isCurrentUser) {\n this.subtask.employees = [{\n id: currentUserId,\n duration: null\n },\n // Empty current user slot\n employee // The clicked employee with data\n ];\n } else {\n // Same user or no current user, just add the clicked employee\n this.subtask.employees = [employee];\n }\n this.subtask.deadline = subtask.deadline;\n this.subtask._deadline_time = subtask._deadline_time;\n setTimeout(() => {\n this.timeblocks = [...(!isCurrentUser ? [{\n date: new Date(subtask.deadline),\n starts_at_time: subtask._deadline_time,\n ends_at_time: null,\n employee_id: currentUserId\n }] : []), {\n date: new Date(subtask.deadline),\n starts_at_time: subtask._deadline_time,\n ends_at_time: null,\n employee_id: subtask.employee_id\n }];\n }, 500);\n }\n if (subtask?.master_task_id && subtask?.project_code) {\n this.subtask.master_task_id = subtask.master_task_id;\n this.subtask.project_code = subtask.project_code;\n }\n }\n this.editMode = editMode || !this.subtask.id;\n } catch (error) {\n this.$toast.error(this.$parseError(error));\n }\n },\n deleteTimeblock(i) {\n this.subtask.timeblocks.splice(i, 1);\n },\n closeModal() {\n this.visible = false;\n this.$router.replace({\n name: this.$route.name\n });\n },\n async validate(concept = false) {\n if (concept === false) {\n const employeesValid = await this._validateEmployees();\n const timeblocksValid = await this._validateTimeblocks();\n if (!(await this.v$.$validate())) return;\n if (!employeesValid || !timeblocksValid) return;\n return true;\n } else {\n this.v$.subtask.master_task_id.$touch();\n return this.v$.subtask.master_task_id.$errors.length === 0;\n }\n },\n async save(concept = false) {\n this.v$.$reset();\n this.wasFormValidationTriggered = true;\n if (!(await this.validate(concept))) return;\n this.subtask.description = this.$refs['description'].getHTML();\n this._mergeDeadlineTimeDate();\n try {\n this.isSaving = true;\n\n // Concept tasks may not have a deadline time set\n this.subtask.deadline = this.subtask.deadline ? moment__WEBPACK_IMPORTED_MODULE_16___default()(this.subtask.deadline).format('YYYY-MM-DD HH:mm:SS') : null;\n if (this.subtask?.id) {\n const timesheets = this.subtask.timesheets.map(timesheet => {\n delete timesheet.employee_name;\n return timesheet;\n });\n\n // Convert timeblocks from internal format to BE format for update\n // Filter out completely empty timeblocks AND timeblocks without all required fields\n const timeblocks = this.timeblocks.filter(timeblock => timeblock.date && timeblock.starts_at_time && timeblock.ends_at_time && timeblock.employee_id == this.subtask.employee_id) // Only send complete timeblocks for this employee\n .map(timeblock => {\n const dateStr = moment__WEBPACK_IMPORTED_MODULE_16___default()(timeblock.date).format('YYYY-MM-DD');\n return {\n id: timeblock.id || null,\n start: `${dateStr} ${timeblock.starts_at_time}:00`,\n end: `${dateStr} ${timeblock.ends_at_time}:00`,\n is_finished: timeblock.is_finished || 0\n };\n });\n const payload = {\n ...this.subtask,\n timesheets,\n timeblocks\n };\n\n // For drafts with multiple employees, include employees array\n if (this.subtask.is_draft && this.isDraftWithMultipleEmployees) {\n const validEmployees = this._filterValidEmployees(this.subtask.employees, concept);\n\n // Assign timeblocks to each employee\n validEmployees.forEach(employee => {\n const employeeTimeblocks = this._getEmployeeTimeblocks(employee.id, true);\n employee.timeblocks = employeeTimeblocks.map(tb => ({\n start: `${moment__WEBPACK_IMPORTED_MODULE_16___default()(tb.date).format('YYYY-MM-DD')} ${tb.starts_at_time}:00`,\n end: `${moment__WEBPACK_IMPORTED_MODULE_16___default()(tb.date).format('YYYY-MM-DD')} ${tb.ends_at_time}:00`,\n id: tb.id || null\n }));\n });\n payload.employees = validEmployees;\n }\n if (concept) {\n payload.is_draft = 1;\n } else {\n payload.is_draft = 0;\n }\n const {\n subtask\n } = await this.$axios.patch_auth_form(`v1/subtasks/${this.subtask.id}`, payload);\n localStorage.removeItem('subtaskData');\n localStorage.removeItem('subtaskTimeblocks');\n this.$store.commit('tm/update_subtask', subtask);\n this.$events.emit('on-subtask-edited', this.subtask);\n } else {\n const validEmployees = this._filterValidEmployees(this.subtask.employees, concept);\n\n // Assign timeblocks to each employee based on employee_id\n // Filter out empty/incomplete timeblocks - only send fully filled timeblocks\n validEmployees.forEach(employee => {\n const employeeTimeblocks = this._getEmployeeTimeblocks(employee.id, true);\n employee.timeblocks = employeeTimeblocks.map(timeblock => {\n return {\n start: `${moment__WEBPACK_IMPORTED_MODULE_16___default()(timeblock.date).format('YYYY-MM-DD')} ${timeblock.starts_at_time}:00`,\n end: `${moment__WEBPACK_IMPORTED_MODULE_16___default()(timeblock.date).format('YYYY-MM-DD')} ${timeblock.ends_at_time}:00`,\n id: null\n };\n });\n });\n const subtaskCopy = {\n ...this.subtask,\n employees: validEmployees\n };\n if (concept) {\n subtaskCopy.is_draft = true;\n subtaskCopy.employees = subtaskCopy.employees?.length > 0 ? subtaskCopy.employees : [{\n id: this.$store.getters['auth/user']?.id,\n duration: 0\n }];\n }\n delete subtaskCopy._master_task;\n const {\n subtasks\n } = await this.$axios.post_auth(`v1/mastertasks/${this.subtask.master_task_id}/subtasks`, subtaskCopy);\n localStorage.removeItem('subtaskData');\n localStorage.removeItem('subtaskTimeblocks');\n this.subtask.id = subtasks[0].id;\n subtasks.forEach(subtask => {\n this.$store.commit('tm/update_subtask', subtask);\n this.$events.emit('on-subtask-edited', this.subtask);\n });\n this.$events.emit('task-created');\n this.$events.emit('close-both-modals');\n }\n this.closeModal();\n } catch (error) {\n console.log('error', error);\n this.$toast.error(this.$parseError(error));\n } finally {\n this.isSaving = false;\n }\n },\n openDeleteTaskModal(subtask) {\n if (subtask.type == 'office365') return this.$events.emit('show-unable-to-edit-office-task-modal', {\n mode: 'delete'\n });\n this.$events.emit('show-delete-task-modal', {\n subtask\n });\n },\n showCompleteTaskModal() {\n this.$events.emit('show-complete-task-modal', {\n subtask: this.subtask\n });\n if (this.subtask.deadline) this.subtask.deadline = _plugins_tm_utils_tm_utils__WEBPACK_IMPORTED_MODULE_15__[\"default\"].formatDateTimeForBackend(this.subtask.deadline);\n },\n filesUploaded(files) {\n this.subtask.files = files;\n },\n updateSubtask(subtask) {\n this.subtask = subtask;\n },\n _mergeDeadlineTimeDate() {\n // Override for concept tasks which may not have a deadline time set (check for invalid date)\n if (isNaN(new Date(this.subtask.deadline).getTime()) || !this.subtask._deadline_time) {\n this.subtask.deadline = null;\n } else {\n const date = new Date(this.subtask.deadline);\n const timeParts = this.subtask._deadline_time.split(':');\n date.setHours(parseInt(timeParts[0]));\n date.setMinutes(parseInt(timeParts[1]));\n this.subtask.deadline = date;\n }\n },\n _filterValidEmployees(employees, isConcept) {\n // Filter employees based on whether it's a concept/draft or published task\n // For concepts: only require id (duration can be null/0)\n // For published tasks: require both id and duration\n if (!Array.isArray(employees)) return [];\n return employees.filter(employee => {\n if (isConcept) {\n return employee.id; // Only require ID for concepts/drafts\n }\n return employee.id && employee.duration; // Require both for published tasks\n });\n },\n _getEmployeeTimeblocks(employeeId, requireComplete = true) {\n // Get timeblocks for a specific employee with proper type handling\n // Use Number() conversion to avoid type mismatch issues (string vs number)\n const filtered = this.timeblocks.filter(tb => {\n const idsMatch = Number(tb.employee_id) === Number(employeeId);\n if (!requireComplete) {\n return idsMatch;\n }\n\n // For complete timeblocks, also require date and time fields\n return idsMatch && tb.date && tb.starts_at_time && tb.ends_at_time;\n });\n return filtered;\n },\n async _validateEmployees() {\n if (this.subtask.id && !this.subtask.is_draft) {\n // For existing subtasks, at least one employee is required\n const hasEmployee = !!(this.subtask.employee_id && this.subtask.duration);\n return hasEmployee;\n } else {\n let valid = true;\n\n // Validate ALL employee component refs (this will show errors on inputs)\n for (let i = 0; i < this.employeeRefs.length; i++) {\n const employeeRef = this.employeeRefs[i];\n\n // Validate employees that have any data (partial or complete)\n if (employeeRef && typeof employeeRef.validate === 'function') {\n if (!(await employeeRef.validate())) {\n valid = false;\n }\n }\n }\n return valid;\n }\n },\n async _validateTimeblocks() {\n // Date alone is valid. Validation only applies if start OR end time is filled.\n // If start OR end is filled, then ALL fields (date, start, end) are required.\n let valid = true;\n for (const timeblock of this.timeblocks) {\n const hasStart = !!timeblock.starts_at_time;\n const hasEnd = !!timeblock.ends_at_time;\n const hasAnyTime = hasStart || hasEnd;\n\n // If no time data (start/end), timeblock is valid (date alone is OK)\n if (!hasAnyTime) {\n continue;\n }\n\n // If start OR end is filled, ALL fields are required\n const hasDate = !!timeblock.date;\n if (!hasDate || !hasStart || !hasEnd) {\n valid = false;\n break;\n }\n\n // Validate that end time is after start time\n const dateStr = moment__WEBPACK_IMPORTED_MODULE_16___default()(timeblock.date).format('YYYY-MM-DD');\n const start = moment__WEBPACK_IMPORTED_MODULE_16___default()(`${dateStr} ${timeblock.starts_at_time}`, 'YYYY-MM-DD HH:mm');\n const end = moment__WEBPACK_IMPORTED_MODULE_16___default()(`${dateStr} ${timeblock.ends_at_time}`, 'YYYY-MM-DD HH:mm');\n if (end.isSameOrBefore(start)) {\n valid = false;\n break;\n }\n }\n return valid;\n },\n _enrichTask(subtask) {\n return {\n ...subtask,\n _created_by: this.enrichedEmployees.find(employee => employee.id == subtask.created_by),\n _employee: this.enrichedEmployees.find(employee => employee.id == subtask.employee_id),\n _master_task: this.mastertasks.find(mastertask => mastertask.id == subtask.master_task_id)\n };\n }\n }\n});\n\n//# sourceURL=webpack://jandl/./src/plugins/tm@modal/task/z-task-modal.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}"); /***/ }), @@ -785,7 +785,7 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _no /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../../../node_modules/css-loader/dist/runtime/noSourceMaps.js */ \"./node_modules/css-loader/dist/runtime/noSourceMaps.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../../../node_modules/css-loader/dist/runtime/api.js */ \"./node_modules/css-loader/dist/runtime/api.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__);\n// Imports\n\n\nvar ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \".completed[data-v-27fac1fc] {\\n background: #06dece;\\n}\\n.existing-timeblock-timeline[data-v-27fac1fc] {\\n margin-top: 8px;\\n padding-left: 16px;\\n}\\n.add-timeblock-modal[data-v-27fac1fc] .timeblock__header__top {\\n display: none;\\n}\\n.add-timeblock-modal[data-v-27fac1fc] .actions {\\n display: none;\\n}\", \"\"]);\n// Exports\n/* harmony default export */ __webpack_exports__[\"default\"] = (___CSS_LOADER_EXPORT___);\n\n\n//# sourceURL=webpack://jandl/./src/plugins/tm@modal/task/_components/_components/a-task-timeblocks.vue?./node_modules/css-loader/dist/cjs.js??clonedRuleSet-27.use%5B1%5D!./node_modules/vue-loader/dist/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-27.use%5B2%5D!./node_modules/sass-loader/dist/cjs.js??clonedRuleSet-27.use%5B3%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}"); +eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../../../node_modules/css-loader/dist/runtime/noSourceMaps.js */ \"./node_modules/css-loader/dist/runtime/noSourceMaps.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../../../node_modules/css-loader/dist/runtime/api.js */ \"./node_modules/css-loader/dist/runtime/api.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__);\n// Imports\n\n\nvar ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \".completed[data-v-27fac1fc] {\\n background: #06dece;\\n}\\n.disabled-check[data-v-27fac1fc] {\\n opacity: 0.5;\\n cursor: not-allowed;\\n}\\n.existing-timeblock-timeline[data-v-27fac1fc] {\\n margin-top: 8px;\\n padding-left: 16px;\\n}\\n.add-timeblock-modal[data-v-27fac1fc] .timeblock__header__top {\\n display: none;\\n}\\n.add-timeblock-modal[data-v-27fac1fc] .actions {\\n display: none;\\n}\", \"\"]);\n// Exports\n/* harmony default export */ __webpack_exports__[\"default\"] = (___CSS_LOADER_EXPORT___);\n\n\n//# sourceURL=webpack://jandl/./src/plugins/tm@modal/task/_components/_components/a-task-timeblocks.vue?./node_modules/css-loader/dist/cjs.js??clonedRuleSet-27.use%5B1%5D!./node_modules/vue-loader/dist/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-27.use%5B2%5D!./node_modules/sass-loader/dist/cjs.js??clonedRuleSet-27.use%5B3%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}"); /***/ }), @@ -840,7 +840,7 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _no /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../../../node_modules/css-loader/dist/runtime/noSourceMaps.js */ \"./node_modules/css-loader/dist/runtime/noSourceMaps.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../../../node_modules/css-loader/dist/runtime/api.js */ \"./node_modules/css-loader/dist/runtime/api.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__);\n// Imports\n\n\nvar ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \".timeline-scroll[data-v-5ca7dec4] {\\n overflow-x: auto;\\n overflow-y: hidden;\\n position: relative;\\n width: 100%;\\n scrollbar-width: none;\\n}\\n.timeline-scroll[data-v-5ca7dec4]::-webkit-scrollbar {\\n display: none;\\n}\\n.timeline-bar[data-v-5ca7dec4] {\\n position: relative;\\n height: 30px;\\n width: 1440px;\\n background: #fafafa;\\n border-radius: 4px;\\n cursor: crosshair;\\n}\\n@media (max-width: 768px) {\\n.timeline-bar[data-v-5ca7dec4] {\\n width: 1200px;\\n}\\n}\\n.non-working-hours[data-v-5ca7dec4] {\\n position: absolute;\\n top: 0;\\n height: 100%;\\n background: repeating-linear-gradient(45deg, transparent, transparent 10px, rgba(224, 224, 224, 0.3) 10px, rgba(224, 224, 224, 0.3) 20px);\\n z-index: 1;\\n pointer-events: none;\\n}\\n.work-hours-bar[data-v-5ca7dec4] {\\n position: absolute;\\n top: 0;\\n height: 100%;\\n background: transparent;\\n z-index: 1;\\n pointer-events: none;\\n}\\n.scheduled-block[data-v-5ca7dec4] {\\n position: absolute;\\n top: 5px;\\n height: 22px;\\n background: #7f39fb;\\n border: 1px solid #6a1bf7;\\n opacity: 0.6;\\n border-radius: 2px;\\n z-index: 2;\\n pointer-events: none;\\n}\\n.scheduled-block--blocker[data-v-5ca7dec4] {\\n background: rgb(176, 0, 32);\\n border: 1px solid rgb(156, 0, 28);\\n opacity: 0.7;\\n}\\n.other-timeblock[data-v-5ca7dec4] {\\n position: absolute;\\n top: 5px;\\n height: 22px;\\n background: #FFA726;\\n opacity: 0.5;\\n border: 2px dashed #FF9800;\\n border-radius: 2px;\\n z-index: 2;\\n pointer-events: none;\\n}\\n.preview-block[data-v-5ca7dec4] {\\n position: absolute;\\n top: 5px;\\n height: 22px;\\n background: #4CAF50;\\n opacity: 0.6;\\n border: 2px dashed #388E3C;\\n border-radius: 2px;\\n z-index: 5;\\n cursor: crosshair;\\n transition: opacity 0.2s, box-shadow 0.2s;\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n}\\n.preview-block[data-v-5ca7dec4]:hover {\\n opacity: 0.8;\\n box-shadow: 0 2px 8px rgba(76, 175, 80, 0.4);\\n}\\n.preview-block.is-stretching[data-v-5ca7dec4] {\\n opacity: 0.8;\\n box-shadow: 0 4px 12px rgba(76, 175, 80, 0.6);\\n cursor: ew-resize;\\n}\\n.preview-time-label[data-v-5ca7dec4] {\\n font-size: 11px;\\n font-weight: 600;\\n color: white;\\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);\\n white-space: nowrap;\\n pointer-events: none;\\n -webkit-user-select: none;\\n -moz-user-select: none;\\n user-select: none;\\n}\\n.current-timeblock[data-v-5ca7dec4] {\\n position: absolute;\\n top: 5px;\\n height: 22px;\\n background: #2196F3;\\n opacity: 0.7;\\n border: 2px solid #1976D2;\\n border-radius: 2px;\\n z-index: 3;\\n transition: box-shadow 0.2s;\\n}\\n.current-timeblock.has-collision[data-v-5ca7dec4] {\\n border-color: #ff5252;\\n}\\n.current-timeblock.is-resizing[data-v-5ca7dec4] {\\n opacity: 0.8;\\n box-shadow: 0 4px 12px rgba(33, 150, 243, 0.6);\\n z-index: 6;\\n}\\n.resize-handle[data-v-5ca7dec4] {\\n position: absolute;\\n top: 0;\\n width: 8px;\\n height: 100%;\\n cursor: ew-resize;\\n z-index: 4;\\n}\\n.resize-handle[data-v-5ca7dec4]:hover {\\n background: rgba(255, 255, 255, 0.3);\\n}\\n.resize-handle--left[data-v-5ca7dec4] {\\n left: 0;\\n border-top-left-radius: 2px;\\n border-bottom-left-radius: 2px;\\n}\\n.resize-handle--right[data-v-5ca7dec4] {\\n right: 0;\\n border-top-right-radius: 2px;\\n border-bottom-right-radius: 2px;\\n}\\n.collision-segment[data-v-5ca7dec4] {\\n position: absolute;\\n top: 5px;\\n height: 22px;\\n background: #ff5252;\\n opacity: 0.6;\\n border-radius: 2px;\\n z-index: 4;\\n pointer-events: none;\\n}\\n.timeblock-duration[data-v-5ca7dec4] {\\n position: absolute;\\n top: 50%;\\n left: 50%;\\n transform: translate(-50%, -50%);\\n font-size: 14px;\\n font-weight: bold;\\n color: white;\\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);\\n pointer-events: none;\\n -webkit-user-select: none;\\n -moz-user-select: none;\\n user-select: none;\\n}\\n.timeline-loading[data-v-5ca7dec4] {\\n height: 60px;\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n font-size: 14px;\\n opacity: 0.5;\\n}\", \"\"]);\n// Exports\n/* harmony default export */ __webpack_exports__[\"default\"] = (___CSS_LOADER_EXPORT___);\n\n\n//# sourceURL=webpack://jandl/./src/plugins/tm@modal/task/_components/employees/a-employee-timeblock-timeline.vue?./node_modules/css-loader/dist/cjs.js??clonedRuleSet-27.use%5B1%5D!./node_modules/vue-loader/dist/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-27.use%5B2%5D!./node_modules/sass-loader/dist/cjs.js??clonedRuleSet-27.use%5B3%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}"); +eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../../../node_modules/css-loader/dist/runtime/noSourceMaps.js */ \"./node_modules/css-loader/dist/runtime/noSourceMaps.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../../../node_modules/css-loader/dist/runtime/api.js */ \"./node_modules/css-loader/dist/runtime/api.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__);\n// Imports\n\n\nvar ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \".timeline-scroll[data-v-5ca7dec4] {\\n overflow-x: auto;\\n overflow-y: hidden;\\n position: relative;\\n width: 100%;\\n scrollbar-width: none;\\n}\\n.timeline-scroll[data-v-5ca7dec4]::-webkit-scrollbar {\\n display: none;\\n}\\n.timeline-bar[data-v-5ca7dec4] {\\n position: relative;\\n height: 30px;\\n width: 1440px;\\n background: #fafafa;\\n border-radius: 4px;\\n cursor: crosshair;\\n}\\n@media (max-width: 768px) {\\n.timeline-bar[data-v-5ca7dec4] {\\n width: 1200px;\\n}\\n}\\n.non-working-hours[data-v-5ca7dec4] {\\n position: absolute;\\n top: 0;\\n height: 100%;\\n background: repeating-linear-gradient(45deg, transparent, transparent 10px, rgba(224, 224, 224, 0.3) 10px, rgba(224, 224, 224, 0.3) 20px);\\n z-index: 1;\\n pointer-events: none;\\n}\\n.work-hours-bar[data-v-5ca7dec4] {\\n position: absolute;\\n top: 0;\\n height: 100%;\\n background: transparent;\\n z-index: 1;\\n pointer-events: none;\\n}\\n.weekend-overlay[data-v-5ca7dec4] {\\n position: absolute;\\n top: 0;\\n left: 0;\\n width: 100%;\\n height: 100%;\\n background: rgba(255, 124, 124, 0.3) !important;\\n z-index: 1;\\n pointer-events: none;\\n border-radius: 4px;\\n}\\n.scheduled-block[data-v-5ca7dec4] {\\n position: absolute;\\n top: 5px;\\n height: 22px;\\n background: #7f39fb;\\n border: 1px solid #6a1bf7;\\n opacity: 0.6;\\n border-radius: 2px;\\n z-index: 2;\\n pointer-events: none;\\n}\\n.scheduled-block--blocker[data-v-5ca7dec4] {\\n background: rgb(176, 0, 32);\\n border: 1px solid rgb(156, 0, 28);\\n opacity: 0.7;\\n}\\n.other-timeblock[data-v-5ca7dec4] {\\n position: absolute;\\n top: 5px;\\n height: 22px;\\n background: #FFA726;\\n opacity: 0.5;\\n border: 2px dashed #FF9800;\\n border-radius: 2px;\\n z-index: 2;\\n pointer-events: none;\\n}\\n.preview-block[data-v-5ca7dec4] {\\n position: absolute;\\n top: 5px;\\n height: 22px;\\n background: #4CAF50;\\n opacity: 0.6;\\n border: 2px dashed #388E3C;\\n border-radius: 2px;\\n z-index: 5;\\n cursor: crosshair;\\n transition: opacity 0.2s, box-shadow 0.2s;\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n}\\n.preview-block[data-v-5ca7dec4]:hover {\\n opacity: 0.8;\\n box-shadow: 0 2px 8px rgba(76, 175, 80, 0.4);\\n}\\n.preview-block.is-stretching[data-v-5ca7dec4] {\\n opacity: 0.8;\\n box-shadow: 0 4px 12px rgba(76, 175, 80, 0.6);\\n cursor: ew-resize;\\n}\\n.preview-time-label[data-v-5ca7dec4] {\\n font-size: 11px;\\n font-weight: 600;\\n color: white;\\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);\\n white-space: nowrap;\\n pointer-events: none;\\n -webkit-user-select: none;\\n -moz-user-select: none;\\n user-select: none;\\n}\\n.current-timeblock[data-v-5ca7dec4] {\\n position: absolute;\\n top: 5px;\\n height: 22px;\\n background: #2196F3;\\n opacity: 0.7;\\n border: 2px solid #1976D2;\\n border-radius: 2px;\\n z-index: 3;\\n transition: box-shadow 0.2s;\\n}\\n.current-timeblock.has-collision[data-v-5ca7dec4] {\\n border-color: #ff5252;\\n}\\n.current-timeblock.is-resizing[data-v-5ca7dec4] {\\n opacity: 0.8;\\n box-shadow: 0 4px 12px rgba(33, 150, 243, 0.6);\\n z-index: 6;\\n}\\n.resize-handle[data-v-5ca7dec4] {\\n position: absolute;\\n top: 0;\\n width: 8px;\\n height: 100%;\\n cursor: ew-resize;\\n z-index: 4;\\n}\\n.resize-handle[data-v-5ca7dec4]:hover {\\n background: rgba(255, 255, 255, 0.3);\\n}\\n.resize-handle--left[data-v-5ca7dec4] {\\n left: 0;\\n border-top-left-radius: 2px;\\n border-bottom-left-radius: 2px;\\n}\\n.resize-handle--right[data-v-5ca7dec4] {\\n right: 0;\\n border-top-right-radius: 2px;\\n border-bottom-right-radius: 2px;\\n}\\n.collision-segment[data-v-5ca7dec4] {\\n position: absolute;\\n top: 5px;\\n height: 22px;\\n background: #ff5252;\\n opacity: 0.6;\\n border-radius: 2px;\\n z-index: 4;\\n pointer-events: none;\\n}\\n.timeblock-duration[data-v-5ca7dec4] {\\n position: absolute;\\n top: 50%;\\n left: 50%;\\n transform: translate(-50%, -50%);\\n font-size: 14px;\\n font-weight: bold;\\n color: white;\\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);\\n pointer-events: none;\\n -webkit-user-select: none;\\n -moz-user-select: none;\\n user-select: none;\\n}\\n.timeline-loading[data-v-5ca7dec4] {\\n height: 60px;\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n font-size: 14px;\\n opacity: 0.5;\\n}\", \"\"]);\n// Exports\n/* harmony default export */ __webpack_exports__[\"default\"] = (___CSS_LOADER_EXPORT___);\n\n\n//# sourceURL=webpack://jandl/./src/plugins/tm@modal/task/_components/employees/a-employee-timeblock-timeline.vue?./node_modules/css-loader/dist/cjs.js??clonedRuleSet-27.use%5B1%5D!./node_modules/vue-loader/dist/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-27.use%5B2%5D!./node_modules/sass-loader/dist/cjs.js??clonedRuleSet-27.use%5B3%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}"); /***/ }), @@ -851,7 +851,7 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _no /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../../../node_modules/css-loader/dist/runtime/noSourceMaps.js */ \"./node_modules/css-loader/dist/runtime/noSourceMaps.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../../../node_modules/css-loader/dist/runtime/api.js */ \"./node_modules/css-loader/dist/runtime/api.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__);\n// Imports\n\n\nvar ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \".timeblock[data-v-681eadcc] {\\n width: 100%;\\n border: 1px solid #e5e5e5;\\n border-radius: 8px;\\n margin-bottom: 8px;\\n overflow: hidden;\\n}\", \"\"]);\n// Exports\n/* harmony default export */ __webpack_exports__[\"default\"] = (___CSS_LOADER_EXPORT___);\n\n\n//# sourceURL=webpack://jandl/./src/plugins/tm@modal/task/_components/employees/a-employee-timeblock.vue?./node_modules/css-loader/dist/cjs.js??clonedRuleSet-27.use%5B1%5D!./node_modules/vue-loader/dist/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-27.use%5B2%5D!./node_modules/sass-loader/dist/cjs.js??clonedRuleSet-27.use%5B3%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}"); +eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../../../node_modules/css-loader/dist/runtime/noSourceMaps.js */ \"./node_modules/css-loader/dist/runtime/noSourceMaps.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../../../node_modules/css-loader/dist/runtime/api.js */ \"./node_modules/css-loader/dist/runtime/api.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__);\n// Imports\n\n\nvar ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \".timeblock[data-v-681eadcc] {\\n width: 100%;\\n border: 1px solid #e5e5e5;\\n border-radius: 8px;\\n margin-bottom: 8px;\\n overflow: hidden;\\n}\\n.timeblock--finished[data-v-681eadcc] {\\n opacity: 0.4;\\n pointer-events: none;\\n cursor: not-allowed;\\n}\", \"\"]);\n// Exports\n/* harmony default export */ __webpack_exports__[\"default\"] = (___CSS_LOADER_EXPORT___);\n\n\n//# sourceURL=webpack://jandl/./src/plugins/tm@modal/task/_components/employees/a-employee-timeblock.vue?./node_modules/css-loader/dist/cjs.js??clonedRuleSet-27.use%5B1%5D!./node_modules/vue-loader/dist/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-27.use%5B2%5D!./node_modules/sass-loader/dist/cjs.js??clonedRuleSet-27.use%5B3%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}"); /***/ }), @@ -1242,7 +1242,7 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var cor /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_esnext_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/esnext.iterator.constructor.js */ \"./node_modules/core-js/modules/esnext.iterator.constructor.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_esnext_iterator_filter_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/esnext.iterator.filter.js */ \"./node_modules/core-js/modules/esnext.iterator.filter.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_filter_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_filter_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var core_js_modules_esnext_iterator_map_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! core-js/modules/esnext.iterator.map.js */ \"./node_modules/core-js/modules/esnext.iterator.map.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_map_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_map_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm-bundler.js\");\n/* harmony import */ var moment__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! moment */ \"./node_modules/moment/moment.js\");\n/* harmony import */ var moment__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(moment__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var _a_employee_timeblock_timeline_header_vue__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./a-employee-timeblock-timeline-header.vue */ \"./src/plugins/tm@modal/task/_components/employees/a-employee-timeblock-timeline-header.vue\");\n\n\n\n\n\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (/*@__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_3__.defineComponent)({\n __name: 'a-employee-timeblock-timeline',\n props: {\n isLoading: {\n type: Boolean,\n required: true\n },\n employee: {\n type: Object,\n required: true\n },\n scheduledBlocks: {\n type: Array,\n required: true\n },\n otherTimeblocks: {\n type: Array,\n required: false,\n default: () => []\n },\n currentTimeblockRange: {\n type: Object,\n required: true\n },\n collision: {\n type: Object,\n required: true\n },\n collisionSegments: {\n type: Array,\n required: true\n },\n timeblockDuration: {\n type: Number,\n required: true\n },\n startHour: {\n type: Number,\n required: true\n },\n endHour: {\n type: Number,\n required: true\n },\n hourWidth: {\n type: Number,\n required: true\n }\n },\n emits: [\"timeblockUpdated\"],\n setup(__props, {\n expose: __expose,\n emit: __emit\n }) {\n const props = __props;\n const emit = __emit;\n const timelineContainer = (0,vue__WEBPACK_IMPORTED_MODULE_3__.ref)(null);\n const timelineScroll = (0,vue__WEBPACK_IMPORTED_MODULE_3__.ref)(null);\n const timelineBar = (0,vue__WEBPACK_IMPORTED_MODULE_3__.ref)(null);\n // Check if mobile device\n const isMobile = (0,vue__WEBPACK_IMPORTED_MODULE_3__.ref)(false);\n // Interactive state\n const showPreview = (0,vue__WEBPACK_IMPORTED_MODULE_3__.ref)(false);\n const previewBlock = (0,vue__WEBPACK_IMPORTED_MODULE_3__.ref)(null);\n const dragState = (0,vue__WEBPACK_IMPORTED_MODULE_3__.ref)({\n isStretching: false,\n isResizingCurrent: false,\n resizeEdge: null,\n startX: 0,\n initialStart: null,\n initialEnd: null\n });\n const resizedCurrentBlock = (0,vue__WEBPACK_IMPORTED_MODULE_3__.ref)(null);\n // Convert other timeblocks to renderable format\n const otherTimeblocksRendered = (0,vue__WEBPACK_IMPORTED_MODULE_3__.computed)(() => {\n return props.otherTimeblocks.map(tb => {\n if (!tb.date || !tb.starts_at_time || !tb.ends_at_time) return null;\n const [startHour, startMinute] = tb.starts_at_time.split(':').map(Number);\n const [endHour, endMinute] = tb.ends_at_time.split(':').map(Number);\n const start = moment__WEBPACK_IMPORTED_MODULE_4___default()(tb.date).set({\n hour: startHour,\n minute: startMinute,\n second: 0\n }).toDate();\n const end = moment__WEBPACK_IMPORTED_MODULE_4___default()(tb.date).set({\n hour: endHour,\n minute: endMinute,\n second: 0\n }).toDate();\n return {\n _start: start,\n _end: end\n };\n }).filter(tb => tb !== null);\n });\n // Position calculations\n const getHourPosition = hour => {\n return (hour - props.startHour) * props.hourWidth;\n };\n const getHourWidth = hours => {\n return hours * props.hourWidth;\n };\n const getTimePosition = date => {\n const hour = date.getHours();\n const minute = date.getMinutes();\n const totalHours = hour + minute / 60;\n return (totalHours - props.startHour) * props.hourWidth + 1;\n };\n const getTimeWidth = (start, end) => {\n const startHour = start.getHours() + start.getMinutes() / 60;\n const endHour = end.getHours() + end.getMinutes() / 60;\n return (endHour - startHour) * props.hourWidth - 2;\n };\n // Time snapping utility - snap to 15 minute intervals\n const snapToInterval = (date, intervalMinutes = 15) => {\n const minutes = date.getMinutes();\n const snappedMinutes = Math.round(minutes / intervalMinutes) * intervalMinutes;\n return moment__WEBPACK_IMPORTED_MODULE_4___default()(date).set({\n minute: snappedMinutes,\n second: 0,\n millisecond: 0\n }).toDate();\n };\n // Convert pixel position to time\n const positionToTime = pixelX => {\n const hoursFromStart = pixelX / props.hourWidth;\n const totalHours = props.startHour + hoursFromStart;\n const hour = Math.floor(totalHours);\n const minute = totalHours % 1 * 60;\n // Use current date from currentTimeblockRange or today\n const baseDate = props.currentTimeblockRange.start ? moment__WEBPACK_IMPORTED_MODULE_4___default()(props.currentTimeblockRange.start) : moment__WEBPACK_IMPORTED_MODULE_4___default()();\n return baseDate.set({\n hour,\n minute,\n second: 0,\n millisecond: 0\n }).toDate();\n };\n // Format time as HH:mm\n const formatTime = date => {\n return moment__WEBPACK_IMPORTED_MODULE_4___default()(date).format('HH:mm');\n };\n // Check if mouse is over an existing block (x is already relative position with scroll)\n const isOverExistingBlock = relativeX => {\n // Check if over any scheduled block\n for (const task of props.scheduledBlocks) {\n const blockLeft = getTimePosition(task._real_start);\n const blockWidth = getTimeWidth(task._real_start, task._real_end);\n if (relativeX >= blockLeft && relativeX <= blockLeft + blockWidth) {\n return true;\n }\n }\n // Check if over any other timeblock\n for (const tb of otherTimeblocksRendered.value) {\n const blockLeft = getTimePosition(tb._start);\n const blockWidth = getTimeWidth(tb._start, tb._end);\n if (relativeX >= blockLeft && relativeX <= blockLeft + blockWidth) {\n return true;\n }\n }\n // Check if over current timeblock\n if (props.currentTimeblockRange.start && props.currentTimeblockRange.end) {\n const blockLeft = getTimePosition(props.currentTimeblockRange.start);\n const blockWidth = getTimeWidth(props.currentTimeblockRange.start, props.currentTimeblockRange.end);\n if (relativeX >= blockLeft && relativeX <= blockLeft + blockWidth) {\n return true;\n }\n }\n return false;\n };\n // Mouse move handler - show preview\n const handleMouseMove = event => {\n // Disable hover preview on mobile\n if (isMobile.value) {\n return;\n }\n if (dragState.value.isStretching) {\n handleStretchMove(event);\n return;\n }\n if (dragState.value.isResizingCurrent) {\n handleResizeCurrentMove(event);\n return;\n }\n if (!timelineScroll.value) return;\n // Get position relative to scroll container, accounting for scroll\n const rect = timelineScroll.value.getBoundingClientRect();\n const scrollLeft = timelineScroll.value.scrollLeft;\n const x = event.clientX - rect.left + scrollLeft;\n // Don't show preview if over existing block (using relative position)\n if (isOverExistingBlock(x)) {\n showPreview.value = false;\n return;\n }\n // Convert to time and snap\n const rawTime = positionToTime(x);\n const snappedStart = snapToInterval(rawTime);\n const snappedEnd = moment__WEBPACK_IMPORTED_MODULE_4___default()(snappedStart).add(1, 'hour').toDate();\n // Only show preview within work hours\n const startHour = snappedStart.getHours() + snappedStart.getMinutes() / 60;\n const endHour = snappedEnd.getHours() + snappedEnd.getMinutes() / 60;\n if (startHour >= props.employee.work_start && endHour <= props.employee.work_end) {\n showPreview.value = true;\n previewBlock.value = {\n start: snappedStart,\n end: snappedEnd\n };\n } else {\n showPreview.value = false;\n }\n };\n // Mouse leave handler\n const handleMouseLeave = () => {\n if (!dragState.value.isStretching && !dragState.value.isResizingCurrent) {\n showPreview.value = false;\n }\n };\n // Mouse down on timeline bar (not on preview or current block)\n const handleMouseDown = _event => {\n // This will only trigger if not clicking on preview or current block\n // (those have @mousedown.stop)\n };\n // Preview block mouse down - start creating/stretching\n const handlePreviewMouseDown = event => {\n if (!previewBlock.value) return;\n dragState.value.isStretching = true;\n dragState.value.startX = event.clientX;\n dragState.value.initialStart = previewBlock.value.start;\n dragState.value.initialEnd = previewBlock.value.end;\n event.preventDefault();\n };\n // Handle stretch move\n const handleStretchMove = event => {\n if (!dragState.value.initialStart || !timelineScroll.value) return;\n const rect = timelineScroll.value.getBoundingClientRect();\n const x = event.clientX - rect.left + timelineScroll.value.scrollLeft;\n const currentTime = positionToTime(x);\n const snappedTime = snapToInterval(currentTime);\n const initialStartTime = dragState.value.initialStart.getTime();\n const snappedTimeValue = snappedTime.getTime();\n if (snappedTimeValue > initialStartTime) {\n // Stretching right (extending end)\n previewBlock.value = {\n start: dragState.value.initialStart,\n end: snappedTime\n };\n } else {\n // Stretching left (extending start)\n previewBlock.value = {\n start: snappedTime,\n end: dragState.value.initialStart\n };\n }\n };\n // Handle stretch end\n const handleStretchEnd = () => {\n if (dragState.value.isStretching && previewBlock.value) {\n // Emit the new timeblock\n emit('timeblockUpdated', {\n starts_at_time: formatTime(previewBlock.value.start),\n ends_at_time: formatTime(previewBlock.value.end)\n });\n }\n dragState.value.isStretching = false;\n dragState.value.initialStart = null;\n dragState.value.initialEnd = null;\n showPreview.value = false;\n };\n // Resize handle mouse down - start resizing\n const handleResizeMouseDown = (event, edge) => {\n if (!props.currentTimeblockRange.start || !props.currentTimeblockRange.end) return;\n dragState.value.isResizingCurrent = true;\n dragState.value.resizeEdge = edge;\n dragState.value.startX = event.clientX;\n dragState.value.initialStart = props.currentTimeblockRange.start;\n dragState.value.initialEnd = props.currentTimeblockRange.end;\n resizedCurrentBlock.value = {\n start: props.currentTimeblockRange.start,\n end: props.currentTimeblockRange.end\n };\n event.preventDefault();\n };\n // Handle resize current block move\n const handleResizeCurrentMove = event => {\n if (!dragState.value.initialStart || !dragState.value.initialEnd || !timelineScroll.value) return;\n const rect = timelineScroll.value.getBoundingClientRect();\n const x = event.clientX - rect.left + timelineScroll.value.scrollLeft;\n const currentTime = positionToTime(x);\n const snappedTime = snapToInterval(currentTime);\n if (dragState.value.resizeEdge === 'left') {\n // Resizing left edge (changing start time)\n // Make sure new start is before end\n if (snappedTime < dragState.value.initialEnd) {\n resizedCurrentBlock.value = {\n start: snappedTime,\n end: dragState.value.initialEnd\n };\n }\n } else if (dragState.value.resizeEdge === 'right') {\n // Resizing right edge (changing end time)\n // Make sure new end is after start\n if (snappedTime > dragState.value.initialStart) {\n resizedCurrentBlock.value = {\n start: dragState.value.initialStart,\n end: snappedTime\n };\n }\n }\n };\n // Handle resize current block end\n const handleResizeCurrentEnd = () => {\n if (dragState.value.isResizingCurrent && resizedCurrentBlock.value) {\n // Emit the updated timeblock\n emit('timeblockUpdated', {\n starts_at_time: formatTime(resizedCurrentBlock.value.start),\n ends_at_time: formatTime(resizedCurrentBlock.value.end)\n });\n }\n dragState.value.isResizingCurrent = false;\n dragState.value.resizeEdge = null;\n dragState.value.initialStart = null;\n dragState.value.initialEnd = null;\n resizedCurrentBlock.value = null;\n };\n // Global mouse up handler\n const handleGlobalMouseUp = () => {\n if (dragState.value.isStretching) {\n handleStretchEnd();\n } else if (dragState.value.isResizingCurrent) {\n handleResizeCurrentEnd();\n }\n };\n // Global mouse move handler\n const handleGlobalMouseMove = event => {\n if (dragState.value.isStretching) {\n handleStretchMove(event);\n } else if (dragState.value.isResizingCurrent) {\n handleResizeCurrentMove(event);\n }\n };\n // Setup global listeners\n (0,vue__WEBPACK_IMPORTED_MODULE_3__.onMounted)(() => {\n // Detect mobile device\n isMobile.value = window.innerWidth <= 768;\n // Listen for resize to update mobile status\n const handleResize = () => {\n isMobile.value = window.innerWidth <= 768;\n };\n window.addEventListener('resize', handleResize);\n document.addEventListener('mouseup', handleGlobalMouseUp);\n document.addEventListener('mousemove', handleGlobalMouseMove);\n });\n (0,vue__WEBPACK_IMPORTED_MODULE_3__.onUnmounted)(() => {\n document.removeEventListener('mouseup', handleGlobalMouseUp);\n document.removeEventListener('mousemove', handleGlobalMouseMove);\n });\n // Expose refs for parent component\n __expose({\n timelineScroll\n });\n const __returned__ = {\n props,\n emit,\n timelineContainer,\n timelineScroll,\n timelineBar,\n isMobile,\n showPreview,\n previewBlock,\n dragState,\n resizedCurrentBlock,\n otherTimeblocksRendered,\n getHourPosition,\n getHourWidth,\n getTimePosition,\n getTimeWidth,\n snapToInterval,\n positionToTime,\n formatTime,\n isOverExistingBlock,\n handleMouseMove,\n handleMouseLeave,\n handleMouseDown,\n handlePreviewMouseDown,\n handleStretchMove,\n handleStretchEnd,\n handleResizeMouseDown,\n handleResizeCurrentMove,\n handleResizeCurrentEnd,\n handleGlobalMouseUp,\n handleGlobalMouseMove,\n AEmployeeTimeblockTimelineHeader: _a_employee_timeblock_timeline_header_vue__WEBPACK_IMPORTED_MODULE_5__[\"default\"]\n };\n Object.defineProperty(__returned__, '__isScriptSetup', {\n enumerable: false,\n value: true\n });\n return __returned__;\n }\n}));\n\n//# sourceURL=webpack://jandl/./src/plugins/tm@modal/task/_components/employees/a-employee-timeblock-timeline.vue?./node_modules/webpack-plugin-vuetify/dist/scriptLoader.js!./node_modules/babel-loader/lib/index.js!./node_modules/ts-loader/index.js??clonedRuleSet-41.use%5B1%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}"); +eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_esnext_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/esnext.iterator.constructor.js */ \"./node_modules/core-js/modules/esnext.iterator.constructor.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_esnext_iterator_filter_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/esnext.iterator.filter.js */ \"./node_modules/core-js/modules/esnext.iterator.filter.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_filter_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_filter_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var core_js_modules_esnext_iterator_map_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! core-js/modules/esnext.iterator.map.js */ \"./node_modules/core-js/modules/esnext.iterator.map.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_map_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_map_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm-bundler.js\");\n/* harmony import */ var moment__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! moment */ \"./node_modules/moment/moment.js\");\n/* harmony import */ var moment__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(moment__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var _a_employee_timeblock_timeline_header_vue__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./a-employee-timeblock-timeline-header.vue */ \"./src/plugins/tm@modal/task/_components/employees/a-employee-timeblock-timeline-header.vue\");\n\n\n\n\n\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (/*@__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_3__.defineComponent)({\n __name: 'a-employee-timeblock-timeline',\n props: {\n isLoading: {\n type: Boolean,\n required: true\n },\n employee: {\n type: Object,\n required: true\n },\n scheduledBlocks: {\n type: Array,\n required: true\n },\n otherTimeblocks: {\n type: Array,\n required: false,\n default: () => []\n },\n currentTimeblockRange: {\n type: Object,\n required: true\n },\n collision: {\n type: Object,\n required: true\n },\n collisionSegments: {\n type: Array,\n required: true\n },\n timeblockDuration: {\n type: Number,\n required: true\n },\n startHour: {\n type: Number,\n required: true\n },\n endHour: {\n type: Number,\n required: true\n },\n hourWidth: {\n type: Number,\n required: true\n }\n },\n emits: [\"timeblockUpdated\"],\n setup(__props, {\n expose: __expose,\n emit: __emit\n }) {\n const props = __props;\n const emit = __emit;\n const timelineContainer = (0,vue__WEBPACK_IMPORTED_MODULE_3__.ref)(null);\n const timelineScroll = (0,vue__WEBPACK_IMPORTED_MODULE_3__.ref)(null);\n const timelineBar = (0,vue__WEBPACK_IMPORTED_MODULE_3__.ref)(null);\n // Check if mobile device\n const isMobile = (0,vue__WEBPACK_IMPORTED_MODULE_3__.ref)(false);\n // Interactive state\n const showPreview = (0,vue__WEBPACK_IMPORTED_MODULE_3__.ref)(false);\n const previewBlock = (0,vue__WEBPACK_IMPORTED_MODULE_3__.ref)(null);\n const dragState = (0,vue__WEBPACK_IMPORTED_MODULE_3__.ref)({\n isStretching: false,\n isResizingCurrent: false,\n resizeEdge: null,\n startX: 0,\n initialStart: null,\n initialEnd: null\n });\n const resizedCurrentBlock = (0,vue__WEBPACK_IMPORTED_MODULE_3__.ref)(null);\n // Check if the current date is a weekend (Saturday or Sunday)\n const isWeekend = (0,vue__WEBPACK_IMPORTED_MODULE_3__.computed)(() => {\n const date = props.currentTimeblockRange.start;\n if (!date) return false;\n const dayOfWeek = moment__WEBPACK_IMPORTED_MODULE_4___default()(date).day(); // 0 = Sunday, 6 = Saturday\n return dayOfWeek === 0 || dayOfWeek === 6;\n });\n // Convert other timeblocks to renderable format\n const otherTimeblocksRendered = (0,vue__WEBPACK_IMPORTED_MODULE_3__.computed)(() => {\n return props.otherTimeblocks.map(tb => {\n if (!tb.date || !tb.starts_at_time || !tb.ends_at_time) return null;\n const [startHour, startMinute] = tb.starts_at_time.split(':').map(Number);\n const [endHour, endMinute] = tb.ends_at_time.split(':').map(Number);\n const start = moment__WEBPACK_IMPORTED_MODULE_4___default()(tb.date).set({\n hour: startHour,\n minute: startMinute,\n second: 0\n }).toDate();\n const end = moment__WEBPACK_IMPORTED_MODULE_4___default()(tb.date).set({\n hour: endHour,\n minute: endMinute,\n second: 0\n }).toDate();\n return {\n _start: start,\n _end: end\n };\n }).filter(tb => tb !== null);\n });\n // Position calculations\n const getHourPosition = hour => {\n return (hour - props.startHour) * props.hourWidth;\n };\n const getHourWidth = hours => {\n return hours * props.hourWidth;\n };\n const getTimePosition = date => {\n const hour = date.getHours();\n const minute = date.getMinutes();\n const totalHours = hour + minute / 60;\n return (totalHours - props.startHour) * props.hourWidth + 1;\n };\n const getTimeWidth = (start, end) => {\n const startHour = start.getHours() + start.getMinutes() / 60;\n const endHour = end.getHours() + end.getMinutes() / 60;\n return (endHour - startHour) * props.hourWidth - 2;\n };\n // Time snapping utility - snap to 15 minute intervals\n const snapToInterval = (date, intervalMinutes = 15) => {\n const minutes = date.getMinutes();\n const snappedMinutes = Math.round(minutes / intervalMinutes) * intervalMinutes;\n return moment__WEBPACK_IMPORTED_MODULE_4___default()(date).set({\n minute: snappedMinutes,\n second: 0,\n millisecond: 0\n }).toDate();\n };\n // Convert pixel position to time\n const positionToTime = pixelX => {\n const hoursFromStart = pixelX / props.hourWidth;\n const totalHours = props.startHour + hoursFromStart;\n const hour = Math.floor(totalHours);\n const minute = totalHours % 1 * 60;\n // Use current date from currentTimeblockRange or today\n const baseDate = props.currentTimeblockRange.start ? moment__WEBPACK_IMPORTED_MODULE_4___default()(props.currentTimeblockRange.start) : moment__WEBPACK_IMPORTED_MODULE_4___default()();\n return baseDate.set({\n hour,\n minute,\n second: 0,\n millisecond: 0\n }).toDate();\n };\n // Format time as HH:mm\n const formatTime = date => {\n return moment__WEBPACK_IMPORTED_MODULE_4___default()(date).format('HH:mm');\n };\n // Check if mouse is over an existing block (x is already relative position with scroll)\n const isOverExistingBlock = relativeX => {\n // Check if over any scheduled block\n for (const task of props.scheduledBlocks) {\n const blockLeft = getTimePosition(task._real_start);\n const blockWidth = getTimeWidth(task._real_start, task._real_end);\n if (relativeX >= blockLeft && relativeX <= blockLeft + blockWidth) {\n return true;\n }\n }\n // Check if over any other timeblock\n for (const tb of otherTimeblocksRendered.value) {\n const blockLeft = getTimePosition(tb._start);\n const blockWidth = getTimeWidth(tb._start, tb._end);\n if (relativeX >= blockLeft && relativeX <= blockLeft + blockWidth) {\n return true;\n }\n }\n // Check if over current timeblock\n if (props.currentTimeblockRange.start && props.currentTimeblockRange.end) {\n const blockLeft = getTimePosition(props.currentTimeblockRange.start);\n const blockWidth = getTimeWidth(props.currentTimeblockRange.start, props.currentTimeblockRange.end);\n if (relativeX >= blockLeft && relativeX <= blockLeft + blockWidth) {\n return true;\n }\n }\n return false;\n };\n // Mouse move handler - show preview\n const handleMouseMove = event => {\n // Disable hover preview on mobile\n if (isMobile.value) {\n return;\n }\n if (dragState.value.isStretching) {\n handleStretchMove(event);\n return;\n }\n if (dragState.value.isResizingCurrent) {\n handleResizeCurrentMove(event);\n return;\n }\n if (!timelineScroll.value) return;\n // Get position relative to scroll container, accounting for scroll\n const rect = timelineScroll.value.getBoundingClientRect();\n const scrollLeft = timelineScroll.value.scrollLeft;\n const x = event.clientX - rect.left + scrollLeft;\n // Don't show preview if over existing block (using relative position)\n if (isOverExistingBlock(x)) {\n showPreview.value = false;\n return;\n }\n // Convert to time and snap\n const rawTime = positionToTime(x);\n const snappedStart = snapToInterval(rawTime);\n // Calculate default end time (1 hour later)\n let snappedEnd = moment__WEBPACK_IMPORTED_MODULE_4___default()(snappedStart).add(1, 'hour').toDate();\n // Only show preview if start is within work hours\n const startHour = snappedStart.getHours() + snappedStart.getMinutes() / 60;\n if (startHour >= props.employee.work_start && startHour < props.employee.work_end) {\n // If the end would exceed work hours, cap it at work_end\n const endHour = snappedEnd.getHours() + snappedEnd.getMinutes() / 60;\n if (endHour > props.employee.work_end) {\n // Create end time at exactly work_end\n snappedEnd = moment__WEBPACK_IMPORTED_MODULE_4___default()(snappedStart).set({\n hour: Math.floor(props.employee.work_end),\n minute: props.employee.work_end % 1 * 60,\n second: 0,\n millisecond: 0\n }).toDate();\n }\n showPreview.value = true;\n previewBlock.value = {\n start: snappedStart,\n end: snappedEnd\n };\n } else {\n showPreview.value = false;\n }\n };\n // Mouse leave handler\n const handleMouseLeave = () => {\n if (!dragState.value.isStretching && !dragState.value.isResizingCurrent) {\n showPreview.value = false;\n }\n };\n // Mouse down on timeline bar (not on preview or current block)\n const handleMouseDown = _event => {\n // This will only trigger if not clicking on preview or current block\n // (those have @mousedown.stop)\n };\n // Preview block mouse down - start creating/stretching\n const handlePreviewMouseDown = event => {\n if (!previewBlock.value) return;\n dragState.value.isStretching = true;\n dragState.value.startX = event.clientX;\n dragState.value.initialStart = previewBlock.value.start;\n dragState.value.initialEnd = previewBlock.value.end;\n event.preventDefault();\n };\n // Handle stretch move\n const handleStretchMove = event => {\n if (!dragState.value.initialStart || !timelineScroll.value) return;\n const rect = timelineScroll.value.getBoundingClientRect();\n const x = event.clientX - rect.left + timelineScroll.value.scrollLeft;\n const currentTime = positionToTime(x);\n let snappedTime = snapToInterval(currentTime);\n const initialStartTime = dragState.value.initialStart.getTime();\n const snappedTimeValue = snappedTime.getTime();\n if (snappedTimeValue > initialStartTime) {\n // Stretching right (extending end)\n // Cap at work_end\n const snappedEndHour = snappedTime.getHours() + snappedTime.getMinutes() / 60;\n if (snappedEndHour > props.employee.work_end) {\n snappedTime = moment__WEBPACK_IMPORTED_MODULE_4___default()(snappedTime).set({\n hour: Math.floor(props.employee.work_end),\n minute: props.employee.work_end % 1 * 60,\n second: 0,\n millisecond: 0\n }).toDate();\n }\n previewBlock.value = {\n start: dragState.value.initialStart,\n end: snappedTime\n };\n } else {\n // Stretching left (extending start)\n // Cap at work_start\n const snappedStartHour = snappedTime.getHours() + snappedTime.getMinutes() / 60;\n if (snappedStartHour < props.employee.work_start) {\n snappedTime = moment__WEBPACK_IMPORTED_MODULE_4___default()(snappedTime).set({\n hour: Math.floor(props.employee.work_start),\n minute: props.employee.work_start % 1 * 60,\n second: 0,\n millisecond: 0\n }).toDate();\n }\n previewBlock.value = {\n start: snappedTime,\n end: dragState.value.initialStart\n };\n }\n };\n // Handle stretch end\n const handleStretchEnd = () => {\n if (dragState.value.isStretching && previewBlock.value) {\n // Emit the new timeblock\n emit('timeblockUpdated', {\n starts_at_time: formatTime(previewBlock.value.start),\n ends_at_time: formatTime(previewBlock.value.end)\n });\n }\n dragState.value.isStretching = false;\n dragState.value.initialStart = null;\n dragState.value.initialEnd = null;\n showPreview.value = false;\n };\n // Resize handle mouse down - start resizing\n const handleResizeMouseDown = (event, edge) => {\n if (!props.currentTimeblockRange.start || !props.currentTimeblockRange.end) return;\n dragState.value.isResizingCurrent = true;\n dragState.value.resizeEdge = edge;\n dragState.value.startX = event.clientX;\n dragState.value.initialStart = props.currentTimeblockRange.start;\n dragState.value.initialEnd = props.currentTimeblockRange.end;\n resizedCurrentBlock.value = {\n start: props.currentTimeblockRange.start,\n end: props.currentTimeblockRange.end\n };\n event.preventDefault();\n };\n // Handle resize current block move\n const handleResizeCurrentMove = event => {\n if (!dragState.value.initialStart || !dragState.value.initialEnd || !timelineScroll.value) return;\n const rect = timelineScroll.value.getBoundingClientRect();\n const x = event.clientX - rect.left + timelineScroll.value.scrollLeft;\n const currentTime = positionToTime(x);\n let snappedTime = snapToInterval(currentTime);\n if (dragState.value.resizeEdge === 'left') {\n // Resizing left edge (changing start time)\n // Cap at work_start\n const snappedStartHour = snappedTime.getHours() + snappedTime.getMinutes() / 60;\n if (snappedStartHour < props.employee.work_start) {\n snappedTime = moment__WEBPACK_IMPORTED_MODULE_4___default()(snappedTime).set({\n hour: Math.floor(props.employee.work_start),\n minute: props.employee.work_start % 1 * 60,\n second: 0,\n millisecond: 0\n }).toDate();\n }\n // Make sure new start is before end\n if (snappedTime < dragState.value.initialEnd) {\n resizedCurrentBlock.value = {\n start: snappedTime,\n end: dragState.value.initialEnd\n };\n }\n } else if (dragState.value.resizeEdge === 'right') {\n // Resizing right edge (changing end time)\n // Cap at work_end\n const snappedEndHour = snappedTime.getHours() + snappedTime.getMinutes() / 60;\n if (snappedEndHour > props.employee.work_end) {\n snappedTime = moment__WEBPACK_IMPORTED_MODULE_4___default()(snappedTime).set({\n hour: Math.floor(props.employee.work_end),\n minute: props.employee.work_end % 1 * 60,\n second: 0,\n millisecond: 0\n }).toDate();\n }\n // Make sure new end is after start\n if (snappedTime > dragState.value.initialStart) {\n resizedCurrentBlock.value = {\n start: dragState.value.initialStart,\n end: snappedTime\n };\n }\n }\n };\n // Handle resize current block end\n const handleResizeCurrentEnd = () => {\n if (dragState.value.isResizingCurrent && resizedCurrentBlock.value) {\n // Emit the updated timeblock\n emit('timeblockUpdated', {\n starts_at_time: formatTime(resizedCurrentBlock.value.start),\n ends_at_time: formatTime(resizedCurrentBlock.value.end)\n });\n }\n dragState.value.isResizingCurrent = false;\n dragState.value.resizeEdge = null;\n dragState.value.initialStart = null;\n dragState.value.initialEnd = null;\n resizedCurrentBlock.value = null;\n };\n // Global mouse up handler\n const handleGlobalMouseUp = () => {\n if (dragState.value.isStretching) {\n handleStretchEnd();\n } else if (dragState.value.isResizingCurrent) {\n handleResizeCurrentEnd();\n }\n };\n // Global mouse move handler\n const handleGlobalMouseMove = event => {\n if (dragState.value.isStretching) {\n handleStretchMove(event);\n } else if (dragState.value.isResizingCurrent) {\n handleResizeCurrentMove(event);\n }\n };\n // Setup global listeners\n (0,vue__WEBPACK_IMPORTED_MODULE_3__.onMounted)(() => {\n // Detect mobile device\n isMobile.value = window.innerWidth <= 768;\n // Listen for resize to update mobile status\n const handleResize = () => {\n isMobile.value = window.innerWidth <= 768;\n };\n window.addEventListener('resize', handleResize);\n document.addEventListener('mouseup', handleGlobalMouseUp);\n document.addEventListener('mousemove', handleGlobalMouseMove);\n });\n (0,vue__WEBPACK_IMPORTED_MODULE_3__.onUnmounted)(() => {\n document.removeEventListener('mouseup', handleGlobalMouseUp);\n document.removeEventListener('mousemove', handleGlobalMouseMove);\n });\n // Expose refs for parent component\n __expose({\n timelineScroll\n });\n const __returned__ = {\n props,\n emit,\n timelineContainer,\n timelineScroll,\n timelineBar,\n isMobile,\n showPreview,\n previewBlock,\n dragState,\n resizedCurrentBlock,\n isWeekend,\n otherTimeblocksRendered,\n getHourPosition,\n getHourWidth,\n getTimePosition,\n getTimeWidth,\n snapToInterval,\n positionToTime,\n formatTime,\n isOverExistingBlock,\n handleMouseMove,\n handleMouseLeave,\n handleMouseDown,\n handlePreviewMouseDown,\n handleStretchMove,\n handleStretchEnd,\n handleResizeMouseDown,\n handleResizeCurrentMove,\n handleResizeCurrentEnd,\n handleGlobalMouseUp,\n handleGlobalMouseMove,\n AEmployeeTimeblockTimelineHeader: _a_employee_timeblock_timeline_header_vue__WEBPACK_IMPORTED_MODULE_5__[\"default\"]\n };\n Object.defineProperty(__returned__, '__isScriptSetup', {\n enumerable: false,\n value: true\n });\n return __returned__;\n }\n}));\n\n//# sourceURL=webpack://jandl/./src/plugins/tm@modal/task/_components/employees/a-employee-timeblock-timeline.vue?./node_modules/webpack-plugin-vuetify/dist/scriptLoader.js!./node_modules/babel-loader/lib/index.js!./node_modules/ts-loader/index.js??clonedRuleSet-41.use%5B1%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}"); /***/ }), @@ -1253,7 +1253,7 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var cor /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_esnext_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/esnext.iterator.constructor.js */ \"./node_modules/core-js/modules/esnext.iterator.constructor.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_esnext_iterator_filter_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/esnext.iterator.filter.js */ \"./node_modules/core-js/modules/esnext.iterator.filter.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_filter_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_filter_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var core_js_modules_esnext_iterator_map_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! core-js/modules/esnext.iterator.map.js */ \"./node_modules/core-js/modules/esnext.iterator.map.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_map_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_map_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm-bundler.js\");\n/* harmony import */ var _vuelidate_core__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @vuelidate/core */ \"./node_modules/@vuelidate/core/dist/index.esm.js\");\n/* harmony import */ var _vuelidate_validators__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @vuelidate/validators */ \"./node_modules/@vuelidate/validators/dist/index.esm.js\");\n/* harmony import */ var _plugins_tm_utils_useEmployeeTimeline__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @/plugins/tm@_utils/useEmployeeTimeline */ \"./src/plugins/tm@_utils/useEmployeeTimeline.ts\");\n/* harmony import */ var _plugins_tm_utils_timeblock_utils__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @/plugins/tm@_utils/timeblock.utils */ \"./src/plugins/tm@_utils/timeblock.utils.ts\");\n/* harmony import */ var _a_employee_timeblock_header_vue__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./a-employee-timeblock-header.vue */ \"./src/plugins/tm@modal/task/_components/employees/a-employee-timeblock-header.vue\");\n/* harmony import */ var _a_employee_timeblock_timeline_vue__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./a-employee-timeblock-timeline.vue */ \"./src/plugins/tm@modal/task/_components/employees/a-employee-timeblock-timeline.vue\");\n/* harmony import */ var moment__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! moment */ \"./node_modules/moment/moment.js\");\n/* harmony import */ var moment__WEBPACK_IMPORTED_MODULE_10___default = /*#__PURE__*/__webpack_require__.n(moment__WEBPACK_IMPORTED_MODULE_10__);\n\n\n\n\n\n\n\n\n\n\n\n\n// Configuration: Set to false to allow editing timeblocks with existing IDs\nconst ALLOW_EDITING_EXISTING_TIMEBLOCKS = true;\nconst HOUR_WIDTH = 60; // pixels per hour (desktop)\nconst HOUR_WIDTH_MOBILE = 50; // pixels per hour (mobile)\nconst START_HOUR = 0; // Start from midnight\nconst END_HOUR = 24; // End at midnight\n// Check if mobile\n/* harmony default export */ __webpack_exports__[\"default\"] = (/*@__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_3__.defineComponent)({\n __name: 'a-employee-timeblock',\n props: {\n modelValue: {\n type: Object,\n required: true\n },\n employee: {\n type: [Object, null],\n required: true\n },\n allEmployeeTimeblocks: {\n type: Array,\n required: false,\n default: () => []\n },\n allTimeblocks: {\n type: Array,\n required: false,\n default: () => []\n },\n deletedTimeblockIds: {\n type: Array,\n required: false,\n default: () => []\n },\n currentIndex: {\n type: Number,\n required: false,\n default: 0\n },\n deletable: {\n type: Boolean,\n required: false,\n default: false\n },\n index: {\n type: Number,\n required: false,\n default: 0\n }\n },\n emits: [\"update:modelValue\", \"addTimeblock\", \"removeTimeblock\"],\n setup(__props, {\n expose: __expose,\n emit: __emit\n }) {\n const props = __props;\n const emit = __emit;\n const timelineRef = (0,vue__WEBPACK_IMPORTED_MODULE_3__.ref)(null);\n // Check if timeblock is editable (based on whether it has an ID)\n const isEditable = (0,vue__WEBPACK_IMPORTED_MODULE_3__.computed)(() => {\n if (ALLOW_EDITING_EXISTING_TIMEBLOCKS) return true;\n return !props.modelValue.id;\n });\n // Minimum date is today (no past dates)\n const minDate = (0,vue__WEBPACK_IMPORTED_MODULE_3__.ref)(new Date());\n // Timeline configuration\n const isMobile = (0,vue__WEBPACK_IMPORTED_MODULE_3__.ref)(false);\n (0,vue__WEBPACK_IMPORTED_MODULE_3__.onMounted)(() => {\n isMobile.value = window.innerWidth <= 768;\n window.addEventListener('resize', () => {\n isMobile.value = window.innerWidth <= 768;\n });\n // Center timeline on mount\n (0,vue__WEBPACK_IMPORTED_MODULE_3__.nextTick)(() => {\n centerTimeline();\n });\n });\n const hourWidth = (0,vue__WEBPACK_IMPORTED_MODULE_3__.computed)(() => isMobile.value ? HOUR_WIDTH_MOBILE : HOUR_WIDTH);\n // Custom validator for time range\n const timeRangeValid = (value, siblings) => {\n if (!siblings.starts_at_time || !siblings.ends_at_time || !siblings.date) {\n return true;\n }\n const {\n start,\n end\n } = (0,_plugins_tm_utils_timeblock_utils__WEBPACK_IMPORTED_MODULE_7__.timeblockToDateRange)(siblings);\n if (!start || !end) return true;\n return end > start;\n };\n // Custom validator: field is required when start OR end time is filled\n // Uses siblings to check the current state of all fields\n const requiredWhenHasTime = (value, siblings) => {\n // Check if timeblock has any TIME data (start or end time)\n const hasStart = !!siblings.starts_at_time;\n const hasEnd = !!siblings.ends_at_time;\n const hasAnyTimeData = hasStart || hasEnd;\n // If no time data, no validation needed\n if (!hasAnyTimeData) return true;\n // When time data exists, field must have value (not null, undefined, or empty string)\n return value !== null && value !== undefined && value !== '';\n };\n // Vuelidate rules - if start OR end is filled, all three fields are required\n const rules = {\n date: {\n requiredWhenHasTime: _vuelidate_validators__WEBPACK_IMPORTED_MODULE_5__.helpers.withMessage('Vyberte dátum', requiredWhenHasTime)\n },\n starts_at_time: {\n requiredWhenHasTime: _vuelidate_validators__WEBPACK_IMPORTED_MODULE_5__.helpers.withMessage('Zadajte začiatok', requiredWhenHasTime)\n },\n ends_at_time: {\n requiredWhenHasTime: _vuelidate_validators__WEBPACK_IMPORTED_MODULE_5__.helpers.withMessage('Zadajte koniec', requiredWhenHasTime),\n timeRangeValid: _vuelidate_validators__WEBPACK_IMPORTED_MODULE_5__.helpers.withMessage('Koniec musí byť po začiatku', timeRangeValid)\n }\n };\n const v$ = (0,_vuelidate_core__WEBPACK_IMPORTED_MODULE_4__.useVuelidate)(rules, props.modelValue, {\n $autoDirty: true\n });\n // Error visibility logic: show errors if field is dirty OR if the opposite time field is filled\n const hasStartTimeError = (0,vue__WEBPACK_IMPORTED_MODULE_3__.computed)(() => {\n // Show error if field is dirty and has error\n if (v$.value.starts_at_time.$dirty && v$.value.starts_at_time.$error) {\n return true;\n }\n // OR if end time is filled but start is not\n if (props.modelValue.ends_at_time && !props.modelValue.starts_at_time) {\n return v$.value.starts_at_time.$error;\n }\n return false;\n });\n const hasEndTimeError = (0,vue__WEBPACK_IMPORTED_MODULE_3__.computed)(() => {\n // Show error if field is dirty and has error\n if (v$.value.ends_at_time.$dirty && v$.value.ends_at_time.$error) {\n return true;\n }\n // OR if start time is filled but end is not\n if (props.modelValue.starts_at_time && !props.modelValue.ends_at_time) {\n return v$.value.ends_at_time.$error;\n }\n return false;\n });\n const endTimeErrorMessage = (0,vue__WEBPACK_IMPORTED_MODULE_3__.computed)(() => {\n if (hasEndTimeError.value) {\n return v$.value.ends_at_time.$errors.map(e => e.$message).join(', ');\n }\n return '';\n });\n // Reactive refs for composable\n const employeeRef = (0,vue__WEBPACK_IMPORTED_MODULE_3__.computed)(() => props.employee);\n const dateRef = (0,vue__WEBPACK_IMPORTED_MODULE_3__.computed)(() => props.modelValue.date);\n const timeblockRef = (0,vue__WEBPACK_IMPORTED_MODULE_3__.computed)(() => props.modelValue);\n // Use timeline composable\n const {\n isLoading,\n timelineTasks,\n scheduledTime: _scheduledTime,\n freeTime: _freeTime,\n timeblockDuration,\n refetch\n } = (0,_plugins_tm_utils_useEmployeeTimeline__WEBPACK_IMPORTED_MODULE_6__.useEmployeeTimeline)(employeeRef, dateRef, timeblockRef);\n // Force refetch when date changes\n (0,vue__WEBPACK_IMPORTED_MODULE_3__.watch)(() => props.modelValue.date, () => {\n if (props.modelValue.date && props.employee?.id) {\n refetch();\n }\n });\n // All tasks from timelineTasks are already filtered for the selected date\n // Filter out timeblocks that are being edited or deleted locally\n const scheduledBlocks = (0,vue__WEBPACK_IMPORTED_MODULE_3__.computed)(() => {\n // Combine IDs that should be filtered: edited locally or deleted\n const hiddenTimeblockIds = new Set([\n // Timeblock IDs being edited locally\n ...props.allTimeblocks.filter(tb => tb.id).map(tb => tb.id),\n // Timeblock IDs that have been deleted\n ...(props.deletedTimeblockIds || [])]);\n // Filter out tasks whose timeblock IDs should be hidden\n return timelineTasks.value.filter(task => !task._timeblock_id || !hiddenTimeblockIds.has(task._timeblock_id));\n });\n // Recalculate collision using filtered scheduled blocks (not raw timeline tasks)\n // This prevents false collisions with timeblocks being edited\n const collision = (0,vue__WEBPACK_IMPORTED_MODULE_3__.computed)(() => {\n return (0,_plugins_tm_utils_timeblock_utils__WEBPACK_IMPORTED_MODULE_7__.detectCollision)(props.modelValue, scheduledBlocks.value);\n });\n // Recalculate collision segments using filtered scheduled blocks\n const collisionSegments = (0,vue__WEBPACK_IMPORTED_MODULE_3__.computed)(() => {\n return (0,_plugins_tm_utils_timeblock_utils__WEBPACK_IMPORTED_MODULE_7__.getCollisionSegments)(props.modelValue, scheduledBlocks.value);\n });\n // Get other timeblocks for the same date (excluding current one)\n // This includes timeblocks from both the current employee and other employees\n const otherTimeblocksForSameDate = (0,vue__WEBPACK_IMPORTED_MODULE_3__.computed)(() => {\n if (!props.modelValue.date) return [];\n const currentDate = moment__WEBPACK_IMPORTED_MODULE_10___default()(props.modelValue.date).format('YYYY-MM-DD');\n // Use allEmployeeTimeblocks which contains timeblocks for this specific employee\n // Filter out the current timeblock by comparing index directly\n return props.allEmployeeTimeblocks.filter((tb, index) => {\n // Skip current timeblock by index\n if (index === props.currentIndex) {\n return false;\n }\n // Must have required fields\n if (!tb.date || !tb.starts_at_time || !tb.ends_at_time) return false;\n // Must be the same date\n return moment__WEBPACK_IMPORTED_MODULE_10___default()(tb.date).format('YYYY-MM-DD') === currentDate;\n });\n });\n // Get current timeblock range\n const currentTimeblockRange = (0,vue__WEBPACK_IMPORTED_MODULE_3__.computed)(() => {\n const {\n start,\n end\n } = (0,_plugins_tm_utils_timeblock_utils__WEBPACK_IMPORTED_MODULE_7__.timeblockToDateRange)(props.modelValue);\n return {\n start,\n end\n };\n });\n // Validate that end time is after start time\n const isTimeRangeValid = (0,vue__WEBPACK_IMPORTED_MODULE_3__.computed)(() => {\n if (!props.modelValue.starts_at_time || !props.modelValue.ends_at_time) {\n return true; // Don't show error if fields are empty\n }\n const {\n start,\n end\n } = currentTimeblockRange.value;\n if (!start || !end) return true;\n return end > start;\n });\n // Center timeline around middle of work hours\n const centerTimeline = () => {\n if (!timelineRef.value?.timelineScroll) return;\n // Calculate the middle of work hours\n const workStart = props.employee?.work_start ?? 8;\n const workEnd = props.employee?.work_end ?? 17;\n const centerHour = (workStart + workEnd) / 2;\n const centerPosition = (centerHour - START_HOUR) * hourWidth.value;\n const containerWidth = timelineRef.value.timelineScroll.clientWidth;\n timelineRef.value.timelineScroll.scrollLeft = centerPosition - containerWidth / 2;\n };\n // Watch for date changes or employee changes to re-center\n (0,vue__WEBPACK_IMPORTED_MODULE_3__.watch)(() => [props.modelValue.date, props.employee?.id], () => {\n (0,vue__WEBPACK_IMPORTED_MODULE_3__.nextTick)(() => {\n centerTimeline();\n });\n });\n // Watch for timeline ref to become available and center it\n (0,vue__WEBPACK_IMPORTED_MODULE_3__.watch)(timelineRef, newRef => {\n if (newRef?.timelineScroll) {\n (0,vue__WEBPACK_IMPORTED_MODULE_3__.nextTick)(() => {\n centerTimeline();\n });\n }\n });\n // Watch for loading state - when data finishes loading, center the timeline\n (0,vue__WEBPACK_IMPORTED_MODULE_3__.watch)(isLoading, (newIsLoading, oldIsLoading) => {\n // When loading changes from true to false, timeline is re-rendered\n if (oldIsLoading && !newIsLoading) {\n // Wait for DOM to update, then center\n (0,vue__WEBPACK_IMPORTED_MODULE_3__.nextTick)(() => {\n setTimeout(() => {\n centerTimeline();\n }, 0); // Small delay to ensure DOM is fully rendered\n });\n }\n });\n // Date navigation\n const previousDay = () => {\n if (!props.modelValue.date) return;\n const currentDate = moment__WEBPACK_IMPORTED_MODULE_10___default()(props.modelValue.date);\n const newDate = currentDate.clone().subtract(1, 'day').toDate();\n // Don't allow going to past dates\n if (moment__WEBPACK_IMPORTED_MODULE_10___default()(newDate).isBefore(moment__WEBPACK_IMPORTED_MODULE_10___default()(), 'day')) return;\n updateDate(newDate);\n };\n const nextDay = () => {\n if (!props.modelValue.date) return;\n const currentDate = moment__WEBPACK_IMPORTED_MODULE_10___default()(props.modelValue.date);\n const newDate = currentDate.clone().add(1, 'day').toDate();\n updateDate(newDate);\n };\n // Update handlers\n const updateDate = date => {\n emit('update:modelValue', {\n ...props.modelValue,\n date\n });\n };\n const updateStartTime = event => {\n const target = event.target;\n emit('update:modelValue', {\n ...props.modelValue,\n starts_at_time: target.value\n });\n };\n const updateEndTime = event => {\n const target = event.target;\n emit('update:modelValue', {\n ...props.modelValue,\n ends_at_time: target.value\n });\n };\n // Handle timeblock updated from timeline (drag/drop or quick add)\n const handleTimeblockUpdated = payload => {\n emit('update:modelValue', {\n ...props.modelValue,\n starts_at_time: payload.starts_at_time,\n ends_at_time: payload.ends_at_time\n });\n // Trigger validation after timeline update\n (0,vue__WEBPACK_IMPORTED_MODULE_3__.nextTick)(() => {\n v$.value.$touch();\n });\n };\n // Expose validate method\n const validate = async () => {\n v$.value.$touch();\n const isValid = await v$.value.$validate();\n return isValid && isTimeRangeValid.value;\n };\n __expose({\n validate\n });\n const __returned__ = {\n ALLOW_EDITING_EXISTING_TIMEBLOCKS,\n props,\n emit,\n timelineRef,\n isEditable,\n minDate,\n HOUR_WIDTH,\n HOUR_WIDTH_MOBILE,\n START_HOUR,\n END_HOUR,\n isMobile,\n hourWidth,\n timeRangeValid,\n requiredWhenHasTime,\n rules,\n v$,\n hasStartTimeError,\n hasEndTimeError,\n endTimeErrorMessage,\n employeeRef,\n dateRef,\n timeblockRef,\n isLoading,\n timelineTasks,\n _scheduledTime,\n _freeTime,\n timeblockDuration,\n refetch,\n scheduledBlocks,\n collision,\n collisionSegments,\n otherTimeblocksForSameDate,\n currentTimeblockRange,\n isTimeRangeValid,\n centerTimeline,\n previousDay,\n nextDay,\n updateDate,\n updateStartTime,\n updateEndTime,\n handleTimeblockUpdated,\n validate,\n AEmployeeTimeblockHeader: _a_employee_timeblock_header_vue__WEBPACK_IMPORTED_MODULE_8__[\"default\"],\n AEmployeeTimeblockTimeline: _a_employee_timeblock_timeline_vue__WEBPACK_IMPORTED_MODULE_9__[\"default\"]\n };\n Object.defineProperty(__returned__, '__isScriptSetup', {\n enumerable: false,\n value: true\n });\n return __returned__;\n }\n}));\n\n//# sourceURL=webpack://jandl/./src/plugins/tm@modal/task/_components/employees/a-employee-timeblock.vue?./node_modules/webpack-plugin-vuetify/dist/scriptLoader.js!./node_modules/babel-loader/lib/index.js!./node_modules/ts-loader/index.js??clonedRuleSet-41.use%5B1%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}"); +eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_esnext_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/esnext.iterator.constructor.js */ \"./node_modules/core-js/modules/esnext.iterator.constructor.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_esnext_iterator_filter_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/esnext.iterator.filter.js */ \"./node_modules/core-js/modules/esnext.iterator.filter.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_filter_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_filter_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var core_js_modules_esnext_iterator_map_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! core-js/modules/esnext.iterator.map.js */ \"./node_modules/core-js/modules/esnext.iterator.map.js\");\n/* harmony import */ var core_js_modules_esnext_iterator_map_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_esnext_iterator_map_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm-bundler.js\");\n/* harmony import */ var _vuelidate_core__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @vuelidate/core */ \"./node_modules/@vuelidate/core/dist/index.esm.js\");\n/* harmony import */ var _vuelidate_validators__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @vuelidate/validators */ \"./node_modules/@vuelidate/validators/dist/index.esm.js\");\n/* harmony import */ var _plugins_tm_utils_useEmployeeTimeline__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @/plugins/tm@_utils/useEmployeeTimeline */ \"./src/plugins/tm@_utils/useEmployeeTimeline.ts\");\n/* harmony import */ var _plugins_tm_utils_timeblock_utils__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @/plugins/tm@_utils/timeblock.utils */ \"./src/plugins/tm@_utils/timeblock.utils.ts\");\n/* harmony import */ var _a_employee_timeblock_header_vue__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./a-employee-timeblock-header.vue */ \"./src/plugins/tm@modal/task/_components/employees/a-employee-timeblock-header.vue\");\n/* harmony import */ var _a_employee_timeblock_timeline_vue__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./a-employee-timeblock-timeline.vue */ \"./src/plugins/tm@modal/task/_components/employees/a-employee-timeblock-timeline.vue\");\n/* harmony import */ var moment__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! moment */ \"./node_modules/moment/moment.js\");\n/* harmony import */ var moment__WEBPACK_IMPORTED_MODULE_10___default = /*#__PURE__*/__webpack_require__.n(moment__WEBPACK_IMPORTED_MODULE_10__);\n/* provided dependency */ var console = __webpack_require__(/*! ./node_modules/console-browserify/index.js */ \"./node_modules/console-browserify/index.js\");\n\n\n\n\n\n\n\n\n\n\n\n\n// Configuration: Set to false to allow editing timeblocks with existing IDs\nconst ALLOW_EDITING_EXISTING_TIMEBLOCKS = true;\nconst HOUR_WIDTH = 60; // pixels per hour (desktop)\nconst HOUR_WIDTH_MOBILE = 50; // pixels per hour (mobile)\nconst START_HOUR = 0; // Start from midnight\nconst END_HOUR = 24; // End at midnight\n// Check if mobile\n/* harmony default export */ __webpack_exports__[\"default\"] = (/*@__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_3__.defineComponent)({\n __name: 'a-employee-timeblock',\n props: {\n modelValue: {\n type: Object,\n required: true\n },\n employee: {\n type: [Object, null],\n required: true\n },\n allEmployeeTimeblocks: {\n type: Array,\n required: false,\n default: () => []\n },\n allTimeblocks: {\n type: Array,\n required: false,\n default: () => []\n },\n deletedTimeblockIds: {\n type: Array,\n required: false,\n default: () => []\n },\n currentIndex: {\n type: Number,\n required: false,\n default: 0\n },\n deletable: {\n type: Boolean,\n required: false,\n default: false\n },\n index: {\n type: Number,\n required: false,\n default: 0\n }\n },\n emits: [\"update:modelValue\", \"addTimeblock\", \"removeTimeblock\"],\n setup(__props, {\n expose: __expose,\n emit: __emit\n }) {\n const props = __props;\n const emit = __emit;\n const timelineRef = (0,vue__WEBPACK_IMPORTED_MODULE_3__.ref)(null);\n // Check if timeblock is editable (based on whether it has an ID)\n const isEditable = (0,vue__WEBPACK_IMPORTED_MODULE_3__.computed)(() => {\n if (ALLOW_EDITING_EXISTING_TIMEBLOCKS) return true;\n return !props.modelValue.id;\n });\n // Minimum date is today (no past dates)\n const minDate = (0,vue__WEBPACK_IMPORTED_MODULE_3__.ref)(new Date());\n // Timeline configuration\n const isMobile = (0,vue__WEBPACK_IMPORTED_MODULE_3__.ref)(false);\n (0,vue__WEBPACK_IMPORTED_MODULE_3__.onMounted)(() => {\n isMobile.value = window.innerWidth <= 768;\n window.addEventListener('resize', () => {\n isMobile.value = window.innerWidth <= 768;\n });\n // Center timeline on mount\n (0,vue__WEBPACK_IMPORTED_MODULE_3__.nextTick)(() => {\n centerTimeline();\n });\n });\n const hourWidth = (0,vue__WEBPACK_IMPORTED_MODULE_3__.computed)(() => isMobile.value ? HOUR_WIDTH_MOBILE : HOUR_WIDTH);\n // Custom validator for time range\n const timeRangeValid = (value, siblings) => {\n if (!siblings.starts_at_time || !siblings.ends_at_time || !siblings.date) {\n return true;\n }\n const {\n start,\n end\n } = (0,_plugins_tm_utils_timeblock_utils__WEBPACK_IMPORTED_MODULE_7__.timeblockToDateRange)(siblings);\n if (!start || !end) return true;\n return end > start;\n };\n // Custom validator: field is required when start OR end time is filled\n // Uses siblings to check the current state of all fields\n const requiredWhenHasTime = (value, siblings) => {\n // Check if timeblock has any TIME data (start or end time)\n const hasStart = !!siblings.starts_at_time;\n const hasEnd = !!siblings.ends_at_time;\n const hasAnyTimeData = hasStart || hasEnd;\n // If no time data, no validation needed\n if (!hasAnyTimeData) return true;\n // When time data exists, field must have value (not null, undefined, or empty string)\n return value !== null && value !== undefined && value !== '';\n };\n // Vuelidate rules - if start OR end is filled, all three fields are required\n const rules = {\n date: {\n requiredWhenHasTime: _vuelidate_validators__WEBPACK_IMPORTED_MODULE_5__.helpers.withMessage('Vyberte dátum', requiredWhenHasTime)\n },\n starts_at_time: {\n requiredWhenHasTime: _vuelidate_validators__WEBPACK_IMPORTED_MODULE_5__.helpers.withMessage('Zadajte začiatok', requiredWhenHasTime)\n },\n ends_at_time: {\n requiredWhenHasTime: _vuelidate_validators__WEBPACK_IMPORTED_MODULE_5__.helpers.withMessage('Zadajte koniec', requiredWhenHasTime),\n timeRangeValid: _vuelidate_validators__WEBPACK_IMPORTED_MODULE_5__.helpers.withMessage('Koniec musí byť po začiatku', timeRangeValid)\n }\n };\n const v$ = (0,_vuelidate_core__WEBPACK_IMPORTED_MODULE_4__.useVuelidate)(rules, props.modelValue, {\n $autoDirty: true\n });\n // Error visibility logic: show errors if field is dirty OR if the opposite time field is filled\n const hasStartTimeError = (0,vue__WEBPACK_IMPORTED_MODULE_3__.computed)(() => {\n // Show error if field is dirty and has error\n if (v$.value.starts_at_time.$dirty && v$.value.starts_at_time.$error) {\n return true;\n }\n // OR if end time is filled but start is not\n if (props.modelValue.ends_at_time && !props.modelValue.starts_at_time) {\n return v$.value.starts_at_time.$error;\n }\n return false;\n });\n const hasEndTimeError = (0,vue__WEBPACK_IMPORTED_MODULE_3__.computed)(() => {\n // Show error if field is dirty and has error\n if (v$.value.ends_at_time.$dirty && v$.value.ends_at_time.$error) {\n return true;\n }\n // OR if start time is filled but end is not\n if (props.modelValue.starts_at_time && !props.modelValue.ends_at_time) {\n return v$.value.ends_at_time.$error;\n }\n return false;\n });\n const endTimeErrorMessage = (0,vue__WEBPACK_IMPORTED_MODULE_3__.computed)(() => {\n if (hasEndTimeError.value) {\n return v$.value.ends_at_time.$errors.map(e => e.$message).join(', ');\n }\n return '';\n });\n // Reactive refs for composable\n const employeeRef = (0,vue__WEBPACK_IMPORTED_MODULE_3__.computed)(() => props.employee);\n const dateRef = (0,vue__WEBPACK_IMPORTED_MODULE_3__.computed)(() => props.modelValue.date);\n const timeblockRef = (0,vue__WEBPACK_IMPORTED_MODULE_3__.computed)(() => props.modelValue);\n // Get other timeblocks for the same date (excluding current one)\n // This includes timeblocks from both the current employee and other employees\n const otherTimeblocksForSameDate = (0,vue__WEBPACK_IMPORTED_MODULE_3__.computed)(() => {\n if (!props.modelValue.date) return [];\n const currentDate = moment__WEBPACK_IMPORTED_MODULE_10___default()(props.modelValue.date).format('YYYY-MM-DD');\n // Use allEmployeeTimeblocks which contains timeblocks for this specific employee\n // Filter out the current timeblock by comparing index directly\n return props.allEmployeeTimeblocks.filter((tb, index) => {\n // Skip current timeblock by index\n if (index === props.currentIndex) {\n return false;\n }\n // Must have required fields\n if (!tb.date || !tb.starts_at_time || !tb.ends_at_time) return false;\n // Must be the same date\n return moment__WEBPACK_IMPORTED_MODULE_10___default()(tb.date).format('YYYY-MM-DD') === currentDate;\n });\n });\n // Use timeline composable\n const {\n isLoading,\n timelineTasks,\n scheduledTime: _scheduledTime,\n freeTime: _freeTime,\n timeblockDuration,\n refetch\n } = (0,_plugins_tm_utils_useEmployeeTimeline__WEBPACK_IMPORTED_MODULE_6__.useEmployeeTimeline)(employeeRef, dateRef, timeblockRef, otherTimeblocksForSameDate);\n // Force refetch when date changes\n (0,vue__WEBPACK_IMPORTED_MODULE_3__.watch)(() => props.modelValue.date, () => {\n if (props.modelValue.date && props.employee?.id) {\n refetch();\n }\n });\n // All tasks from timelineTasks are already filtered for the selected date\n // Filter out timeblocks that are being edited or deleted locally\n const scheduledBlocks = (0,vue__WEBPACK_IMPORTED_MODULE_3__.computed)(() => {\n // Combine IDs that should be filtered: edited locally or deleted\n const hiddenTimeblockIds = new Set([\n // Timeblock IDs being edited locally\n ...props.allTimeblocks.filter(tb => tb.id).map(tb => tb.id),\n // Timeblock IDs that have been deleted\n ...(props.deletedTimeblockIds || [])]);\n // Filter out tasks whose timeblock IDs should be hidden\n return timelineTasks.value.filter(task => !task._timeblock_id || !hiddenTimeblockIds.has(task._timeblock_id));\n });\n // Convert other unsaved timeblocks to task format for collision detection\n const otherTimeblocksAsTasks = (0,vue__WEBPACK_IMPORTED_MODULE_3__.computed)(() => {\n return otherTimeblocksForSameDate.value.map(tb => {\n const {\n start,\n end\n } = (0,_plugins_tm_utils_timeblock_utils__WEBPACK_IMPORTED_MODULE_7__.timeblockToDateRange)(tb);\n if (!start || !end) return null;\n return {\n _real_start: start,\n _real_end: end,\n _timeblock_id: tb.id || null\n };\n }).filter(task => task !== null);\n });\n // Combine scheduled blocks with other unsaved timeblocks for collision detection\n const allBlocksForCollisionCheck = (0,vue__WEBPACK_IMPORTED_MODULE_3__.computed)(() => {\n return [...scheduledBlocks.value, ...otherTimeblocksAsTasks.value];\n });\n // Recalculate collision using filtered scheduled blocks AND other unsaved timeblocks\n // This prevents false collisions with timeblocks being edited, but catches collisions with other unsaved timeblocks\n const collision = (0,vue__WEBPACK_IMPORTED_MODULE_3__.computed)(() => {\n return (0,_plugins_tm_utils_timeblock_utils__WEBPACK_IMPORTED_MODULE_7__.detectCollision)(props.modelValue, allBlocksForCollisionCheck.value);\n });\n // Recalculate collision segments using filtered scheduled blocks AND other unsaved timeblocks\n const collisionSegments = (0,vue__WEBPACK_IMPORTED_MODULE_3__.computed)(() => {\n return (0,_plugins_tm_utils_timeblock_utils__WEBPACK_IMPORTED_MODULE_7__.getCollisionSegments)(props.modelValue, allBlocksForCollisionCheck.value);\n });\n // Get current timeblock range\n const currentTimeblockRange = (0,vue__WEBPACK_IMPORTED_MODULE_3__.computed)(() => {\n const {\n start,\n end\n } = (0,_plugins_tm_utils_timeblock_utils__WEBPACK_IMPORTED_MODULE_7__.timeblockToDateRange)(props.modelValue);\n return {\n start,\n end\n };\n });\n // Validate that end time is after start time\n const isTimeRangeValid = (0,vue__WEBPACK_IMPORTED_MODULE_3__.computed)(() => {\n if (!props.modelValue.starts_at_time || !props.modelValue.ends_at_time) {\n return true; // Don't show error if fields are empty\n }\n const {\n start,\n end\n } = currentTimeblockRange.value;\n if (!start || !end) return true;\n return end > start;\n });\n // Center timeline around middle of work hours\n const centerTimeline = () => {\n if (!timelineRef.value?.timelineScroll) return;\n // Calculate the middle of work hours\n const workStart = props.employee?.work_start ?? 8;\n const workEnd = props.employee?.work_end ?? 17;\n const centerHour = (workStart + workEnd) / 2;\n const centerPosition = (centerHour - START_HOUR) * hourWidth.value;\n const containerWidth = timelineRef.value.timelineScroll.clientWidth;\n timelineRef.value.timelineScroll.scrollLeft = centerPosition - containerWidth / 2;\n };\n // Watch for date changes or employee changes to re-center\n (0,vue__WEBPACK_IMPORTED_MODULE_3__.watch)(() => [props.modelValue.date, props.employee?.id], () => {\n (0,vue__WEBPACK_IMPORTED_MODULE_3__.nextTick)(() => {\n centerTimeline();\n });\n });\n // Watch for timeline ref to become available and center it\n (0,vue__WEBPACK_IMPORTED_MODULE_3__.watch)(timelineRef, newRef => {\n if (newRef?.timelineScroll) {\n (0,vue__WEBPACK_IMPORTED_MODULE_3__.nextTick)(() => {\n centerTimeline();\n });\n }\n });\n // Watch for loading state - when data finishes loading, center the timeline\n (0,vue__WEBPACK_IMPORTED_MODULE_3__.watch)(isLoading, (newIsLoading, oldIsLoading) => {\n // When loading changes from true to false, timeline is re-rendered\n if (oldIsLoading && !newIsLoading) {\n // Wait for DOM to update, then center\n (0,vue__WEBPACK_IMPORTED_MODULE_3__.nextTick)(() => {\n setTimeout(() => {\n centerTimeline();\n }, 0); // Small delay to ensure DOM is fully rendered\n });\n }\n });\n // Date navigation\n const previousDay = () => {\n if (!props.modelValue.date) return;\n const currentDate = moment__WEBPACK_IMPORTED_MODULE_10___default()(props.modelValue.date);\n const newDate = currentDate.clone().subtract(1, 'day').toDate();\n // Don't allow going to past dates\n if (moment__WEBPACK_IMPORTED_MODULE_10___default()(newDate).isBefore(moment__WEBPACK_IMPORTED_MODULE_10___default()(), 'day')) return;\n updateDate(newDate);\n };\n const nextDay = () => {\n if (!props.modelValue.date) return;\n const currentDate = moment__WEBPACK_IMPORTED_MODULE_10___default()(props.modelValue.date);\n const newDate = currentDate.clone().add(1, 'day').toDate();\n updateDate(newDate);\n };\n // Update handlers\n const updateDate = date => {\n emit('update:modelValue', {\n ...props.modelValue,\n date\n });\n };\n const updateStartTime = event => {\n const target = event.target;\n emit('update:modelValue', {\n ...props.modelValue,\n starts_at_time: target.value\n });\n };\n const updateEndTime = event => {\n const target = event.target;\n emit('update:modelValue', {\n ...props.modelValue,\n ends_at_time: target.value\n });\n };\n // Handle timeblock updated from timeline (drag/drop or quick add)\n const handleTimeblockUpdated = payload => {\n const {\n starts_at_time\n } = payload;\n let {\n ends_at_time\n } = payload;\n // Fix accidental same start/end time by adding 1 hour to end\n if (starts_at_time === ends_at_time) {\n const [hours, minutes] = starts_at_time.split(':').map(Number);\n const newEndHour = (hours + 1) % 24; // Wrap around at midnight\n ends_at_time = `${String(newEndHour).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`;\n }\n emit('update:modelValue', {\n ...props.modelValue,\n starts_at_time,\n ends_at_time\n });\n // Trigger validation after timeline update\n (0,vue__WEBPACK_IMPORTED_MODULE_3__.nextTick)(() => {\n v$.value.$touch();\n });\n };\n // Expose validate method\n const validate = async () => {\n v$.value.$touch();\n const isValid = await v$.value.$validate();\n return isValid && isTimeRangeValid.value;\n };\n __expose({\n validate\n });\n (0,vue__WEBPACK_IMPORTED_MODULE_3__.watch)(() => props.modelValue.ends_at_time, () => {\n if (v$.value.ends_at_time.$model !== props.modelValue.ends_at_time) {\n v$.value.ends_at_time.$model = props.modelValue.ends_at_time;\n }\n });\n (0,vue__WEBPACK_IMPORTED_MODULE_3__.watch)(() => props.modelValue.starts_at_time, () => {\n if (v$.value.starts_at_time.$model !== props.modelValue.starts_at_time) {\n v$.value.starts_at_time.$model = props.modelValue.starts_at_time;\n console.log('starts_at_time changed', v$.value.starts_at_time.$model);\n }\n });\n (0,vue__WEBPACK_IMPORTED_MODULE_3__.watch)(() => props.modelValue.date, () => {\n if (v$.value.date.$model !== props.modelValue.date) {\n v$.value.date.$model = props.modelValue.date;\n }\n });\n const __returned__ = {\n ALLOW_EDITING_EXISTING_TIMEBLOCKS,\n props,\n emit,\n timelineRef,\n isEditable,\n minDate,\n HOUR_WIDTH,\n HOUR_WIDTH_MOBILE,\n START_HOUR,\n END_HOUR,\n isMobile,\n hourWidth,\n timeRangeValid,\n requiredWhenHasTime,\n rules,\n v$,\n hasStartTimeError,\n hasEndTimeError,\n endTimeErrorMessage,\n employeeRef,\n dateRef,\n timeblockRef,\n otherTimeblocksForSameDate,\n isLoading,\n timelineTasks,\n _scheduledTime,\n _freeTime,\n timeblockDuration,\n refetch,\n scheduledBlocks,\n otherTimeblocksAsTasks,\n allBlocksForCollisionCheck,\n collision,\n collisionSegments,\n currentTimeblockRange,\n isTimeRangeValid,\n centerTimeline,\n previousDay,\n nextDay,\n updateDate,\n updateStartTime,\n updateEndTime,\n handleTimeblockUpdated,\n validate,\n AEmployeeTimeblockHeader: _a_employee_timeblock_header_vue__WEBPACK_IMPORTED_MODULE_8__[\"default\"],\n AEmployeeTimeblockTimeline: _a_employee_timeblock_timeline_vue__WEBPACK_IMPORTED_MODULE_9__[\"default\"]\n };\n Object.defineProperty(__returned__, '__isScriptSetup', {\n enumerable: false,\n value: true\n });\n return __returned__;\n }\n}));\n\n//# sourceURL=webpack://jandl/./src/plugins/tm@modal/task/_components/employees/a-employee-timeblock.vue?./node_modules/webpack-plugin-vuetify/dist/scriptLoader.js!./node_modules/babel-loader/lib/index.js!./node_modules/ts-loader/index.js??clonedRuleSet-41.use%5B1%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}"); /***/ }), @@ -1297,7 +1297,7 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpa /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ render: function() { return /* binding */ render; }\n/* harmony export */ });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm-bundler.js\");\n/* harmony import */ var vuetify_lib_components_VTextField_index_mjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! vuetify/lib/components/VTextField/index.mjs */ \"./node_modules/vuetify/lib/components/VTextField/VTextField.mjs\");\n\nconst _hoisted_1 = {\n class: \"timeblock__header\"\n};\nconst _hoisted_2 = {\n class: \"timeblock__header__top\"\n};\nconst _hoisted_3 = {\n class: \"timeblock__header__content\"\n};\nconst _hoisted_4 = {\n class: \"timeblock__date-wrapper\"\n};\nconst _hoisted_5 = {\n class: \"timeblock__date\"\n};\nconst _hoisted_6 = [\"disabled\"];\nconst _hoisted_7 = [\"disabled\"];\nconst _hoisted_8 = {\n class: \"actions actions--mobile\"\n};\nconst _hoisted_9 = {\n class: \"timeblock__controls\"\n};\nconst _hoisted_10 = {\n class: \"timeblock__controls__time\"\n};\nconst _hoisted_11 = {\n class: \"timeblock__time-overview\"\n};\nconst _hoisted_12 = {\n key: 0,\n class: \"validation-error\"\n};\nconst _hoisted_13 = {\n class: \"actions actions--desktop\"\n};\nfunction render(_ctx, _cache, $props, $setup, $data, $options) {\n \n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", _hoisted_1, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_2, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"p\", null, \" Časový blok \" + (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($props.index + 1) + \" - \" + (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($props.employee._fullName), 1 /* TEXT */)]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_3, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_4, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_5, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n class: \"timeblock__date-button\",\n disabled: $setup.isCurrentDay || !$props.isEditable,\n onClick: _cache[0] || (_cache[0] = $event => _ctx.$emit('previousDay'))\n }, [...(_cache[9] || (_cache[9] = [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"svg\", {\n width: \"20\",\n height: \"20\",\n viewBox: \"0 0 24 24\",\n fill: \"currentColor\"\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"path\", {\n d: \"M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z\"\n })], -1 /* CACHED */)]))], 8 /* PROPS */, _hoisted_6), ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)($setup[\"ZDatepicker\"], {\n key: $setup.dateFormat,\n \"model-value\": $props.modelValue.date,\n format: $setup.dateFormat,\n locale: \"sk\",\n \"select-text\": \"Vybrať\",\n \"cancel-text\": \"Zrušiť\",\n placeholder: \"Dátum\",\n \"auto-apply\": true,\n \"enable-time-picker\": false,\n \"min-date\": $props.minDate,\n disabled: !$props.isEditable,\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([\"timeblock__date-picker\", {\n 'timeblock__date-picker--disabled': !$props.isEditable\n }]),\n \"onUpdate:modelValue\": _cache[1] || (_cache[1] = $event => _ctx.$emit('updateDate', $event))\n }, null, 8 /* PROPS */, [\"model-value\", \"format\", \"min-date\", \"disabled\", \"class\"])), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n class: \"timeblock__date-button\",\n disabled: !$props.isEditable,\n onClick: _cache[2] || (_cache[2] = $event => _ctx.$emit('nextDay'))\n }, [...(_cache[10] || (_cache[10] = [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"svg\", {\n width: \"20\",\n height: \"20\",\n viewBox: \"0 0 24 24\",\n fill: \"currentColor\"\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"path\", {\n d: \"M8.59 16.59L10 18l6-6-6-6-1.41 1.41L13.17 12z\"\n })], -1 /* CACHED */)]))], 8 /* PROPS */, _hoisted_7)]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_8, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)($setup[\"AEmployeeTimeblockHeaderActions\"], {\n deletable: $props.deletable,\n onAddTimeblock: _cache[3] || (_cache[3] = $event => _ctx.$emit('addTimeblock')),\n onRemoveTimeblock: _cache[4] || (_cache[4] = $event => _ctx.$emit('removeTimeblock'))\n }, null, 8 /* PROPS */, [\"deletable\"])])]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_9, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_10, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(vuetify_lib_components_VTextField_index_mjs__WEBPACK_IMPORTED_MODULE_1__.VTextField, {\n value: $props.modelValue.starts_at_time,\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)({\n 'error-input': $props.collision.startCollides || !$props.isTimeRangeValid || $props.hasValidationErrors && $props.hasStartTimeError\n }),\n disabled: !$props.isEditable,\n type: \"time\",\n variant: \"solo\",\n \"bg-color\": \"white\",\n label: \"Začiatok\",\n density: \"compact\",\n \"hide-details\": \"\",\n onInput: _cache[5] || (_cache[5] = $event => _ctx.$emit('updateStartTime', $event))\n }, null, 8 /* PROPS */, [\"value\", \"class\", \"disabled\"]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(vuetify_lib_components_VTextField_index_mjs__WEBPACK_IMPORTED_MODULE_1__.VTextField, {\n value: $props.modelValue.ends_at_time,\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)({\n 'error-input': $props.collision.endCollides || !$props.isTimeRangeValid || $props.hasValidationErrors && $props.hasEndTimeError\n }),\n disabled: !$props.isEditable,\n type: \"time\",\n variant: \"solo\",\n \"bg-color\": \"white\",\n label: \"Koniec\",\n density: \"compact\",\n \"hide-details\": \"\",\n onInput: _cache[6] || (_cache[6] = $event => _ctx.$emit('updateEndTime', $event))\n }, null, 8 /* PROPS */, [\"value\", \"class\", \"disabled\"])]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_11, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"p\", null, [_cache[11] || (_cache[11] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", {\n class: \"timeblock__time-overview__label timeblock__time-overview__label--desktop\"\n }, \"Naplánovaný čas:\", -1 /* CACHED */)), _cache[12] || (_cache[12] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", {\n class: \"timeblock__time-overview__label timeblock__time-overview__label--mobile\"\n }, \"Nap. čas:\", -1 /* CACHED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($props.plannedTime) + \"h\", 1 /* TEXT */)]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"p\", null, [_cache[13] || (_cache[13] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", {\n class: \"timeblock__time-overview__label timeblock__time-overview__label--desktop\"\n }, \"Volný čas:\", -1 /* CACHED */)), _cache[14] || (_cache[14] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", {\n class: \"timeblock__time-overview__label timeblock__time-overview__label--mobile\"\n }, \"Vol. čas:\", -1 /* CACHED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($props.freeTime) + \"h\", 1 /* TEXT */)])])]), !$props.isTimeRangeValid || $props.endTimeErrorMessage ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", _hoisted_12, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($props.endTimeErrorMessage || 'Koniec musí byť po začiatku'), 1 /* TEXT */)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_13, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)($setup[\"AEmployeeTimeblockHeaderActions\"], {\n deletable: $props.deletable,\n onAddTimeblock: _cache[7] || (_cache[7] = $event => _ctx.$emit('addTimeblock')),\n onRemoveTimeblock: _cache[8] || (_cache[8] = $event => _ctx.$emit('removeTimeblock'))\n }, null, 8 /* PROPS */, [\"deletable\"])])])]);\n}\n\n/* Vuetify */\n\n\n\n\n//# sourceURL=webpack://jandl/./src/plugins/tm@modal/task/_components/employees/a-employee-timeblock-header.vue?./node_modules/webpack-plugin-vuetify/dist/scriptLoader.js!./node_modules/babel-loader/lib/index.js!./node_modules/ts-loader/index.js??clonedRuleSet-41.use%5B1%5D!./node_modules/vue-loader/dist/templateLoader.js??ruleSet%5B1%5D.rules%5B5%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}"); +eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ render: function() { return /* binding */ render; }\n/* harmony export */ });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm-bundler.js\");\n/* harmony import */ var vuetify_lib_components_VTextField_index_mjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! vuetify/lib/components/VTextField/index.mjs */ \"./node_modules/vuetify/lib/components/VTextField/VTextField.mjs\");\n\nconst _hoisted_1 = {\n class: \"timeblock__header\"\n};\nconst _hoisted_2 = {\n class: \"timeblock__header__top\"\n};\nconst _hoisted_3 = {\n class: \"timeblock__header__content\"\n};\nconst _hoisted_4 = {\n class: \"timeblock__date-wrapper\"\n};\nconst _hoisted_5 = {\n class: \"timeblock__date\"\n};\nconst _hoisted_6 = [\"disabled\"];\nconst _hoisted_7 = [\"disabled\"];\nconst _hoisted_8 = {\n class: \"actions actions--mobile\"\n};\nconst _hoisted_9 = {\n class: \"timeblock__controls\"\n};\nconst _hoisted_10 = {\n class: \"timeblock__controls__time\"\n};\nconst _hoisted_11 = {\n class: \"timeblock__time-overview\"\n};\nconst _hoisted_12 = {\n key: 0,\n class: \"validation-error\"\n};\nconst _hoisted_13 = {\n class: \"actions actions--desktop\"\n};\nfunction render(_ctx, _cache, $props, $setup, $data, $options) {\n \n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", _hoisted_1, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_2, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"p\", null, \" Časový blok \" + (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($props.index + 1) + \" - \" + (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($props.employee._fullName), 1 /* TEXT */)]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_3, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_4, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_5, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n class: \"timeblock__date-button\",\n disabled: $setup.isCurrentDay || !$props.isEditable,\n onClick: _cache[0] || (_cache[0] = $event => _ctx.$emit('previousDay'))\n }, [...(_cache[9] || (_cache[9] = [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"svg\", {\n width: \"20\",\n height: \"20\",\n viewBox: \"0 0 24 24\",\n fill: \"currentColor\"\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"path\", {\n d: \"M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z\"\n })], -1 /* CACHED */)]))], 8 /* PROPS */, _hoisted_6), ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)($setup[\"ZDatepicker\"], {\n key: $setup.dateFormat,\n \"model-value\": $props.modelValue.date,\n format: $setup.dateFormat,\n locale: \"sk\",\n \"select-text\": \"Vybrať\",\n \"cancel-text\": \"Zrušiť\",\n placeholder: \"Dátum\",\n \"auto-apply\": true,\n \"enable-time-picker\": false,\n \"min-date\": $props.minDate,\n disabled: !$props.isEditable,\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([\"timeblock__date-picker\", {\n 'timeblock__date-picker--disabled': !$props.isEditable\n }]),\n \"onUpdate:modelValue\": _cache[1] || (_cache[1] = $event => _ctx.$emit('updateDate', $event))\n }, null, 8 /* PROPS */, [\"model-value\", \"format\", \"min-date\", \"disabled\", \"class\"])), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n class: \"timeblock__date-button\",\n disabled: !$props.isEditable,\n onClick: _cache[2] || (_cache[2] = $event => _ctx.$emit('nextDay'))\n }, [...(_cache[10] || (_cache[10] = [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"svg\", {\n width: \"20\",\n height: \"20\",\n viewBox: \"0 0 24 24\",\n fill: \"currentColor\"\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"path\", {\n d: \"M8.59 16.59L10 18l6-6-6-6-1.41 1.41L13.17 12z\"\n })], -1 /* CACHED */)]))], 8 /* PROPS */, _hoisted_7)]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_8, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)($setup[\"AEmployeeTimeblockHeaderActions\"], {\n deletable: $props.deletable,\n onAddTimeblock: _cache[3] || (_cache[3] = $event => _ctx.$emit('addTimeblock')),\n onRemoveTimeblock: _cache[4] || (_cache[4] = $event => _ctx.$emit('removeTimeblock'))\n }, null, 8 /* PROPS */, [\"deletable\"])])]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_9, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_10, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(vuetify_lib_components_VTextField_index_mjs__WEBPACK_IMPORTED_MODULE_1__.VTextField, {\n value: $props.modelValue.starts_at_time,\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)({\n 'error-input': $props.collision.startCollides || !$props.isTimeRangeValid || $props.hasValidationErrors && $props.hasStartTimeError\n }),\n disabled: !$props.isEditable,\n type: \"time\",\n variant: \"solo\",\n \"bg-color\": \"white\",\n label: \"Začiatok\",\n density: \"compact\",\n \"hide-details\": \"\",\n onInput: _cache[5] || (_cache[5] = $event => _ctx.$emit('updateStartTime', $event))\n }, null, 8 /* PROPS */, [\"value\", \"class\", \"disabled\"]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(vuetify_lib_components_VTextField_index_mjs__WEBPACK_IMPORTED_MODULE_1__.VTextField, {\n value: $props.modelValue.ends_at_time,\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)({\n 'error-input': $props.collision.endCollides || !$props.isTimeRangeValid || $props.hasValidationErrors && $props.hasEndTimeError\n }),\n disabled: !$props.isEditable,\n type: \"time\",\n variant: \"solo\",\n \"bg-color\": \"white\",\n label: \"Koniec\",\n density: \"compact\",\n \"hide-details\": \"\",\n onInput: _cache[6] || (_cache[6] = $event => _ctx.$emit('updateEndTime', $event))\n }, null, 8 /* PROPS */, [\"value\", \"class\", \"disabled\"])]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_11, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"p\", null, [_cache[11] || (_cache[11] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", {\n class: \"timeblock__time-overview__label timeblock__time-overview__label--desktop\"\n }, \"Naplánovaný čas:\", -1 /* CACHED */)), _cache[12] || (_cache[12] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", {\n class: \"timeblock__time-overview__label timeblock__time-overview__label--mobile\"\n }, \"Nap. čas:\", -1 /* CACHED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($props.plannedTime) + \"h\", 1 /* TEXT */)]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"p\", null, [_cache[13] || (_cache[13] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", {\n class: \"timeblock__time-overview__label timeblock__time-overview__label--desktop\"\n }, \"Volný čas:\", -1 /* CACHED */)), _cache[14] || (_cache[14] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", {\n class: \"timeblock__time-overview__label timeblock__time-overview__label--mobile\"\n }, \"Vol. čas:\", -1 /* CACHED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", {\n style: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeStyle)({\n color: Number($props.freeTime) < 0 ? 'red' : undefined\n })\n }, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($props.freeTime) + \"h\", 5 /* TEXT, STYLE */)])])]), !$props.isTimeRangeValid || $props.endTimeErrorMessage ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", _hoisted_12, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($props.endTimeErrorMessage || 'Koniec musí byť po začiatku'), 1 /* TEXT */)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_13, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)($setup[\"AEmployeeTimeblockHeaderActions\"], {\n deletable: $props.deletable,\n onAddTimeblock: _cache[7] || (_cache[7] = $event => _ctx.$emit('addTimeblock')),\n onRemoveTimeblock: _cache[8] || (_cache[8] = $event => _ctx.$emit('removeTimeblock'))\n }, null, 8 /* PROPS */, [\"deletable\"])])])]);\n}\n\n/* Vuetify */\n\n\n\n\n//# sourceURL=webpack://jandl/./src/plugins/tm@modal/task/_components/employees/a-employee-timeblock-header.vue?./node_modules/webpack-plugin-vuetify/dist/scriptLoader.js!./node_modules/babel-loader/lib/index.js!./node_modules/ts-loader/index.js??clonedRuleSet-41.use%5B1%5D!./node_modules/vue-loader/dist/templateLoader.js??ruleSet%5B1%5D.rules%5B5%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}"); /***/ }), @@ -1319,7 +1319,7 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpa /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ render: function() { return /* binding */ render; }\n/* harmony export */ });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm-bundler.js\");\n\nconst _hoisted_1 = {\n class: \"timeline\"\n};\nconst _hoisted_2 = {\n key: 0,\n class: \"timeline-loading\"\n};\nconst _hoisted_3 = {\n key: 1,\n ref: \"timelineContainer\",\n class: \"timeline__content\"\n};\nconst _hoisted_4 = {\n ref: \"timelineScroll\",\n class: \"timeline-scroll\"\n};\nconst _hoisted_5 = [\"title\"];\nconst _hoisted_6 = {\n class: \"preview-time-label\"\n};\nconst _hoisted_7 = {\n key: 0\n};\nconst _hoisted_8 = {\n key: 1\n};\nconst _hoisted_9 = {\n key: 0,\n class: \"timeblock-duration\"\n};\nconst _hoisted_10 = {\n key: 0,\n class: \"preview-time-label\"\n};\nconst _hoisted_11 = {\n key: 1,\n class: \"preview-time-label\"\n};\nfunction render(_ctx, _cache, $props, $setup, $data, $options) {\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", _hoisted_1, [$props.isLoading ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", _hoisted_2, [...(_cache[2] || (_cache[2] = [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", null, \"Načítavam...\", -1 /* CACHED */)]))])) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", _hoisted_3, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_4, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)($setup[\"AEmployeeTimeblockTimelineHeader\"], {\n \"start-hour\": $props.startHour,\n \"end-hour\": $props.endHour,\n \"hour-width\": $props.hourWidth\n }, null, 8 /* PROPS */, [\"start-hour\", \"end-hour\", \"hour-width\"]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", {\n ref: \"timelineBar\",\n class: \"timeline-bar\",\n onMousemove: $setup.handleMouseMove,\n onMouseleave: $setup.handleMouseLeave,\n onMousedown: $setup.handleMouseDown\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\" Non-working hours - before work \"), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", {\n class: \"non-working-hours\",\n style: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeStyle)({\n left: '0px',\n width: `${$setup.getHourPosition($props.employee.work_start)}px`\n })\n }, null, 4 /* STYLE */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\" Non-working hours - after work \"), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", {\n class: \"non-working-hours\",\n style: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeStyle)({\n left: `${$setup.getHourPosition($props.employee.work_end)}px`,\n width: `${$setup.getHourWidth(24 - $props.employee.work_end)}px`\n })\n }, null, 4 /* STYLE */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\" Work hours background (transparent/white) \"), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", {\n class: \"work-hours-bar\",\n style: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeStyle)({\n left: `${$setup.getHourPosition($props.employee.work_start)}px`,\n width: `${$setup.getHourWidth($props.employee.work_end - $props.employee.work_start)}px`\n })\n }, null, 4 /* STYLE */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\" Existing scheduled blocks \"), ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderList)($props.scheduledBlocks, (task, index) => {\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", {\n key: `task-${index}`,\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([\"scheduled-block\", {\n 'scheduled-block--blocker': ['blocker', 'adhoc', 'home_office', 'vacation', 'free_day', 'office365_blocker'].includes(task.type)\n }]),\n style: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeStyle)({\n left: `${$setup.getTimePosition(task._real_start)}px`,\n width: `${$setup.getTimeWidth(task._real_start, task._real_end)}px`\n }),\n title: `${task.subtask?.title || task.blocker?.type || 'Task'}`\n }, null, 14 /* CLASS, STYLE, PROPS */, _hoisted_5);\n }), 128 /* KEYED_FRAGMENT */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\" Other timeblocks for same date \"), ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderList)($setup.otherTimeblocksRendered, (timeblock, index) => {\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", {\n key: `other-${index}`,\n class: \"other-timeblock\",\n style: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeStyle)({\n left: `${$setup.getTimePosition(timeblock._start)}px`,\n width: `${$setup.getTimeWidth(timeblock._start, timeblock._end)}px`\n }),\n title: `Other timeblock`\n }, null, 4 /* STYLE */);\n }), 128 /* KEYED_FRAGMENT */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\" Hover preview block \"), $setup.showPreview && $setup.previewBlock ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", {\n key: 0,\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([\"preview-block\", {\n 'is-stretching': $setup.dragState.isStretching\n }]),\n style: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeStyle)({\n left: `${$setup.getTimePosition($setup.previewBlock.start)}px`,\n width: `${$setup.getTimeWidth($setup.previewBlock.start, $setup.previewBlock.end)}px`\n }),\n onMousedown: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($setup.handlePreviewMouseDown, [\"stop\"])\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_6, [$setup.getTimeWidth($setup.previewBlock.start, $setup.previewBlock.end) <= 58 ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", _hoisted_7, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.formatTime($setup.previewBlock.start)), 1 /* TEXT */)) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", _hoisted_8, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.formatTime($setup.previewBlock.start)) + \" - \" + (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.formatTime($setup.previewBlock.end)), 1 /* TEXT */))])], 38 /* CLASS, STYLE, NEED_HYDRATION */)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\" Current timeblock (if valid) \"), $props.currentTimeblockRange.start && $props.currentTimeblockRange.end && !$setup.dragState.isResizingCurrent ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", {\n key: 1,\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([\"current-timeblock\", {\n 'has-collision': $props.collision.hasCollision\n }]),\n style: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeStyle)({\n left: `${$setup.getTimePosition($props.currentTimeblockRange.start)}px`,\n width: `${$setup.getTimeWidth($props.currentTimeblockRange.start, $props.currentTimeblockRange.end)}px`\n })\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\" Duration display (centered in current timeblock) \"), $props.timeblockDuration > 0 ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", _hoisted_9, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($props.timeblockDuration.toFixed(2)) + \"h \", 1 /* TEXT */)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\" Resize handles \"), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", {\n class: \"resize-handle resize-handle--left\",\n onMousedown: _cache[0] || (_cache[0] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($event => $setup.handleResizeMouseDown($event, 'left'), [\"stop\"]))\n }, null, 32 /* NEED_HYDRATION */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", {\n class: \"resize-handle resize-handle--right\",\n onMousedown: _cache[1] || (_cache[1] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($event => $setup.handleResizeMouseDown($event, 'right'), [\"stop\"]))\n }, null, 32 /* NEED_HYDRATION */)], 6 /* CLASS, STYLE */)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\" Resizing current timeblock preview \"), $setup.dragState.isResizingCurrent && $setup.resizedCurrentBlock ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", {\n key: 2,\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([\"current-timeblock is-resizing\", {\n 'has-collision': $props.collision.hasCollision\n }]),\n style: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeStyle)({\n left: `${$setup.getTimePosition($setup.resizedCurrentBlock.start)}px`,\n width: `${$setup.getTimeWidth($setup.resizedCurrentBlock.start, $setup.resizedCurrentBlock.end)}px`\n })\n }, [$setup.getTimeWidth($setup.resizedCurrentBlock.start, $setup.resizedCurrentBlock.end) <= 58 ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", _hoisted_10, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.formatTime($setup.resizedCurrentBlock.start)), 1 /* TEXT */)) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", _hoisted_11, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.formatTime($setup.resizedCurrentBlock.start)) + \" - \" + (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.formatTime($setup.resizedCurrentBlock.end)), 1 /* TEXT */))], 6 /* CLASS, STYLE */)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\" Collision segments \"), ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderList)($props.collisionSegments, (segment, index) => {\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", {\n key: `collision-${index}`,\n class: \"collision-segment\",\n style: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeStyle)({\n left: `${$setup.getTimePosition(segment.start)}px`,\n width: `${$setup.getTimeWidth(segment.start, segment.end)}px`\n })\n }, null, 4 /* STYLE */);\n }), 128 /* KEYED_FRAGMENT */))], 544 /* NEED_HYDRATION, NEED_PATCH */)], 512 /* NEED_PATCH */)], 512 /* NEED_PATCH */))]);\n}\n\n//# sourceURL=webpack://jandl/./src/plugins/tm@modal/task/_components/employees/a-employee-timeblock-timeline.vue?./node_modules/webpack-plugin-vuetify/dist/scriptLoader.js!./node_modules/babel-loader/lib/index.js!./node_modules/ts-loader/index.js??clonedRuleSet-41.use%5B1%5D!./node_modules/vue-loader/dist/templateLoader.js??ruleSet%5B1%5D.rules%5B5%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}"); +eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ render: function() { return /* binding */ render; }\n/* harmony export */ });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm-bundler.js\");\n\nconst _hoisted_1 = {\n class: \"timeline\"\n};\nconst _hoisted_2 = {\n key: 0,\n class: \"timeline-loading\"\n};\nconst _hoisted_3 = {\n key: 1,\n ref: \"timelineContainer\",\n class: \"timeline__content\"\n};\nconst _hoisted_4 = {\n ref: \"timelineScroll\",\n class: \"timeline-scroll\"\n};\nconst _hoisted_5 = {\n key: 0,\n class: \"weekend-overlay\"\n};\nconst _hoisted_6 = [\"title\"];\nconst _hoisted_7 = {\n class: \"preview-time-label\"\n};\nconst _hoisted_8 = {\n key: 0\n};\nconst _hoisted_9 = {\n key: 1\n};\nconst _hoisted_10 = {\n key: 0,\n class: \"timeblock-duration\"\n};\nconst _hoisted_11 = {\n key: 0,\n class: \"preview-time-label\"\n};\nconst _hoisted_12 = {\n key: 1,\n class: \"preview-time-label\"\n};\nfunction render(_ctx, _cache, $props, $setup, $data, $options) {\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", _hoisted_1, [$props.isLoading ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", _hoisted_2, [...(_cache[2] || (_cache[2] = [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", null, \"Načítavam...\", -1 /* CACHED */)]))])) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", _hoisted_3, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_4, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)($setup[\"AEmployeeTimeblockTimelineHeader\"], {\n \"start-hour\": $props.startHour,\n \"end-hour\": $props.endHour,\n \"hour-width\": $props.hourWidth\n }, null, 8 /* PROPS */, [\"start-hour\", \"end-hour\", \"hour-width\"]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", {\n ref: \"timelineBar\",\n class: \"timeline-bar\",\n onMousemove: $setup.handleMouseMove,\n onMouseleave: $setup.handleMouseLeave,\n onMousedown: $setup.handleMouseDown\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\" Non-working hours - before work \"), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", {\n class: \"non-working-hours\",\n style: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeStyle)({\n left: '0px',\n width: `${$setup.getHourPosition($props.employee.work_start)}px`\n })\n }, null, 4 /* STYLE */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\" Non-working hours - after work \"), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", {\n class: \"non-working-hours\",\n style: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeStyle)({\n left: `${$setup.getHourPosition($props.employee.work_end)}px`,\n width: `${$setup.getHourWidth(24 - $props.employee.work_end)}px`\n })\n }, null, 4 /* STYLE */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\" Work hours background (transparent/white) \"), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", {\n class: \"work-hours-bar\",\n style: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeStyle)({\n left: `${$setup.getHourPosition($props.employee.work_start)}px`,\n width: `${$setup.getHourWidth($props.employee.work_end - $props.employee.work_start)}px`\n })\n }, null, 4 /* STYLE */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\" Weekend background overlay \"), $setup.isWeekend ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", _hoisted_5)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\" Existing scheduled blocks \"), ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderList)($props.scheduledBlocks, (task, index) => {\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", {\n key: `task-${index}`,\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([\"scheduled-block\", {\n 'scheduled-block--blocker': ['blocker', 'adhoc', 'home_office', 'vacation', 'free_day', 'office365_blocker'].includes(task.type)\n }]),\n style: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeStyle)({\n left: `${$setup.getTimePosition(task._real_start)}px`,\n width: `${$setup.getTimeWidth(task._real_start, task._real_end)}px`\n }),\n title: `${task.subtask?.title || task.blocker?.type || 'Task'}`\n }, null, 14 /* CLASS, STYLE, PROPS */, _hoisted_6);\n }), 128 /* KEYED_FRAGMENT */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\" Other timeblocks for same date \"), ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderList)($setup.otherTimeblocksRendered, (timeblock, index) => {\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", {\n key: `other-${index}`,\n class: \"other-timeblock\",\n style: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeStyle)({\n left: `${$setup.getTimePosition(timeblock._start)}px`,\n width: `${$setup.getTimeWidth(timeblock._start, timeblock._end)}px`\n }),\n title: `Other timeblock`\n }, null, 4 /* STYLE */);\n }), 128 /* KEYED_FRAGMENT */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\" Hover preview block \"), $setup.showPreview && $setup.previewBlock ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", {\n key: 1,\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([\"preview-block\", {\n 'is-stretching': $setup.dragState.isStretching\n }]),\n style: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeStyle)({\n left: `${$setup.getTimePosition($setup.previewBlock.start)}px`,\n width: `${$setup.getTimeWidth($setup.previewBlock.start, $setup.previewBlock.end)}px`\n }),\n onMousedown: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($setup.handlePreviewMouseDown, [\"stop\"])\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_7, [$setup.getTimeWidth($setup.previewBlock.start, $setup.previewBlock.end) <= 58 ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", _hoisted_8, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.formatTime($setup.previewBlock.start)), 1 /* TEXT */)) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", _hoisted_9, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.formatTime($setup.previewBlock.start)) + \" - \" + (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.formatTime($setup.previewBlock.end)), 1 /* TEXT */))])], 38 /* CLASS, STYLE, NEED_HYDRATION */)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\" Current timeblock (if valid) \"), $props.currentTimeblockRange.start && $props.currentTimeblockRange.end && !$setup.dragState.isResizingCurrent ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", {\n key: 2,\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([\"current-timeblock\", {\n 'has-collision': $props.collision.hasCollision\n }]),\n style: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeStyle)({\n left: `${$setup.getTimePosition($props.currentTimeblockRange.start)}px`,\n width: `${$setup.getTimeWidth($props.currentTimeblockRange.start, $props.currentTimeblockRange.end)}px`\n })\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\" Duration display (centered in current timeblock) \"), $props.timeblockDuration > 0 ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", _hoisted_10, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($props.timeblockDuration.toFixed(2)) + \"h \", 1 /* TEXT */)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\" Resize handles \"), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", {\n class: \"resize-handle resize-handle--left\",\n onMousedown: _cache[0] || (_cache[0] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($event => $setup.handleResizeMouseDown($event, 'left'), [\"stop\"]))\n }, null, 32 /* NEED_HYDRATION */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", {\n class: \"resize-handle resize-handle--right\",\n onMousedown: _cache[1] || (_cache[1] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($event => $setup.handleResizeMouseDown($event, 'right'), [\"stop\"]))\n }, null, 32 /* NEED_HYDRATION */)], 6 /* CLASS, STYLE */)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\" Resizing current timeblock preview \"), $setup.dragState.isResizingCurrent && $setup.resizedCurrentBlock ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", {\n key: 3,\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([\"current-timeblock is-resizing\", {\n 'has-collision': $props.collision.hasCollision\n }]),\n style: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeStyle)({\n left: `${$setup.getTimePosition($setup.resizedCurrentBlock.start)}px`,\n width: `${$setup.getTimeWidth($setup.resizedCurrentBlock.start, $setup.resizedCurrentBlock.end)}px`\n })\n }, [$setup.getTimeWidth($setup.resizedCurrentBlock.start, $setup.resizedCurrentBlock.end) <= 58 ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", _hoisted_11, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.formatTime($setup.resizedCurrentBlock.start)), 1 /* TEXT */)) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", _hoisted_12, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.formatTime($setup.resizedCurrentBlock.start)) + \" - \" + (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.formatTime($setup.resizedCurrentBlock.end)), 1 /* TEXT */))], 6 /* CLASS, STYLE */)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\" Collision segments \"), ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderList)($props.collisionSegments, (segment, index) => {\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", {\n key: `collision-${index}`,\n class: \"collision-segment\",\n style: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeStyle)({\n left: `${$setup.getTimePosition(segment.start)}px`,\n width: `${$setup.getTimeWidth(segment.start, segment.end)}px`\n })\n }, null, 4 /* STYLE */);\n }), 128 /* KEYED_FRAGMENT */))], 544 /* NEED_HYDRATION, NEED_PATCH */)], 512 /* NEED_PATCH */)], 512 /* NEED_PATCH */))]);\n}\n\n//# sourceURL=webpack://jandl/./src/plugins/tm@modal/task/_components/employees/a-employee-timeblock-timeline.vue?./node_modules/webpack-plugin-vuetify/dist/scriptLoader.js!./node_modules/babel-loader/lib/index.js!./node_modules/ts-loader/index.js??clonedRuleSet-41.use%5B1%5D!./node_modules/vue-loader/dist/templateLoader.js??ruleSet%5B1%5D.rules%5B5%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}"); /***/ }), @@ -1330,7 +1330,7 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpa /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ render: function() { return /* binding */ render; }\n/* harmony export */ });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm-bundler.js\");\n\nconst _hoisted_1 = {\n class: \"timeblock\"\n};\nfunction render(_ctx, _cache, $props, $setup, $data, $options) {\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", _hoisted_1, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)($setup[\"AEmployeeTimeblockHeader\"], {\n \"model-value\": $props.modelValue,\n \"min-date\": $setup.minDate,\n deletable: $props.deletable,\n \"is-editable\": $setup.isEditable,\n \"is-time-range-valid\": $setup.isTimeRangeValid,\n collision: $setup.collision,\n \"has-validation-errors\": $setup.v$.$error && $setup.v$.$anyDirty,\n \"has-start-time-error\": $setup.hasStartTimeError,\n \"has-end-time-error\": $setup.hasEndTimeError,\n \"end-time-error-message\": $setup.endTimeErrorMessage,\n \"planned-time\": $setup._scheduledTime,\n \"free-time\": $setup._freeTime,\n employee: $props.employee,\n index: $props.index,\n onPreviousDay: $setup.previousDay,\n onNextDay: $setup.nextDay,\n onUpdateDate: $setup.updateDate,\n onUpdateStartTime: $setup.updateStartTime,\n onUpdateEndTime: $setup.updateEndTime,\n onAddTimeblock: _cache[0] || (_cache[0] = $event => _ctx.$emit('addTimeblock')),\n onRemoveTimeblock: _cache[1] || (_cache[1] = $event => _ctx.$emit('removeTimeblock'))\n }, null, 8 /* PROPS */, [\"model-value\", \"min-date\", \"deletable\", \"is-editable\", \"is-time-range-valid\", \"collision\", \"has-validation-errors\", \"has-start-time-error\", \"has-end-time-error\", \"end-time-error-message\", \"planned-time\", \"free-time\", \"employee\", \"index\"]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\" Timeline Visualization \"), $props.modelValue.date && $props.employee ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)($setup[\"AEmployeeTimeblockTimeline\"], {\n key: 0,\n ref: \"timelineRef\",\n \"is-loading\": $setup.isLoading,\n employee: $props.employee,\n \"scheduled-blocks\": $setup.scheduledBlocks,\n \"other-timeblocks\": $setup.otherTimeblocksForSameDate,\n \"current-timeblock-range\": $setup.currentTimeblockRange,\n collision: $setup.collision,\n \"collision-segments\": $setup.collisionSegments,\n \"timeblock-duration\": $setup.timeblockDuration,\n \"start-hour\": $setup.START_HOUR,\n \"end-hour\": $setup.END_HOUR,\n \"hour-width\": $setup.hourWidth,\n onTimeblockUpdated: $setup.handleTimeblockUpdated\n }, null, 8 /* PROPS */, [\"is-loading\", \"employee\", \"scheduled-blocks\", \"other-timeblocks\", \"current-timeblock-range\", \"collision\", \"collision-segments\", \"timeblock-duration\", \"hour-width\"])) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true)]);\n}\n\n//# sourceURL=webpack://jandl/./src/plugins/tm@modal/task/_components/employees/a-employee-timeblock.vue?./node_modules/webpack-plugin-vuetify/dist/scriptLoader.js!./node_modules/babel-loader/lib/index.js!./node_modules/ts-loader/index.js??clonedRuleSet-41.use%5B1%5D!./node_modules/vue-loader/dist/templateLoader.js??ruleSet%5B1%5D.rules%5B5%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}"); +eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ render: function() { return /* binding */ render; }\n/* harmony export */ });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm-bundler.js\");\n\nconst _hoisted_1 = {\n key: 0,\n class: \"timeline-wrapper\"\n};\nfunction render(_ctx, _cache, $props, $setup, $data, $options) {\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", {\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([\"timeblock\", {\n 'timeblock--finished': $props.modelValue.is_finished\n }])\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)($setup[\"AEmployeeTimeblockHeader\"], {\n \"model-value\": $props.modelValue,\n \"min-date\": $setup.minDate,\n deletable: $props.deletable,\n \"is-editable\": $setup.isEditable,\n \"is-time-range-valid\": $setup.isTimeRangeValid,\n collision: $setup.collision,\n \"has-validation-errors\": $setup.v$.$error && $setup.v$.$anyDirty,\n \"has-start-time-error\": $setup.hasStartTimeError,\n \"has-end-time-error\": $setup.hasEndTimeError,\n \"end-time-error-message\": $setup.endTimeErrorMessage,\n \"planned-time\": $setup._scheduledTime,\n \"free-time\": $setup._freeTime,\n employee: $props.employee,\n index: $props.index,\n onPreviousDay: $setup.previousDay,\n onNextDay: $setup.nextDay,\n onUpdateDate: $setup.updateDate,\n onUpdateStartTime: $setup.updateStartTime,\n onUpdateEndTime: $setup.updateEndTime,\n onAddTimeblock: _cache[0] || (_cache[0] = $event => _ctx.$emit('addTimeblock')),\n onRemoveTimeblock: _cache[1] || (_cache[1] = $event => _ctx.$emit('removeTimeblock'))\n }, null, 8 /* PROPS */, [\"model-value\", \"min-date\", \"deletable\", \"is-editable\", \"is-time-range-valid\", \"collision\", \"has-validation-errors\", \"has-start-time-error\", \"has-end-time-error\", \"end-time-error-message\", \"planned-time\", \"free-time\", \"employee\", \"index\"]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\" Timeline Visualization \"), $props.modelValue.date && $props.employee ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", _hoisted_1, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)($setup[\"AEmployeeTimeblockTimeline\"], {\n ref: \"timelineRef\",\n \"is-loading\": $setup.isLoading,\n employee: $props.employee,\n \"scheduled-blocks\": $setup.scheduledBlocks,\n \"other-timeblocks\": $setup.otherTimeblocksForSameDate,\n \"current-timeblock-range\": $setup.currentTimeblockRange,\n collision: $setup.collision,\n \"collision-segments\": $setup.collisionSegments,\n \"timeblock-duration\": $setup.timeblockDuration,\n \"start-hour\": $setup.START_HOUR,\n \"end-hour\": $setup.END_HOUR,\n \"hour-width\": $setup.hourWidth,\n onTimeblockUpdated: $setup.handleTimeblockUpdated\n }, null, 8 /* PROPS */, [\"is-loading\", \"employee\", \"scheduled-blocks\", \"other-timeblocks\", \"current-timeblock-range\", \"collision\", \"collision-segments\", \"timeblock-duration\", \"hour-width\"])])) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true)], 2 /* CLASS */);\n}\n\n//# sourceURL=webpack://jandl/./src/plugins/tm@modal/task/_components/employees/a-employee-timeblock.vue?./node_modules/webpack-plugin-vuetify/dist/scriptLoader.js!./node_modules/babel-loader/lib/index.js!./node_modules/ts-loader/index.js??clonedRuleSet-41.use%5B1%5D!./node_modules/vue-loader/dist/templateLoader.js??ruleSet%5B1%5D.rules%5B5%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}"); /***/ }), @@ -1770,7 +1770,7 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpa /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ render: function() { return /* binding */ render; }\n/* harmony export */ });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm-bundler.js\");\n/* harmony import */ var vuetify_lib_components_VBtn_index_mjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! vuetify/lib/components/VBtn/index.mjs */ \"./node_modules/vuetify/lib/components/VBtn/VBtn.mjs\");\n/* harmony import */ var vuetify_lib_components_VCard_index_mjs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! vuetify/lib/components/VCard/index.mjs */ \"./node_modules/vuetify/lib/components/VCard/VCard.mjs\");\n/* harmony import */ var vuetify_lib_components_VCard_index_mjs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! vuetify/lib/components/VCard/index.mjs */ \"./node_modules/vuetify/lib/components/VCard/VCardActions.mjs\");\n/* harmony import */ var vuetify_lib_components_VDialog_index_mjs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! vuetify/lib/components/VDialog/index.mjs */ \"./node_modules/vuetify/lib/components/VDialog/VDialog.mjs\");\n/* harmony import */ var vuetify_lib_components_VGrid_index_mjs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! vuetify/lib/components/VGrid/index.mjs */ \"./node_modules/vuetify/lib/components/VGrid/VCol.mjs\");\n/* harmony import */ var vuetify_lib_components_VGrid_index_mjs__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! vuetify/lib/components/VGrid/index.mjs */ \"./node_modules/vuetify/lib/components/VGrid/VRow.mjs\");\n/* harmony import */ var vuetify_lib_components_VIcon_index_mjs__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! vuetify/lib/components/VIcon/index.mjs */ \"./node_modules/vuetify/lib/components/VIcon/VIcon.mjs\");\n/* harmony import */ var vuetify_lib_components_VSheet_index_mjs__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! vuetify/lib/components/VSheet/index.mjs */ \"./node_modules/vuetify/lib/components/VSheet/VSheet.mjs\");\n/* harmony import */ var vuetify_lib_components_VTextField_index_mjs__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! vuetify/lib/components/VTextField/index.mjs */ \"./node_modules/vuetify/lib/components/VTextField/VTextField.mjs\");\n\nconst _hoisted_1 = {\n class: \"d-flex align-center\"\n};\nconst _hoisted_2 = {\n class: \"d-flex align-center mb-3\"\n};\nconst _hoisted_3 = {\n class: \"d-flex align-center flex-start width-100\"\n};\nconst _hoisted_4 = {\n class: \"task-badge rounded-pill\"\n};\nconst _hoisted_5 = {\n class: \"ml-5\"\n};\nconst _hoisted_6 = {\n class: \"d-flex justify-space-between align-center\"\n};\nconst _hoisted_7 = {\n class: \"d-flex align-start\"\n};\nfunction render(_ctx, _cache, $props, $setup, $data, $options) {\n \n \n \n \n const _component_a_reset_size_button = (0,vue__WEBPACK_IMPORTED_MODULE_0__.resolveComponent)(\"a-reset-size-button\");\n const _component_a_close_button = (0,vue__WEBPACK_IMPORTED_MODULE_0__.resolveComponent)(\"a-close-button\");\n \n \n \n const _component_a_resize_handle = (0,vue__WEBPACK_IMPORTED_MODULE_0__.resolveComponent)(\"a-resize-handle\");\n \n \n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(vuetify_lib_components_VGrid_index_mjs__WEBPACK_IMPORTED_MODULE_6__.VRow, {\n \"no-gutters\": \"\"\n }, {\n default: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(() => [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(vuetify_lib_components_VGrid_index_mjs__WEBPACK_IMPORTED_MODULE_5__.VCol, {\n cols: \"5\"\n }, {\n default: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(() => [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(vuetify_lib_components_VSheet_index_mjs__WEBPACK_IMPORTED_MODULE_8__.VSheet, {\n class: \"py-3\"\n }, {\n default: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(() => [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_1, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(vuetify_lib_components_VIcon_index_mjs__WEBPACK_IMPORTED_MODULE_7__.VIcon, {\n icon: \"mdi-clock-time-three-outline\",\n size: \"large\"\n }), _cache[5] || (_cache[5] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"p\", {\n class: \"mx-3\"\n }, \"Odpracovaný čas\", -1 /* CACHED */))])]),\n _: 1 /* STABLE */\n })]),\n _: 1 /* STABLE */\n }), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(vuetify_lib_components_VGrid_index_mjs__WEBPACK_IMPORTED_MODULE_5__.VCol, {\n cols: \"7\"\n }, {\n default: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(() => [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(vuetify_lib_components_VSheet_index_mjs__WEBPACK_IMPORTED_MODULE_8__.VSheet, {\n class: \"py-3\"\n }, {\n default: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(() => [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"p\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($props.hours) + \" h\", 1 /* TEXT */)]),\n _: 1 /* STABLE */\n }), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(vuetify_lib_components_VSheet_index_mjs__WEBPACK_IMPORTED_MODULE_8__.VSheet, {\n class: \"py-3\"\n }, {\n default: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(() => [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_2, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(vuetify_lib_components_VIcon_index_mjs__WEBPACK_IMPORTED_MODULE_7__.VIcon, {\n class: \"add-date cursor-pointer mr-2\",\n icon: \"mdi-plus\",\n size: \"medium\",\n onClick: _cache[0] || (_cache[0] = $event => $data.showModal = true)\n }), _cache[6] || (_cache[6] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"p\", {\n class: \"task-badge rounded-pill\"\n }, \"Pridať záznam\", -1 /* CACHED */))]), $props.subtask.timesheets.length ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, {\n key: 0\n }, (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderList)($props.subtask.timesheets, timesheet => {\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", {\n key: timesheet.id,\n class: \"d-flex align-center mb-3\"\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(vuetify_lib_components_VIcon_index_mjs__WEBPACK_IMPORTED_MODULE_7__.VIcon, {\n class: \"circle-border cursor-pointer mr-2\",\n icon: \"mdi-minus\",\n size: \"medium\",\n onClick: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($event => $options.deleteTimesheet(timesheet), [\"stop\"])\n }, null, 8 /* PROPS */, [\"onClick\"]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_3, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"p\", _hoisted_4, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)(timesheet.time), 1 /* TEXT */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"
{{ timesheet.employee_name }} ({{ moment(timesheet.timestamp).format('D.M.YYYY') }})
\"), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"p\", _hoisted_5, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)(timesheet.employee_name) + \" (\" + (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)(timesheet.timestamp) + \") \", 1 /* TEXT */)])]);\n }), 128 /* KEYED_FRAGMENT */)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true)]),\n _: 1 /* STABLE */\n })]),\n _: 1 /* STABLE */\n })]),\n _: 1 /* STABLE */\n }), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(vuetify_lib_components_VDialog_index_mjs__WEBPACK_IMPORTED_MODULE_4__.VDialog, {\n modelValue: $data.showModal,\n \"onUpdate:modelValue\": _cache[4] || (_cache[4] = $event => $data.showModal = $event),\n width: _ctx.modalWidth,\n height: _ctx.modalHeight,\n persistent: \"\",\n \"retain-focus\": false\n }, {\n default: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(() => [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(vuetify_lib_components_VCard_index_mjs__WEBPACK_IMPORTED_MODULE_2__.VCard, null, {\n default: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(() => [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_6, [_cache[7] || (_cache[7] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"h1\", null, \"Pridať odpracovaný čas\", -1 /* CACHED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_7, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_a_reset_size_button, {\n onReset: _ctx.resetModalSize\n }, null, 8 /* PROPS */, [\"onReset\"]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_a_close_button, {\n onClose: _cache[1] || (_cache[1] = $event => $options.closeModal())\n })])]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(vuetify_lib_components_VCard_index_mjs__WEBPACK_IMPORTED_MODULE_3__.VCardActions, {\n class: \"mt-10 d-flex justify-start align-center\"\n }, {\n default: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(() => [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(vuetify_lib_components_VTextField_index_mjs__WEBPACK_IMPORTED_MODULE_9__.VTextField, {\n modelValue: $data.form.hours,\n \"onUpdate:modelValue\": _cache[2] || (_cache[2] = $event => $data.form.hours = $event),\n variant: \"solo\",\n \"bg-color\": \"white\",\n type: \"number\",\n hint: $data.v$.form.hours.$errors ? $data.errorUtils.parseErrors($data.v$.form.hours.$errors) : null,\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([{\n error: $data.v$.form.hours.$errors.length\n }, \"mb-2\"]),\n label: \"Odpracovaný čas\"\n }, null, 8 /* PROPS */, [\"modelValue\", \"hint\", \"class\"])]),\n _: 1 /* STABLE */\n }), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(vuetify_lib_components_VBtn_index_mjs__WEBPACK_IMPORTED_MODULE_1__.VBtn, {\n class: \"button primary mt-5\",\n onClick: _cache[3] || (_cache[3] = $event => $options.submit())\n }, {\n default: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(() => [...(_cache[8] || (_cache[8] = [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createTextVNode)(\"Potvrdiť\", -1 /* CACHED */)]))]),\n _: 1 /* STABLE */\n }), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_a_resize_handle, {\n \"current-width\": _ctx.modalWidthPx,\n \"current-height\": _ctx.modalHeightPx,\n onResize: _ctx.handleModalResize,\n onResizeEnd: _ctx.handleResizeEnd\n }, null, 8 /* PROPS */, [\"current-width\", \"current-height\", \"onResize\", \"onResizeEnd\"])]),\n _: 1 /* STABLE */\n })]),\n _: 1 /* STABLE */\n }, 8 /* PROPS */, [\"modelValue\", \"width\", \"height\"])], 64 /* STABLE_FRAGMENT */);\n}\n\n/* Vuetify */\n\n\n\n\n\n\n\n\n\n\n//# sourceURL=webpack://jandl/./src/plugins/tm@modal/task/_components/_components/a-task-spent-time.vue?./node_modules/webpack-plugin-vuetify/dist/scriptLoader.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/templateLoader.js??ruleSet%5B1%5D.rules%5B5%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}"); +eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ render: function() { return /* binding */ render; }\n/* harmony export */ });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm-bundler.js\");\n/* harmony import */ var vuetify_lib_components_VBtn_index_mjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! vuetify/lib/components/VBtn/index.mjs */ \"./node_modules/vuetify/lib/components/VBtn/VBtn.mjs\");\n/* harmony import */ var vuetify_lib_components_VCard_index_mjs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! vuetify/lib/components/VCard/index.mjs */ \"./node_modules/vuetify/lib/components/VCard/VCard.mjs\");\n/* harmony import */ var vuetify_lib_components_VCard_index_mjs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! vuetify/lib/components/VCard/index.mjs */ \"./node_modules/vuetify/lib/components/VCard/VCardActions.mjs\");\n/* harmony import */ var vuetify_lib_components_VDialog_index_mjs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! vuetify/lib/components/VDialog/index.mjs */ \"./node_modules/vuetify/lib/components/VDialog/VDialog.mjs\");\n/* harmony import */ var vuetify_lib_components_VGrid_index_mjs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! vuetify/lib/components/VGrid/index.mjs */ \"./node_modules/vuetify/lib/components/VGrid/VCol.mjs\");\n/* harmony import */ var vuetify_lib_components_VGrid_index_mjs__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! vuetify/lib/components/VGrid/index.mjs */ \"./node_modules/vuetify/lib/components/VGrid/VRow.mjs\");\n/* harmony import */ var vuetify_lib_components_VIcon_index_mjs__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! vuetify/lib/components/VIcon/index.mjs */ \"./node_modules/vuetify/lib/components/VIcon/VIcon.mjs\");\n/* harmony import */ var vuetify_lib_components_VSheet_index_mjs__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! vuetify/lib/components/VSheet/index.mjs */ \"./node_modules/vuetify/lib/components/VSheet/VSheet.mjs\");\n/* harmony import */ var vuetify_lib_components_VTextField_index_mjs__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! vuetify/lib/components/VTextField/index.mjs */ \"./node_modules/vuetify/lib/components/VTextField/VTextField.mjs\");\n\nconst _hoisted_1 = {\n class: \"d-flex align-center\"\n};\nconst _hoisted_2 = {\n class: \"d-flex align-center mb-3\"\n};\nconst _hoisted_3 = {\n class: \"d-flex align-center flex-start width-100\"\n};\nconst _hoisted_4 = {\n class: \"task-badge rounded-pill\"\n};\nconst _hoisted_5 = {\n class: \"ml-5\"\n};\nconst _hoisted_6 = {\n class: \"d-flex justify-space-between align-center\"\n};\nconst _hoisted_7 = {\n class: \"d-flex align-start\"\n};\nfunction render(_ctx, _cache, $props, $setup, $data, $options) {\n \n \n \n \n const _component_a_reset_size_button = (0,vue__WEBPACK_IMPORTED_MODULE_0__.resolveComponent)(\"a-reset-size-button\");\n const _component_a_close_button = (0,vue__WEBPACK_IMPORTED_MODULE_0__.resolveComponent)(\"a-close-button\");\n \n \n \n const _component_a_resize_handle = (0,vue__WEBPACK_IMPORTED_MODULE_0__.resolveComponent)(\"a-resize-handle\");\n \n \n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(vuetify_lib_components_VGrid_index_mjs__WEBPACK_IMPORTED_MODULE_6__.VRow, {\n \"no-gutters\": \"\"\n }, {\n default: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(() => [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(vuetify_lib_components_VGrid_index_mjs__WEBPACK_IMPORTED_MODULE_5__.VCol, {\n cols: \"5\"\n }, {\n default: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(() => [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(vuetify_lib_components_VSheet_index_mjs__WEBPACK_IMPORTED_MODULE_8__.VSheet, {\n class: \"py-3\"\n }, {\n default: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(() => [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_1, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(vuetify_lib_components_VIcon_index_mjs__WEBPACK_IMPORTED_MODULE_7__.VIcon, {\n icon: \"mdi-clock-time-three-outline\",\n size: \"large\"\n }), _cache[5] || (_cache[5] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"p\", {\n class: \"mx-3\"\n }, \"Odpracovaný čas\", -1 /* CACHED */))])]),\n _: 1 /* STABLE */\n })]),\n _: 1 /* STABLE */\n }), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(vuetify_lib_components_VGrid_index_mjs__WEBPACK_IMPORTED_MODULE_5__.VCol, {\n cols: \"7\"\n }, {\n default: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(() => [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(vuetify_lib_components_VSheet_index_mjs__WEBPACK_IMPORTED_MODULE_8__.VSheet, {\n class: \"py-3\"\n }, {\n default: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(() => [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"p\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($props.hours) + \" h\", 1 /* TEXT */)]),\n _: 1 /* STABLE */\n }), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(vuetify_lib_components_VSheet_index_mjs__WEBPACK_IMPORTED_MODULE_8__.VSheet, {\n class: \"py-3\"\n }, {\n default: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(() => [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_2, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(vuetify_lib_components_VIcon_index_mjs__WEBPACK_IMPORTED_MODULE_7__.VIcon, {\n class: \"add-date cursor-pointer mr-2\",\n icon: \"mdi-plus\",\n size: \"medium\",\n onClick: _cache[0] || (_cache[0] = $event => $data.showModal = true)\n }), _cache[6] || (_cache[6] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"p\", {\n class: \"task-badge rounded-pill\"\n }, \"Pridať záznam\", -1 /* CACHED */))]), $props.subtask.timesheets.length ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, {\n key: 0\n }, (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderList)($props.subtask.timesheets, timesheet => {\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", {\n key: timesheet.id,\n class: \"d-flex align-center mb-3\"\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(vuetify_lib_components_VIcon_index_mjs__WEBPACK_IMPORTED_MODULE_7__.VIcon, {\n class: \"circle-border cursor-pointer mr-2\",\n icon: \"mdi-minus\",\n size: \"medium\",\n onClick: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($event => $options.deleteTimesheet(timesheet), [\"stop\"])\n }, null, 8 /* PROPS */, [\"onClick\"]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_3, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"p\", _hoisted_4, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)(timesheet.time), 1 /* TEXT */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"{{ timesheet.employee_name }} ({{ moment(timesheet.timestamp).format('D.M.YYYY') }})
\"), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"p\", _hoisted_5, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)(timesheet.employee_name) + \" (\" + (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)(timesheet.timestamp) + \") \", 1 /* TEXT */)])]);\n }), 128 /* KEYED_FRAGMENT */)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true)]),\n _: 1 /* STABLE */\n })]),\n _: 1 /* STABLE */\n })]),\n _: 1 /* STABLE */\n }), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(vuetify_lib_components_VDialog_index_mjs__WEBPACK_IMPORTED_MODULE_4__.VDialog, {\n modelValue: $data.showModal,\n \"onUpdate:modelValue\": _cache[4] || (_cache[4] = $event => $data.showModal = $event),\n width: _ctx.modalWidth,\n height: _ctx.modalHeight,\n persistent: \"\",\n \"retain-focus\": false\n }, {\n default: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(() => [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(vuetify_lib_components_VCard_index_mjs__WEBPACK_IMPORTED_MODULE_2__.VCard, {\n style: {\n \"position\": \"relative\",\n \"height\": \"100%\"\n }\n }, {\n default: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(() => [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_6, [_cache[7] || (_cache[7] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"h1\", null, \"Pridať odpracovaný čas\", -1 /* CACHED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_7, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_a_reset_size_button, {\n onReset: _ctx.resetModalSize\n }, null, 8 /* PROPS */, [\"onReset\"]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_a_close_button, {\n onClose: _cache[1] || (_cache[1] = $event => $options.closeModal())\n })])]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(vuetify_lib_components_VCard_index_mjs__WEBPACK_IMPORTED_MODULE_3__.VCardActions, {\n class: \"mt-10 d-flex justify-start align-center\"\n }, {\n default: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(() => [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(vuetify_lib_components_VTextField_index_mjs__WEBPACK_IMPORTED_MODULE_9__.VTextField, {\n modelValue: $data.form.hours,\n \"onUpdate:modelValue\": _cache[2] || (_cache[2] = $event => $data.form.hours = $event),\n variant: \"solo\",\n \"bg-color\": \"white\",\n type: \"number\",\n hint: $data.v$.form.hours.$errors ? $data.errorUtils.parseErrors($data.v$.form.hours.$errors) : null,\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([{\n error: $data.v$.form.hours.$errors.length\n }, \"mb-2\"]),\n label: \"Odpracovaný čas\"\n }, null, 8 /* PROPS */, [\"modelValue\", \"hint\", \"class\"])]),\n _: 1 /* STABLE */\n }), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(vuetify_lib_components_VBtn_index_mjs__WEBPACK_IMPORTED_MODULE_1__.VBtn, {\n class: \"button primary mt-5\",\n onClick: _cache[3] || (_cache[3] = $event => $options.submit())\n }, {\n default: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(() => [...(_cache[8] || (_cache[8] = [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createTextVNode)(\"Potvrdiť\", -1 /* CACHED */)]))]),\n _: 1 /* STABLE */\n }), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_a_resize_handle, {\n \"current-width\": _ctx.modalWidthPx,\n \"current-height\": _ctx.modalHeightPx,\n onResize: _ctx.handleModalResize,\n onResizeEnd: _ctx.handleResizeEnd\n }, null, 8 /* PROPS */, [\"current-width\", \"current-height\", \"onResize\", \"onResizeEnd\"])]),\n _: 1 /* STABLE */\n })]),\n _: 1 /* STABLE */\n }, 8 /* PROPS */, [\"modelValue\", \"width\", \"height\"])], 64 /* STABLE_FRAGMENT */);\n}\n\n/* Vuetify */\n\n\n\n\n\n\n\n\n\n\n//# sourceURL=webpack://jandl/./src/plugins/tm@modal/task/_components/_components/a-task-spent-time.vue?./node_modules/webpack-plugin-vuetify/dist/scriptLoader.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/templateLoader.js??ruleSet%5B1%5D.rules%5B5%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}"); /***/ }), @@ -1781,7 +1781,7 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpa /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ render: function() { return /* binding */ render; }\n/* harmony export */ });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm-bundler.js\");\n/* harmony import */ var vuetify_lib_components_VBtn_index_mjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! vuetify/lib/components/VBtn/index.mjs */ \"./node_modules/vuetify/lib/components/VBtn/VBtn.mjs\");\n/* harmony import */ var vuetify_lib_components_VCard_index_mjs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! vuetify/lib/components/VCard/index.mjs */ \"./node_modules/vuetify/lib/components/VCard/VCard.mjs\");\n/* harmony import */ var vuetify_lib_components_VCard_index_mjs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! vuetify/lib/components/VCard/index.mjs */ \"./node_modules/vuetify/lib/components/VCard/VCardActions.mjs\");\n/* harmony import */ var vuetify_lib_components_VCard_index_mjs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! vuetify/lib/components/VCard/index.mjs */ \"./node_modules/vuetify/lib/components/VCard/VCardText.mjs\");\n/* harmony import */ var vuetify_lib_components_VDialog_index_mjs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! vuetify/lib/components/VDialog/index.mjs */ \"./node_modules/vuetify/lib/components/VDialog/VDialog.mjs\");\n/* harmony import */ var vuetify_lib_components_VGrid_index_mjs__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! vuetify/lib/components/VGrid/index.mjs */ \"./node_modules/vuetify/lib/components/VGrid/VCol.mjs\");\n/* harmony import */ var vuetify_lib_components_VGrid_index_mjs__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! vuetify/lib/components/VGrid/index.mjs */ \"./node_modules/vuetify/lib/components/VGrid/VRow.mjs\");\n/* harmony import */ var vuetify_lib_components_VIcon_index_mjs__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! vuetify/lib/components/VIcon/index.mjs */ \"./node_modules/vuetify/lib/components/VIcon/VIcon.mjs\");\n/* harmony import */ var vuetify_lib_components_VSheet_index_mjs__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! vuetify/lib/components/VSheet/index.mjs */ \"./node_modules/vuetify/lib/components/VSheet/VSheet.mjs\");\n\nconst _hoisted_1 = {\n class: \"d-flex align-center\"\n};\nconst _hoisted_2 = {\n key: 0,\n class: \"d-flex align-center mb-3\"\n};\nconst _hoisted_3 = {\n class: \"d-flex align-center mb-2\"\n};\nconst _hoisted_4 = {\n class: \"d-flex justify-space-between align-center pa-4\"\n};\nconst _hoisted_5 = {\n class: \"d-flex align-start\"\n};\nconst _hoisted_6 = {\n class: \"d-flex justify-space-between align-center\"\n};\nconst _hoisted_7 = {\n class: \"text-red\"\n};\nconst _hoisted_8 = {\n class: \"text-black\"\n};\nconst _hoisted_9 = {\n class: \"d-flex align-start\"\n};\nfunction render(_ctx, _cache, $props, $setup, $data, $options) {\n \n \n \n \n const _component_a_reset_size_button = (0,vue__WEBPACK_IMPORTED_MODULE_0__.resolveComponent)(\"a-reset-size-button\");\n const _component_a_close_button = (0,vue__WEBPACK_IMPORTED_MODULE_0__.resolveComponent)(\"a-close-button\");\n const _component_a_employee_timeblock = (0,vue__WEBPACK_IMPORTED_MODULE_0__.resolveComponent)(\"a-employee-timeblock\");\n \n \n \n const _component_a_resize_handle = (0,vue__WEBPACK_IMPORTED_MODULE_0__.resolveComponent)(\"a-resize-handle\");\n \n \n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(vuetify_lib_components_VGrid_index_mjs__WEBPACK_IMPORTED_MODULE_7__.VRow, {\n \"no-gutters\": \"\"\n }, {\n default: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(() => [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(vuetify_lib_components_VGrid_index_mjs__WEBPACK_IMPORTED_MODULE_6__.VCol, {\n cols: \"5\"\n }, {\n default: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(() => [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(vuetify_lib_components_VSheet_index_mjs__WEBPACK_IMPORTED_MODULE_9__.VSheet, {\n class: \"py-3\"\n }, {\n default: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(() => [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_1, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(vuetify_lib_components_VIcon_index_mjs__WEBPACK_IMPORTED_MODULE_8__.VIcon, {\n icon: \"mdi-calendar-week\",\n size: \"large\"\n }), _cache[9] || (_cache[9] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"p\", {\n class: \"mx-3\"\n }, \"Trvanie\", -1 /* CACHED */))])]),\n _: 1 /* STABLE */\n })]),\n _: 1 /* STABLE */\n }), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(vuetify_lib_components_VGrid_index_mjs__WEBPACK_IMPORTED_MODULE_6__.VCol, {\n cols: \"7\"\n }, {\n default: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(() => [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(vuetify_lib_components_VSheet_index_mjs__WEBPACK_IMPORTED_MODULE_9__.VSheet, {\n class: \"py-3\"\n }, {\n default: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(() => [!$options.isOffice365Task ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", _hoisted_2, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(vuetify_lib_components_VIcon_index_mjs__WEBPACK_IMPORTED_MODULE_8__.VIcon, {\n class: \"add-date cursor-pointer mr-2\",\n icon: \"mdi-plus\",\n size: \"medium\",\n onClick: _cache[0] || (_cache[0] = $event => $data.showModal = true)\n }), _cache[10] || (_cache[10] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"p\", {\n class: \"task-badge rounded-pill\"\n }, \"Pridať záznam\", -1 /* CACHED */))])) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderList)($props.timeblocks, (timeblock, index) => {\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", {\n key: timeblock.id || `timeblock-${index}`,\n class: \"timeblock-item mb-3\"\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_3, [!$options.isOffice365Task ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)(vuetify_lib_components_VIcon_index_mjs__WEBPACK_IMPORTED_MODULE_8__.VIcon, {\n key: 0,\n class: \"circle-border cursor-pointer mr-2\",\n icon: \"mdi-minus\",\n size: \"medium\",\n onClick: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($event => $props.subtask.id ? $options.deleteTimeblock(timeblock) : $options.deleteTimeblockWithoutId(index), [\"stop\"])\n }, null, 8 /* PROPS */, [\"onClick\"])) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"p\", {\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([\"task-badge rounded-pill\", {\n 'strike-through': timeblock.is_finished\n }])\n }, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($options.formatTimeblockStart(timeblock)) + \" - \" + (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($options.formatTimeblockEnd(timeblock)), 3 /* TEXT, CLASS */), !$options.isOffice365Task ? (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)(((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)(vuetify_lib_components_VIcon_index_mjs__WEBPACK_IMPORTED_MODULE_8__.VIcon, {\n key: 1,\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([\"circle-border cursor-pointer ml-2\", {\n completed: timeblock.is_finished\n }]),\n icon: \"mdi-check\",\n size: \"medium\",\n onClick: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($event => $options.toggleTimeblockIsFinished(timeblock), [\"stop\"])\n }, null, 8 /* PROPS */, [\"class\", \"onClick\"])), [[vue__WEBPACK_IMPORTED_MODULE_0__.vShow, $props.subtask.id]]) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true)]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\" Timeline Visualization for existing timeblock \"), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"