From 2b1b0dbcbd962c011c26bffa8108480d4f912260 Mon Sep 17 00:00:00 2001 From: Nic D Date: Mon, 23 Feb 2026 14:36:51 -0500 Subject: [PATCH] fix(timesheets): add autofill functionality to sick, vacation, holiday shifts. --- .../mobile/shift-list-day-row-mobile.vue | 80 +++++++++++++--- .../components/shift-list-day-row.vue | 63 ++++++------ .../timesheets/components/shift-list-day.vue | 3 +- src/modules/timesheets/models/shift.models.ts | 1 + .../timesheets/models/timesheet.models.ts | 1 + src/modules/timesheets/utils/shift.util.ts | 96 ++++++++++++++----- src/utils/date-and-time-utils.ts | 27 ++++-- 7 files changed, 194 insertions(+), 77 deletions(-) diff --git a/src/modules/timesheets/components/mobile/shift-list-day-row-mobile.vue b/src/modules/timesheets/components/mobile/shift-list-day-row-mobile.vue index 2939255..abfdc34 100644 --- a/src/modules/timesheets/components/mobile/shift-list-day-row-mobile.vue +++ b/src/modules/timesheets/components/mobile/shift-list-day-row-mobile.vue @@ -5,32 +5,46 @@ import { computed, onMounted, ref } from 'vue'; import { QSelect, QInput } 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 { getCurrentDailyMinutesWorked, getTimeStringFromMinutes, SHIFT_OPTIONS } from 'src/modules/timesheets/utils/shift.util'; + import type { Shift, ShiftOption, ShiftType } from 'src/modules/timesheets/models/shift.models'; + import { getHoursMinutesStringFromHoursFloat } from 'src/utils/date-and-time-utils'; + // ========== state ======================================== + const SHIFT_TYPES_WITH_PREDEFINED_TIMES: ShiftType[] = ['HOLIDAY', 'SICK', 'VACATION']; const COMMENT_LENGTH_MAX = 280; const shift = defineModel('shift', { required: true }); - - const { errorMessage = undefined, dense = false, hasShiftAfter = false, isTimesheetApproved = false } = defineProps<{ + + const { + dense = false, + hasShiftAfter = false, + isTimesheetApproved = false, + errorMessage = undefined, + expectedDailyHours = 8, + currentShifts, + } = defineProps<{ dense?: boolean; hasShiftAfter?: boolean; isTimesheetApproved?: boolean; errorMessage?: string | undefined; + expectedDailyHours?: number; + currentShifts: Shift[]; }>(); const emit = defineEmits<{ 'requestDelete': [void]; 'onTimeFieldBlur': [void]; }>(); - + const ui_store = useUiStore(); - const shift_type_selected = ref(SHIFT_OPTIONS.find(option => option.value == shift.value.type)); + const shiftTypeSelected = ref(SHIFT_OPTIONS.find(option => option.value == shift.value.type)); const select_ref = ref(null); const is_showing_comment_popup = ref(false); const error_message = ref(''); + const isShowingPredefinedTime = ref(shift.value.type === 'HOLIDAY'); + const predefinedHoursString = ref(''); + const predefinedHoursBgColor = ref(`bg-${shiftTypeSelected.value?.icon_color ?? ''}`); // ========== computed ======================================== @@ -39,7 +53,7 @@ // ========== methods ========================================= const onBlurShiftTypeSelect = () => { - if (shift_type_selected.value === undefined) { + if (shiftTypeSelected.value === undefined) { shift.value.type = 'REGULAR'; shift.value.id = 0; emit('requestDelete'); @@ -63,11 +77,35 @@ return 'negative'; }; + const onShiftTypeChange = (option: ShiftOption) => { + shift.value.type = option.value; + + if (SHIFT_TYPES_WITH_PREDEFINED_TIMES.includes(option.value)) { + predefinedHoursBgColor.value = `bg-${option.icon_color}`; + shift.value.start_time = '00:00'; + + if (option.value === 'SICK' || option.value === 'VACATION') { + const workedMinutes = getCurrentDailyMinutesWorked(currentShifts); + console.log('worked minutes: ', workedMinutes); + const expectedWorkedMinutes = expectedDailyHours * 60; + const leftOverMinutes = expectedWorkedMinutes - workedMinutes; + + shift.value.end_time = getTimeStringFromMinutes(leftOverMinutes); + isShowingPredefinedTime.value = false; + } else { + isShowingPredefinedTime.value = true; + predefinedHoursString.value = getHoursMinutesStringFromHoursFloat(expectedDailyHours); + shift.value.end_time = getTimeStringFromMinutes(expectedDailyHours * 60); + } + } else + isShowingPredefinedTime.value = false; + } + onMounted(() => { if (ui_store.focus_next_component) { select_ref.value?.focus(); select_ref.value?.showPopup(); - shift_type_selected.value = undefined; + shiftTypeSelected.value = undefined; ui_store.focus_next_component = false; } @@ -131,7 +169,7 @@