From 89148343b610fa81733123eadcb447cc5a53a699 Mon Sep 17 00:00:00 2001 From: Nicolas Drolet Date: Tue, 2 Sep 2025 16:56:04 -0400 Subject: [PATCH 1/5] feat(approvals): add chart to track total hours for each type, chart to track expenses, begin work on widget to display detailed shift info. --- src/i18n/en-ca/index.ts | 2 +- ...al-employee-details-hours-worked-chart.vue | 26 +---- ...val-employee-details-shift-types-chart.vue | 63 ++++++++++++ ...sheet-approval-employee-expenses-chart.vue | 81 ++++++++++++++++ ...sheet-approval-employee-details-shifts.vue | 14 +++ .../timesheet-approval-employee-details.vue | 95 +++++++++++++++++-- ...esheet-approval-employee-overview-list.vue | 12 ++- .../composables/use-timesheet-approval-api.ts | 12 ++- .../services/services-timesheet-approval.ts | 3 +- .../types/timesheet-details-interface.ts | 25 ++--- 10 files changed, 282 insertions(+), 51 deletions(-) create mode 100644 src/modules/timesheet-approval/components/graphs/timesheet-approval-employee-details-shift-types-chart.vue create mode 100644 src/modules/timesheet-approval/components/graphs/timesheet-approval-employee-expenses-chart.vue create mode 100644 src/modules/timesheet-approval/components/timesheet-approval-employee-details-shifts.vue diff --git a/src/i18n/en-ca/index.ts b/src/i18n/en-ca/index.ts index 71b4552..c7ac6d0 100644 --- a/src/i18n/en-ca/index.ts +++ b/src/i18n/en-ca/index.ts @@ -246,7 +246,7 @@ export default { newUsers: 'New user', updateUsers: 'Update user', timeSheets: 'Time sheet', - timeSheetValidations: 'Time sheet', + timeSheetValidations: 'Time sheet approvals', }, timeSheet: { timeSheetTab_1: 'Shifts', diff --git a/src/modules/timesheet-approval/components/graphs/timesheet-approval-employee-details-hours-worked-chart.vue b/src/modules/timesheet-approval/components/graphs/timesheet-approval-employee-details-hours-worked-chart.vue index 95bcbfc..0b57ee6 100644 --- a/src/modules/timesheet-approval/components/graphs/timesheet-approval-employee-details-hours-worked-chart.vue +++ b/src/modules/timesheet-approval/components/graphs/timesheet-approval-employee-details-hours-worked-chart.vue @@ -6,6 +6,7 @@ import type { PayPeriodEmployeeDetails } from 'src/modules/timesheet-approval/types/timesheet-approval-pay-period-employee-details-interface'; const { t } = useI18n(); + ChartJS.register(Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale); ChartJS.defaults.font.family = '"Roboto", sans-serif'; @@ -21,8 +22,7 @@ }); const hours_worked_labels = ref([]); - const hours_worked_dataset = ref[]>([]); - + const hours_worked_dataset = ref[]>([]); const getHoursWorkedData = (): ChartData<'bar'> => { if (props.rawData) { @@ -63,30 +63,12 @@ datasets: hours_worked_dataset.value, }; }; - \ No newline at end of file diff --git a/src/modules/timesheet-approval/components/graphs/timesheet-approval-employee-details-shift-types-chart.vue b/src/modules/timesheet-approval/components/graphs/timesheet-approval-employee-details-shift-types-chart.vue new file mode 100644 index 0000000..a736325 --- /dev/null +++ b/src/modules/timesheet-approval/components/graphs/timesheet-approval-employee-details-shift-types-chart.vue @@ -0,0 +1,63 @@ + + + \ No newline at end of file diff --git a/src/modules/timesheet-approval/components/graphs/timesheet-approval-employee-expenses-chart.vue b/src/modules/timesheet-approval/components/graphs/timesheet-approval-employee-expenses-chart.vue new file mode 100644 index 0000000..1817716 --- /dev/null +++ b/src/modules/timesheet-approval/components/graphs/timesheet-approval-employee-expenses-chart.vue @@ -0,0 +1,81 @@ + + + \ No newline at end of file diff --git a/src/modules/timesheet-approval/components/timesheet-approval-employee-details-shifts.vue b/src/modules/timesheet-approval/components/timesheet-approval-employee-details-shifts.vue new file mode 100644 index 0000000..6806242 --- /dev/null +++ b/src/modules/timesheet-approval/components/timesheet-approval-employee-details-shifts.vue @@ -0,0 +1,14 @@ + + + \ No newline at end of file diff --git a/src/modules/timesheet-approval/components/timesheet-approval-employee-details.vue b/src/modules/timesheet-approval/components/timesheet-approval-employee-details.vue index cf235b1..9c7c955 100644 --- a/src/modules/timesheet-approval/components/timesheet-approval-employee-details.vue +++ b/src/modules/timesheet-approval/components/timesheet-approval-employee-details.vue @@ -1,17 +1,25 @@ \ No newline at end of file diff --git a/src/modules/timesheet-approval/components/timesheet-approval-employee-overview-list.vue b/src/modules/timesheet-approval/components/timesheet-approval-employee-overview-list.vue index 3f361fb..e97cd0c 100644 --- a/src/modules/timesheet-approval/components/timesheet-approval-employee-overview-list.vue +++ b/src/modules/timesheet-approval/components/timesheet-approval-employee-overview-list.vue @@ -26,6 +26,7 @@ const report_filter_company = ref([true, true]); const report_filter_type = ref([true, true, true, true]); const clicked_employee_name = ref(''); + const clicked_employee_email = ref(''); const update_key = ref(0); const columns = computed((): QTableColumn[] => [ @@ -114,13 +115,19 @@ } } + const getEmployeeOverview = (email: string): PayPeriodOverviewEmployee | undefined => { + return timesheet_approval_api.getPayPeriodOverviewByEmployeeEmail(email); + } + const onDateSelected = async (date_string: string) => { await timesheet_approval_api.getPayPeriodOverviewByDate(date_string); }; const onClickedDetails = async (email: string, name: string) => { - clicked_employee_name.value = name; + clicked_employee_name.value = name; + clicked_employee_email.value = email; is_showing_details.value = true; + await timesheet_approval_api.getTimesheetsByPayPeriodAndEmail(email); }; @@ -143,13 +150,14 @@ transition-show="jump-down" transition-hide="jump-down" @before-show="() => update_key += 1" + class="full-width" >
diff --git a/src/modules/timesheet-approval/composables/use-timesheet-approval-api.ts b/src/modules/timesheet-approval/composables/use-timesheet-approval-api.ts index 4f424d5..3b7018d 100644 --- a/src/modules/timesheet-approval/composables/use-timesheet-approval-api.ts +++ b/src/modules/timesheet-approval/composables/use-timesheet-approval-api.ts @@ -1,6 +1,7 @@ import { useTimesheetStore } from "src/stores/timesheet-store"; import { useAuthStore } from "src/stores/auth-store"; import type { PayPeriodReportFilters } from "../types/timesheet-approval-pay-period-report-interface"; +import type { PayPeriodOverviewEmployee } from "../types/timesheet-approval-pay-period-overview-employee-interface"; export const useTimesheetApprovalApi = () => { const timesheet_store = useTimesheetStore(); @@ -15,6 +16,10 @@ export const useTimesheetApprovalApi = () => { } } + const getPayPeriodOverviewByEmployeeEmail = (email: string): PayPeriodOverviewEmployee | undefined => { + return timesheet_store.pay_period_overview_employees.find(overview => overview.email === email); + }; + /* This method attempts to get the next or previous pay period. It checks if pay period number is within a certain range, adjusts pay period and year accordingly. It then requests the matching pay period object to set as current pay period from server. @@ -39,11 +44,11 @@ export const useTimesheetApprovalApi = () => { if (success) { await timesheet_store.getTimesheetApprovalPayPeriodEmployeeOverviews(new_pay_year, new_pay_period_no, auth_store.user.email); } - } + }; const getTimesheetsByPayPeriodAndEmail = async (employee_email: string) => { await timesheet_store.getTimesheetsByPayPeriodAndEmail(employee_email); - } + }; const getTimesheetApprovalCSVReport = async ( report_filter_company: boolean[], report_filter_type: boolean[] ) => { const [ targo, solucom ] = report_filter_company; @@ -54,11 +59,12 @@ export const useTimesheetApprovalApi = () => { } as PayPeriodReportFilters; await timesheet_store.getTimesheetApprovalCSVReport(options); - } + }; return { getPayPeriodOverviewByDate, getNextPayPeriodOverview, + getPayPeriodOverviewByEmployeeEmail, getTimesheetsByPayPeriodAndEmail, getTimesheetApprovalCSVReport } diff --git a/src/modules/timesheet-approval/services/services-timesheet-approval.ts b/src/modules/timesheet-approval/services/services-timesheet-approval.ts index 43f509d..814e7f1 100644 --- a/src/modules/timesheet-approval/services/services-timesheet-approval.ts +++ b/src/modules/timesheet-approval/services/services-timesheet-approval.ts @@ -19,13 +19,12 @@ export const timesheetApprovalService = { getPayPeriodEmployeeOverviews: async (year: number, period_number: number, supervisor_email: string): Promise => { // TODO: REMOVE MOCK DATA PEFORE PUSHING TO PROD const response = await api.get(`pay-periods/${year}/${period_number}/${supervisor_email}`); - console.log('all employee data: ', response.data); + console.log('pay period data: ', response.data); return response.data; }, getTimesheetsByPayPeriodAndEmail: async (year: number, period_no: number, email: string): Promise => { const response = await api.get('timesheets', { params: { year, period_no, email, }}); - console.log('employee details: ', response.data); return response.data; }, diff --git a/src/modules/timesheets/types/timesheet-details-interface.ts b/src/modules/timesheets/types/timesheet-details-interface.ts index b9d940d..13a2817 100644 --- a/src/modules/timesheets/types/timesheet-details-interface.ts +++ b/src/modules/timesheets/types/timesheet-details-interface.ts @@ -6,6 +6,16 @@ export interface TimesheetDetailsWeek { expenses: WeekDay; } +export interface TimesheetDetailsDailySchedule { + shifts: Shift[]; + regular_hours: number; + evening_hours: number; + emergency_hours: number; + overtime_hours: number; + short_date: string; // ex. 08/24 + break_duration?: number; +} + type WeekDay = { sun: T; mon: T; @@ -16,23 +26,14 @@ type WeekDay = { sat: T; } -interface TimesheetDetailsDailySchedule { - shifts: Shift[]; - regular_hours: number; - evening_hours: number; - emergency_hours: number; - overtime_hours: number; - short_date: string; // ex. 08/24 - break_duration?: number; -} interface TimesheetDetailsDailyExpenses { - costs: Expense[]; - mileage: Expense[]; + cash: Expense[]; + km: Expense[]; [otherType: string]: Expense[]; //for possible future types of expenses } -interface Expense { +export interface Expense { is_approved: boolean; amount: number; }; \ No newline at end of file From 5bd19c4a9c2b63ff12f7bfa2f05b3d05373346ac Mon Sep 17 00:00:00 2001 From: Nicolas Drolet Date: Thu, 4 Sep 2025 17:04:03 -0400 Subject: [PATCH 2/5] feat(deatils): add component to show row details, finalize appearance of chart layout, finetune mobile layout --- src/css/quasar.variables.scss | 4 +- src/i18n/en-ca/index.ts | 16 +- src/i18n/fr-ca/index.ts | 16 +- .../supervisor/supervisor-crew-table.vue | 36 ++-- .../navigation/header-bar-avatar.vue | 2 +- ...al-employee-details-hours-worked-chart.vue | 2 +- ...val-employee-details-shift-types-chart.vue | 2 +- ...sheet-approval-employee-expenses-chart.vue | 23 +-- ...t-approval-employee-details-shifts-row.vue | 28 +++ ...sheet-approval-employee-details-shifts.vue | 67 ++++++- .../timesheet-approval-employee-details.vue | 125 ------------- ...t-approval-employee-overview-list-item.vue | 2 +- ...esheet-approval-employee-overview-list.vue | 9 +- .../timesheet-approval-period-picker.vue | 2 +- .../composables/use-timesheet-approval-api.ts | 8 +- .../timesheet-approval-employee-details.vue | 166 ++++++++++++++++++ .../pages/timesheet-approval.vue | 17 +- .../services/services-timesheet-approval.ts | 1 + ...l-pay-period-employee-details-interface.ts | 9 +- ...-pay-period-overview-employee-interface.ts | 14 +- .../types/timesheet-details-interface.ts | 41 ++++- .../types/timesheet-shift-interface.ts | 8 +- src/stores/timesheet-store.ts | 4 +- 23 files changed, 398 insertions(+), 204 deletions(-) create mode 100644 src/modules/timesheet-approval/components/timesheet-approval-employee-details-shifts-row.vue delete mode 100644 src/modules/timesheet-approval/components/timesheet-approval-employee-details.vue create mode 100644 src/modules/timesheet-approval/pages/timesheet-approval-employee-details.vue diff --git a/src/css/quasar.variables.scss b/src/css/quasar.variables.scss index f919a2b..1725989 100644 --- a/src/css/quasar.variables.scss +++ b/src/css/quasar.variables.scss @@ -24,7 +24,7 @@ $dark: #000; $dark-page: #323232; $positive: #21ba45; -$negative: #ff576ba9; -$info: #54bbdd; +$negative: #e6364b; +$info: #6bb9e7; $warning: #eec964; $white: white; diff --git a/src/i18n/en-ca/index.ts b/src/i18n/en-ca/index.ts index c7ac6d0..beebf76 100644 --- a/src/i18n/en-ca/index.ts +++ b/src/i18n/en-ca/index.ts @@ -260,13 +260,13 @@ export default { shiftComment: 'Comment', overTimeTitle: 'Overtime regular hours: ', totalPayedHours: 'Total hours worked: ', - //shiftOptions - regularShift: 'Regular', - eveningShift: 'Evening', - emergencyShift: 'Emergency', - sickDay: 'Sick working day', - vacancyDay: 'vacation', - holiday: 'Holiday', + // shift options + shiftRegular: 'regular', + shiftEvening: 'evening', + shiftEmergency: 'emergency', + shiftSick: 'sick', + shiftVacation: 'vacation', + shiftHoliday: 'holiday', dateRangesFrom: 'from', dateRangesTo: 'to', shiftBankedHours: 'Total hours to bank', @@ -369,7 +369,7 @@ export default { message_start: 'Attention: You will be automatically logged out in', message_end: 'seconds if you do not interact with the screen.', }, - daysOfWeek: { + weekdays: { Sunday: ' Sunday', Monday: 'Monday', Tuesday: 'Tuesday', diff --git a/src/i18n/fr-ca/index.ts b/src/i18n/fr-ca/index.ts index 2008d4a..8e4aeba 100644 --- a/src/i18n/fr-ca/index.ts +++ b/src/i18n/fr-ca/index.ts @@ -55,7 +55,7 @@ export default { message_start: 'Attention : vous serez automatiquement déconnecté dans', message_end: 'secondes si vous n’interagissez pas avec l’écran.', }, - daysOfWeek: { + weekdays: { Sunday: 'dimanche', Monday: 'lundi', Tuesday: 'mardi', @@ -310,13 +310,13 @@ export default { shiftComment: 'Commentaire', overTimeTitle: 'Heures régulières supplémentaires: ', totalPayedHours: 'Total des heures travaillées: ', - //shiftOptions - regularShift: 'Régulier', - eveningShift: 'Soir', - emergencyShift: 'Urgence', - sickDay: 'Maladie', - vacancyDay: 'Vacances', - holiday: 'Férié', + // shift options + shiftRegular: 'régulier', + shiftEvening: 'soir', + shiftEmergency: 'urgence', + shiftSick: 'maladie', + shiftVacation: 'vacances', + shiftHoliday: 'férié', dateRangesFrom: 'du', dateRangesTo: 'au', shiftBankedHours: 'Totale d’heures à banquer', diff --git a/src/modules/employee-list/components/supervisor/supervisor-crew-table.vue b/src/modules/employee-list/components/supervisor/supervisor-crew-table.vue index df4b982..8b40260 100644 --- a/src/modules/employee-list/components/supervisor/supervisor-crew-table.vue +++ b/src/modules/employee-list/components/supervisor/supervisor-crew-table.vue @@ -68,24 +68,26 @@ diff --git a/src/modules/shared/components/navigation/header-bar-avatar.vue b/src/modules/shared/components/navigation/header-bar-avatar.vue index 420a6cb..89e7edf 100644 --- a/src/modules/shared/components/navigation/header-bar-avatar.vue +++ b/src/modules/shared/components/navigation/header-bar-avatar.vue @@ -14,7 +14,7 @@ - {{ notifAmount }} + {{ notifAmount }} diff --git a/src/modules/timesheet-approval/components/graphs/timesheet-approval-employee-details-hours-worked-chart.vue b/src/modules/timesheet-approval/components/graphs/timesheet-approval-employee-details-hours-worked-chart.vue index 0b57ee6..424e65c 100644 --- a/src/modules/timesheet-approval/components/graphs/timesheet-approval-employee-details-hours-worked-chart.vue +++ b/src/modules/timesheet-approval/components/graphs/timesheet-approval-employee-details-hours-worked-chart.vue @@ -47,7 +47,7 @@ { label: t('timeSheetValidations.hoursWorkedEmergency'), data: emergency_hours, - backgroundColor: getComputedStyle(document.body).getPropertyValue('--q-warning').trim(), + backgroundColor: getComputedStyle(document.body).getPropertyValue('--q-accent').trim(), }, { label: t('timeSheetValidations.hoursWorkedOvertime'), diff --git a/src/modules/timesheet-approval/components/graphs/timesheet-approval-employee-details-shift-types-chart.vue b/src/modules/timesheet-approval/components/graphs/timesheet-approval-employee-details-shift-types-chart.vue index a736325..f5b4c1a 100644 --- a/src/modules/timesheet-approval/components/graphs/timesheet-approval-employee-details-shift-types-chart.vue +++ b/src/modules/timesheet-approval/components/graphs/timesheet-approval-employee-details-shift-types-chart.vue @@ -35,7 +35,7 @@ backgroundColor: [ getComputedStyle(document.body).getPropertyValue('--q-primary').trim(), getComputedStyle(document.body).getPropertyValue('--q-info').trim(), - getComputedStyle(document.body).getPropertyValue('--q-warning').trim(), + getComputedStyle(document.body).getPropertyValue('--q-accent').trim(), getComputedStyle(document.body).getPropertyValue('--q-negative').trim(), ] }]; diff --git a/src/modules/timesheet-approval/components/graphs/timesheet-approval-employee-expenses-chart.vue b/src/modules/timesheet-approval/components/graphs/timesheet-approval-employee-expenses-chart.vue index 1817716..7bd78b5 100644 --- a/src/modules/timesheet-approval/components/graphs/timesheet-approval-employee-expenses-chart.vue +++ b/src/modules/timesheet-approval/components/graphs/timesheet-approval-employee-expenses-chart.vue @@ -1,35 +1,34 @@