refactor(many): change some components to respect 'props down, events up' convention for modularity and reusability. Keep branch open for future possible refactors.

This commit is contained in:
Nicolas Drolet 2025-08-22 11:11:14 -04:00
parent b0dcfdc73c
commit 7dbb30259c
11 changed files with 285 additions and 140 deletions

View File

@ -1,25 +1,18 @@
<script setup lang="ts"> <script setup lang="ts">
/* eslint-disable */ /* eslint-disable */
import { useEmployeeStore } from 'src/stores/employee-store';
import type { EmployeeListTableItem } from 'src/modules/employee-list/types/employee-list-table-interface'; import type { EmployeeListTableItem } from 'src/modules/employee-list/types/employee-list-table-interface';
import { useEmployeeListApi } from 'src/modules/employee-list/composables/use-employee-api';
const employeeStore = useEmployeeStore();
const employeeListApi = useEmployeeListApi();
const getEmployeeAvatar = (first_name: string, last_name: string) => { const getEmployeeAvatar = (first_name: string, last_name: string) => {
// add logic here to see if user has an avatar image and return that instead of initials // add logic here to see if user has an avatar image and return that instead of initials
return first_name.charAt(0) + last_name.charAt(0); return first_name.charAt(0) + last_name.charAt(0);
}; };
const onProfileCardClick = (email: string) => {
employeeStore.isShowingEmployeeAddModifyWindow = true;
console.log("clicked profile!");
employeeListApi.getEmployeeDetails(email);
}
const props = defineProps<{ const props = defineProps<{
row: EmployeeListTableItem row: EmployeeListTableItem
}>() }>()
const emit = defineEmits<{
onProfileClick: [email: string]
}>();
</script> </script>
<template> <template>
@ -27,7 +20,7 @@ import { useEmployeeListApi } from 'src/modules/employee-list/composables/use-em
v-ripple v-ripple
class="rounded-15 bg-white col-xs-6 col-sm-4 col-md-3 col-lg-2 column no-wrap cursor-pointer q-ma-sm" class="rounded-15 bg-white col-xs-6 col-sm-4 col-md-3 col-lg-2 column no-wrap cursor-pointer q-ma-sm"
style="max-width: 230px;" style="max-width: 230px;"
@click="onProfileCardClick(props.row.email)" @click="emit('onProfileClick', props.row.email)"
> >
<q-card-section class="text-center col-5"> <q-card-section class="text-center col-5">
<q-avatar color="primary" size="8em"> <q-avatar color="primary" size="8em">

View File

@ -0,0 +1,42 @@
<script setup lang="ts">
const props = defineProps<{
searchModel: string | number | null
}>();
const emit = defineEmits<{
onSearchValueUpdated: [value: string | number | null]
}>();
</script>
<template>
<!-- Filters toggle -->
<q-btn-dropdown
rounded
push
class="q-mr-md bg-white text-primary"
label="filters"
icon="filter_alt"
/>
<!-- Search bar -->
<q-input
outlined
dense
rounded
debounce="300"
v-model="props.searchModel"
:label="$t('shared.searchBar')"
label-color="primary"
bg-color="white"
color="primary"
@update:model-value="value => emit('onSearchValueUpdated', value)"
>
<template v-slot:append>
<q-icon
name="search"
color="primary"
/>
</template>
</q-input>
</template>

View File

@ -1,6 +0,0 @@
import type { PayPeriod } from "./pay-period-interface";
export interface PayPeriodBundle {
current: PayPeriod;
periods: PayPeriod[];
}

View File

@ -0,0 +1,15 @@
export interface QDateDetails {
year: number;
month: number;
day: number;
from?: {
year: number;
month: number;
day: number;
};
to?: {
year: number;
month: number;
day: number;
};
}

View File

