refactor(approvals): move functionalities for separation of concern, page formatting, i18n refactoring, consideration for mobile appearance.

This commit is contained in:
Nicolas Drolet 2025-08-21 17:06:57 -04:00
parent 27e73f8f51
commit d0e64bdffc
13 changed files with 153 additions and 72 deletions

View File

@ -4,26 +4,19 @@ import { createI18n } from 'vue-i18n';
import messages from 'src/i18n'; import messages from 'src/i18n';
export type MessageLanguages = keyof typeof messages; export type MessageLanguages = keyof typeof messages;
// Type-define 'en-US' as the master schema for the resource export type MessageSchema = typeof messages['en-CA'];
export type MessageSchema = typeof messages['en'];
// See https://vue-i18n.intlify.dev/guide/advanced/typescript.html#global-resource-schema-type-definition
/* eslint-disable @typescript-eslint/no-empty-object-type */ /* eslint-disable @typescript-eslint/no-empty-object-type */
declare module 'vue-i18n' { declare module 'vue-i18n' {
// define the locale messages schema
export interface DefineLocaleMessage extends MessageSchema {} export interface DefineLocaleMessage extends MessageSchema {}
// define the datetime format schema
export interface DefineDateTimeFormat {} export interface DefineDateTimeFormat {}
// define the number format schema
export interface DefineNumberFormat {} export interface DefineNumberFormat {}
} }
/* eslint-enable @typescript-eslint/no-empty-object-type */
/* eslint-enable @typescript-eslint/no-empty-object-type */
export default defineBoot(({ app }) => { export default defineBoot(({ app }) => {
const i18n = createI18n<{ message: MessageSchema }, MessageLanguages>({ const i18n = createI18n<{ message: MessageSchema }, MessageLanguages>({
locale: 'fr', locale: 'fr-FR',
legacy: false, legacy: false,
messages, messages,
}); });

View File

@ -24,7 +24,7 @@ export default {
}, },
navBar: { navBar: {
userMenuHome: 'Homepage', userMenuHome: 'Homepage',
userMenuEmployeeList: 'Employee list', userMenuEmployeeList: 'Employee Directory',
userMenuShiftValidation: 'Timesheet Approval', userMenuShiftValidation: 'Timesheet Approval',
userMenuProfile: 'Profile', userMenuProfile: 'Profile',
userMenuHelp: 'Help', userMenuHelp: 'Help',
@ -140,7 +140,7 @@ export default {
card_4: 'Customers', card_4: 'Customers',
}, },
usersListPage: { usersListPage: {
tableHeader: 'Employee list', tableHeader: 'Employee Directory',
searchInput: 'Search', searchInput: 'Search',
userListFirstName: 'First name', userListFirstName: 'First name',
userListLastName: 'Last name', userListLastName: 'Last name',
@ -162,6 +162,7 @@ export default {
loading: 'Obtaining data...', loading: 'Obtaining data...',
failedToLoad: 'No data to show', failedToLoad: 'No data to show',
failedToSearch: 'No data matching search', failedToSearch: 'No data matching search',
languageLabel: 'Language',
}, },
editUserPage: { editUserPage: {
title: 'Edit Account', title: 'Edit Account',
@ -240,11 +241,12 @@ export default {
passwordValidation: 'Password must meet all criteria.', passwordValidation: 'Password must meet all criteria.',
confirmPasswordValidation: 'Password must match new Password.', confirmPasswordValidation: 'Password must match new Password.',
}, },
pagesTitles: { pageTitles: {
newUserPageTitle: 'New user', employeeDirectory: 'Employee Directory',
updateUserPageTitle: 'Update user', newUsers: 'New user',
timeSheetPageTitle: 'Time sheet', updateUsers: 'Update user',
timeSheetValidationsIdPageTitle: 'Time sheet', timeSheets: 'Time sheet',
timeSheetValidations: 'Time sheet',
}, },
timeSheet: { timeSheet: {
timeSheetTab_1: 'Shifts', timeSheetTab_1: 'Shifts',
@ -265,7 +267,7 @@ export default {
sickDay: 'Sick working day', sickDay: 'Sick working day',
vacancyDay: 'vacation', vacancyDay: 'vacation',
holiday: 'Holiday', holiday: 'Holiday',
dateRangesWeek: 'Week from', dateRangesFrom: 'from',
dateRangesTo: 'to', dateRangesTo: 'to',
shiftBankedHours: 'Total hours to bank', shiftBankedHours: 'Total hours to bank',
bankedHoursHint_1: ' on', bankedHoursHint_1: ' on',
@ -294,7 +296,6 @@ export default {
mileage: 'Mileage', mileage: 'Mileage',
}, },
timeSheetValidations: { timeSheetValidations: {
tableHeader: 'List of employees',
tableColumnLabelFullname: 'Full name', tableColumnLabelFullname: 'Full name',
tableColumnLabelRegularHours: 'regular hours', tableColumnLabelRegularHours: 'regular hours',
tableColumnLabelEveningHours: 'evening', tableColumnLabelEveningHours: 'evening',

View File

@ -163,7 +163,7 @@ export default {
}, },
navBar: { navBar: {
userMenuHome: 'Accueil', userMenuHome: 'Accueil',
userMenuEmployeeList: 'Liste employés', userMenuEmployeeList: 'Répertoire employés',
userMenuShiftValidation: 'Valider les heures', userMenuShiftValidation: 'Valider les heures',
userMenuProfile: 'Profil', userMenuProfile: 'Profil',
userMenuHelp: 'Aide', userMenuHelp: 'Aide',
@ -181,11 +181,12 @@ export default {
deleteAll: 'Supprimer tout', deleteAll: 'Supprimer tout',
close: 'Fermer', close: 'Fermer',
}, },
pagesTitles: { pageTitles: {
newUserPageTitle: 'Nouvel utilisateur', employeeDirectory: 'Répertoire des Employés',
updateUserPageTitle: 'Mettre à jour lutilisateur', newUsers: 'Nouvel utilisateur',
timeSheetPageTitle: 'Carte de temps', updateUsers: 'Mettre à jour lutilisateur',
timeSheetValidationsIdPageTitle: 'Carte de temps', timeSheets: 'Carte de temps',
timeSheetValidations: 'Validation cartes de temps',
}, },
profilePage: { profilePage: {
title: 'Profil', title: 'Profil',
@ -231,6 +232,7 @@ export default {
loading: 'Téléchargement des données en cours...', loading: 'Téléchargement des données en cours...',
failedToLoad: 'Aucune donnée à afficher', failedToLoad: 'Aucune donnée à afficher',
failedToSearch: 'Aucun résultat de recherche obtenu', failedToSearch: 'Aucun résultat de recherche obtenu',
languageLabel: 'Langue',
}, },
shiftColumns: { shiftColumns: {
title: 'Quarts de travail', title: 'Quarts de travail',
@ -315,7 +317,7 @@ export default {
sickDay: 'Maladie', sickDay: 'Maladie',
vacancyDay: 'Vacances', vacancyDay: 'Vacances',
holiday: 'Férié', holiday: 'Férié',
dateRangesWeek: 'Semaine du', dateRangesFrom: 'du',
dateRangesTo: 'au', dateRangesTo: 'au',
shiftBankedHours: 'Totale dheures à banquer', shiftBankedHours: 'Totale dheures à banquer',
bankedHoursHint_1: ' sur', bankedHoursHint_1: ' sur',
@ -344,7 +346,6 @@ export default {
mileage: 'Kilometrage', mileage: 'Kilometrage',
}, },
timeSheetValidations: { timeSheetValidations: {
tableHeader: 'Liste des employés',
tableColumnLabelFullname: 'nom complet', tableColumnLabelFullname: 'nom complet',
tableColumnLabelRegularHours: 'heures régulières', tableColumnLabelRegularHours: 'heures régulières',
tableColumnLabelEveningHours: 'soir', tableColumnLabelEveningHours: 'soir',
@ -378,7 +379,7 @@ export default {
unlockToolTip: 'Déverrouiller la semaine', unlockToolTip: 'Déverrouiller la semaine',
}, },
usersListPage: { usersListPage: {
tableHeader: 'Liste demployées', tableHeader: 'Répertoire du personnel',
searchInput: 'rechercher', searchInput: 'rechercher',
userListFirstName: 'prénom', userListFirstName: 'prénom',
userListLastName: 'nom de famille', userListLastName: 'nom de famille',

View File

@ -2,6 +2,6 @@ import enCA from './en-ca';
import frCA from './fr-ca'; import frCA from './fr-ca';
export default { export default {
'en': enCA, 'en-CA': enCA,
'fr': frCA, 'fr-FR': frCA,
}; };

View File

@ -6,8 +6,8 @@
<template> <template>
<q-page> <q-page>
<EmployeeListAddModifyDialog /> <EmployeeListAddModifyDialog />
<div class="text-h4 row justify-center q-py-sm q-mt-lg text-uppercase text-weight-bolder text-primary"> <div class="text-h4 row justify-center q-py-sm q-mt-lg text-uppercase text-weight-bolder text-grey-8">
{{ $t('usersListPage.tableHeader') }} {{ $t('pageTitles.employeeDirectory') }}
</div> </div>
<SupervisorCrewTable /> <SupervisorCrewTable />
</q-page> </q-page>

View File

@ -2,19 +2,33 @@
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
const { locale } = useI18n(); const { locale } = useI18n();
const setLocale = (newLocale: string) => { locale.value = newLocale; };
const localeOptions = [ const localeOptions = [
{ value: 'en', label: 'English' }, { value: 'en-CA', label: 'English' },
{ value: 'fr', label: 'Francais' }, { value: 'fr-FR', label: 'Francais' },
]; ];
</script> </script>
<template> <template>
<q-btn-dropdown flat :label=locale class="rounded-borders" icon="language"> <q-btn-dropdown flat :label="$t('shared.languageLabel')" class="rounded-borders" icon="language">
<q-list> <q-list>
<q-item clickable v-close-popup v-for="option in localeOptions" :key="option.value" @click="setLocale(option.value)"> <q-item clickable v-close-popup v-for="option in localeOptions" :key="option.value" @click="locale = option.value">
<q-item-section>{{ option.label }}</q-item-section> <q-item-section>{{ option.label }}</q-item-section>
</q-item> </q-item>
</q-list> </q-list>
</q-btn-dropdown> </q-btn-dropdown>
<!-- <q-select
v-model="locale"
:options="localeOptions"
dense
borderless
emit-value
map-options
hide-dropdown-icon
class="text-white"
>
<template v-slot:prepend>
<q-icon name="language" color="white"/>
</template>
</q-select> -->
</template> </template>

View File

@ -1,10 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
import { useAuthStore } from 'src/stores/auth-store'; import { useAuthStore } from 'src/stores/auth-store';
import { useUiStore } from 'src/stores/ui-store'; import { ref } from 'vue';
import { ref } from 'vue';
const authStore = useAuthStore(); const authStore = useAuthStore();
const uiStore = useUiStore();
const currentUser = authStore.user; const currentUser = authStore.user;
// Will need to implement this eventually, just testing the look for now // Will need to implement this eventually, just testing the look for now
@ -12,15 +10,15 @@ import { ref } from 'vue';
</script> </script>
<template> <template>
<q-item clickable v-ripple dark @click="uiStore.toggleRightDrawer"> <q-item clickable v-ripple dark class="q-pa-none">
<q-item-section side> <q-item-section :side="$q.screen.gt.sm">
<q-avatar rounded > <q-avatar rounded >
<q-img src="src/assets/targo-default-avatar.png" /> <q-img src="src/assets/targo-default-avatar.png" />
<q-badge floating color="red" v-if="notifAmount > 0" >{{ notifAmount }}</q-badge> <q-badge floating color="red" v-if="notifAmount > 0" >{{ notifAmount }}</q-badge>
</q-avatar> </q-avatar>
</q-item-section> </q-item-section>
<q-item-section> <q-item-section v-if="$q.screen.gt.sm">
<q-item-label>{{ currentUser.firstName }} {{ currentUser.lastName }}</q-item-label> <q-item-label>{{ currentUser.firstName }} {{ currentUser.lastName }}</q-item-label>
<q-item-label caption>{{ notifAmount }} new messages</q-item-label> <q-item-label caption>{{ notifAmount }} new messages</q-item-label>
</q-item-section> </q-item-section>

View File

@ -36,7 +36,7 @@
<q-icon name="home" color="primary" /> <q-icon name="home" color="primary" />
</q-item-section> </q-item-section>
<q-item-section> <q-item-section>
<q-item-label>{{ $t('navBar.userMenuHome') }}</q-item-label> <q-item-label class="text-uppercase text-grey-8 text-weight-bold">{{ $t('navBar.userMenuHome') }}</q-item-label>
</q-item-section> </q-item-section>
</q-item> </q-item>
@ -47,7 +47,7 @@
<q-icon name="event_available" color="primary" /> <q-icon name="event_available" color="primary" />
</q-item-section> </q-item-section>
<q-item-section> <q-item-section>
<q-item-label>{{ $t('navBar.userMenuShiftValidation') }}</q-item-label> <q-item-label class="text-uppercase text-grey-8 text-weight-bold">{{ $t('navBar.userMenuShiftValidation') }}</q-item-label>
</q-item-section> </q-item-section>
</q-item> </q-item>
@ -58,7 +58,7 @@
<q-icon name="view_list" color="primary" /> <q-icon name="view_list" color="primary" />
</q-item-section> </q-item-section>
<q-item-section> <q-item-section>
<q-item-label>{{ $t('navBar.userMenuEmployeeList') }}</q-item-label> <q-item-label class="text-uppercase text-grey-8 text-weight-bold">{{ $t('navBar.userMenuEmployeeList') }}</q-item-label>
</q-item-section> </q-item-section>
</q-item> </q-item>
@ -68,7 +68,7 @@
<q-icon name="account_box" color="primary" /> <q-icon name="account_box" color="primary" />
</q-item-section> </q-item-section>
<q-item-section> <q-item-section>
<q-item-label>{{ $t('navBar.userMenuProfile') }}</q-item-label> <q-item-label class="text-uppercase text-grey-8 text-weight-bold">{{ $t('navBar.userMenuProfile') }}</q-item-label>
</q-item-section> </q-item-section>
</q-item> </q-item>
@ -78,7 +78,7 @@
<q-icon name="contact_support" color="primary" /> <q-icon name="contact_support" color="primary" />
</q-item-section> </q-item-section>
<q-item-section> <q-item-section>
<q-item-label>{{ $t('navBar.userMenuHelp') }}</q-item-label> <q-item-label class="text-uppercase text-grey-8 text-weight-bold">{{ $t('navBar.userMenuHelp') }}</q-item-label>
</q-item-section> </q-item-section>
</q-item> </q-item>
</q-list> </q-list>
@ -89,7 +89,7 @@
<q-icon name="exit_to_app" color="primary" /> <q-icon name="exit_to_app" color="primary" />
</q-item-section> </q-item-section>
<q-item-section> <q-item-section>
<q-item-label>{{ $t('navBar.userMenuLogout') }}</q-item-label> <q-item-label class="text-uppercase text-grey-8 text-weight-bold">{{ $t('navBar.userMenuLogout') }}</q-item-label>
</q-item-section> </q-item-section>
</q-item> </q-item>
</q-scroll-area> </q-scroll-area>

View File

@ -9,6 +9,7 @@
import { getCurrentPayPeriod } from 'src/utils/pay-period-calculator'; import { getCurrentPayPeriod } from 'src/utils/pay-period-calculator';
import { useAuthStore } from 'src/stores/auth-store'; import { useAuthStore } from 'src/stores/auth-store';
import { useTimesheetStore } from 'src/stores/timesheet-store'; import { useTimesheetStore } from 'src/stores/timesheet-store';
import TimesheetApprovalPeriodPicker from '../components/timesheet-approval-period-picker.vue';
const { t } = useI18n(); const { t } = useI18n();
@ -39,8 +40,7 @@
const filter = ref(''); const filter = ref('');
onMounted( async () => { onMounted( async () => {
await timesheetApprovalApi.getPayPeriodByDate(new Date()); await timesheetApprovalApi.getPayPeriodOverviewByDate(new Date());
await timesheetApprovalApi.getTimesheetApprovalPayPeriodEmployeeOverviews(currentYear, currentPayPeriod, authStore.user.email);
originalApprovals.value = Object.fromEntries( timesheetStore.payPeriodEmployeeOverviews.map(emp => [emp.email, emp.is_approved])); originalApprovals.value = Object.fromEntries( timesheetStore.payPeriodEmployeeOverviews.map(emp => [emp.email, emp.is_approved]));
}) })
</script> </script>
@ -66,7 +66,10 @@
> >
<!-- Top Bar that contains Search, Title, Filters --> <!-- Top Bar that contains Search, Title, Filters -->
<template v-slot:top> <template v-slot:top>
<div class="full-width row"> <div :class="$q.screen.lt.md ? 'column justify-center items-center' : 'full-width row'">
<!-- Date Picker -->
<TimesheetApprovalPeriodPicker />
<q-space /> <q-space />
<!-- Filters toggle --> <!-- Filters toggle -->

View File

@ -1,18 +1,55 @@
<script setup lang="ts"> <script setup lang="ts">
/* eslint-disable */
import { ref, computed } from 'vue';
import { useTimesheetApprovalApi } from '../composables/use-timesheet-approval-api'; import { useTimesheetApprovalApi } from '../composables/use-timesheet-approval-api';
import { useTimesheetStore } from 'src/stores/timesheet-store'; import { useTimesheetStore } from 'src/stores/timesheet-store';
import { date } from 'quasar';
const timesheet_approval_api = useTimesheetApprovalApi(); const timesheet_approval_api = useTimesheetApprovalApi();
const timesheet_store = useTimesheetStore(); const timesheet_store = useTimesheetStore();
const is_showing_calendar_picker = ref(false);
const calendar_date = ref(date.formatDate( Date.now(), 'YYYY/MM/DD' ));
const is_calendar_limit = computed( () => {
return timesheet_store.currentPayPeriod.pay_year === 2024 && timesheet_store.currentPayPeriod.pay_period_no <= 1;
});
</script> </script>
<template> <template>
<div class="column items-center"> <div class="row">
<div class="text-primary text-h5">{{ timesheet_store.currentPayPeriod?.label || '' }}</div> <q-btn
<q-btn-group push rounded> push rounded
<q-btn push icon="keyboard_arrow_left" color="primary" class="q-px-xl" @click="timesheet_approval_api.getNextPayPeriodOverview(-1)"/> icon="keyboard_arrow_left"
<q-btn push icon="date_range" color="primary" class="q-px-xl" /> color="primary"
<q-btn push icon="keyboard_arrow_right" color="primary" class="q-px-xl" @click="timesheet_approval_api.getNextPayPeriodOverview(1)"/> @click="timesheet_approval_api.getNextPayPeriodOverview(-1)"
</q-btn-group> :disable="is_calendar_limit || timesheet_store.isLoading"
class="q-mr-sm q-px-sm"
/>
<q-btn
push rounded
icon="date_range"
color="primary"
@click="is_showing_calendar_picker = true"
:disable="timesheet_store.isLoading"
class="q-px-lg"
/>
<q-btn
push rounded
icon="keyboard_arrow_right"
color="primary"
@click="timesheet_approval_api.getNextPayPeriodOverview(1)"
:disable="timesheet_store.isLoading"
class="q-ml-sm q-px-sm"
/>
</div> </div>
<q-dialog v-model="is_showing_calendar_picker" transition-show="slide-down" transition-hide="slide-up" position="top">
<q-date
v-model="calendar_date"
color="primary"
class="q-mt-xl"
today-btn
:options="date => date > '2023/12/16'"
/>
</q-dialog>
</template> </template>

View File

@ -5,8 +5,13 @@ export const useTimesheetApprovalApi = () => {
const timesheet_store = useTimesheetStore(); const timesheet_store = useTimesheetStore();
const auth_store = useAuthStore(); const auth_store = useAuthStore();
const getPayPeriodByDate = async (date: Date) => { const getPayPeriodOverviewByDate = async (date: Date) => {
await timesheet_store.getPayPeriodByDate(date); const success = await timesheet_store.getPayPeriodByDate(date);
if (success) {
const current_pay_period = timesheet_store.currentPayPeriod;
await timesheet_store.getTimesheetApprovalPayPeriodEmployeeOverviews(current_pay_period.pay_year, current_pay_period.pay_period_no, auth_store.user.email);
}
} }
/* This method attempts to get the next or previous pay period. /* This method attempts to get the next or previous pay period.
@ -35,13 +40,8 @@ export const useTimesheetApprovalApi = () => {
} }
} }
const getTimesheetApprovalPayPeriodEmployeeOverviews = async (year: number, period_number: number, supervisor_email: string): Promise<void> => {
await timesheet_store.getTimesheetApprovalPayPeriodEmployeeOverviews(year, period_number, supervisor_email);
}
return { return {
getPayPeriodByDate, getPayPeriodOverviewByDate,
getNextPayPeriodOverview, getNextPayPeriodOverview,
getTimesheetApprovalPayPeriodEmployeeOverviews,
} }
}; };

View File

@ -1,12 +1,39 @@
<script setup lang="ts"> <script setup lang="ts">
// const testDates: string[] = ['25 Juin 2025', '12 Juillet 2025', '13 Juillet 2025', '26 Juillet 2025', '27 Juillet 2025', '9 Aout 2025']
import TimesheetApprovalPeriodPicker from '../components/timesheet-approval-period-picker.vue';
import TimesheetApprovalEmployeeOverviewList from '../components/timesheet-approval-employee-overview-list.vue'; import TimesheetApprovalEmployeeOverviewList from '../components/timesheet-approval-employee-overview-list.vue';
import { computed } from 'vue';
import { useI18n } from 'vue-i18n';
import { useTimesheetStore } from 'src/stores/timesheet-store';
import { date } from 'quasar';
const { locale } = useI18n();
const timesheet_store = useTimesheetStore();
const date_options: Intl.DateTimeFormatOptions = {
day: 'numeric',
month: "long",
year: 'numeric',
};
const pay_period_label = computed(() => {
const dates = timesheet_store.currentPayPeriod.label.split('.');
const start_date = new Intl.DateTimeFormat(locale.value, date_options).format(date.extractDate(dates[0] as string, 'YYYY-MM-DD'));
const end_date = new Intl.DateTimeFormat(locale.value, date_options).format(date.extractDate(dates[1] as string, 'YYYY-MM-DD'));
return {
start_date: start_date,
end_date: end_date,
};
});
</script> </script>
<template> <template>
<q-page padding class="q-pa-md bg-secondary"> <q-page padding class="q-pa-md bg-secondary">
<TimesheetApprovalPeriodPicker /> <div class="text-h4 row justify-center q-mt-lg text-uppercase text-weight-bolder text-grey-8">{{ $t('pageTitles.timeSheetValidations') }}</div>
<div class="row items-center justify-center q-py-none q-my-none">
<div class="text-primary text-h6 text-uppercase">{{ pay_period_label.start_date }}</div>
<div class="text-grey-8 text-weight-bold text-uppercase q-mx-md">{{ $t('timeSheet.dateRangesTo') }}</div>
<div class="text-primary text-h6 text-uppercase">{{ pay_period_label.end_date }}</div>
</div>
<TimesheetApprovalEmployeeOverviewList /> <TimesheetApprovalEmployeeOverviewList />
</q-page> </q-page>
</template> </template>

View File

@ -18,18 +18,23 @@ export const useTimesheetStore = defineStore('timesheet', () => {
const payPeriodEmployeeOverviews = ref<PayPeriodEmployeeOverview[]>([]); const payPeriodEmployeeOverviews = ref<PayPeriodEmployeeOverview[]>([]);
const isLoading = ref<boolean>(false); const isLoading = ref<boolean>(false);
const getPayPeriodByDate = async (date: Date) => { const getPayPeriodByDate = async (date: Date): Promise<boolean> => {
isLoading.value = true; isLoading.value = true;
try { try {
const response = await timesheetApprovalService.getPayPeriodByDate(date); const response = await timesheetApprovalService.getPayPeriodByDate(date);
currentPayPeriod.value = response; currentPayPeriod.value = response;
isLoading.value = false;
return true;
} catch(error){ } catch(error){
console.error('Could not get current pay period: ', error ); console.error('Could not get current pay period: ', error );
//TODO: More in-depth error-handling here //TODO: More in-depth error-handling here
} }
isLoading.value = false; isLoading.value = false;
return false;
}; };
const getPayPeriodByYearAndPeriodNumber = async (year: number, period_number: number): Promise<boolean> => { const getPayPeriodByYearAndPeriodNumber = async (year: number, period_number: number): Promise<boolean> => {
@ -38,6 +43,8 @@ export const useTimesheetStore = defineStore('timesheet', () => {
try { try {
const response = await timesheetApprovalService.getPayPeriodByYearAndPeriodNumber(year, period_number); const response = await timesheetApprovalService.getPayPeriodByYearAndPeriodNumber(year, period_number);
currentPayPeriod.value = response; currentPayPeriod.value = response;
isLoading.value = false;
return true; return true;
} catch(error){ } catch(error){
console.error('Could not get current pay period: ', error ); console.error('Could not get current pay period: ', error );