refactor(approvals): remake entire card appearance, hook up to pay period picker to backend, make the period picker actually functional.
This commit is contained in:
parent
0c1d214420
commit
21b98ec825
|
|
@ -1,7 +1,7 @@
|
|||
// app global css in SCSS form
|
||||
@each $size in (5, 10, 15, 20, 25) {
|
||||
.rounded-#{$size} {
|
||||
border-radius: #{$size}px;
|
||||
border-radius: #{$size}px !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -297,11 +297,11 @@ export default {
|
|||
tableHeader: 'List of employees',
|
||||
tableColumnLabelFullname: 'Full name',
|
||||
tableColumnLabelRegularHours: 'regular hours',
|
||||
tableColumnLabelEveningHours: 'evening hours',
|
||||
tableColumnLabelEmergencyHours: 'emergency hours',
|
||||
tableColumnLabelOvertime: 'overtime hours',
|
||||
tableColumnLabelExpenses: 'of expenses',
|
||||
tableColumnLabelMileage: 'of mileage',
|
||||
tableColumnLabelEveningHours: 'evening',
|
||||
tableColumnLabelEmergencyHours: 'emergency',
|
||||
tableColumnLabelOvertime: 'overtime',
|
||||
tableColumnLabelExpenses: 'expenses',
|
||||
tableColumnLabelMileage: 'mileage',
|
||||
actionTitle: 'Please save the changes made.',
|
||||
actionButton: 'Save',
|
||||
timeSheetStatusVerified: 'approved',
|
||||
|
|
|
|||
|
|
@ -347,11 +347,11 @@ export default {
|
|||
tableHeader: 'Liste des employés',
|
||||
tableColumnLabelFullname: 'nom complet',
|
||||
tableColumnLabelRegularHours: 'heures régulières',
|
||||
tableColumnLabelEveningHours: 'heures de soir',
|
||||
tableColumnLabelEmergencyHours: 'heures d’urgence',
|
||||
tableColumnLabelOvertime: 'heures supplémentaires',
|
||||
tableColumnLabelExpenses: 'de dépenses',
|
||||
tableColumnLabelMileage: 'de kilométrage',
|
||||
tableColumnLabelEveningHours: 'soir',
|
||||
tableColumnLabelEmergencyHours: 'urgence',
|
||||
tableColumnLabelOvertime: 'supplémentaires',
|
||||
tableColumnLabelExpenses: 'dépenses',
|
||||
tableColumnLabelMileage: 'kilométrage',
|
||||
actionTitle: 'Veuillez enregistrer les changements effectués.',
|
||||
actionButton: 'Enregistrer',
|
||||
timeSheetStatusVerified: 'validé',
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ import { useEmployeeListApi } from 'src/modules/employee-list/composables/use-em
|
|||
<template>
|
||||
<q-card
|
||||
v-ripple
|
||||
class="rounded-15 bg-white col-xs-6 col-sm-4 col-md-3 col-lg-2 column no-wrap cursor-pointer"
|
||||
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;"
|
||||
@click="onProfileCardClick(props.row.email)"
|
||||
>
|
||||
|
|
@ -37,9 +37,9 @@ import { useEmployeeListApi } from 'src/modules/employee-list/composables/use-em
|
|||
<q-card-section class="text-center text-h6 text-primary text-weight-medium text-uppercase q-pb-none col-2 content-end" style="line-height: 0.7em;">
|
||||
<div class="ellipsis">
|
||||
{{ props.row.first_name }} {{ props.row.last_name }}
|
||||
<q-separator color="primary" />
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-separator color="primary" class="q-mx-sm q-mt-xs" />
|
||||
<q-card-section class="text-caption text-grey-8 text-body2 text-uppercase q-pt-none text-center col content-start" style="min-height: 5em;">
|
||||
<div class=" ellipsis-2-lines">
|
||||
{{ props.row.job_title }}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
const { t } = useI18n();
|
||||
const filter = ref("");
|
||||
const isGridMode = ref(true);
|
||||
const pagination = ref({ rowsPerPage: 0 });
|
||||
|
||||
const employeeListColumns = computed((): QTableColumn<EmployeeListTableItem>[] => [
|
||||
{name: 'first_name', label: t('usersListPage.userListFirstName'), field: 'first_name', align: 'left'},
|
||||
|
|
@ -35,24 +36,30 @@
|
|||
<template>
|
||||
<div class="q-pa-lg col">
|
||||
<q-table
|
||||
title=" "
|
||||
dense
|
||||
flat
|
||||
hide-pagination
|
||||
virtual-scroll
|
||||
title=" "
|
||||
card-style="max-height: 70vh;"
|
||||
:rows="employeeStore.employeeList"
|
||||
:columns="employeeListColumns"
|
||||
row-key="name"
|
||||
v-model:pagination="pagination"
|
||||
:rows-per-page-options="[0]"
|
||||
:filter="filter"
|
||||
class="q-pa-md bg-transparent"
|
||||
color="primary"
|
||||
table-header-class="text-primary text-uppercase"
|
||||
card-container-class="justify-center q-gutter-md"
|
||||
card-container-class="justify-center"
|
||||
:grid="isGridMode"
|
||||
:loading="isLoadingList"
|
||||
dense
|
||||
flat
|
||||
:no-data-label="$t('shared.failedToLoad')"
|
||||
:no-results-label="$t('shared.failedToSearch')"
|
||||
:loading-label="$t('shared.loading')"
|
||||
table-class="bg-white q-pa-md q-mx-md rounded-15 shadow-12"
|
||||
table-class="bg-white q-pa-md q-mx-md rounded-10 shadow-12"
|
||||
table-style=""
|
||||
@row-click="() => console.log('click!')"
|
||||
>
|
||||
<template v-slot:item="props">
|
||||
<SupervisorCrewTableItem :row="props.row"/>
|
||||
|
|
|
|||
6
src/modules/shared/types/pay-period-bundle-interface.ts
Normal file
6
src/modules/shared/types/pay-period-bundle-interface.ts
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
import type { PayPeriod } from "./pay-period-interface";
|
||||
|
||||
export interface PayPeriodBundle {
|
||||
current: PayPeriod;
|
||||
periods: PayPeriod[];
|
||||
}
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
export interface PayPeriod {
|
||||
period_number: number;
|
||||
start_date: string;
|
||||
end_date: string;
|
||||
year: number;
|
||||
pay_period_no: number;
|
||||
period_start: string;
|
||||
period_end: string;
|
||||
payday: string;
|
||||
pay_year: number;
|
||||
label: string;
|
||||
};
|
||||
}
|
||||
|
|
@ -15,24 +15,68 @@
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div class="q-px-sm q-pb-sm col-xs-6 col-sm-4 col-md-3 col-lg-2 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-section class="q-pb-sm">
|
||||
<div class="text-primary text-h5 text-weight-bolder ellipsis">{{ props.row.employee_name }}</div>
|
||||
<!-- Card header with employee name -->
|
||||
<q-card-section 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>
|
||||
<div
|
||||
v-for="col in props.cols.filter(col => col.name !== 'employee_name')"
|
||||
:key="col.name"
|
||||
class="q-pa-none q-mx-sm items-center row"
|
||||
:class="{ 'bg-warning': col.name == 'overtime_hours' && col.value as number > 0 }"
|
||||
>
|
||||
<q-card-section class="text-right text-weight-bolder text-subtitle1 text-primary q-pr-sm q-py-none col-3 ellipsis" style="line-height: 1.2em;">{{ col.value }}</q-card-section>
|
||||
<q-card-section class="text-weight-bold q-pa-none col-9" >{{ col.label }}</q-card-section>
|
||||
</div>
|
||||
|
||||
<q-separator color="accent" style="height: 2px;"/>
|
||||
|
||||
<!-- Main body of pay period card -->
|
||||
<q-card-section class="q-pa-none q-mt-xs q-mb-sm">
|
||||
<div class="row no-wrap">
|
||||
<!-- left portion of pay period card -->
|
||||
<div class="column no-wrap" :class="$q.screen.lt.md ? 'col' : 'col-8'">
|
||||
<!-- Regular hours segment -->
|
||||
<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">
|
||||
{{ props.cols.find(c => c.name === 'regular_hours')?.label }}
|
||||
</q-item-label>
|
||||
<q-item-label class="text-weight-bolder text-h3 text-grey-8 q-py-none">
|
||||
{{ props.cols.find(c => c.name === 'regular_hours')?.value }}
|
||||
</q-item-label>
|
||||
</q-item>
|
||||
|
||||
<q-separator color="accent" class="q-mx-sm"/>
|
||||
|
||||
<!-- Other hour types segment -->
|
||||
<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-label class="text-weight-bold text-primary q-pa-none text-uppercase text-caption" style="font-size: 0.65em;">
|
||||
{{ col.label }}
|
||||
</q-item-label>
|
||||
<q-item-label class="text-weight-bolder q-pa-none text-h6 text-grey-8">
|
||||
{{ col.value }}
|
||||
</q-item-label>
|
||||
</q-item>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<q-separator vertical color="accent" class="q-mt-xs q-mb-none"/>
|
||||
|
||||
<!-- Right portion of pay period card -->
|
||||
<div class="no-wrap ellipsis col">
|
||||
<q-item 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 }}
|
||||
</q-item-label>
|
||||
<q-item-label class="text-weight-bolder q-pa-none text-h6 text-grey-8">
|
||||
{{ col.value }}
|
||||
</q-item-label>
|
||||
</q-item>
|
||||
</div>
|
||||
</div>
|
||||
</q-card-section>
|
||||
|
||||
<q-separator color="primary" style="height: 2px;" />
|
||||
|
||||
<!-- Validate entire Pay Period section -->
|
||||
<q-card-section
|
||||
horizontal
|
||||
class="q-pa-sm q-mt-sm text-weight-bold"
|
||||
:class="props.modelValue ? 'text-white bg-primary' : 'text-primary bg-white'"
|
||||
horizontal
|
||||
class="q-pa-sm text-weight-bold"
|
||||
:class="props.modelValue ? 'text-white bg-primary' : 'text-primary bg-white'"
|
||||
>
|
||||
<q-space />
|
||||
<q-checkbox
|
||||
|
|
|
|||
|
|
@ -11,11 +11,20 @@
|
|||
import { useTimesheetStore } from 'src/stores/timesheet-store';
|
||||
|
||||
const { t } = useI18n();
|
||||
const timesheetApprovalApi = useTimesheetApprovalApi();
|
||||
|
||||
const currentPayPeriod = getCurrentPayPeriod();
|
||||
const currentYear = (new Date()).getFullYear();
|
||||
|
||||
const originalApprovals = ref<Record<string, boolean>>({});
|
||||
const hasChanges = computed(() => {
|
||||
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>[] => [
|
||||
{ name: 'employee_name', label: t('timeSheetValidations.tableColumnLabelFullname'), field: 'employee_name', sortable: true },
|
||||
|
|
@ -30,7 +39,9 @@
|
|||
const filter = ref('');
|
||||
|
||||
onMounted( async () => {
|
||||
await timesheetApprovalApi.getCurrentAndAllPayPeriods();
|
||||
await timesheetApprovalApi.getTimesheetApprovalPayPeriodEmployeeOverviews(currentYear, currentPayPeriod, authStore.user.email);
|
||||
originalApprovals.value = Object.fromEntries( timesheetStore.payPeriodEmployeeOverviews.map(emp => [emp.email, emp.is_approved]));
|
||||
})
|
||||
</script>
|
||||
|
||||
|
|
@ -44,9 +55,10 @@
|
|||
:filter="filter"
|
||||
grid
|
||||
dense
|
||||
hide-pagination
|
||||
color="primary"
|
||||
:rows-per-page-options="[0]"
|
||||
card-container-class="justify-center q-gutter-md"
|
||||
card-container-class="justify-center"
|
||||
:loading="timesheetStore.isLoading"
|
||||
:no-data-label="$t('shared.failedToLoad')"
|
||||
:no-results-label="$t('shared.failedToSearch')"
|
||||
|
|
@ -54,7 +66,7 @@
|
|||
>
|
||||
<!-- Top Bar that contains Search, Title, Filters -->
|
||||
<template v-slot:top>
|
||||
<q-card flat class="full-width bg-transparent row q-px-md">
|
||||
<div class="full-width row">
|
||||
<q-space />
|
||||
|
||||
<!-- Filters toggle -->
|
||||
|
|
@ -79,7 +91,7 @@
|
|||
<q-icon name="search" color="primary"/>
|
||||
</template>
|
||||
</q-input>
|
||||
</q-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- Template for individual employee cards -->
|
||||
|
|
|
|||
|
|
@ -2,20 +2,15 @@
|
|||
import { useTimesheetStore } from 'src/stores/timesheet-store';
|
||||
|
||||
const timesheetStore = useTimesheetStore();
|
||||
|
||||
const updateCurrentPayPeriod = () => {
|
||||
timesheetStore.getCurrentPayPeriod();
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="column items-center">
|
||||
<div class="text-primary text-h5">{{ timesheetStore.currentPayPeriod?.label }}</div>
|
||||
<div class="text-primary text-h5">{{ timesheetStore.currentPayPeriod?.label || '' }}</div>
|
||||
<q-btn-group push rounded>
|
||||
<q-btn push icon="keyboard_arrow_left" color="primary" class="q-px-xl" />
|
||||
<q-btn push icon="date_range" color="primary" class="q-px-xl" @click="updateCurrentPayPeriod" />
|
||||
<q-btn push icon="keyboard_arrow_right" color="primary" class="q-px-xl" />
|
||||
<q-btn push icon="keyboard_arrow_left" color="primary" class="q-px-xl" @click="timesheetStore.getPreviousOrNextPayPeriod(-1)"/>
|
||||
<q-btn push icon="date_range" color="primary" class="q-px-xl" />
|
||||
<q-btn push icon="keyboard_arrow_right" color="primary" class="q-px-xl" @click="timesheetStore.getPreviousOrNextPayPeriod(1)"/>
|
||||
</q-btn-group>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -1,13 +1,18 @@
|
|||
import { useTimesheetStore } from "src/stores/timesheet-store";
|
||||
|
||||
export const useTimesheetApprovalApi = () => {
|
||||
const timesheetStore = useTimesheetStore();
|
||||
const timesheet_store = useTimesheetStore();
|
||||
|
||||
const getCurrentAndAllPayPeriods = async () => {
|
||||
await timesheet_store.getCurrentAndAllPayPeriods();
|
||||
}
|
||||
|
||||
const getTimesheetApprovalPayPeriodEmployeeOverviews = async (year: number, period_number: number, supervisor_email: string): Promise<void> => {
|
||||
await timesheetStore.getTimesheetApprovalPayPeriodEmployeeOverviews(year, period_number, supervisor_email);
|
||||
await timesheet_store.getTimesheetApprovalPayPeriodEmployeeOverviews(year, period_number, supervisor_email);
|
||||
}
|
||||
|
||||
return {
|
||||
getTimesheetApprovalPayPeriodEmployeeOverviews,
|
||||
getCurrentAndAllPayPeriods,
|
||||
}
|
||||
};
|
||||
|
|
@ -1,22 +1,11 @@
|
|||
import { api } from "src/boot/axios";
|
||||
import { mock_pay_periods } from "../timesheet-approval-test-constants";
|
||||
import type { PayPeriod } from "src/modules/shared/types/pay-period-interface";
|
||||
import type { PayPeriodOverview } from "../types/timesheet-approval-pay-period-overview-interface";
|
||||
import type { PayPeriodBundle } from "src/modules/shared/types/pay-period-bundle-interface";
|
||||
|
||||
export const timesheetApprovalService = {
|
||||
getCurrentPayPeriod: (): PayPeriod => {
|
||||
return {
|
||||
"period_number": 15,
|
||||
"start_date": "2025-07-27",
|
||||
"end_date": "2025-08-09",
|
||||
"year": 2025,
|
||||
"label": "2025-07-27 → 2025-08-09"
|
||||
} as PayPeriod;
|
||||
},
|
||||
|
||||
getAllPayPeriods: async () => {
|
||||
// TODO: REMOVE MOCK DATA PEFORE PUSHING TO PROD
|
||||
return await api.get(`/pay-periods/`) || mock_pay_periods;
|
||||
getCurrentAndAllPayPeriod: async (): Promise<PayPeriodBundle> => {
|
||||
const response = await api.get('pay-periods/bundle/current-and-all');
|
||||
return response.data;
|
||||
},
|
||||
|
||||
getPayPeriodEmployeeOverviews: async (year: number, period_number: number, supervisor_email: string): Promise<PayPeriodOverview> => {
|
||||
|
|
|
|||
|
|
@ -1,287 +1,287 @@
|
|||
import type { PayPeriod } from "../shared/types/pay-period-interface";
|
||||
import type { PayPeriodEmployeeOverview } from "./types/timesheet-approval-pay-period-employee-overview-interface"
|
||||
// import type { PayPeriod } from "../shared/types/pay-period-interface";
|
||||
// import type { PayPeriodEmployeeOverview } from "./types/timesheet-approval-pay-period-employee-overview-interface"
|
||||
|
||||
export const mock_pay_period_employee_overviews: PayPeriodEmployeeOverview[] = [
|
||||
{
|
||||
"email": 'EMP-001',
|
||||
"employee_name": 'Alice Johnson',
|
||||
"regular_hours": 75,
|
||||
"evening_hours": 12,
|
||||
"emergency_hours": 3,
|
||||
"overtime_hours": 5,
|
||||
"expenses": 120.50,
|
||||
"mileage": 45,
|
||||
"is_approved": false
|
||||
},
|
||||
{
|
||||
"email": 'EMP-002',
|
||||
"employee_name": 'Brian Smith',
|
||||
"regular_hours": 80,
|
||||
"evening_hours": 8,
|
||||
"emergency_hours": 0,
|
||||
"overtime_hours": 2,
|
||||
"expenses": 75.00,
|
||||
"mileage": 12,
|
||||
"is_approved": true
|
||||
},
|
||||
{
|
||||
"email": 'EMP-003',
|
||||
"employee_name": 'Chloe Ramirez',
|
||||
"regular_hours": 68,
|
||||
"evening_hours": 15,
|
||||
"emergency_hours": 1,
|
||||
"overtime_hours": 0,
|
||||
"expenses": 200.00,
|
||||
"mileage": 88,
|
||||
"is_approved": false
|
||||
},
|
||||
{
|
||||
"email": 'EMP-004',
|
||||
"employee_name": 'David Lee',
|
||||
"regular_hours": 82,
|
||||
"evening_hours": 5,
|
||||
"emergency_hours": 4,
|
||||
"overtime_hours": 6,
|
||||
"expenses": 50.75,
|
||||
"mileage": 20,
|
||||
"is_approved": true
|
||||
},
|
||||
{
|
||||
"email": 'EMP-005',
|
||||
"employee_name": 'Emily Carter',
|
||||
"regular_hours": 78,
|
||||
"evening_hours": 10,
|
||||
"emergency_hours": 2,
|
||||
"overtime_hours": 3,
|
||||
"expenses": 95.25,
|
||||
"mileage": 60,
|
||||
"is_approved": false
|
||||
},
|
||||
{
|
||||
"email": 'EMP-006',
|
||||
"employee_name": 'Maxime Murray Gendron',
|
||||
"regular_hours": 80,
|
||||
"evening_hours": 0,
|
||||
"emergency_hours": 0,
|
||||
"overtime_hours": 0,
|
||||
"expenses": 0,
|
||||
"mileage": 0,
|
||||
"is_approved": false
|
||||
},
|
||||
{
|
||||
"email": 'EMP-007',
|
||||
"employee_name": 'Marc-André Henrico',
|
||||
"regular_hours": 80,
|
||||
"evening_hours": 0,
|
||||
"emergency_hours": 0,
|
||||
"overtime_hours": 0,
|
||||
"expenses": 0,
|
||||
"mileage": 0,
|
||||
"is_approved": false
|
||||
},
|
||||
{
|
||||
"email": 'EMP-008',
|
||||
"employee_name": 'Jessy Sharock',
|
||||
"regular_hours": 80,
|
||||
"evening_hours": 0,
|
||||
"emergency_hours": 0,
|
||||
"overtime_hours": 0,
|
||||
"expenses": 0,
|
||||
"mileage": 0,
|
||||
"is_approved": false
|
||||
},
|
||||
{
|
||||
"email": 'EMP-009',
|
||||
"employee_name": 'David Richer',
|
||||
"regular_hours": 80,
|
||||
"evening_hours": 0,
|
||||
"emergency_hours": 0,
|
||||
"overtime_hours": 0,
|
||||
"expenses": 0,
|
||||
"mileage": 0,
|
||||
"is_approved": false
|
||||
},
|
||||
{
|
||||
"email": 'EMP-010',
|
||||
"employee_name": 'Nicolas Drolet',
|
||||
"regular_hours": 80,
|
||||
"evening_hours": 0,
|
||||
"emergency_hours": 0,
|
||||
"overtime_hours": 0,
|
||||
"expenses": 0,
|
||||
"mileage": 0,
|
||||
"is_approved": false
|
||||
},
|
||||
{
|
||||
"email": 'EMP-011',
|
||||
"employee_name": 'Frederick Pruneau',
|
||||
"regular_hours": 16,
|
||||
"evening_hours": 0,
|
||||
"emergency_hours": 0,
|
||||
"overtime_hours": 0,
|
||||
"expenses": 0,
|
||||
"mileage": 0,
|
||||
"is_approved": false
|
||||
},
|
||||
{
|
||||
"email": 'EMP-012',
|
||||
"employee_name": 'Matthieu Haineault Gervais',
|
||||
"regular_hours": 80,
|
||||
"evening_hours": 0,
|
||||
"emergency_hours": 0,
|
||||
"overtime_hours": 0,
|
||||
"expenses": 0,
|
||||
"mileage": 0,
|
||||
"is_approved": false
|
||||
},
|
||||
{
|
||||
"email": 'EMP-013',
|
||||
"employee_name": 'Robinson Viaud',
|
||||
"regular_hours": 80,
|
||||
"evening_hours": 0,
|
||||
"emergency_hours": 0,
|
||||
"overtime_hours": 0,
|
||||
"expenses": 0,
|
||||
"mileage": 0,
|
||||
"is_approved": false
|
||||
},
|
||||
{
|
||||
"email": 'EMP-014',
|
||||
"employee_name": 'Geneviève Bourdon',
|
||||
"regular_hours": 80,
|
||||
"evening_hours": 0,
|
||||
"emergency_hours": 0,
|
||||
"overtime_hours": 0,
|
||||
"expenses": 0,
|
||||
"mileage": 0,
|
||||
"is_approved": false
|
||||
},
|
||||
{
|
||||
"email": 'EMP-015',
|
||||
"employee_name": 'Frédérique Soulard',
|
||||
"regular_hours": 80,
|
||||
"evening_hours": 0,
|
||||
"emergency_hours": 0,
|
||||
"overtime_hours": 0,
|
||||
"expenses": 0,
|
||||
"mileage": 0,
|
||||
"is_approved": false
|
||||
},
|
||||
{
|
||||
"email": 'EMP-016',
|
||||
"employee_name": 'Patrick Doucet',
|
||||
"regular_hours": 80,
|
||||
"evening_hours": 0,
|
||||
"emergency_hours": 0,
|
||||
"overtime_hours": 0,
|
||||
"expenses": 0,
|
||||
"mileage": 0,
|
||||
"is_approved": false
|
||||
},
|
||||
{
|
||||
"email": 'EMP-017',
|
||||
"employee_name": 'Dahlia Tremblay',
|
||||
"regular_hours": 80,
|
||||
"evening_hours": 0,
|
||||
"emergency_hours": 0,
|
||||
"overtime_hours": 0,
|
||||
"expenses": 0,
|
||||
"mileage": 0,
|
||||
"is_approved": false
|
||||
},
|
||||
{
|
||||
"email": 'EMP-018',
|
||||
"employee_name": 'Louis Morneau',
|
||||
"regular_hours": 80,
|
||||
"evening_hours": 0,
|
||||
"emergency_hours": 0,
|
||||
"overtime_hours": 0,
|
||||
"expenses": 0,
|
||||
"mileage": 0,
|
||||
"is_approved": false
|
||||
},
|
||||
{
|
||||
"email": 'EMP-019',
|
||||
"employee_name": 'Michel Blais',
|
||||
"regular_hours": 80,
|
||||
"evening_hours": 0,
|
||||
"emergency_hours": 0,
|
||||
"overtime_hours": 0,
|
||||
"expenses": 0,
|
||||
"mileage": 0,
|
||||
"is_approved": false
|
||||
}
|
||||
];
|
||||
// export const mock_pay_period_employee_overviews: PayPeriodEmployeeOverview[] = [
|
||||
// {
|
||||
// "email": 'EMP-001',
|
||||
// "employee_name": 'Alice Johnson',
|
||||
// "regular_hours": 75,
|
||||
// "evening_hours": 12,
|
||||
// "emergency_hours": 3,
|
||||
// "overtime_hours": 5,
|
||||
// "expenses": 120.50,
|
||||
// "mileage": 45,
|
||||
// "is_approved": false
|
||||
// },
|
||||
// {
|
||||
// "email": 'EMP-002',
|
||||
// "employee_name": 'Brian Smith',
|
||||
// "regular_hours": 80,
|
||||
// "evening_hours": 8,
|
||||
// "emergency_hours": 0,
|
||||
// "overtime_hours": 2,
|
||||
// "expenses": 75.00,
|
||||
// "mileage": 12,
|
||||
// "is_approved": true
|
||||
// },
|
||||
// {
|
||||
// "email": 'EMP-003',
|
||||
// "employee_name": 'Chloe Ramirez',
|
||||
// "regular_hours": 68,
|
||||
// "evening_hours": 15,
|
||||
// "emergency_hours": 1,
|
||||
// "overtime_hours": 0,
|
||||
// "expenses": 200.00,
|
||||
// "mileage": 88,
|
||||
// "is_approved": false
|
||||
// },
|
||||
// {
|
||||
// "email": 'EMP-004',
|
||||
// "employee_name": 'David Lee',
|
||||
// "regular_hours": 82,
|
||||
// "evening_hours": 5,
|
||||
// "emergency_hours": 4,
|
||||
// "overtime_hours": 6,
|
||||
// "expenses": 50.75,
|
||||
// "mileage": 20,
|
||||
// "is_approved": true
|
||||
// },
|
||||
// {
|
||||
// "email": 'EMP-005',
|
||||
// "employee_name": 'Emily Carter',
|
||||
// "regular_hours": 78,
|
||||
// "evening_hours": 10,
|
||||
// "emergency_hours": 2,
|
||||
// "overtime_hours": 3,
|
||||
// "expenses": 95.25,
|
||||
// "mileage": 60,
|
||||
// "is_approved": false
|
||||
// },
|
||||
// {
|
||||
// "email": 'EMP-006',
|
||||
// "employee_name": 'Maxime Murray Gendron',
|
||||
// "regular_hours": 80,
|
||||
// "evening_hours": 0,
|
||||
// "emergency_hours": 0,
|
||||
// "overtime_hours": 0,
|
||||
// "expenses": 0,
|
||||
// "mileage": 0,
|
||||
// "is_approved": false
|
||||
// },
|
||||
// {
|
||||
// "email": 'EMP-007',
|
||||
// "employee_name": 'Marc-André Henrico',
|
||||
// "regular_hours": 80,
|
||||
// "evening_hours": 0,
|
||||
// "emergency_hours": 0,
|
||||
// "overtime_hours": 0,
|
||||
// "expenses": 0,
|
||||
// "mileage": 0,
|
||||
// "is_approved": false
|
||||
// },
|
||||
// {
|
||||
// "email": 'EMP-008',
|
||||
// "employee_name": 'Jessy Sharock',
|
||||
// "regular_hours": 80,
|
||||
// "evening_hours": 0,
|
||||
// "emergency_hours": 0,
|
||||
// "overtime_hours": 0,
|
||||
// "expenses": 0,
|
||||
// "mileage": 0,
|
||||
// "is_approved": false
|
||||
// },
|
||||
// {
|
||||
// "email": 'EMP-009',
|
||||
// "employee_name": 'David Richer',
|
||||
// "regular_hours": 80,
|
||||
// "evening_hours": 0,
|
||||
// "emergency_hours": 0,
|
||||
// "overtime_hours": 0,
|
||||
// "expenses": 0,
|
||||
// "mileage": 0,
|
||||
// "is_approved": false
|
||||
// },
|
||||
// {
|
||||
// "email": 'EMP-010',
|
||||
// "employee_name": 'Nicolas Drolet',
|
||||
// "regular_hours": 80,
|
||||
// "evening_hours": 0,
|
||||
// "emergency_hours": 0,
|
||||
// "overtime_hours": 0,
|
||||
// "expenses": 0,
|
||||
// "mileage": 0,
|
||||
// "is_approved": false
|
||||
// },
|
||||
// {
|
||||
// "email": 'EMP-011',
|
||||
// "employee_name": 'Frederick Pruneau',
|
||||
// "regular_hours": 16,
|
||||
// "evening_hours": 0,
|
||||
// "emergency_hours": 0,
|
||||
// "overtime_hours": 0,
|
||||
// "expenses": 0,
|
||||
// "mileage": 0,
|
||||
// "is_approved": false
|
||||
// },
|
||||
// {
|
||||
// "email": 'EMP-012',
|
||||
// "employee_name": 'Matthieu Haineault Gervais',
|
||||
// "regular_hours": 80,
|
||||
// "evening_hours": 0,
|
||||
// "emergency_hours": 0,
|
||||
// "overtime_hours": 0,
|
||||
// "expenses": 0,
|
||||
// "mileage": 0,
|
||||
// "is_approved": false
|
||||
// },
|
||||
// {
|
||||
// "email": 'EMP-013',
|
||||
// "employee_name": 'Robinson Viaud',
|
||||
// "regular_hours": 80,
|
||||
// "evening_hours": 0,
|
||||
// "emergency_hours": 0,
|
||||
// "overtime_hours": 0,
|
||||
// "expenses": 0,
|
||||
// "mileage": 0,
|
||||
// "is_approved": false
|
||||
// },
|
||||
// {
|
||||
// "email": 'EMP-014',
|
||||
// "employee_name": 'Geneviève Bourdon',
|
||||
// "regular_hours": 80,
|
||||
// "evening_hours": 0,
|
||||
// "emergency_hours": 0,
|
||||
// "overtime_hours": 0,
|
||||
// "expenses": 0,
|
||||
// "mileage": 0,
|
||||
// "is_approved": false
|
||||
// },
|
||||
// {
|
||||
// "email": 'EMP-015',
|
||||
// "employee_name": 'Frédérique Soulard',
|
||||
// "regular_hours": 80,
|
||||
// "evening_hours": 0,
|
||||
// "emergency_hours": 0,
|
||||
// "overtime_hours": 0,
|
||||
// "expenses": 0,
|
||||
// "mileage": 0,
|
||||
// "is_approved": false
|
||||
// },
|
||||
// {
|
||||
// "email": 'EMP-016',
|
||||
// "employee_name": 'Patrick Doucet',
|
||||
// "regular_hours": 80,
|
||||
// "evening_hours": 0,
|
||||
// "emergency_hours": 0,
|
||||
// "overtime_hours": 0,
|
||||
// "expenses": 0,
|
||||
// "mileage": 0,
|
||||
// "is_approved": false
|
||||
// },
|
||||
// {
|
||||
// "email": 'EMP-017',
|
||||
// "employee_name": 'Dahlia Tremblay',
|
||||
// "regular_hours": 80,
|
||||
// "evening_hours": 0,
|
||||
// "emergency_hours": 0,
|
||||
// "overtime_hours": 0,
|
||||
// "expenses": 0,
|
||||
// "mileage": 0,
|
||||
// "is_approved": false
|
||||
// },
|
||||
// {
|
||||
// "email": 'EMP-018',
|
||||
// "employee_name": 'Louis Morneau',
|
||||
// "regular_hours": 80,
|
||||
// "evening_hours": 0,
|
||||
// "emergency_hours": 0,
|
||||
// "overtime_hours": 0,
|
||||
// "expenses": 0,
|
||||
// "mileage": 0,
|
||||
// "is_approved": false
|
||||
// },
|
||||
// {
|
||||
// "email": 'EMP-019',
|
||||
// "employee_name": 'Michel Blais',
|
||||
// "regular_hours": 80,
|
||||
// "evening_hours": 0,
|
||||
// "emergency_hours": 0,
|
||||
// "overtime_hours": 0,
|
||||
// "expenses": 0,
|
||||
// "mileage": 0,
|
||||
// "is_approved": false
|
||||
// }
|
||||
// ];
|
||||
|
||||
export const mock_pay_periods: PayPeriod[] = [
|
||||
{
|
||||
"period_number": 15,
|
||||
"start_date": "2025-07-27",
|
||||
"end_date": "2025-08-09",
|
||||
"year": 2025,
|
||||
"label": "2025-07-27 → 2025-08-09"
|
||||
},
|
||||
{
|
||||
"period_number": 14,
|
||||
"start_date": "2025-07-13",
|
||||
"end_date": "2025-07-26",
|
||||
"year": 2025,
|
||||
"label": "2025-07-13 → 2025-07-26"
|
||||
},
|
||||
{
|
||||
"period_number": 13,
|
||||
"start_date": "2025-06-29",
|
||||
"end_date": "2025-07-12",
|
||||
"year": 2025,
|
||||
"label": "2025-06-29 → 2025-07-12"
|
||||
},
|
||||
{
|
||||
"period_number": 12,
|
||||
"start_date": "2025-06-15",
|
||||
"end_date": "2025-06-28",
|
||||
"year": 2025,
|
||||
"label": "2025-06-15 → 2025-06-28"
|
||||
},
|
||||
{
|
||||
"period_number": 11,
|
||||
"start_date": "2025-06-01",
|
||||
"end_date": "2025-06-14",
|
||||
"year": 2025,
|
||||
"label": "2025-06-01 → 2025-06-14"
|
||||
},
|
||||
{
|
||||
"period_number": 10,
|
||||
"start_date": "2025-05-18",
|
||||
"end_date": "2025-05-31",
|
||||
"year": 2025,
|
||||
"label": "2025-05-18 → 2025-05-31"
|
||||
},
|
||||
{
|
||||
"period_number": 9,
|
||||
"start_date": "2025-05-04",
|
||||
"end_date": "2025-05-17",
|
||||
"year": 2025,
|
||||
"label": "2025-05-04 → 2025-05-17"
|
||||
},
|
||||
{
|
||||
"period_number": 8,
|
||||
"start_date": "2025-04-20",
|
||||
"end_date": "2025-05-03",
|
||||
"year": 2025,
|
||||
"label": "2025-04-20 → 2025-05-03"
|
||||
},
|
||||
{
|
||||
"period_number": 7,
|
||||
"start_date": "2025-04-06",
|
||||
"end_date": "2025-04-19",
|
||||
"year": 2025,
|
||||
"label": "2025-04-06 → 2025-04-19"
|
||||
},
|
||||
{
|
||||
"period_number": 6,
|
||||
"start_date": "2025-03-23",
|
||||
"end_date": "2025-04-05",
|
||||
"year": 2025,
|
||||
"label": "2025-03-23 → 2025-04-05"
|
||||
}
|
||||
]
|
||||
// export const mock_pay_periods: PayPeriod[] = [
|
||||
// {
|
||||
// "period_number": 15,
|
||||
// "start_date": "2025-07-27",
|
||||
// "end_date": "2025-08-09",
|
||||
// "year": 2025,
|
||||
// "label": "2025-07-27 → 2025-08-09"
|
||||
// },
|
||||
// {
|
||||
// "period_number": 14,
|
||||
// "start_date": "2025-07-13",
|
||||
// "end_date": "2025-07-26",
|
||||
// "year": 2025,
|
||||
// "label": "2025-07-13 → 2025-07-26"
|
||||
// },
|
||||
// {
|
||||
// "period_number": 13,
|
||||
// "start_date": "2025-06-29",
|
||||
// "end_date": "2025-07-12",
|
||||
// "year": 2025,
|
||||
// "label": "2025-06-29 → 2025-07-12"
|
||||
// },
|
||||
// {
|
||||
// "period_number": 12,
|
||||
// "start_date": "2025-06-15",
|
||||
// "end_date": "2025-06-28",
|
||||
// "year": 2025,
|
||||
// "label": "2025-06-15 → 2025-06-28"
|
||||
// },
|
||||
// {
|
||||
// "period_number": 11,
|
||||
// "start_date": "2025-06-01",
|
||||
// "end_date": "2025-06-14",
|
||||
// "year": 2025,
|
||||
// "label": "2025-06-01 → 2025-06-14"
|
||||
// },
|
||||
// {
|
||||
// "period_number": 10,
|
||||
// "start_date": "2025-05-18",
|
||||
// "end_date": "2025-05-31",
|
||||
// "year": 2025,
|
||||
// "label": "2025-05-18 → 2025-05-31"
|
||||
// },
|
||||
// {
|
||||
// "period_number": 9,
|
||||
// "start_date": "2025-05-04",
|
||||
// "end_date": "2025-05-17",
|
||||
// "year": 2025,
|
||||
// "label": "2025-05-04 → 2025-05-17"
|
||||
// },
|
||||
// {
|
||||
// "period_number": 8,
|
||||
// "start_date": "2025-04-20",
|
||||
// "end_date": "2025-05-03",
|
||||
// "year": 2025,
|
||||
// "label": "2025-04-20 → 2025-05-03"
|
||||
// },
|
||||
// {
|
||||
// "period_number": 7,
|
||||
// "start_date": "2025-04-06",
|
||||
// "end_date": "2025-04-19",
|
||||
// "year": 2025,
|
||||
// "label": "2025-04-06 → 2025-04-19"
|
||||
// },
|
||||
// {
|
||||
// "period_number": 6,
|
||||
// "start_date": "2025-03-23",
|
||||
// "end_date": "2025-04-05",
|
||||
// "year": 2025,
|
||||
// "label": "2025-03-23 → 2025-04-05"
|
||||
// }
|
||||
// ]
|
||||
|
|
|
|||
|
|
@ -4,17 +4,31 @@ import { timesheetApprovalService } from 'src/modules/timesheet-approval/service
|
|||
import type { PayPeriod } from 'src/modules/shared/types/pay-period-interface';
|
||||
import type { PayPeriodEmployeeOverview } from "src/modules/timesheet-approval/types/timesheet-approval-pay-period-employee-overview-interface";
|
||||
|
||||
|
||||
const default_current_pay_period: PayPeriod = {"period_number": 1, "start_date": "1970-01-01", "end_date": "1970-01-15", "year": 1970, "label": "1970-01-01 → 1970-01-15"};
|
||||
|
||||
export const useTimesheetStore = defineStore('timesheet', () => {
|
||||
const payPeriods = ref<PayPeriod[]>([]);
|
||||
const currentPayPeriod = ref<PayPeriod>(default_current_pay_period);
|
||||
const currentPayPeriod = ref<PayPeriod>();
|
||||
const currentPayPeriodIndex = ref<number>(-1);
|
||||
const payPeriodEmployeeOverviews = ref<PayPeriodEmployeeOverview[]>([]);
|
||||
const isLoading = ref<boolean>(false);
|
||||
|
||||
const getCurrentPayPeriod = () => {
|
||||
currentPayPeriod.value = timesheetApprovalService.getCurrentPayPeriod();
|
||||
const getCurrentAndAllPayPeriods = async () => {
|
||||
isLoading.value = true;
|
||||
try {
|
||||
const response = await timesheetApprovalService.getCurrentAndAllPayPeriod();
|
||||
currentPayPeriod.value = response.current;
|
||||
payPeriods.value = response.periods;
|
||||
currentPayPeriodIndex.value = payPeriods.value.findIndex( pay_period => pay_period.pay_period_no === currentPayPeriod.value?.pay_period_no);
|
||||
} catch( error ){
|
||||
console.error('Could not get current pay period: ', error );
|
||||
}
|
||||
isLoading.value = false;
|
||||
};
|
||||
|
||||
const getPreviousOrNextPayPeriod = (direction: number) => {
|
||||
if ( currentPayPeriodIndex.value + direction >= 0 && currentPayPeriodIndex.value + direction < payPeriods.value.length ) {
|
||||
currentPayPeriodIndex.value += direction;
|
||||
currentPayPeriod.value = payPeriods.value.at(currentPayPeriodIndex.value);
|
||||
}
|
||||
}
|
||||
|
||||
const getTimesheetApprovalPayPeriodEmployeeOverviews = async (year: number, period_number: number, supervisor_email: string) => {
|
||||
|
|
@ -27,7 +41,7 @@ export const useTimesheetStore = defineStore('timesheet', () => {
|
|||
// TODO: trigger an alert window with an error message here!
|
||||
}
|
||||
isLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
return { payPeriods, currentPayPeriod, payPeriodEmployeeOverviews, isLoading, getCurrentPayPeriod, getTimesheetApprovalPayPeriodEmployeeOverviews};
|
||||
return { payPeriods, currentPayPeriod, payPeriodEmployeeOverviews, isLoading, getCurrentAndAllPayPeriods, getTimesheetApprovalPayPeriodEmployeeOverviews, getPreviousOrNextPayPeriod};
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user