@ -18,19 +18,34 @@
<div class="q-px-sm q-pb-sm col-xs-12 col-sm-6 col-md-4 col-lg-4 col-xl-3 grid-style-transition"> <div class="q-px-sm q-pb-sm col-xs-12 col-sm-6 col-md-4 col-lg-4 col-xl-3 grid-style-transition">
<q-card class="rounded-10"> <q-card class="rounded-10">
<!-- Card header with employee name --> <!-- Card header with employee name -->
<q-card-section horizontal class="q-py-none q-px-md"> <q-card-section
<div class="text-primary text-h5 text-weight-bolder q-pt-xs overflow-hidden">{{ props.row.employee_name }}</div> horizontal
class="q-py-none q-px-md"
>
<div class="text-primary text-h5 text-weight-bolder q-pt-xs overflow-hidden">
{{ props.row.employee_name }}
</div>
</q-card-section> </q-card-section>
<q-separator color="accent" style="height: 2px;"/> <q-separator
color="accent"
style="height: 2px;"
/>
<!-- Main body of pay period card --> <!-- Main body of pay period card -->
<q-card-section class="q-pa-none q-mt-xs q-mb-sm"> <q-card-section class="q-pa-none q-mt-xs q-mb-sm">
<div class="row no-wrap"> <div class="row no-wrap">
<!-- left portion of pay period card --> <!-- left portion of pay period card -->
<div class="column no-wrap" :class="$q.screen.lt.md ? 'col' : 'col-8'"> <div
class="column no-wrap"
:class="$q.screen.lt.md ? 'col' : 'col-8'"
>
<!-- Regular hours segment --> <!-- Regular hours segment -->
<q-item dense class="column" :class="$q.screen.lt.md ? 'col' : 'col-8'"> <q-item
dense
class="column"
:class="$q.screen.lt.md ? 'col' : 'col-8'"
>
<q-item-label class="text-weight-bold text-primary q-pa-none text-uppercase text-caption"> <q-item-label class="text-weight-bold text-primary q-pa-none text-uppercase text-caption">
{{ props.cols.find(c => c.name === 'regular_hours')?.label }} {{ props.cols.find(c => c.name === 'regular_hours')?.label }}
</q-item-label> </q-item-label>
@ -39,12 +54,23 @@
</q-item-label> </q-item-label>
</q-item> </q-item>
<q-separator color="accent" class="q-mx-sm"/> <q-separator
color="accent"
class="q-mx-sm"
/>
<!-- Other hour types segment --> <!-- Other hour types segment -->
<div :class="$q.screen.lt.md ? 'column' : 'row no-wrap'"> <div :class="$q.screen.lt.md ? 'column' : 'row no-wrap'">
<q-item dense class="column ellipsis " v-for="col in props.cols.slice(2, 5)" :key="col.label"> <q-item
<q-item-label class="text-weight-bold text-primary q-pa-none text-uppercase text-caption" style="font-size: 0.65em;"> dense
class="column ellipsis "
v-for="col in props.cols.slice(2, 5)"
:key="col.label"
>
<q-item-label
class="text-weight-bold text-primary q-pa-none text-uppercase text-caption"
style="font-size: 0.65em;"
>
{{ col.label }} {{ col.label }}
</q-item-label> </q-item-label>
<q-item-label class="text-weight-bolder q-pa-none text-h6 text-grey-8"> <q-item-label class="text-weight-bolder q-pa-none text-h6 text-grey-8">
@ -54,12 +80,24 @@
</div> </div>
</div> </div>
<q-separator vertical color="accent" class="q-mt-xs q-mb-none"/> <q-separator
vertical
color="accent"
class="q-mt-xs q-mb-none"
/>
<!-- Right portion of pay period card --> <!-- Right portion of pay period card -->
<div class="no-wrap ellipsis col"> <div class="no-wrap ellipsis col">
<q-item dense class="column" v-for="col in props.cols.slice(5, )" :key="col.label"> <q-item
<q-item-label class="text-weight-bold text-primary q-pa-none text-uppercase text-caption ellipsis" style="font-size: 0.8em;"> dense
class="column"
v-for="col in props.cols.slice(5, )"
:key="col.label"
>
<q-item-label
class="text-weight-bold text-primary q-pa-none text-uppercase text-caption ellipsis"
style="font-size: 0.8em;"
>
{{ col.label }} {{ col.label }}
</q-item-label> </q-item-label>
<q-item-label class="text-weight-bolder q-pa-none text-h6 text-grey-8"> <q-item-label class="text-weight-bolder q-pa-none text-h6 text-grey-8">
@ -70,7 +108,10 @@
</div> </div>
</q-card-section> </q-card-section>
<q-separator color="primary" style="height: 2px;" /> <q-separator
color="primary"
style="height: 2px;"
/>
<!-- Validate entire Pay Period section --> <!-- Validate entire Pay Period section -->
<q-card-section <q-card-section

