refactor(employee-list): might finally be done with module, need to test add feature.

This commit is contained in:
Nicolas Drolet 2025-12-03 17:02:15 -05:00
parent af6cdbe890
commit 8852f5990b
6 changed files with 157 additions and 17 deletions

View File

@ -83,6 +83,7 @@ export default {
company: "company", company: "company",
supervisor: "supervisor", supervisor: "supervisor",
hired_date: "hiring date", hired_date: "hiring date",
fired_date: "departure date",
bankroll_id: "payroll ID", bankroll_id: "payroll ID",
}, },
preferences: { preferences: {

View File

@ -83,6 +83,7 @@ export default {
company: "compagnie", company: "compagnie",
supervisor: "nom du superviseur", supervisor: "nom du superviseur",
hired_date: "date d'embauche", hired_date: "date d'embauche",
fired_date: "date de départ",
bankroll_id: "identifiant de paie", bankroll_id: "identifiant de paie",
}, },
preferences: { preferences: {

View File

@ -2,9 +2,13 @@
setup setup
lang="ts" lang="ts"
> >
import { ref, computed } from 'vue';
import { useEmployeeStore } from 'src/stores/employee-store'; import { useEmployeeStore } from 'src/stores/employee-store';
const employee_store = useEmployeeStore(); const employee_store = useEmployeeStore();
const last_work_day = computed(() => employee_store.employee.last_work_day ?? '---');
const is_first_day_picker_open = ref(false);
const is_last_day_picker_open = ref(false);
</script> </script>
<template> <template>
@ -75,6 +79,7 @@
color="accent" color="accent"
stack-label stack-label
label-slot label-slot
mask="(###) ### - ####"
class="col q-mx-md" class="col q-mx-md"
> >
<template #label> <template #label>
@ -149,7 +154,8 @@
</q-input> </q-input>
<q-input <q-input
v-model="employee_store.employee.phone_number" v-if="employee_store.management_mode === 'modify_employee'"
v-model="employee_store.employee.external_payroll_id"
color="accent" color="accent"
stack-label stack-label
label-slot label-slot
@ -165,6 +171,93 @@
</template> </template>
</q-input> </q-input>
</div> </div>
<div
class="q-ma-xs"
:class="$q.screen.lt.md ? 'column' : 'row'"
>
<q-input
v-model="employee_store.employee.first_work_day"
color="accent"
stack-label
label-slot
mask="####-##-##"
class="col q-mx-md"
>
<template #label>
<span
class="text-weight-bolder text-uppercase"
style="font-size: 0.85em;"
>
{{ $t('profile.employee.hired_date') }}
</span>
</template>
<template #append>
<q-btn
flat
dense
size="lg"
icon="calendar_month"
color="accent"
@click="is_first_day_picker_open = true"
>
<q-dialog
v-model="is_first_day_picker_open"
backdrop-filter="none"
>
<q-date
v-model="employee_store.employee.first_work_day"
mask="YYYY-MM-DD"
color="accent"
@update:model-value="is_first_day_picker_open = false"
/>
</q-dialog>
</q-btn>
</template>
</q-input>
<q-input
v-model="last_work_day"
color="accent"
stack-label
label-slot
mask="####-##-##"
class="col q-mx-md"
>
<template #label>
<span
class="text-weight-bolder text-uppercase"
style="font-size: 0.85em;"
>
{{ $t('profile.employee.fired_date') }}
</span>
</template>
<template #append>
<q-btn
flat
dense
size="lg"
icon="calendar_month"
color="accent"
@click="is_last_day_picker_open = true"
>
<q-dialog
v-model="is_last_day_picker_open"
backdrop-filter="none"
>
<q-date
v-model="employee_store.employee.last_work_day"
mask="YYYY-MM-DD"
color="accent"
@update:model-value="is_last_day_picker_open = false"
/>
</q-dialog>
</q-btn>
</template>
</q-input>
</div>
</q-form> </q-form>
</div> </div>
</template> </template>

View File

@ -124,6 +124,7 @@
color="accent" color="accent"
:label="employee_store.management_mode === 'add_employee' ? $t('shared.label.save') : $t('shared.label.update')" :label="employee_store.management_mode === 'add_employee' ? $t('shared.label.save') : $t('shared.label.update')"
class="col-auto q-py-sm shadow-up-5" class="col-auto q-py-sm shadow-up-5"
@click="employee_store.createOrUpdateEmployee(employee_store.employee)"
/> />
<q-inner-loading :showing="employee_store.is_loading" /> <q-inner-loading :showing="employee_store.is_loading" />
</div> </div>

View File

@ -1,19 +1,33 @@
import { api } from 'src/boot/axios'; import { api } from 'src/boot/axios';
import type { EmployeeProfile } from 'src/modules/employee-list/models/employee-profile.models'; import { EmployeeProfile } from 'src/modules/employee-list/models/employee-profile.models';
import type { BackendResponse } from 'src/modules/shared/models/backend-response.models';
export const EmployeeListService = { export const EmployeeListService = {
getEmployeeList: async (): Promise<EmployeeProfile[]> => { getEmployeeList: async (): Promise<EmployeeProfile[]> => {
const response = await api.get<{success: boolean, data: EmployeeProfile[], error?: string }>('/employees/employee-list') const response = await api.get<BackendResponse<EmployeeProfile[]>>('/employees/employee-list')
return response.data.data; if (response.data.data) return response.data.data;
return [];
}, },
getEmployeeDetails: async (): Promise<EmployeeProfile> => { getEmployeeDetails: async (): Promise<EmployeeProfile> => {
const response = await api.get<{success: boolean, data: EmployeeProfile, error?: string}>('employees/profile'); const response = await api.get<BackendResponse<EmployeeProfile>>('employees/profile');
return response.data.data; if (response.data.data) return response.data.data;
return new EmployeeProfile;
}, },
getEmployeeDetailsWithEmployeeEmail: async (employee_email: string): Promise<EmployeeProfile> => { getEmployeeDetailsWithEmployeeEmail: async (employee_email: string): Promise<EmployeeProfile> => {
const response = await api.get<{success: boolean, data: EmployeeProfile, error?: string}>(`employees/profile?employee_email=${employee_email}`); const response = await api.get<BackendResponse<EmployeeProfile>>(`employees/profile?employee_email=${employee_email}`);
return response.data.data; if (response.data.data) return response.data.data;
} return new EmployeeProfile;
},
createNewEmployee: async (profile: Omit<EmployeeProfile, 'last_work_day' | 'birth_date' | 'external_payroll_id'>): Promise<boolean> => {
const response = await api.post<BackendResponse<EmployeeProfile>>('employees/create', profile);
return response.data.success;
},
updateEmployee: async (profile: EmployeeProfile): Promise<boolean> => {
const response = await api.patch<BackendResponse<EmployeeProfile>>('employees/update', profile);
return response.data.success;
},
}; };

View File

@ -1,7 +1,9 @@
/* eslint-disable */
import { ref } from "vue"; import { ref } from "vue";
import { defineStore } from "pinia"; import { defineStore } from "pinia";
import { EmployeeListService } from "src/modules/employee-list/services/employee-list-service"; import { EmployeeListService } from "src/modules/employee-list/services/employee-list-service";
import { EmployeeProfile } from "src/modules/employee-list/models/employee-profile.models"; import { EmployeeProfile } from "src/modules/employee-list/models/employee-profile.models";
import { Notify } from "quasar";
export const useEmployeeStore = defineStore('employee', () => { export const useEmployeeStore = defineStore('employee', () => {
const employee = ref<EmployeeProfile>(new EmployeeProfile); const employee = ref<EmployeeProfile>(new EmployeeProfile);
@ -10,7 +12,7 @@ export const useEmployeeStore = defineStore('employee', () => {
const management_mode = ref<'modify_employee' | 'add_employee'>('add_employee'); const management_mode = ref<'modify_employee' | 'add_employee'>('add_employee');
const is_loading = ref(false); const is_loading = ref(false);
const openAddModifyDialog = async (employee_email?: string) =>{ const openAddModifyDialog = async (employee_email?: string) => {
is_add_modify_dialog_open.value = true; is_add_modify_dialog_open.value = true;
if (employee_email === undefined) { if (employee_email === undefined) {
@ -25,6 +27,12 @@ export const useEmployeeStore = defineStore('employee', () => {
is_loading.value = false; is_loading.value = false;
} }
const closeAddModifyDialog = () => {
is_add_modify_dialog_open.value = false;
management_mode.value = 'add_employee';
employee.value = new EmployeeProfile;
};
const getEmployeeList = async () => { const getEmployeeList = async () => {
is_loading.value = true; is_loading.value = true;
try { try {
@ -43,7 +51,7 @@ export const useEmployeeStore = defineStore('employee', () => {
if (email === undefined) { if (email === undefined) {
const response = await EmployeeListService.getEmployeeDetails(); const response = await EmployeeListService.getEmployeeDetails();
employee.value = response; employee.value = response;
} else{ } else {
const response = await EmployeeListService.getEmployeeDetailsWithEmployeeEmail(email); const response = await EmployeeListService.getEmployeeDetailsWithEmployeeEmail(email);
employee.value = response; employee.value = response;
} }
@ -55,15 +63,37 @@ export const useEmployeeStore = defineStore('employee', () => {
is_loading.value = false; is_loading.value = false;
}; };
return { const createOrUpdateEmployee = async (profile: EmployeeProfile) => {
employee, let success = false;
employee_list,
if (management_mode.value === 'add_employee') {
const { birth_date, external_payroll_id, last_work_day, ...create_payload} = profile;
success = await EmployeeListService.createNewEmployee(create_payload);
} else {
success = await EmployeeListService.updateEmployee(profile);
}
closeAddModifyDialog();
if (success) { await getEmployeeList(); }
else { Notify.create({
message: 'failed to update or create employee',
color: 'negative',
})}
};
return {
employee,
employee_list,
is_add_modify_dialog_open, is_add_modify_dialog_open,
management_mode, management_mode,
is_loading, is_loading,
getEmployeeList, getEmployeeList,
getEmployeeDetails, getEmployeeDetails,
openAddModifyDialog, openAddModifyDialog,
closeAddModifyDialog,
createOrUpdateEmployee,
}; };
}); });