173 lines
5.8 KiB
Vue
173 lines
5.8 KiB
Vue
<script
|
||
setup
|
||
lang="ts"
|
||
>
|
||
import { computed, ref } from 'vue';
|
||
import { useShiftStore } from 'src/stores/shift-store';
|
||
import { useShiftApi } from 'src/modules/timesheets/composables/api/use-shift-api';
|
||
import { SHIFT_TYPES } from 'src/modules/timesheets/models/shift.models';
|
||
|
||
const { date_iso, mode, current_shift, is_open, close } = useShiftStore();
|
||
const { upsertOrDeleteShiftByEmployeeEmail } = useShiftApi();
|
||
|
||
const { employeeEmail } = defineProps<{
|
||
employeeEmail: string;
|
||
}>();
|
||
|
||
const isSubmitting = ref(false);
|
||
const errorBanner = ref<string | null>(null);
|
||
const conflicts = ref<Array<{ start_time: string; end_time: string; type: string }>>([]);
|
||
|
||
const canSubmit = computed(() =>
|
||
mode === 'delete' ||
|
||
(current_shift.start_time.trim().length === 5 &&
|
||
current_shift.end_time.trim().length === 5 &&
|
||
current_shift.type !== undefined)
|
||
);
|
||
</script>
|
||
|
||
<template>
|
||
<q-dialog
|
||
v-model=" is_open"
|
||
persistent
|
||
transition-show="fade"
|
||
transition-hide="fade"
|
||
>
|
||
|
||
<q-card class="q-pa-md">
|
||
<div class="row items-center q-mb-sm">
|
||
<q-icon
|
||
name="schedule"
|
||
size="24px"
|
||
class="q-mr-sm"
|
||
/>
|
||
<div class="text-h6">
|
||
{{
|
||
mode === 'create'
|
||
? $t('timesheet.shift.actions.add')
|
||
: mode === 'update'
|
||
? $t('timesheet.shift.actions.edit')
|
||
: $t('timesheet.shift.actions.delete')
|
||
}}
|
||
</div>
|
||
<q-space />
|
||
<q-badge
|
||
outline
|
||
color="primary"
|
||
>
|
||
{{ date_iso }}
|
||
</q-badge>
|
||
</div>
|
||
|
||
<q-separator spaced />
|
||
|
||
<div
|
||
v-if="mode !== 'delete'"
|
||
class="column q-gutter-md"
|
||
>
|
||
<div class="row ">
|
||
<div class="col">
|
||
<q-input
|
||
v-model="current_shift.start_time"
|
||
:label="$t('timesheet.shift.fields.start')"
|
||
filled
|
||
dense
|
||
inputmode="numeric"
|
||
mask="##:##"
|
||
/>
|
||
</div>
|
||
<div class="col">
|
||
<q-input
|
||
v-model="current_shift.end_time"
|
||
:label="$t('timesheet.shift.fields.end')"
|
||
filled
|
||
dense
|
||
inputmode="numeric"
|
||
mask="##:##"
|
||
/>
|
||
</div>
|
||
</div>
|
||
<div class="row items-center">
|
||
<q-select
|
||
v-model="current_shift.type"
|
||
options-dense
|
||
:options="SHIFT_TYPES"
|
||
:label="$t('timesheet.shift.types.label')"
|
||
class="col"
|
||
color="primary"
|
||
filled
|
||
dense
|
||
hide-dropdown-icon
|
||
emit-value
|
||
map-options
|
||
/>
|
||
<q-toggle
|
||
v-model="current_shift.is_remote"
|
||
:label="$t('timesheet.shift.types.REMOTE')"
|
||
class="col-auto"
|
||
/>
|
||
</div>
|
||
<q-input
|
||
v-model="current_shift.comment"
|
||
type="textarea"
|
||
autogrow
|
||
filled
|
||
dense
|
||
:label="$t('timesheet.shift.fields.header_comment')"
|
||
:counter="true"
|
||
:maxlength="512"
|
||
/>
|
||
</div>
|
||
|
||
<div
|
||
v-else
|
||
class="q-pa-md"
|
||
>
|
||
{{ $t('timesheet.shift.actions.delete_confirmation_msg') }}
|
||
</div>
|
||
|
||
<div
|
||
v-if="errorBanner"
|
||
class="q-mt-md"
|
||
>
|
||
<q-banner
|
||
dense
|
||
class="bg-red-2 text-negative"
|
||
>{{ errorBanner }}</q-banner>
|
||
<div
|
||
v-if="conflicts.length"
|
||
class="q-mt-xs"
|
||
>
|
||
<div class="text-caption">Conflits :</div>
|
||
<ul class="q-pl-md q-mt-xs">
|
||
<li
|
||
v-for="(c, i) in conflicts"
|
||
:key="i"
|
||
>
|
||
{{ c.start_time }}–{{ c.end_time }} ({{ c.type }})
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
|
||
<q-separator spaced />
|
||
|
||
<div class="row justify-end q-gutter-sm">
|
||
<q-btn
|
||
flat
|
||
color="grey-8"
|
||
:label="$t('timesheet.cancel_button')"
|
||
@click="close"
|
||
/>
|
||
<q-btn
|
||
color="primary"
|
||
icon="save_alt"
|
||
:label="mode === 'delete' ? $t('timesheet.delete_button') : $t('timesheet.save_button')"
|
||
:loading="isSubmitting"
|
||
:disable="!canSubmit"
|
||
@click="upsertOrDeleteShiftByEmployeeEmail(employeeEmail)"
|
||
/>
|
||
</div>
|
||
</q-card>
|
||
</q-dialog>
|
||
</template> |