From a07086fa2ecdaa266b3554536f3b9fd72a4e8748 Mon Sep 17 00:00:00 2001 From: Nicolas Drolet Date: Thu, 18 Dec 2025 11:00:31 -0500 Subject: [PATCH 1/6] feat(timesheet-approval): add filter template, working on filling. Merging with other changes on main. --- .../components/overview-list-filters.vue | 12 ++++ .../components/overview-list.vue | 5 +- src/pages/timesheet-approval-page.vue | 59 ++++++++++++++----- 3 files changed, 56 insertions(+), 20 deletions(-) create mode 100644 src/modules/timesheet-approval/components/overview-list-filters.vue diff --git a/src/modules/timesheet-approval/components/overview-list-filters.vue b/src/modules/timesheet-approval/components/overview-list-filters.vue new file mode 100644 index 0000000..46728a4 --- /dev/null +++ b/src/modules/timesheet-approval/components/overview-list-filters.vue @@ -0,0 +1,12 @@ + + + \ No newline at end of file diff --git a/src/modules/timesheet-approval/components/overview-list.vue b/src/modules/timesheet-approval/components/overview-list.vue index 46153d8..848c2ef 100644 --- a/src/modules/timesheet-approval/components/overview-list.vue +++ b/src/modules/timesheet-approval/components/overview-list.vue @@ -26,10 +26,7 @@ overview_column_names.IS_APPROVED, ]); - const overview_rows = computed(() => timesheet_store.pay_period_overviews[0]?.regular_hours === -1 ? - [] : - timesheet_store.pay_period_overviews - ) + const overview_rows = computed(() => timesheet_store.pay_period_overviews.filter(overview => overview)) const onClickedDetails = async (row: TimesheetOverview) => { timesheet_store.current_pay_period_overview = row; diff --git a/src/pages/timesheet-approval-page.vue b/src/pages/timesheet-approval-page.vue index 562a618..a4c60b4 100644 --- a/src/pages/timesheet-approval-page.vue +++ b/src/pages/timesheet-approval-page.vue @@ -3,19 +3,23 @@ lang="ts" > /* eslint-disable */ - import { onMounted, ref } from 'vue'; - import { date } from 'quasar'; - import { useTimesheetApprovalApi } from 'src/modules/timesheet-approval/composables/use-timesheet-approval-api'; - import { useTimesheetStore } from 'src/stores/timesheet-store'; import PageHeaderTemplate from 'src/modules/shared/components/page-header-template.vue'; import OverviewList from 'src/modules/timesheet-approval/components/overview-list.vue'; import DetailsDialog from 'src/modules/timesheet-approval/components/details-dialog.vue'; import QTableFilters from 'src/modules/shared/components/q-table-filters.vue'; import PayPeriodNavigator from 'src/modules/shared/components/pay-period-navigator.vue'; + import OverviewListFilters from 'src/modules/timesheet-approval/components/overview-list-filters.vue'; + + import { date } from 'quasar'; + import { onMounted, ref } from 'vue'; + import { useTimesheetApprovalApi } from 'src/modules/timesheet-approval/composables/use-timesheet-approval-api'; + import { useTimesheetStore } from 'src/stores/timesheet-store'; const timesheet_approval_api = useTimesheetApprovalApi(); const timesheet_store = useTimesheetStore(); + const is_showing_filters = ref(false); + onMounted(async () => { await timesheet_approval_api.getTimesheetOverviewsByDate(date.formatDate(new Date(), 'YYYY-MM-DD')); }); @@ -40,14 +44,15 @@ />
@@ -59,27 +64,49 @@ color="white" text-color="accent" toggle-color="accent" - :class="$q.screen.lt.md ? 'q-mb-sm' : 'q-mr-md'" + class="col-auto" + :class="$q.platform.is.mobile ? 'q-mb-sm' : 'q-mr-md'" :options="[ { icon: 'grid_view', value: true }, { icon: 'view_list', value: false }, ]" + style="height: 40px;" /> -
- + - +
+ + + + + + \ No newline at end of file From 4231b51c11a2bfd4baf8cc9574fc66da83f968df Mon Sep 17 00:00:00 2001 From: Nicolas Drolet Date: Thu, 18 Dec 2025 17:14:31 -0500 Subject: [PATCH 2/6] refactor(timesheet): More UI/UX adjustments to timesheet approval filters, mostly work on timesheets UI/UX for mobile --- src/i18n/en-ca/index.ts | 22 +- src/i18n/fr-ca/index.ts | 22 +- .../components/main-layout-header-bar.vue | 4 +- src/layouts/main-layout.vue | 11 +- .../components/employee/menu-employee.vue | 2 +- .../shared/menu-panel-preferences.vue | 15 +- .../components/shared/menu-template.vue | 8 +- .../components/overview-list-filters.vue | 37 ++- .../mobile/shift-list-day-row-mobile.vue | 295 ++++++++++++++++++ .../components/shift-list-day-row.vue | 14 +- .../timesheets/components/shift-list-day.vue | 31 +- .../timesheets/components/shift-list.vue | 101 +++--- .../components/timesheet-wrapper.vue | 119 +++++-- src/modules/timesheets/utils/shift.util.ts | 12 +- src/pages/profile-page.vue | 3 +- src/pages/timesheet-approval-page.vue | 58 ++-- src/pages/timesheet-page.vue | 2 +- src/stores/ui-store.ts | 8 +- 18 files changed, 576 insertions(+), 188 deletions(-) create mode 100644 src/modules/timesheets/components/mobile/shift-list-day-row-mobile.vue diff --git a/src/i18n/en-ca/index.ts b/src/i18n/en-ca/index.ts index b7c97ea..c02d48e 100644 --- a/src/i18n/en-ca/index.ts +++ b/src/i18n/en-ca/index.ts @@ -176,6 +176,10 @@ export default { timesheet: { page_header: "Timesheet", + week: "week", + total_hours: "total hours: ", + current_shifts: "shifts worked", + apply_preset: "auto-fill", apply_preset_day: "Apply schedule to day", apply_preset_week: "Apply schedule to week", nav_button: { @@ -254,15 +258,6 @@ export default { timesheet_approvals: { page_title: "Validation cartes de temps", - table: { - full_name: "full name", - email: "email address", - is_approved: "approval", - expenses: "expenses", - mileage: "mileage", - verified: "approved", - unverified: "pending", - }, chart: { hours_worked_title: "hours worked", expenses_title: "expenses accrued", @@ -275,6 +270,15 @@ export default { expenses: "expenses", options: "options", }, + table: { + full_name: "full name", + email: "email address", + is_approved: "approval", + expenses: "expenses", + mileage: "mileage", + verified: "approved", + unverified: "pending", + }, tooltip: { button_detailed_view: "detailed view", }, diff --git a/src/i18n/fr-ca/index.ts b/src/i18n/fr-ca/index.ts index ed464e9..e402331 100644 --- a/src/i18n/fr-ca/index.ts +++ b/src/i18n/fr-ca/index.ts @@ -177,6 +177,10 @@ export default { timesheet: { page_header: "Carte de temps", + week: "semaine", + total_hours: "heures totales: ", + current_shifts: "quarts entrées", + apply_preset: "auto-remplir", apply_preset_day: "Appliquer horaire pour la journée", apply_preset_week: "Appliquer horaire pour la semaine", nav_button: { @@ -255,15 +259,6 @@ export default { timesheet_approvals: { page_title: "Validation cartes de temps", - table: { - full_name: "nom complet", - email: "courriel", - is_approved: "approuvé", - expenses: "dépenses", - mileage: "kilométrage", - verified: "approuvé", - unverified: "à vérifier", - }, chart: { hours_worked_title: "heures travaillées", expenses_title: "dépenses encourues" @@ -276,6 +271,15 @@ export default { expenses: "dépenses", options: "options", }, + table: { + full_name: "nom complet", + email: "courriel", + is_approved: "approuvé", + expenses: "dépenses", + mileage: "kilométrage", + verified: "approuvé", + unverified: "à vérifier", + }, tooltip: { button_detailed_view: "vue détaillée", }, diff --git a/src/layouts/components/main-layout-header-bar.vue b/src/layouts/components/main-layout-header-bar.vue index 0d4beb8..31d67da 100644 --- a/src/layouts/components/main-layout-header-bar.vue +++ b/src/layouts/components/main-layout-header-bar.vue @@ -3,7 +3,7 @@ setup > import { useUiStore } from 'src/stores/ui-store'; - import HeaderBarNotification from './main-layout-header-bar-notification.vue'; + // import HeaderBarNotification from './main-layout-header-bar-notification.vue'; const uiStore = useUiStore(); @@ -29,7 +29,7 @@ - + diff --git a/src/layouts/main-layout.vue b/src/layouts/main-layout.vue index 97163be..6c730c9 100644 --- a/src/layouts/main-layout.vue +++ b/src/layouts/main-layout.vue @@ -2,16 +2,15 @@ lang="ts" setup > - import { RouterView } from 'vue-router'; import HeaderBar from 'src/layouts/components/main-layout-header-bar.vue'; import FooterBar from 'src/layouts/components/main-layout-footer-bar.vue'; import LeftDrawer from 'src/layouts/components/main-layout-left-drawer.vue'; - import { useUiStore } from 'src/stores/ui-store'; + import { onMounted, watch, ref } from 'vue'; - import { useI18n } from 'vue-i18n'; - - const { t } = useI18n(); + import { RouterView } from 'vue-router'; + import { useUiStore } from 'src/stores/ui-store'; + const ui_store = useUiStore(); const user_preferences = ref(ui_store.user_preferences); @@ -23,7 +22,7 @@ watch(user_preferences, async () => { if (ui_store.user_preferences.id !== -1) { - await ui_store.updateUserPreferences(t); + await ui_store.updateUserPreferences(); return } await ui_store.getUserPreferences(); diff --git a/src/modules/profile/components/employee/menu-employee.vue b/src/modules/profile/components/employee/menu-employee.vue index 1637ee1..7d666ba 100644 --- a/src/modules/profile/components/employee/menu-employee.vue +++ b/src/modules/profile/components/employee/menu-employee.vue @@ -25,7 +25,7 @@
\ No newline at end of file diff --git a/src/modules/timesheets/components/shift-list.vue b/src/modules/timesheets/components/shift-list.vue index 329ebca..cf06e4b 100644 --- a/src/modules/timesheets/components/shift-list.vue +++ b/src/modules/timesheets/components/shift-list.vue @@ -47,20 +47,24 @@ return day.shifts.every(shift => shift.is_approved === true); } - const handleSwipe = async (direction: 'left' | 'up' | 'down' | 'right' | undefined, distance: {x?: number, y?: number}) => { + const handleSwipe = async (direction: 'left' | 'up' | 'down' | 'right' | undefined, distance: { x?: number, y?: number }) => { mobile_animation_direction.value = direction === 'left' ? 'fadeInRight' : 'fadeInLeft'; - if (distance.x && Math.abs(distance.x) > 10 ) { - await timesheet_api.getTimesheetsBySwiping( direction === 'left' ? 1 : -1 ) + if (distance.x && Math.abs(distance.x) > 10) { + await timesheet_api.getTimesheetsBySwiping(direction === 'left' ? 1 : -1) } } \ No newline at end of file diff --git a/src/modules/timesheets/components/timesheet-wrapper.vue b/src/modules/timesheets/components/timesheet-wrapper.vue index ad8cdee..0d0a5bc 100644 --- a/src/modules/timesheets/components/timesheet-wrapper.vue +++ b/src/modules/timesheets/components/timesheet-wrapper.vue @@ -39,7 +39,7 @@
@@ -63,20 +63,7 @@ @click="expenses_store.open" /> - - - - + + + + +
+ + + + +
+ +
+ +
+ +
{{ $t('timesheet.week') + ` ${timesheet_index + 1}` }}
+ + +
+ {{ + $t('timesheet.total_hours') }} + {{ + (timesheet.weekly_hours.regular + + timesheet.weekly_hours.evening + + timesheet.weekly_hours.emergency + + timesheet.weekly_hours.overtime).toFixed(2) + }} +
+ + +
{{ $t('timesheet.current_shifts') }}
+ + +
+
+ + {{ day.shifts.length > 0 ? day.shifts.length : '' + }} + +
+
+
+ + +
+ +
+
- - - + diff --git a/src/modules/timesheets/utils/shift.util.ts b/src/modules/timesheets/utils/shift.util.ts index 00fb6ef..0dc2c5e 100644 --- a/src/modules/timesheets/utils/shift.util.ts +++ b/src/modules/timesheets/utils/shift.util.ts @@ -1,4 +1,4 @@ -import { date, patterns, type ValidationRule } from "quasar"; +import { date } from "quasar"; import type { SchedulePresetShift } from "src/modules/employee-list/models/schedule-presets.models"; import type { Shift, ShiftOption } from "src/modules/timesheets/models/shift.models"; @@ -26,16 +26,6 @@ export const isShiftOverlap = (shifts: Shift[] | SchedulePresetShift[]): boolean return false; }; -export const useShiftRules = (time_required_error: string, overlap_error_string: string, day_shifts: Shift[]) => { - const isTimeRequiredRule: ValidationRule = (time_string: string) => (!!time_string && patterns.testPattern.time(time_string)) || time_required_error; - const isShiftOverlapRule: ValidationRule = (_time_string: string) => !isShiftOverlap(day_shifts) || overlap_error_string; - - return { - isTimeRequiredRule, - isShiftOverlapRule - }; -}; - export const SHIFT_OPTIONS: ShiftOption[] = [ { label: 'timesheet.shift.types.REGULAR', value: 'REGULAR', icon: 'wb_sunny', icon_color: 'accent' }, { label: 'timesheet.shift.types.EVENING', value: 'EVENING', icon: 'bedtime', icon_color: 'orange-5' }, diff --git a/src/pages/profile-page.vue b/src/pages/profile-page.vue index e010de1..cfb2309 100644 --- a/src/pages/profile-page.vue +++ b/src/pages/profile-page.vue @@ -21,10 +21,11 @@ import { onMounted } from 'vue'; \ No newline at end of file diff --git a/src/pages/timesheet-approval-page.vue b/src/pages/timesheet-approval-page.vue index a13fe15..d2aea1f 100644 --- a/src/pages/timesheet-approval-page.vue +++ b/src/pages/timesheet-approval-page.vue @@ -16,8 +16,8 @@ import { useTimesheetApprovalApi } from 'src/modules/timesheet-approval/composables/use-timesheet-approval-api'; import { useTimesheetStore } from 'src/stores/timesheet-store'; -const timesheet_approval_api = useTimesheetApprovalApi(); -const timesheet_store = useTimesheetStore(); + const timesheet_approval_api = useTimesheetApprovalApi(); + const timesheet_store = useTimesheetStore(); const is_showing_filters = ref(false); @@ -58,34 +58,24 @@ const timesheet_store = useTimesheetStore(); - -
- @@ -102,22 +93,31 @@ const timesheet_store = useTimesheetStore(); v-model:search="timesheet_store.search_filter" class="col-auto q-mb-xs" /> + +
- + - diff --git a/src/pages/timesheet-page.vue b/src/pages/timesheet-page.vue index fd440f9..f632dab 100644 --- a/src/pages/timesheet-page.vue +++ b/src/pages/timesheet-page.vue @@ -16,7 +16,7 @@