feat(shift): start to add logic to lock timestamp entry when selecting certain shift types
This commit is contained in:
parent
b09057a6be
commit
6368beb24d
|
|
@ -6,15 +6,29 @@
|
|||
import { computed, inject, onMounted, ref } from 'vue';
|
||||
import { QSelect, QInput, useQuasar, type QSelectProps, QPopupProxy } from 'quasar';
|
||||
import { useUiStore } from 'src/stores/ui-store';
|
||||
import { SHIFT_OPTIONS } from 'src/modules/timesheets/utils/shift.util';
|
||||
import type { Shift } from 'src/modules/timesheets/models/shift.models';
|
||||
import { useAuthStore } from 'src/stores/auth-store';
|
||||
import { SHIFT_OPTIONS } from 'src/modules/timesheets/utils/shift.util';
|
||||
import type { TotalHours } from 'src/modules/timesheets/models/timesheet.models';
|
||||
import type { Shift, ShiftOption, ShiftType } from 'src/modules/timesheets/models/shift.models';
|
||||
import { getHoursMinutesStringFromHoursFloat } from 'src/utils/date-and-time-utils';
|
||||
|
||||
// ================== State ==================
|
||||
// ========== Constants ========================================
|
||||
|
||||
const SHIFT_TYPES_WITH_PREDEFINED_TIMES: ShiftType[] = ['HOLIDAY', 'SICK', 'VACATION'];
|
||||
|
||||
// ========== State ========================================
|
||||
|
||||
const shift = defineModel<Shift>('shift', { required: true });
|
||||
|
||||
const { errorMessage = undefined, isTimesheetApproved = false, holiday = false } = defineProps<{
|
||||
const {
|
||||
errorMessage = undefined,
|
||||
isTimesheetApproved = false,
|
||||
holiday = false,
|
||||
expectedDailyHours = 8,
|
||||
dailyHours,
|
||||
} = defineProps<{
|
||||
dailyHours: TotalHours;
|
||||
expectedDailyHours?: number;
|
||||
isTimesheetApproved?: boolean;
|
||||
errorMessage?: string | undefined;
|
||||
holiday?: boolean | undefined;
|
||||
|
|
@ -39,7 +53,10 @@
|
|||
const selectRef = ref<QSelect | null>(null);
|
||||
const shiftErrorMessage = ref<string | undefined>();
|
||||
const is_showing_delete_confirm = ref(false);
|
||||
const isShowingPredefinedTime = ref(false);
|
||||
const popupProxyRef = ref<QPopupProxy | null>(null);
|
||||
const predefinedHours = ref(0);
|
||||
const predefinedHoursBgColor = ref('');
|
||||
|
||||
// ================== Computed ==================
|
||||
|
||||
|
|
@ -128,6 +145,28 @@
|
|||
popupProxyRef.value.hide();
|
||||
}
|
||||
|
||||
const onShiftTypeChange = (option: ShiftOption) => {
|
||||
shift.value.type = option.value;
|
||||
|
||||
if (SHIFT_TYPES_WITH_PREDEFINED_TIMES.includes(option.value)) {
|
||||
isShowingPredefinedTime.value = true;
|
||||
predefinedHoursBgColor.value = `bg-${option.icon_color}`;
|
||||
|
||||
if (option.value === 'SICK') {
|
||||
const workedHours =
|
||||
dailyHours.regular +
|
||||
dailyHours.emergency +
|
||||
dailyHours.evening +
|
||||
dailyHours.holiday +
|
||||
dailyHours.sick +
|
||||
dailyHours.vacation;
|
||||
predefinedHours.value = Math.max(expectedDailyHours - workedHours, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
isShowingPredefinedTime.value = false;
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (ui_store.focus_next_component) {
|
||||
selectRef.value?.focus();
|
||||
|
|
@ -206,7 +245,7 @@
|
|||
v-model="shiftTypeSelected"
|
||||
v-bind="shiftTypeSelectProps"
|
||||
@blur="onBlurShiftTypeSelect"
|
||||
@update:model-value="option => shift.type = option.value"
|
||||
@update:model-value="onShiftTypeChange"
|
||||
>
|
||||
<template #selected-item="scope">
|
||||
<div
|
||||
|
|
@ -291,40 +330,58 @@
|
|||
</q-select>
|
||||
</div>
|
||||
|
||||
<div class="col row items-start text-uppercase rounded-5 q-pa-xs">
|
||||
<!-- punch in field -->
|
||||
<q-input
|
||||
ref="start_time"
|
||||
v-model="shift.start_time"
|
||||
v-bind="timeInputProps"
|
||||
type="time"
|
||||
@blur="onTimeFieldBlur(shift.start_time)"
|
||||
<div class="col row">
|
||||
<!-- If shift type has predefined timestamps -->
|
||||
<div
|
||||
v-if="isShowingPredefinedTime"
|
||||
class="col row q-px-sm relative-position flex-center"
|
||||
>
|
||||
<template #label>
|
||||
<span
|
||||
class="text-weight-bolder"
|
||||
:class="shift.is_approved ? ' q-ml-md' : ''"
|
||||
style="font-size: 0.95em;"
|
||||
>{{ $t('shared.misc.in') }}</span>
|
||||
</template>
|
||||
</q-input>
|
||||
<div
|
||||
class="absolute-full rounded-5 q-mx-sm"
|
||||
:class="predefinedHoursBgColor"
|
||||
style="opacity: 0.3;"
|
||||
></div>
|
||||
<span class="col text-center text-uppercase text-h6 text-bold">{{ getHoursMinutesStringFromHoursFloat(predefinedHours) }}</span>
|
||||
</div>
|
||||
|
||||
<!-- punch out field -->
|
||||
<q-input
|
||||
ref="end_time"
|
||||
v-model="shift.end_time"
|
||||
v-bind="timeInputProps"
|
||||
type="time"
|
||||
@blur="onTimeFieldBlur(shift.end_time)"
|
||||
<!-- Else show input fields for in-out timestamps -->
|
||||
<div
|
||||
v-else
|
||||
class="col row items-start text-uppercase rounded-5 q-pa-xs"
|
||||
>
|
||||
<template #label>
|
||||
<span
|
||||
class="text-weight-bolder"
|
||||
:class="shift.is_approved ? ' q-ml-md' : ''"
|
||||
style="font-size: 0.95em;"
|
||||
>{{ $t('shared.misc.out') }}</span>
|
||||
</template>
|
||||
</q-input>
|
||||
<q-input
|
||||
ref="start_time"
|
||||
v-model="shift.start_time"
|
||||
v-bind="timeInputProps"
|
||||
type="time"
|
||||
@blur="onTimeFieldBlur(shift.start_time)"
|
||||
>
|
||||
<template #label>
|
||||
<span
|
||||
class="text-weight-bolder"
|
||||
:class="shift.is_approved ? ' q-ml-md' : ''"
|
||||
style="font-size: 0.95em;"
|
||||
>{{ $t('shared.misc.in') }}</span>
|
||||
</template>
|
||||
</q-input>
|
||||
|
||||
<!-- punch out field -->
|
||||
<q-input
|
||||
ref="end_time"
|
||||
v-model="shift.end_time"
|
||||
v-bind="timeInputProps"
|
||||
type="time"
|
||||
@blur="onTimeFieldBlur(shift.end_time)"
|
||||
>
|
||||
<template #label>
|
||||
<span
|
||||
class="text-weight-bolder"
|
||||
:class="shift.is_approved ? ' q-ml-md' : ''"
|
||||
style="font-size: 0.95em;"
|
||||
>{{ $t('shared.misc.out') }}</span>
|
||||
</template>
|
||||
</q-input>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="row full-height"
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@
|
|||
v-else
|
||||
v-model:shift="day.shifts[shift_index]!"
|
||||
:holiday="holiday"
|
||||
:daily-hours="day.daily_hours"
|
||||
:is-timesheet-approved="approved"
|
||||
:error-message="shift_error_message"
|
||||
@request-delete="deleteCurrentShift(shift)"
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import type { QSelectOption } from "quasar";
|
||||
|
||||
export const SHIFT_TYPES: ShiftType[] = [
|
||||
'REGULAR',
|
||||
'EVENING',
|
||||
|
|
@ -39,7 +41,7 @@ export class Shift {
|
|||
}
|
||||
}
|
||||
|
||||
export interface ShiftOption {
|
||||
export interface ShiftOption extends QSelectOption {
|
||||
label: string;
|
||||
value: ShiftType;
|
||||
icon: string;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ import { type FederalHoliday, TARGO_HOLIDAY_NAMES_FR } from 'src/modules/timeshe
|
|||
import type { RouteNames } from 'src/router/router-constants';
|
||||
import type { RouteRecordNameGeneric } from 'vue-router';
|
||||
|
||||
|
||||
export const useTimesheetStore = defineStore('timesheet', () => {
|
||||
const { t } = useI18n();
|
||||
const is_loading = ref<boolean>(false);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user