From 6368beb24d1ae725a78b886f69c241e119603653 Mon Sep 17 00:00:00 2001 From: Nic D Date: Wed, 18 Feb 2026 16:12:51 -0500 Subject: [PATCH] feat(shift): start to add logic to lock timestamp entry when selecting certain shift types --- .../components/shift-list-day-row.vue | 129 +++++++++++++----- .../timesheets/components/shift-list-day.vue | 1 + src/modules/timesheets/models/shift.models.ts | 4 +- src/stores/timesheet-store.ts | 1 - 4 files changed, 97 insertions(+), 38 deletions(-) diff --git a/src/modules/timesheets/components/shift-list-day-row.vue b/src/modules/timesheets/components/shift-list-day-row.vue index f2d2aac..fed9ed9 100644 --- a/src/modules/timesheets/components/shift-list-day-row.vue +++ b/src/modules/timesheets/components/shift-list-day-row.vue @@ -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', { 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(null); const shiftErrorMessage = ref(); const is_showing_delete_confirm = ref(false); + const isShowingPredefinedTime = ref(false); const popupProxyRef = ref(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" >