[events] Validate jobs before adding new
This commit is contained in:
parent
6a35f3c669
commit
7d1993e3fa
|
@ -82,9 +82,12 @@
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<template v-for="(job, index) in event.jobs" :key="index">
|
<template v-for="(job, index) in event.jobs" :key="index">
|
||||||
<job
|
<job
|
||||||
|
:ref="active === index ? 'activeRef' : undefined"
|
||||||
v-model="event.jobs[index]"
|
v-model="event.jobs[index]"
|
||||||
:can-delete="jobDeleteDisabled"
|
:active="active === index"
|
||||||
|
class="q-mb-xs"
|
||||||
@remove-job="removeJob(index)"
|
@remove-job="removeJob(index)"
|
||||||
|
@update:active="active = index"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
|
@ -117,13 +120,13 @@ export default defineComponent({
|
||||||
components: { IsoDateInput, Job, RecurrenceRule },
|
components: { IsoDateInput, Job, RecurrenceRule },
|
||||||
props: {
|
props: {
|
||||||
modelValue: {
|
modelValue: {
|
||||||
default: () => emptyEvent,
|
default: () => emptyEvent(),
|
||||||
type: Object as PropType<EditableEvent>,
|
type: Object as PropType<EditableEvent>,
|
||||||
},
|
},
|
||||||
date: {
|
date: {
|
||||||
required: false,
|
required: false,
|
||||||
default: () => new Date(),
|
default: () => new Date(),
|
||||||
type: [Object, String, Number] as PropType<Date | string | number>,
|
type: [Object, Number] as PropType<Date | number>,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
emits: {
|
emits: {
|
||||||
|
@ -131,20 +134,19 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
const store = useScheduleStore();
|
const store = useScheduleStore();
|
||||||
|
const active = ref(0);
|
||||||
const date = computed(() => new Date(props.date));
|
const activeRef = ref(Job);
|
||||||
const event = ref<EditableEvent>(
|
|
||||||
props.modelValue.id
|
|
||||||
? props.modelValue
|
|
||||||
: Object.assign({}, props.modelValue, { start: date.value })
|
|
||||||
);
|
|
||||||
const eventtypes = computed(() => store.eventTypes);
|
const eventtypes = computed(() => store.eventTypes);
|
||||||
const form = ref<QForm>();
|
const form = ref<QForm>();
|
||||||
const jobDeleteDisabled = computed(() => event.value.jobs.length < 2);
|
|
||||||
const recurrent = ref(false);
|
const recurrent = ref(false);
|
||||||
const recurrenceRule = ref<FG.RecurrenceRule>({ frequency: 'daily', interval: 1 });
|
const recurrenceRule = ref<FG.RecurrenceRule>({ frequency: 'daily', interval: 1 });
|
||||||
const templates = computed(() => store.templates);
|
const templates = computed(() => store.templates);
|
||||||
const template = ref<FG.Event>();
|
const template = ref<FG.Event>();
|
||||||
|
const event = ref<EditableEvent>(
|
||||||
|
props.modelValue.id
|
||||||
|
? props.modelValue
|
||||||
|
: Object.assign({}, props.modelValue, { start: new Date(props.date) })
|
||||||
|
);
|
||||||
|
|
||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
void store.getEventTypes();
|
void store.getEventTypes();
|
||||||
|
@ -152,25 +154,34 @@ export default defineComponent({
|
||||||
void store.getTemplates();
|
void store.getTemplates();
|
||||||
});
|
});
|
||||||
|
|
||||||
function addJob() {
|
async function addJob() {
|
||||||
event.value.jobs.push(Object.assign({}, emptyJob));
|
if (event.value.jobs.length > 0) {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
||||||
|
if (!(await activeRef.value?.validate())) return;
|
||||||
|
event.value.jobs.sort((a, b) => {
|
||||||
|
if (a.end && b.end)
|
||||||
|
if (a.end < b.end) return -1;
|
||||||
|
else if (a.end > b.end) return 1;
|
||||||
|
|
||||||
|
return a.start.getTime() - b.start.getTime();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
event.value.jobs.push(
|
||||||
|
emptyJob(event.value.jobs[event.value.jobs.length - 1]?.end || new Date(props.date))
|
||||||
|
);
|
||||||
|
active.value = event.value.jobs.length - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeJob(index: number) {
|
function removeJob(index: number) {
|
||||||
event.value.jobs.splice(index, 1);
|
event.value.jobs.splice(index, 1);
|
||||||
|
active.value = index == active.value ? event.value.jobs.length - 1 : index;
|
||||||
}
|
}
|
||||||
|
|
||||||
function fromTemplate(tpl: FG.Event) {
|
function fromTemplate(tpl: FG.Event) {
|
||||||
template.value = tpl;
|
template.value = tpl;
|
||||||
event.value = Object.assign({}, tpl);
|
event.value = Object.assign({}, tpl);
|
||||||
event.value.start = new Date(
|
event.value.start = qdate.buildDate({ hours: 0, minutes: 0, seconds: 0 });
|
||||||
date.value.getUTCFullYear(),
|
|
||||||
date.value.getUTCMonth(),
|
|
||||||
date.value.getUTCDate()
|
|
||||||
);
|
|
||||||
const diff = event.value.start.getTime() - tpl.start.getTime();
|
const diff = event.value.start.getTime() - tpl.start.getTime();
|
||||||
console.log(event.value);
|
|
||||||
console.log(diff);
|
|
||||||
if (event.value.end) event.value.end = new Date(event.value.end.getTime() + diff);
|
if (event.value.end) event.value.end = new Date(event.value.end.getTime() + diff);
|
||||||
|
|
||||||
event.value.jobs.forEach((job) => {
|
event.value.jobs.forEach((job) => {
|
||||||
|
@ -231,12 +242,13 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
|
|
||||||
function reset() {
|
function reset() {
|
||||||
event.value = Object.assign({}, props.modelValue || emptyEvent);
|
event.value = Object.assign({}, props.modelValue || emptyEvent());
|
||||||
template.value = undefined;
|
template.value = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
jobDeleteDisabled,
|
active,
|
||||||
|
activeRef,
|
||||||
addJob,
|
addJob,
|
||||||
eventtypes,
|
eventtypes,
|
||||||
templates,
|
templates,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<q-card class="fit row justify-start content-center items-center">
|
<q-card class="fit row justify-start content-center items-center" @click="activate">
|
||||||
<q-card-section class="fit row justify-start content-center items-center">
|
<q-form v-if="active" ref="form" class="fit row justify-start content-center items-center">
|
||||||
<IsoDateInput
|
<IsoDateInput
|
||||||
v-model="job.start"
|
v-model="job.start"
|
||||||
class="col-xs-12 col-sm-6 q-pa-sm"
|
class="col-xs-12 col-sm-6 q-pa-sm"
|
||||||
|
@ -40,44 +40,57 @@
|
||||||
<q-input
|
<q-input
|
||||||
v-model="job.comment"
|
v-model="job.comment"
|
||||||
class="col-12 q-pa-sm"
|
class="col-12 q-pa-sm"
|
||||||
label="Beschreibung"
|
label="Kommentar"
|
||||||
type="textarea"
|
type="textarea"
|
||||||
filled
|
filled
|
||||||
/>
|
/>
|
||||||
|
</q-form>
|
||||||
|
<q-card-section v-else class="fit row justify-start content-center items-center text-center">
|
||||||
|
<div class="text-h6 col-12">{{ formatStartEnd(job.start, job.end) }}</div>
|
||||||
|
<div class="text-subtitle1 col-12">
|
||||||
|
{{ job?.type?.name || 'Typ fehlt' }} ({{ job.required_services }})
|
||||||
|
</div>
|
||||||
|
<div class="text-body2 text-italic text-left col-12">{{ job.comment }}</div>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-card-actions>
|
<q-card-actions class="fit row" align="right">
|
||||||
<q-btn label="Schicht löschen" color="negative" :disabled="canDelete" @click="removeJob" />
|
<q-btn label="Schicht löschen" color="negative" @click="removeJob" />
|
||||||
</q-card-actions>
|
</q-card-actions>
|
||||||
</q-card>
|
</q-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, computed, onBeforeMount, PropType } from 'vue';
|
import { defineComponent, computed, onBeforeMount, PropType, ref } from 'vue';
|
||||||
import IsoDateInput from 'src/components/utils/IsoDateInput.vue';
|
import IsoDateInput from 'src/components/utils/IsoDateInput.vue';
|
||||||
import { notEmpty } from 'src/utils/validators';
|
import { notEmpty } from 'src/utils/validators';
|
||||||
import { useScheduleStore } from '../../store';
|
import { useScheduleStore } from '../../store';
|
||||||
|
import { QForm } from 'quasar';
|
||||||
|
import { asDate, asHour } from 'src/utils/datetime';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'Job',
|
name: 'Job',
|
||||||
components: { IsoDateInput },
|
components: { IsoDateInput },
|
||||||
props: {
|
props: {
|
||||||
|
active: {
|
||||||
|
default: () => true,
|
||||||
|
type: Boolean,
|
||||||
|
},
|
||||||
modelValue: {
|
modelValue: {
|
||||||
required: true,
|
required: true,
|
||||||
type: Object as PropType<FG.Job>,
|
type: Object as PropType<FG.Job>,
|
||||||
},
|
},
|
||||||
canDelete: Boolean,
|
|
||||||
},
|
},
|
||||||
emits: {
|
emits: {
|
||||||
'remove-job': () => true,
|
'remove-job': () => true,
|
||||||
|
'update:active': (active: boolean) => typeof active === 'boolean',
|
||||||
'update:modelValue': (job: FG.Job) => !!job,
|
'update:modelValue': (job: FG.Job) => !!job,
|
||||||
},
|
},
|
||||||
setup(props, { emit }) {
|
setup(props, { emit, expose }) {
|
||||||
const store = useScheduleStore();
|
const store = useScheduleStore();
|
||||||
|
|
||||||
onBeforeMount(() => store.getJobTypes());
|
onBeforeMount(() => store.getJobTypes());
|
||||||
|
|
||||||
|
const form = ref<QForm>();
|
||||||
const jobtypes = computed(() => store.jobTypes);
|
const jobtypes = computed(() => store.jobTypes);
|
||||||
|
|
||||||
const job = new Proxy(props.modelValue, {
|
const job = new Proxy(props.modelValue, {
|
||||||
get(target, prop) {
|
get(target, prop) {
|
||||||
if (typeof prop === 'string') {
|
if (typeof prop === 'string') {
|
||||||
|
@ -93,6 +106,15 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function formatStartEnd(start: Date, end?: Date) {
|
||||||
|
const startDate = asDate(start);
|
||||||
|
const endDate = end ? asDate(end) : end;
|
||||||
|
return (
|
||||||
|
`${startDate}, ${asHour(start)}` +
|
||||||
|
(endDate ? ` - ${endDate !== startDate ? endDate + ', ' : ''}` + asHour(end) : '')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function removeJob() {
|
function removeJob() {
|
||||||
emit('remove-job');
|
emit('remove-job');
|
||||||
}
|
}
|
||||||
|
@ -101,7 +123,19 @@ export default defineComponent({
|
||||||
return props.modelValue.start < new Date(val) || 'Ende muss hinter dem Start liegen';
|
return props.modelValue.start < new Date(val) || 'Ende muss hinter dem Start liegen';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function activate() {
|
||||||
|
emit('update:active', true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function validate() {
|
||||||
|
return form.value?.validate() || new Promise((r) => r(false));
|
||||||
|
}
|
||||||
|
expose({ validate });
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
activate,
|
||||||
|
form,
|
||||||
|
formatStartEnd,
|
||||||
job,
|
job,
|
||||||
jobtypes,
|
jobtypes,
|
||||||
removeJob,
|
removeJob,
|
||||||
|
|
Loading…
Reference in New Issue