feat(timesheet): created interfaces and access button to access and employee timesheet

This commit is contained in:
Matthieu Haineault 2025-08-29 16:29:07 -04:00
parent 61d2b96c32
commit 2eae6e5a21
10 changed files with 130 additions and 1 deletions

View File

@ -26,6 +26,7 @@ export default {
userMenuHome: 'Homepage',
userMenuEmployeeList: 'Employee Directory',
userMenuShiftValidation: 'Timesheet Approval',
userMenuTimesheetTemp: 'Timesheet',
userMenuProfile: 'Profile',
userMenuHelp: 'Help',
userMenuLogout: 'Log Out',

View File

@ -165,6 +165,7 @@ export default {
userMenuHome: 'Accueil',
userMenuEmployeeList: 'Répertoire employés',
userMenuShiftValidation: 'Valider les heures',
userMenuTimesheetTemp: 'Carte de temps',
userMenuProfile: 'Profil',
userMenuHelp: 'Aide',
userMenuLogout: 'Déconnexion',

View File

@ -62,6 +62,17 @@
</q-item-section>
</q-item>
<!-- Employee Timesheet temp -- Employee, Supervisor, Accounting only -->
<q-item v-ripple clickable side @click="goToPageName(RouteNames.TIMESHEET_TEMP)"
v-if="['supervisor', 'accounting', 'employee'].includes(authStore.user.role)">
<q-item-section avatar>
<q-icon name="punch_clock" color="primary" />
</q-item-section>
<q-item-section>
<q-item-label class="text-uppercase text-grey-8 text-weight-bold">{{ $t('navBar.userMenuTimesheetTemp') }}</q-item-label>
</q-item-section>
</q-item>
<!-- Profile -->
<q-item v-ripple clickable side @click="goToPageName(RouteNames.PROFILE)">
<q-item-section avatar>

View File

@ -0,0 +1,54 @@
<script setup lang="ts">
import { date } from 'quasar';
import { useTimesheetStore } from 'src/stores/timesheet-store';
import { computed } from 'vue';
import { useI18n } from 'vue-i18n';
const {locale} = useI18n();
const timeSheet_store = useTimesheetStore();
const date_options: Intl.DateTimeFormatOptions = {
day: 'numeric',
month: 'long',
year: 'numeric',
};
const timesheet_label = computed(() => {
const dates = timeSheet_store.current_timesheet.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'));
if ( dates.length === 1) {
return {
start_date: '_',
end_date: '_',
}
}
return { start_date, end_date };
});
</script>
<template>
<q-page
padding
class="q-pa-md bg secondary"
>
<div class="text-h4 row justify-center q-mt-lg text-uppercase text-weight-bolder text-gray-8">
{{ $t('pageTitles.timeSheets') }}
</div>
<div class="row items-center justify-center q-py-none q-my-none">
<div class="text-primary text-h6 text-uppercase">
{{ timesheet_label.start_date }}
</div>
<div class="text-primary text-h6 text-uppercase">
{{ $t('timeSheet.dateRangesTo') }}
</div>
<div class="text-primary text-h6 text-uppercase">
{{ timesheet_label.end_date }}
</div>
</div>
<!-- insert here TimesheetTemp -->
</q-page>
</template>

View File

@ -0,0 +1,9 @@
import { api } from "src/boot/axios";
import type {Timesheet} from "src/modules/timesheets/types/timesheet-interface";
export const timesheetTempService = {
getTimesheetsByNumberAndEmail: async ( timesheet_id: number, email: string): Promise<Timesheet> => {
const response = await api.get(`timesheet/id/${timesheet_id}/email/${email}`);
return response.data;
},
};

View File

@ -35,4 +35,11 @@ interface TimesheetDetailsDailyExpenses {
interface Expense {
is_approved: boolean;
amount: number;
};
};
//employee timesheet template
export interface EmployeeTimesheetDetailsWeek {
is_approved: boolean;
shifts: WeekDay<TimesheetDetailsDailySchedule>;
expenses: WeekDay<TimesheetDetailsDailyExpenses>;
}

View File

@ -0,0 +1,9 @@
export interface Timesheet {
timesheet_id: number;
is_approved: boolean;
start_day: string;
end_day: string;
label: string;
shifts: Shifts[];
expenses: Expenses;
}

View File

@ -6,4 +6,5 @@ export enum RouteNames {
TIMESHEET_APPROVALS = 'timesheet-approvals',
EMPLOYEE_LIST = 'employee-list',
PROFILE = 'user/profile',
TIMESHEET_TEMP = 'timesheet-temp'
}

View File

@ -22,6 +22,11 @@ const routes: RouteRecordRaw[] = [
name: RouteNames.EMPLOYEE_LIST,
component: () => import('src/modules/employee-list/pages/supervisor-crew-page.vue'),
},
{
path: 'timesheet-temp',
name: RouteNames.TIMESHEET_TEMP,
component: () => import('src/modules/timesheets/pages/timesheet-temp-page.vue')
}
],
},

