[tm@store] Added store

This commit is contained in:
Matej Glasnák committed 2023-02-15 15:56:24 +01:00
1 parent a1a410c54d
commit 774ca7b607
44 files changed
+989 -720

No files matched your search

@@ -0,0 +1,30 @@
<template>
<v-row no-gutters class="align-center">
<v-col cols="5">
<v-sheet class="py-3">
<div class="d-flex align-center">
<v-icon icon="mdi-link" size="large"></v-icon>
<p class="mx-3">Mastertask</p>
</div>
</v-sheet>
</v-col>
<v-col cols="7">
<v-sheet class="py-3">
<p class="task-badge px-4 py-2 rounded-pill">
{{ name }}
</p>
</v-sheet>
</v-col>
</v-row>
</template>
<script>
export default {
props: {
name: {
type: String,
required: true
}
}
}
</script>
@@ -0,0 +1,29 @@
<template>
<v-row no-gutters class="align-center">
<v-col cols="5">
<v-sheet class="py-3">
<div class="d-flex align-center">
<v-icon icon="mdi-drag-vertical" size="large"></v-icon>
<p class="mx-3">Status</p>
</div>
</v-sheet>
</v-col>
<v-col cols="7">
<v-sheet class="py-3">
<p v-if="isFinished" class="status-badge px-4 py-2 rounded-pill">Ukončený</p>
<p v-else class="status-badge px-4 py-2 rounded-pill">Neukončený</p>
</v-sheet>
</v-col>
</v-row>
</template>
<script>
export default {
props: {
isFinished: {
type: Number,
default: () => 0
}
}
}
</script>
@@ -0,0 +1,32 @@
<template>
<v-row no-gutters class="align-center">
<v-col cols="5">
<v-sheet class="py-3">
<div class="d-flex align-center">
<v-icon icon="mdi-account-outline" size="large"></v-icon>
<p class="mx-3">Priradený</p>
</div>
</v-sheet>
</v-col>
<v-col cols="7">
<v-sheet class="py-3 d-flex align-center">
<p class="employee-selected-avatar d-flex justify-center align-center">
{{ employee.name.charAt(0) + employee.surname.charAt(0) }}
</p>
<p class="ml-2" v-html="`${employee.name} ${employee.surname}`" />
</v-sheet>
</v-col>
</v-row>
</template>
<script>
export default {
props: {
employee: {
type: Object,
required: true
}
}
}
</script>
@@ -0,0 +1,17 @@
<template>
<div class="px-5 py-5 border-bottom">
<p>Popis zadania</p>
<section v-html="description" class="description-detail px-2 py-2 w-100 rounded mt-2" />
</div>
</template>
<script>
export default {
props: {
description: {
type: String,
default: () => ''
}
}
}
</script>
@@ -0,0 +1,28 @@
<template>
<v-row no-gutters class="align-center">
<v-col cols="5">
<v-sheet class="py-3">
<div class="d-flex align-center">
<v-icon icon="mdi-clock-time-three-outline" size="large"></v-icon>
<p class="mx-3">Naplánovaný čas</p>
</div>
</v-sheet>
</v-col>
<v-col cols="7">
<v-sheet class="py-3">
<p>{{ hours }} h</p>
</v-sheet>
</v-col>
</v-row>
</template>
<script>
export default {
props: {
hours: {
type: Number,
required: true
}
}
}
</script>
@@ -0,0 +1,29 @@
<template>
<v-row no-gutters class="align-center border-bottom">
<v-col cols="5">
<v-sheet class="py-3">
<div class="d-flex align-center">
<v-icon icon="mdi-clock-time-three-outline" size="large"></v-icon>
<p class="mx-3">Zostávajúci čas</p>
</div>
</v-sheet>
</v-col>
<v-col cols="7">
<v-sheet class="py-3">
<p>{{ hours }} h</p>
</v-sheet>
</v-col>
</v-row>
</template>
<script>
export default {
props: {
hours: {
type: Number,
required: true
}
}
}
</script>
@@ -0,0 +1,129 @@
<template>
<v-row no-gutters>
<v-col cols="5">
<v-sheet class="py-3">
<div class="d-flex align-center">
<v-icon icon="mdi-clock-time-three-outline" size="large"></v-icon>
<p class="mx-3">Odpracovaný čas</p>
</div>
</v-sheet>
</v-col>
<v-col cols="7">
<v-sheet class="py-3">
<p>{{ hours }} h</p>
</v-sheet>
<v-sheet class="py-3">
<div class="d-flex align-center mb-3">
<v-icon @click="showModal = true" class="add-date cursor-pointer mr-2" icon="mdi-plus" size="medium" />
<p class="task-badge rounded-pill">Pridať záznam</p>
</div>
<template v-if="task.timesheets.length">
<div v-for="timesheet in task.timesheets" :key="timesheet.id" class="d-flex align-center mb-3">
<v-icon @click.stop="deleteTimesheet(timesheet)" class="remove-date cursor-pointer mr-2" icon="mdi-minus" size="medium" />
<p class="task-badge rounded-pill">{{ timesheet.time }}</p>
</div>
</template>
</v-sheet>
</v-col>
</v-row>
<v-dialog max-width="750" v-model="showModal">
<v-card>
<div class="d-flex justify-space-between align-center">
<h1>Pridať odpracovaný čas</h1>
<v-icon @click.stop="closeModal()" icon="mdi-close" size="large"></v-icon>
</div>
<v-card-actions class="mt-10 d-flex justify-start align-center">
<v-text-field v-model="form.hours" variant="solo" bg-color="white" type="number" :hint="v$.form.hours.$errors ? errorUtils.parseErrors(v$.form.hours.$errors) : null" :class="{ error: v$.form.hours.$errors.length }" class="mb-2" label="Odpracovaný čas" />
</v-card-actions>
<v-btn @click="submit()" class="button primary mt-5">Potvrdiť</v-btn>
</v-card>
</v-dialog>
</template>
<script>
import errorUtils from '@/plugins/lib@auth/_utils/error.utils'
import useVuelidate from '@vuelidate/core'
import { required, numeric, minValue } from '@vuelidate/validators'
export default {
props: {
hours: {
type: Number,
required: true
},
task: {
type: Object,
required: true
}
},
data() {
return {
v$: useVuelidate(),
errorUtils,
showModal: false,
form: {
hours: null
}
}
},
validations() {
return {
form: {
hours: {required, numeric, minValue: minValue(1)}
}
}
},
methods: {
async submit() {
if (!await this.v$.$validate())
return
const task = JSON.parse(JSON.stringify(this.task))
task.timesheets.push({
id: null,
employee_id: task.employee_id,
time: typeof this.form.hours == 'string' ? parseInt(this.form.hours) : this.form.hours
})
this._update(task)
},
async deleteTimesheet({ id }) {
const task = JSON.parse(JSON.stringify(this.task))
task.timesheets = task.timesheets.filter(timesheet => timesheet.id != id)
this._update(task)
},
closeModal() {
this.form = {
hours: null
}
this.showModal = false
this.$nextTick(() => this.v$.$reset())
},
async _update(task) {
try {
const { subtask } = await this.$axios.put_auth(`v1/subtasks/${task.id}`, task)
this.closeModal()
this.$events.emit('on-task-edited', subtask)
} catch (error) {
this.$toast.error(error.message || error)
}
}
}
}
</script>
@@ -0,0 +1,148 @@
<template>
<v-row no-gutters>
<v-col cols="5">
<v-sheet class="py-3">
<div class="d-flex align-center">
<v-icon icon="mdi-calendar-week" size="large"></v-icon>
<p class="mx-3">Trvanie</p>
</div>
</v-sheet>
</v-col>
<v-col cols="7">
<v-sheet class="py-3">
<div class="d-flex align-center mb-3">
<v-icon @click="showModal = true" class="add-date cursor-pointer mr-2" icon="mdi-plus" size="medium" />
<p class="task-badge rounded-pill">Pridať záznam</p>
</div>
<div v-for="timeblock in timeblocks" :key="timeblock.id" class="d-flex align-center mb-3">
<v-icon @click.stop="deleteTimeblock(timeblock)" class="remove-date cursor-pointer mr-2" icon="mdi-minus" size="medium" />
<p class="task-badge rounded-pill">{{ tmUtils.formatDateTime(timeblock.start) }} - {{ tmUtils.formatDateTime(timeblock.end) }}</p>
</div>
</v-sheet>
</v-col>
</v-row>
<v-dialog max-width="750" v-model="showModal">
<v-card>
<div class="d-flex justify-space-between align-center">
<h1>Pridať dátum</h1>
<v-icon @click.stop="clsoeModal()" icon="mdi-close" size="large"></v-icon>
</div>
<v-card-actions class="mt-10 d-flex flex-column modal-content">
<Datepicker v-model="form.date" format="dd.MM.yyyy" locale="sk" select-text="Vybrať" cancel-text="Zrušiť" placeholder="Dátum" :enable-time-picker="false" class="mb-5 modal-input" />
<v-text-field v-model="form.starts_at_time" type="time" variant="solo" bg-color="white" :hint="v$.form.starts_at_time.$errors ? errorUtils.parseErrors(v$.form.starts_at_time.$errors) : null" :class="{ error: v$.form.starts_at_time.$errors.length }" class="mb-1 modal-input" label="Začiatok" />
<v-text-field v-model="form.ends_at_time" type="time" variant="solo" bg-color="white" :hint="v$.form.ends_at_time.$errors ? errorUtils.parseErrors(v$.form.ends_at_time.$errors) : null" :class="{ error: v$.form.ends_at_time.$errors.length }" class="modal-input" label="Koniec" />
</v-card-actions>
<v-btn @click="submit()" class="button primary mt-5">Potvrdiť</v-btn>
</v-card>
</v-dialog>
</template>
<script>
import tmUtils from '@/plugins/tm@_utils/tm.utils'
import errorUtils from '@/plugins/lib@auth/_utils/error.utils'
import useVuelidate from '@vuelidate/core'
import { required } from '@vuelidate/validators'
import Datepicker from '@vuepic/vue-datepicker'
import moment from 'moment'
export default {
components: {
Datepicker
},
props: {
timeblocks: {
type: Array,
required: true
},
task: {
type: Object,
required: true
}
},
data() {
return {
v$: useVuelidate(),
errorUtils,
tmUtils,
showModal: false,
form: {
date: null,
starts_at_time: '09:00',
ends_at_time: '16:00'
}
}
},
validations() {
return {
form: {
date: { required },
starts_at_time: { required },
ends_at_time: { required }
}
}
},
methods: {
async submit() {
if (!await this.v$.$validate())
return
const task = JSON.parse(JSON.stringify(this.task))
const splittedStartsAtTime = this.form.starts_at_time.split(':')
const splittedEndsAtTime = this.form.ends_at_time.split(':')
const start = moment(this.form.date).hours(parseInt(splittedStartsAtTime[0])).minutes(parseInt(splittedStartsAtTime[1])).toISOString()
const end = moment(this.form.date).hours(parseInt(splittedEndsAtTime[0])).minutes(parseInt(splittedEndsAtTime[1])).toISOString()
task.timeblocks.push({
id: null,
start: tmUtils.formatDateTimeForBackend(start),
end: tmUtils.formatDateTimeForBackend(end)
})
this._update(task)
},
async deleteTimeblock({ id }) {
const task = JSON.parse(JSON.stringify(this.task))
task.timeblocks = task.timeblocks.filter(timeblock => timeblock.id != id)
console.log(task.timeblocks)
console.log(id)
this._update(task)
},
async _update(task) {
try {
const { subtask } = await this.$axios.put_auth(`v1/subtasks/${task.id}`, task)
this.closeModal()
this.$events.emit('on-task-edited', subtask)
} catch (error) {
this.$toast.error(error.message || error)
}
},
closeModal() {
this.form = {
date: null,
starts_at_time: '09:00',
ends_at_time: '16:00'
}
this.showModal = false
this.$nextTick(() => this.v$.$reset())
}
}
}
</script>
@@ -0,0 +1,44 @@
<template>
<A-mastertask-name :name="task.master_task.name" />
<A-mastertask-status :status="task.is_finished" />
<A-task-timeblocks :timeblocks="task.timeblocks" :task="task" />
<A-task-assigned-employee :employee="task.employee" />
<A-task-planned-time :hours="task.duration" />
<A-task-remaining-time :hours="task.duration - task.spent_time" />
<A-task-spent-time :hours="task.spent_time" :task="task" />
<A-task-description :description="task.description" />
<Z-files :files="task.files" />
</template>
<script>
import AMastertaskName from './_components/a-mastertask-name.vue'
import AMastertaskStatus from './_components/a-mastertask-status.vue'
import ATaskTimeblocks from './_components/a-task-timeblocks.vue'
import ATaskAssignedEmployee from './_components/a-task-assigned-employee.vue'
import ATaskPlannedTime from './_components/a-task-planned-time.vue'
import ATaskSpentTime from './_components/a-task-spent-time.vue'
import ATaskRemainingTime from './_components/a-task-remaining-time.vue'
import ATaskDescription from './_components/a-task-description.vue'
import ZFiles from '@/plugins/tm@modal/_components/z-files.vue'
export default {
components: {
ZFiles,
AMastertaskName,
AMastertaskStatus,
ATaskTimeblocks,
ATaskAssignedEmployee,
ATaskPlannedTime,
ATaskSpentTime,
ATaskRemainingTime,
ATaskDescription
},
props: {
task: {
type: Object,
required: true
}
}
}
</script>