View File

@ -2,54 +2,96 @@
/* eslint-disable */ /* eslint-disable */
import { computed, onMounted, ref } from 'vue'; import { computed, onMounted, ref } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import type { PayPeriodEmployeeOverview } from '../types/timesheet-approval-pay-period-employee-overview-interface';
import type { QTableColumn } from 'quasar';
import TimesheetApprovalEmployeeOverviewListItem from './timesheet-approval-employee-overview-list-item.vue';
import { useTimesheetApprovalApi } from '../composables/use-timesheet-approval-api';
import { getCurrentPayPeriod } from 'src/utils/pay-period-calculator';
import { useAuthStore } from 'src/stores/auth-store';
import { useTimesheetStore } from 'src/stores/timesheet-store'; import { useTimesheetStore } from 'src/stores/timesheet-store';
import { useTimesheetApprovalApi } from '../composables/use-timesheet-approval-api';
import TimesheetApprovalPeriodPicker from '../components/timesheet-approval-period-picker.vue'; import TimesheetApprovalPeriodPicker from '../components/timesheet-approval-period-picker.vue';
import TimesheetApprovalEmployeeOverviewListItem from './timesheet-approval-employee-overview-list-item.vue';
import { date, type QTableColumn } from 'quasar';
import type { PayPeriodEmployeeOverview } from '../types/timesheet-approval-pay-period-employee-overview-interface';
const { t } = useI18n(); const { t } = useI18n();
const timesheet_store = useTimesheetStore();
const timesheet_approval_api = useTimesheetApprovalApi();
const currentPayPeriod = getCurrentPayPeriod(); const FORWARD = 1
const currentYear = (new Date()).getFullYear(); const BACKWARD = -1
const originalApprovals = ref<Record<string, boolean>>({}); const filter = ref<string | number | null>('');
const hasChanges = computed(() => { const original_approvals = ref<Record<string, boolean>>({});
return timesheetStore.payPeriodEmployeeOverviews.some(emp => {
return emp.is_approved !== originalApprovals.value[emp.email];
});
});
const authStore = useAuthStore();
const timesheetStore = useTimesheetStore();
const timesheetApprovalApi = useTimesheetApprovalApi();
const columns = computed((): QTableColumn<PayPeriodEmployeeOverview>[] => [ const columns = computed((): QTableColumn<PayPeriodEmployeeOverview>[] => [
{ name: 'employee_name', label: t('timeSheetValidations.tableColumnLabelFullname'), field: 'employee_name', sortable: true }, {
{ name: 'regular_hours', label: t('timeSheetValidations.tableColumnLabelRegularHours'), field: 'regular_hours', sortable: true }, name: 'employee_name',
{ name: 'evening_hours', label: t('timeSheetValidations.tableColumnLabelEveningHours'), field: 'evening_hours' }, label: t('timeSheetValidations.tableColumnLabelFullname'),
{ name: 'emergency_hours', label: t('timeSheetValidations.tableColumnLabelEmergencyHours'), field: 'emergency_hours' }, field: 'employee_name',
{ name: 'overtime_hours', label: t('timeSheetValidations.tableColumnLabelOvertime'), field: 'overtime_hours' }, sortable: true
{ name: 'expenses', label: t('timeSheetValidations.tableColumnLabelExpenses'), field: 'expenses', sortable: true }, },
{ name: 'mileage', label: t('timeSheetValidations.tableColumnLabelMileage'), field: 'mileage', sortable: true } {
name: 'regular_hours',
label: t('timeSheetValidations.tableColumnLabelRegularHours'),
field: 'regular_hours',
sortable: true
},
{
name: 'evening_hours',
label: t('timeSheetValidations.tableColumnLabelEveningHours'),
field: 'evening_hours'
},
{
name: 'emergency_hours',
label: t('timeSheetValidations.tableColumnLabelEmergencyHours'),
field: 'emergency_hours'
},
{
name: 'overtime_hours',
label: t('timeSheetValidations.tableColumnLabelOvertime'),
field: 'overtime_hours'
},
{
name: 'expenses',
label: t('timeSheetValidations.tableColumnLabelExpenses'),
field: 'expenses',
sortable: true
},
{
name: 'mileage',
label: t('timeSheetValidations.tableColumnLabelMileage'),
field: 'mileage',
sortable: true
}
]); ]);
const filter = ref(''); const has_changes = computed(() => {
return timesheet_store.pay_period_employee_overviews.some(emp => {
return emp.is_approved !== original_approvals.value[emp.email];
});
});
const is_calendar_limit = computed( () => {
return timesheet_store.current_pay_period.pay_year === 2024 &&
timesheet_store.current_pay_period.pay_period_no <= 1;
});
const onDateSelected = async (date_string: string) => {
await timesheet_approval_api.getPayPeriodOverviewByDate(date_string);
}
onMounted( async () => { onMounted( async () => {
await timesheetApprovalApi.getPayPeriodOverviewByDate(new Date()); const today = date.formatDate(new Date(), 'YYYY-MM-DD');
originalApprovals.value = Object.fromEntries( timesheetStore.payPeriodEmployeeOverviews.map(emp => [emp.email, emp.is_approved])); await timesheet_approval_api.getPayPeriodOverviewByDate(today);
const approvals = timesheet_store.pay_period_employee_overviews.map(emp => [emp.email, emp.is_approved]);
original_approvals.value = Object.fromEntries(approvals);
}) })
</script> </script>
<template> <template>
<div class="q-pa-md"> <div class="q-pa-md">
<q-table <q-table
:rows="timesheetStore.payPeriodEmployeeOverviews" :rows="timesheet_store.pay_period_employee_overviews"
:columns="columns" :columns="columns"
row-key="email" row-key="email"
:filter="filter" :filter="filter"
@ -59,7 +101,7 @@
color="primary" color="primary"
:rows-per-page-options="[0]" :rows-per-page-options="[0]"
card-container-class="justify-center" card-container-class="justify-center"
:loading="timesheetStore.isLoading" :loading="timesheet_store.is_loading"
:no-data-label="$t('shared.failedToLoad')" :no-data-label="$t('shared.failedToLoad')"
:no-results-label="$t('shared.failedToSearch')" :no-results-label="$t('shared.failedToSearch')"
:loading-label="$t('shared.loading')" :loading-label="$t('shared.loading')"
@ -68,37 +110,25 @@
<template v-slot:top> <template v-slot:top>
<div :class="$q.screen.lt.md ? 'column justify-center items-center' : 'full-width row'"> <div :class="$q.screen.lt.md ? 'column justify-center items-center' : 'full-width row'">
<!-- Date Picker --> <!-- Date Picker -->
<TimesheetApprovalPeriodPicker /> <TimesheetApprovalPeriodPicker
:is-disabled="timesheet_store.is_loading"
:is-previous-limit="is_calendar_limit"
@date-selected="onDateSelected"
@pressed-previous-button="timesheet_approval_api.getNextPayPeriodOverview(BACKWARD)"
@pressed-next-button="timesheet_approval_api.getNextPayPeriodOverview(FORWARD)"
/>
<q-space /> <q-space />
<!-- Filters toggle -->
<q-btn-dropdown
rounded
push
class="q-mr-md bg-white text-primary"
label="filters"
icon="filter_alt"
/>
<!-- Search bar -->
<q-input
outlined
dense
rounded
v-model="filter"
:label="$t('shared.searchBar')"
label-color="primary" bg-color="white" color="primary"
>
<template v-slot:append>
<q-icon name="search" color="primary"/>
</template>
</q-input>
</div> </div>
</template> </template>
<!-- Template for individual employee cards --> <!-- Template for individual employee cards -->
<template v-slot:item="props: { cols: (QTableColumn<PayPeriodEmployeeOverview> & { value: unknown })[], row: PayPeriodEmployeeOverview }"> <template v-slot:item="props: {
cols: (QTableColumn<PayPeriodEmployeeOverview> & { value: unknown })[],
row: PayPeriodEmployeeOverview
}">
<TimesheetApprovalEmployeeOverviewListItem <TimesheetApprovalEmployeeOverviewListItem
:cols="props.cols" :cols="props.cols"
:row="props.row" :row="props.row"
@ -111,7 +141,10 @@
<span class="text-h6 q-mt-xl"> <span class="text-h6 q-mt-xl">
{{ message }} {{ message }}
</span> </span>
<q-icon size="4em" :name="filter ? 'filter_alt_off' : 'error_outline'" /> <q-icon
size="4em"
:name="filter ? 'filter_alt_off' : 'error_outline'"
/>
</div> </div>
</template> </template>
</q-table> </q-table>

