Merge pull request 'feat(timesheet): add backend and frontend logic to display paid time off' (#76) from release/nicolas/v1.1 into main

Reviewed-on: Targo/targo_frontend#76
This commit is contained in:
Nicolas 2026-02-05 08:05:28 -05:00
commit 6ba03b76ad
3 changed files with 41 additions and 6 deletions

View File

@ -2,21 +2,29 @@
setup setup
lang="ts" lang="ts"
> >
import { computed, onMounted } from 'vue';
import { useAuthStore } from 'src/stores/auth-store'; import { useAuthStore } from 'src/stores/auth-store';
import { useTimesheetStore } from 'src/stores/timesheet-store';
import { getHoursMinutesStringFromHoursFloat } from 'src/utils/date-and-time-utils'; import { getHoursMinutesStringFromHoursFloat } from 'src/utils/date-and-time-utils';
const { mode = 'totals', timesheetMode = 'normal', totalHours = 0, vacationHours = 0, sickHours = 0, bankedHours = 0, totalExpenses = 0 } = defineProps<{ const { mode = 'totals', timesheetMode = 'normal', totalHours = 0, totalExpenses = 0 } = defineProps<{
mode: 'total-hours' | 'off-hours'; mode: 'total-hours' | 'off-hours';
timesheetMode: 'approval' | 'normal'; timesheetMode: 'approval' | 'normal';
totalHours?: number; totalHours?: number;
vacationHours?: number;
sickHours?: number;
bankedHours?: number;
totalExpenses?: number; totalExpenses?: number;
}>(); }>();
const auth_store = useAuthStore(); const auth_store = useAuthStore();
const timesheetStore = useTimesheetStore();
const is_management = auth_store.user?.user_module_access.includes('timesheets_approval'); const is_management = auth_store.user?.user_module_access.includes('timesheets_approval');
const vacationHours = computed(() => timesheetStore.paid_time_off_totals.vacation_hours);
const sickHours = computed(() => timesheetStore.paid_time_off_totals.sick_hours);
const bankedHours = computed(() => timesheetStore.paid_time_off_totals.banked_hours);
onMounted(async () => {
await timesheetStore.getPaidTimeOffTotalsWithOptionalEmployeeEmail();
})
</script> </script>
<template> <template>

View File

@ -4,6 +4,7 @@ import type { TimesheetResponse } from "src/modules/timesheets/models/timesheet.
import type { TimesheetApprovalOverview } from "src/modules/timesheet-approval/models/timesheet-overview.models"; import type { TimesheetApprovalOverview } from "src/modules/timesheet-approval/models/timesheet-overview.models";
import type { BackendResponse } from "src/modules/shared/models/backend-response.models"; import type { BackendResponse } from "src/modules/shared/models/backend-response.models";
import type { FederalHoliday } from "src/modules/timesheets/models/federal-holidays.models"; import type { FederalHoliday } from "src/modules/timesheets/models/federal-holidays.models";
import type { PaidTimeOff } from "src/modules/employee-list/models/employee-profile.models";
export const timesheetService = { export const timesheetService = {
getAllFederalHolidays: async (year?: number): Promise<FederalHoliday[]> => { getAllFederalHolidays: async (year?: number): Promise<FederalHoliday[]> => {
@ -36,6 +37,16 @@ export const timesheetService = {
} }
}, },
getPaidTimeOffTotalsWithOptionalEmployeeEmail: async (email?: string): Promise<BackendResponse<PaidTimeOff>> => {
if (email) {
const response = await api.get<BackendResponse<PaidTimeOff>>(`paid-time-off/totals?email=${email}`);
return response.data;
}
const response = await api.get<BackendResponse<PaidTimeOff>>('paid-time-off/totals');
return response.data;
},
applyPresetToWeek: async (timesheet_id: number, employeeEmail?: string): Promise<BackendResponse<boolean>> => { applyPresetToWeek: async (timesheet_id: number, employeeEmail?: string): Promise<BackendResponse<boolean>> => {
if (employeeEmail) { if (employeeEmail) {
const response = await api.post<BackendResponse<boolean>>(`schedule-presets/apply-preset/${employeeEmail}`, { timesheet_id }); const response = await api.post<BackendResponse<boolean>>(`schedule-presets/apply-preset/${employeeEmail}`, { timesheet_id });

View File

@ -1,3 +1,5 @@
import { Notify } from 'quasar';
import { useI18n } from 'vue-i18n';
import { computed, ref } from 'vue'; import { computed, ref } from 'vue';
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import { unwrapAndClone } from 'src/utils/unwrap-and-clone'; import { unwrapAndClone } from 'src/utils/unwrap-and-clone';
@ -6,11 +8,10 @@ import { timesheetService } from 'src/modules/timesheets/services/timesheet-serv
import type { PayPeriodOverviewResponse, TimesheetApprovalOverview } from "src/modules/timesheet-approval/models/timesheet-overview.models"; import type { PayPeriodOverviewResponse, TimesheetApprovalOverview } from "src/modules/timesheet-approval/models/timesheet-overview.models";
import type { PayPeriod } from 'src/modules/shared/models/pay-period.models'; import type { PayPeriod } from 'src/modules/shared/models/pay-period.models';
import type { Timesheet } from 'src/modules/timesheets/models/timesheet.models'; import type { Timesheet } from 'src/modules/timesheets/models/timesheet.models';
import type { PaidTimeOff } from 'src/modules/employee-list/models/employee-profile.models';
import type { PayPeriodEvent } from 'src/modules/timesheet-approval/models/pay-period-event.models'; import type { PayPeriodEvent } from 'src/modules/timesheet-approval/models/pay-period-event.models';
import type { TimesheetApprovalCSVReportFilters } from 'src/modules/timesheet-approval/models/timesheet-approval-csv-report.models'; import type { TimesheetApprovalCSVReportFilters } from 'src/modules/timesheet-approval/models/timesheet-approval-csv-report.models';
import { type FederalHoliday, TARGO_HOLIDAY_NAMES_FR } from 'src/modules/timesheets/models/federal-holidays.models'; import { type FederalHoliday, TARGO_HOLIDAY_NAMES_FR } from 'src/modules/timesheets/models/federal-holidays.models';
import { Notify } from 'quasar';
import { useI18n } from 'vue-i18n';
export const useTimesheetStore = defineStore('timesheet', () => { export const useTimesheetStore = defineStore('timesheet', () => {
@ -20,6 +21,7 @@ export const useTimesheetStore = defineStore('timesheet', () => {
const timesheets = ref<Timesheet[]>([]); const timesheets = ref<Timesheet[]>([]);
const all_current_shifts = computed(() => timesheets.value.flatMap(week => week.days.flatMap(day => day.shifts)) ?? []); const all_current_shifts = computed(() => timesheets.value.flatMap(week => week.days.flatMap(day => day.shifts)) ?? []);
const initial_timesheets = ref<Timesheet[]>([]); const initial_timesheets = ref<Timesheet[]>([]);
const paid_time_off_totals = ref<PaidTimeOff>({ sick_hours: 0, vacation_hours: 0, banked_hours: 0 });
const pay_period_overviews = ref<TimesheetApprovalOverview[]>([]); const pay_period_overviews = ref<TimesheetApprovalOverview[]>([]);
const pay_period_infos = ref<PayPeriodOverviewResponse>(); const pay_period_infos = ref<PayPeriodOverviewResponse>();
@ -135,6 +137,18 @@ export const useTimesheetStore = defineStore('timesheet', () => {
} }
}; };
const getPaidTimeOffTotalsWithOptionalEmployeeEmail = async (email?: string) => {
try {
const response = await timesheetService.getPaidTimeOffTotalsWithOptionalEmployeeEmail(email);
if (response.success && response.data)
paid_time_off_totals.value = response.data;
} catch (error) {
console.error('error getting paid time off totals: ', error);
}
};
const toggleTimesheetsApprovalByEmployeeEmail = async (email: string, approval_status: boolean): Promise<boolean> => { const toggleTimesheetsApprovalByEmployeeEmail = async (email: string, approval_status: boolean): Promise<boolean> => {
try { try {
const timesheet_ids = timesheets.value.map(timesheet => timesheet.timesheet_id); const timesheet_ids = timesheets.value.map(timesheet => timesheet.timesheet_id);
@ -230,6 +244,7 @@ export const useTimesheetStore = defineStore('timesheet', () => {
all_current_shifts, all_current_shifts,
initial_timesheets, initial_timesheets,
federal_holidays, federal_holidays,
paid_time_off_totals,
getCurrentFederalHolidays, getCurrentFederalHolidays,
getNextOrPreviousPayPeriod, getNextOrPreviousPayPeriod,
getPayPeriodByDateOrYearAndNumber, getPayPeriodByDateOrYearAndNumber,
@ -241,5 +256,6 @@ export const useTimesheetStore = defineStore('timesheet', () => {
closeReportDialog, closeReportDialog,
subscribeToPayPeriodObservable, subscribeToPayPeriodObservable,
unsubscribeToPayPeriodObservable, unsubscribeToPayPeriodObservable,
getPaidTimeOffTotalsWithOptionalEmployeeEmail,
}; };
}); });