View File

@ -5,6 +5,9 @@ import type { PayPeriod } from 'src/modules/shared/types/pay-period-interface';
import type { PayPeriodOverviewEmployee } from "src/modules/timesheet-approval/types/timesheet-approval-pay-period-overview-employee-interface";
import type { PayPeriodEmployeeDetails } from 'src/modules/timesheet-approval/types/timesheet-approval-pay-period-employee-details-interface';
import type { PayPeriodReportFilters } from 'src/modules/timesheet-approval/types/timesheet-approval-pay-period-report-interface';
import type { Timesheet } from 'src/modules/timesheets/types/timesheet-interface';
import { timesheetTempService } from 'src/modules/timesheets/services/timesheet-services';
import type { EmployeeTimesheetDetailsWeek } from 'src/modules/timesheets/types/timesheet-details-interface';
const default_pay_period: PayPeriod = {
pay_period_no: -1,
@ -15,6 +18,13 @@ const default_pay_period: PayPeriod = {
label: ''
};
const default_timesheet: Timesheet = {
timesheet_id: -1,
start_day: '',
end_day: '',
label: '',
};
export const useTimesheetStore = defineStore('timesheet', () => {
const is_loading = ref<boolean>(false);
const current_pay_period = ref<PayPeriod>(default_pay_period);
@ -23,6 +33,10 @@ export const useTimesheetStore = defineStore('timesheet', () => {
const pay_period_employee_details = ref<PayPeriodEmployeeDetails | undefined>();
const pay_period_report = ref();
//employee timesheet
const current_timesheet = ref<Timesheet>(default_timesheet);
const timesheet_employee_details = ref<EmployeeTimesheetDetailsWeek | undefined>();
const getPayPeriodByDate = async (date_string: string): Promise<boolean> => {
is_loading.value = true;
@ -85,6 +99,21 @@ export const useTimesheetStore = defineStore('timesheet', () => {
is_loading.value = false;
};
const getTimesheetByNumberAndEmail = async (employee_email: string) => {
is_loading.value = true;
try{
const response = await timesheetTempService.getTimesheetsByNumberAndEmail(
current_timesheet.value.timesheet_id,
employee_email
);
timesheet_employee_details.value = response;
}catch (error) {
console.error('There was an error retrieving timesheet details for this employee: ', error);
}
is_loading.value = false;
}
const getTimesheetsByPayPeriodAndEmail = async (employee_email: string) => {
is_loading.value = true;
@ -126,8 +155,10 @@ export const useTimesheetStore = defineStore('timesheet', () => {
pay_period_overview_employees,
pay_period_overview_employee_approval_statuses,
pay_period_employee_details,
current_timesheet,
is_loading,
getPayPeriodByDate,
getTimesheetByNumberAndEmail,
getPayPeriodByYearAndPeriodNumber,
getTimesheetApprovalPayPeriodEmployeeOverviews,
getTimesheetsByPayPeriodAndEmail,