View File

@ -1,18 +1,28 @@
<script setup lang="ts"> <script setup lang="ts">
/* eslint-disable */ /* eslint-disable */
import { ref, computed } from 'vue'; import { ref } from 'vue';
import { useTimesheetApprovalApi } from '../composables/use-timesheet-approval-api';
import { useTimesheetStore } from 'src/stores/timesheet-store';
import { date } from 'quasar'; import { date } from 'quasar';
import type { QDateDetails } from 'src/modules/shared/types/q-date-details';
const timesheet_approval_api = useTimesheetApprovalApi();
const timesheet_store = useTimesheetStore();
const is_showing_calendar_picker = ref(false); const is_showing_calendar_picker = ref(false);
const calendar_date = ref(date.formatDate( Date.now(), 'YYYY/MM/DD' )); 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;
});
const props = defineProps<{
isDisabled: boolean,
isPreviousLimit: boolean,
}>();
const emit = defineEmits<{
'date-selected': [value: string, reason?: string, details?: QDateDetails]
'pressed-previous-button': void
'pressed-next-button': void
}>();
const onDateSelected = (value: string, reason: string, details: QDateDetails) => {
calendar_date.value = value;
is_showing_calendar_picker.value = false;
emit('date-selected', value, reason, details);
}
</script> </script>
<template> <template>
@ -21,8 +31,8 @@
push rounded push rounded
icon="keyboard_arrow_left" icon="keyboard_arrow_left"
color="primary" color="primary"
@click="timesheet_approval_api.getNextPayPeriodOverview(-1)" @click="$emit('pressed-previous-button')"
:disable="is_calendar_limit || timesheet_store.isLoading" :disable="props.isPreviousLimit || props.isDisabled"
class="q-mr-sm q-px-sm" class="q-mr-sm q-px-sm"
/> />
<q-btn <q-btn
@ -30,26 +40,28 @@
icon="date_range" icon="date_range"
color="primary" color="primary"
@click="is_showing_calendar_picker = true" @click="is_showing_calendar_picker = true"
:disable="timesheet_store.isLoading" :disable="props.isDisabled"
class="q-px-lg" class="q-px-lg"
/> />
<q-btn <q-btn
push rounded push rounded
icon="keyboard_arrow_right" icon="keyboard_arrow_right"
color="primary" color="primary"
@click="timesheet_approval_api.getNextPayPeriodOverview(1)" @click="$emit('pressed-next-button')"
:disable="timesheet_store.isLoading" :disable="props.isDisabled"
class="q-ml-sm q-px-sm" 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-dialog v-model="is_showing_calendar_picker" transition-show="jump-down" transition-hide="jump-up" position="top">
<q-date <q-date
v-model="calendar_date" v-model="calendar_date"
color="primary" color="primary"
class="q-mt-xl" class="q-mt-xl"
today-btn today-btn
:options="date => date > '2023/12/16'" mask="YYYY-MM-DD"
:options="date => date > '2023-12-16'"
@update:model-value="onDateSelected"
/> />
</q-dialog> </q-dialog>
</template> </template>

