diff --git a/app/src/plugins/tm@modal/_mixins/vuetify-fix-focus.ts b/app/src/plugins/tm@modal/_mixins/vuetify-fix-focus.ts
index cadcb57..7e55738 100644
--- a/app/src/plugins/tm@modal/_mixins/vuetify-fix-focus.ts
+++ b/app/src/plugins/tm@modal/_mixins/vuetify-fix-focus.ts
@@ -7,6 +7,12 @@ export default {
},
methods: {
+ setFocusEvent() {
+ document.querySelectorAll('.v-autocomplete input').forEach(input => {
+ input.addEventListener('focus', this.onInputFocus)
+ })
+ },
+
onDateFocus($event) {
if ($event == undefined) {
this.preventInputFocus = true
diff --git a/app/src/plugins/tm@modal/blocker/z-blocker-modal.vue b/app/src/plugins/tm@modal/blocker/z-blocker-modal.vue
index eda6ef9..c93cf23 100644
--- a/app/src/plugins/tm@modal/blocker/z-blocker-modal.vue
+++ b/app/src/plugins/tm@modal/blocker/z-blocker-modal.vue
@@ -98,7 +98,10 @@ export default {
this.starts_at_time = null
this.ends_at_time = null
- this.$nextTick(() => this.v$.$reset())
+ this.$nextTick(() => {
+ this.setFocusEvent()
+ this.v$.$reset()
+ })
try {
if (blocker?.id) {
diff --git a/app/src/plugins/tm@modal/master-task/z-master-task-modal.vue b/app/src/plugins/tm@modal/master-task/z-master-task-modal.vue
index d786a4a..ff75880 100644
--- a/app/src/plugins/tm@modal/master-task/z-master-task-modal.vue
+++ b/app/src/plugins/tm@modal/master-task/z-master-task-modal.vue
@@ -260,6 +260,7 @@ export default {
this.visible = true
this.mastertask = null
this.$nextTick(() => {
+ this.setFocusEvent()
this.v$.$reset()
})
diff --git a/app/src/plugins/tm@modal/task/_components/a-timeblock.vue b/app/src/plugins/tm@modal/task/_components/a-timeblock.vue
new file mode 100644
index 0000000..9ee7d38
--- /dev/null
+++ b/app/src/plugins/tm@modal/task/_components/a-timeblock.vue
@@ -0,0 +1,103 @@
+
+
+
+
+
+
+e
\ No newline at end of file
diff --git a/app/src/plugins/tm@modal/task/z-task-modal.vue b/app/src/plugins/tm@modal/task/z-task-modal.vue
index 9f26eba..b67a629 100644
--- a/app/src/plugins/tm@modal/task/z-task-modal.vue
+++ b/app/src/plugins/tm@modal/task/z-task-modal.vue
@@ -16,7 +16,7 @@
-
+
@@ -62,11 +62,28 @@
+
+
+
updateTimeblock(val, index)" @removeTimeblock="removeTimeblock(index)" @onDateFocus="onDateFocus" :timeblock="timeblock" :deletable="index > 0" editable :ref="`timetable-${index}`" />
+
+
+
+
+
+
+
+
@@ -123,7 +140,7 @@ import Datepicker from '@vuepic/vue-datepicker'
import ZFilesUpload from '@/plugins/tm@_components/z-files-upload.vue'
import ATaskTimeblocks from '@/plugins/tm@modal/task/_components/_components/a-task-timeblocks.vue'
import useVuelidate from '@vuelidate/core'
-import { required, requiredIf } from '@vuelidate/validators'
+import { required, requiredIf, optional } from '@vuelidate/validators'
import errorUtils from '@/plugins/lib@auth/_utils/error.utils'
import { QuillEditor } from '@vueup/vue-quill'
import VuetifyFixFocusMixin from '@/plugins/tm@modal/_mixins/vuetify-fix-focus'
@@ -135,15 +152,19 @@ import '@vueup/vue-quill/dist/vue-quill.snow.css'
import AutocompleteMixin from '@/plugins/tm@_mixins/autocomplete.mixin'
import ZTaskReadonlyInfo from './_components/z-task-readonly-info.vue'
+import ATimeblock from './_components/a-timeblock.vue'
import { mapGetters } from 'vuex'
import modalMixin from '@/plugins/tm@modal/_mixins/modal.mixin'
+import axios from 'axios'
+
export default {
emits: ['close', 'refresh'],
mixins: [VuetifyFixFocusMixin, SelectsMixin, AutocompleteMixin, modalMixin],
components: {
ZTaskReadonlyInfo,
+ ATimeblock,
ZFilesUpload,
Datepicker,
// ATaskTimeblocks,
@@ -160,9 +181,13 @@ export default {
errorUtils,
v$: useVuelidate(),
employeeValidations: [],
- preventInputFocus: false,
showDatePicker: false,
- selectedNewDate: []
+ selectedNewDate: [],
+ timeblocks: [{
+ date: null,
+ starts_at_time: null,
+ ends_at_time: null
+ }]
}
},
@@ -176,9 +201,6 @@ export default {
master_task_id: { required },
deadline: { required },
_deadline_time: { required },
- // starts_at_time: { requiredIf: requiredIf(this.subtask.date) },
- // ends_at_time: { requiredIf: requiredIf(this.subtask.starts_at_time) }
- // description: { required }
}
}
},
@@ -210,11 +232,28 @@ export default {
},
methods: {
+ updateTimeblock(val, index) {
+ this.timeblocks[index] = val
+ },
+
+ removeTimeblock(index) {
+ this.timeblocks.splice(index, 1)
+ },
+
async showModal({ subtask, editMode = false, mastertask = {} }) {
+ console.log(subtask)
this.isSaving = false
this.subtask = null
this.visible = true
- this.$nextTick(() => this.v$.$reset())
+ this.timeblocks = [{
+ date: null,
+ starts_at_time: null,
+ ends_at_time: null
+ }]
+ this.$nextTick(() => {
+ this.v$.$reset()
+ this.setFocusEvent()
+ })
try {
if (subtask?.id) {
@@ -263,9 +302,10 @@ export default {
async save() {
const employeesValid = await this._validateEmployees()
+ const timeblocksValid = this.subtask?.id ? true : await this._validateTimeblocks()
if (!(await this.v$.$validate())) return
- if (!employeesValid) return
+ if (!employeesValid || !timeblocksValid) return
this.subtask.description = this.$refs['description'].getHTML()
this._mergeDeadlineTimeDate()
@@ -286,7 +326,13 @@ export default {
this.$store.commit('tm/update_subtask', subtask)
this.$events.emit('on-subtask-edited', this.subtask)
} else {
- const { subtasks } = await this.$axios.post_auth(`v1/mastertasks/${this.subtask.master_task_id}/subtasks`, this.subtask)
+ this.subtask.employees.forEach(employee => {
+ if (employee.id)
+ employee.timeblocks = this.timeblocks.filter(timeblock => timeblock.date).map(timeblock => { return { start: `${moment(timeblock.date).format('YYYY-MM-DD')} ${timeblock.starts_at_time}:00`, end: `${moment(timeblock.date).format('YYYY-MM-DD')} ${timeblock.ends_at_time}:00`, id: null } })
+ })
+ const subtaskCopy = JSON.parse(JSON.stringify(this.subtask))
+ delete subtaskCopy._master_task
+ const { subtasks } = await this.$axios.post_auth(`v1/mastertasks/${this.subtask.master_task_id}/subtasks`, subtaskCopy)
this.subtask.id = subtasks[0].id
subtasks.forEach((subtask) => {
@@ -364,6 +410,15 @@ export default {
})
},
+ async _validateTimeblocks() {
+ let invalid = false
+ for(let i = 0; i < this.timeblocks.length; i++) {
+ const ref = this.$refs[`timetable-${i}`]
+ invalid = await ref[0].v$.$validate() || invalid
+ }
+ return invalid
+ },
+
_enrichTask(subtask) {
return {
...subtask,
@@ -470,8 +525,41 @@ export default {
.files
margin-top: 104px !important
-// .splitted-time-inputs
-// display: flex !important
-// flex-direction: row !important
-// gap: 15px
+.timeblocks
+ display: flex
+ flex-direction: column
+ align-items: center
+ border-bottom: 1px solid #e0e0e0
+
+ .end-button
+ width: 100%
+ display: flex
+ justify-content: flex-end
+ align-items: center
+ border-top: 1px solid #e0e0e0
+ height: 70px
+
+ button
+ background: #7f39fb !important
+ border-radius: 4px !important
+ color: #fff !important
+ height: 50px
+ width: 203px
+
+ .splitted-time-inputs
+ display: flex !important
+ flex-direction: row !important
+ gap: 15px
+ margin-bottom: -11px
+
+.timeblock
+ position: relative
+ border-top: 1px solid #e0e0e0
+ padding: 20px 0 10px 0
+
+ .splitted-time-inputs
+ display: flex !important
+ flex-direction: row !important
+ gap: 15px
+ margin-bottom: -11px