View File

@ -5,11 +5,11 @@ export const useTimesheetApprovalApi = () => {
const timesheet_store = useTimesheetStore(); const timesheet_store = useTimesheetStore();
const auth_store = useAuthStore(); const auth_store = useAuthStore();
const getPayPeriodOverviewByDate = async (date: Date) => { const getPayPeriodOverviewByDate = async (date_string: string) => {
const success = await timesheet_store.getPayPeriodByDate(date); const success = await timesheet_store.getPayPeriodByDate(date_string);
if (success) { if (success) {
const current_pay_period = timesheet_store.currentPayPeriod; const current_pay_period = timesheet_store.current_pay_period;
await timesheet_store.getTimesheetApprovalPayPeriodEmployeeOverviews(current_pay_period.pay_year, current_pay_period.pay_period_no, auth_store.user.email); await timesheet_store.getTimesheetApprovalPayPeriodEmployeeOverviews(current_pay_period.pay_year, current_pay_period.pay_period_no, auth_store.user.email);
} }
} }
@ -19,7 +19,7 @@ export const useTimesheetApprovalApi = () => {
It then requests the matching pay period object to set as current pay period from server. It then requests the matching pay period object to set as current pay period from server.
If successful, it then requests pay period overviews from that new pay period. */ If successful, it then requests pay period overviews from that new pay period. */
const getNextPayPeriodOverview = async (direction: number) => { const getNextPayPeriodOverview = async (direction: number) => {
const current_pay_period = timesheet_store.currentPayPeriod; const current_pay_period = timesheet_store.current_pay_period;
let new_pay_period_no = current_pay_period.pay_period_no + direction; let new_pay_period_no = current_pay_period.pay_period_no + direction;
let new_pay_year = current_pay_period.pay_year; let new_pay_year = current_pay_period.pay_year;

View File

@ -1,5 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import TimesheetApprovalEmployeeOverviewList from '../components/timesheet-approval-employee-overview-list.vue'; import TimesheetApprovalEmployeeOverviewList from '/src/modules/timesheet-approval/\
components/timesheet-approval-employee-overview-list.vue';
import { computed } from 'vue'; import { computed } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useTimesheetStore } from 'src/stores/timesheet-store'; import { useTimesheetStore } from 'src/stores/timesheet-store';
@ -15,9 +16,12 @@
const pay_period_label = computed(() => { const pay_period_label = computed(() => {
const dates = timesheet_store.currentPayPeriod.label.split('.'); const dates = timesheet_store.current_pay_period.label.split('.');
const start_date = new Intl.DateTimeFormat(locale.value, date_options).format(date.extractDate(dates[0] as string, 'YYYY-MM-DD')); const start_date = new Intl.DateTimeFormat(locale.value, date_options);
const end_date = new Intl.DateTimeFormat(locale.value, date_options).format(date.extractDate(dates[1] as string, 'YYYY-MM-DD')); const end_date = new Intl.DateTimeFormat(locale.value, date_options);
start_date.format(date.extractDate(dates[0] as string, 'YYYY-MM-DD'));
end_date.format(date.extractDate(dates[1] as string, 'YYYY-MM-DD'));
return { return {
start_date: start_date, start_date: start_date,
@ -27,12 +31,23 @@
</script> </script>
<template> <template>
<q-page padding class="q-pa-md bg-secondary"> <q-page
<div class="text-h4 row justify-center q-mt-lg text-uppercase text-weight-bolder text-grey-8">{{ $t('pageTitles.timeSheetValidations') }}</div> padding
class="q-pa-md bg-secondary"
>
<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="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-primary text-h6 text-uppercase">
<div class="text-grey-8 text-weight-bold text-uppercase q-mx-md">{{ $t('timeSheet.dateRangesTo') }}</div> {{ pay_period_label.start_date }}
<div class="text-primary text-h6 text-uppercase">{{ pay_period_label.end_date }}</div> </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> </div>
<TimesheetApprovalEmployeeOverviewList /> <TimesheetApprovalEmployeeOverviewList />
</q-page> </q-page>

View File

@ -3,8 +3,8 @@ import type { PayPeriodOverview } from "../types/timesheet-approval-pay-period-o
import type { PayPeriod } from "src/modules/shared/types/pay-period-interface"; import type { PayPeriod } from "src/modules/shared/types/pay-period-interface";
export const timesheetApprovalService = { export const timesheetApprovalService = {
getPayPeriodByDate: async (date: Date): Promise<PayPeriod> => { getPayPeriodByDate: async (date_string: string): Promise<PayPeriod> => {
const response = await api.get(`pay-periods/date/${date.toISOString()}`); const response = await api.get(`pay-periods/date/${date_string}`);
return response.data; return response.data;
}, },

View File

@ -14,17 +14,17 @@ const default_pay_period: PayPeriod = {
}; };
export const useTimesheetStore = defineStore('timesheet', () => { export const useTimesheetStore = defineStore('timesheet', () => {
const currentPayPeriod = ref<PayPeriod>(default_pay_period); const current_pay_period = ref<PayPeriod>(default_pay_period);
const payPeriodEmployeeOverviews = ref<PayPeriodEmployeeOverview[]>([]); const pay_period_employee_overviews = ref<PayPeriodEmployeeOverview[]>([]);
const isLoading = ref<boolean>(false); const is_loading = ref<boolean>(false);
const getPayPeriodByDate = async (date: Date): Promise<boolean> => { const getPayPeriodByDate = async (date_string: string): Promise<boolean> => {
isLoading.value = true; is_loading.value = true;
try { try {
const response = await timesheetApprovalService.getPayPeriodByDate(date); const response = await timesheetApprovalService.getPayPeriodByDate(date_string);
currentPayPeriod.value = response; current_pay_period.value = response;
isLoading.value = false; is_loading.value = false;
return true; return true;
} catch(error){ } catch(error){
@ -32,18 +32,18 @@ export const useTimesheetStore = defineStore('timesheet', () => {
//TODO: More in-depth error-handling here //TODO: More in-depth error-handling here
} }
isLoading.value = false; is_loading.value = false;
return false; return false;
}; };
const getPayPeriodByYearAndPeriodNumber = async (year: number, period_number: number): Promise<boolean> => { const getPayPeriodByYearAndPeriodNumber = async (year: number, period_number: number): Promise<boolean> => {
isLoading.value = true; is_loading.value = true;
try { try {
const response = await timesheetApprovalService.getPayPeriodByYearAndPeriodNumber(year, period_number); const response = await timesheetApprovalService.getPayPeriodByYearAndPeriodNumber(year, period_number);
currentPayPeriod.value = response; current_pay_period.value = response;
isLoading.value = false; is_loading.value = false;
return true; return true;
} catch(error){ } catch(error){
@ -51,30 +51,30 @@ export const useTimesheetStore = defineStore('timesheet', () => {
//TODO: More in-depth error-handling here //TODO: More in-depth error-handling here
} }
isLoading.value = false; is_loading.value = false;
return false; return false;
}; };
const getTimesheetApprovalPayPeriodEmployeeOverviews = async (pay_year: number, period_number: number, supervisor_email: string) => { const getTimesheetApprovalPayPeriodEmployeeOverviews = async (pay_year: number, period_number: number, supervisor_email: string) => {
isLoading.value = true; is_loading.value = true;
try { try {
const response = await timesheetApprovalService.getPayPeriodEmployeeOverviews(pay_year, period_number, supervisor_email); const response = await timesheetApprovalService.getPayPeriodEmployeeOverviews(pay_year, period_number, supervisor_email);
payPeriodEmployeeOverviews.value = response.employees_overview; pay_period_employee_overviews.value = response.employees_overview;
} catch (error) { } catch (error) {
console.error('There was an error retrieving Employee Pay Period overviews: ', error); console.error('There was an error retrieving Employee Pay Period overviews: ', error);
payPeriodEmployeeOverviews.value = []; pay_period_employee_overviews.value = [];
// TODO: trigger an alert window with an error message here! // TODO: trigger an alert window with an error message here!
} }
isLoading.value = false; is_loading.value = false;
}; };
return { return {
currentPayPeriod, current_pay_period,
payPeriodEmployeeOverviews, pay_period_employee_overviews,
isLoading, is_loading,
getPayPeriodByDate, getPayPeriodByDate,
getPayPeriodByYearAndPeriodNumber, getPayPeriodByYearAndPeriodNumber,
getTimesheetApprovalPayPeriodEmployeeOverviews, getTimesheetApprovalPayPeriodEmployeeOverviews,