fix(app): refactor and slim i18n files, correct and update pages, rework and refactor verbose code on some components and pages

This commit is contained in:
Nicolas Drolet 2025-09-22 14:11:29 -04:00
parent 45b2c3eef0
commit dec2ec84f1
20 changed files with 141 additions and 139 deletions

View File

@ -106,7 +106,7 @@ export default defineConfig((ctx) => {
color: 'primary',
avatar: 'https://cdn.quasar.dev/img/boy-avatar.png',
},
dark: 'auto',
dark: false,
},
// iconSet: 'material-icons', // Quasar icon set

View File

@ -24,18 +24,12 @@
background: #00ff260c;
}
div.q-dark {
color: $grey-2;
}
div.q-light {
color: $grey-8;
}
body.body--dark {
--q-secondary: #0f1114;
color: $grey-2;
}
.body--light {
--q-dark: #FFF;
color: $grey-8;
}

View File

@ -22,8 +22,7 @@ $elevation-dark-umbra : rgba($dark-shadow-color, 0.4);
$elevation-dark-penumbra : rgba($dark-shadow-color, 0);
$elevation-dark-ambient : rgba($dark-shadow-color, 0);
$dark-shadow-2 : 0 3px 5px -1px $elevation-dark-umbra, 0 5px 8px $elevation-dark-penumbra, 0 1px 14px $elevation-dark-ambient;
$dark-shadow-2 : 0 3px 5px -1px $elevation-dark-umbra, 0 5px 8px $elevation-dark-penumbra, 0 1px 14px $elevation-dark-ambient;
$layout-shadow-dark : 0 0 10px 5px rgba($dark-shadow-color, 0.5);
$dark : #333;

View File

@ -90,6 +90,8 @@ export default {
from: "from",
yes: "yes",
no: "no",
in: "in",
out: "out",
},
shift_type: {
regular: "regular",

View File

@ -90,6 +90,8 @@ export default {
from: "de",
yes: "oui",
no: "non",
in: "entrée",
out: "sortie",
},
shift_type: {
regular: "régulier",

View File

@ -47,13 +47,13 @@
v-model="employee_form_data.job_title"
class="col"
:is-editing="is_editing"
:label-string="$t('profilePage.employeeInfo.jobTitle')"
:label-string="$t('profile.employee.job_title')"
/>
<ProfileInputField
v-model="employee_form_data.company_name"
class="col"
:is-editing="is_editing"
:label-string="$t('profilePage.employeeInfo.companyName')"
:label-string="$t('profile.employee.company')"
/>
</div>
@ -61,7 +61,7 @@
<ProfileSelectField
v-model="employee_form_data.supervisor_full_name"
:options="supervisor_options"
:label-string="$t('profilePage.employeeInfo.supervisorName')"
:label-string="$t('profile.employee.supervisor')"
:is-editing="is_editing"
/>
</div>
@ -72,7 +72,7 @@
v-model="employee_form_data.email"
class="col"
:is-editing="is_editing"
:label-string="$t('profilePage.employeeInfo.workEmail')"
:label-string="$t('profile.employee.email')"
/>
<ProfileInputField
v-model="employee_form_data.first_work_day"
@ -80,7 +80,7 @@
class="col"
type="date"
:is-editing="is_editing"
:label-string="$t('profilePage.employeeInfo.hiredDate')"
:label-string="$t('profile.employee.hired_date')"
/>
</div>
@ -94,7 +94,7 @@
type="reset"
icon="cancel"
class="q-ma-sm"
:label="$t('timesheet.cancel_button')"
:label="$t('shared.label.cancel')"
/>
<q-btn
push
@ -102,7 +102,7 @@
color="primary"
:icon="is_editing ? 'save_alt' : 'create'"
class="q-ma-sm"
:label="is_editing ? $t('timesheet.saveButton') : $t('shiftsTemplate.updateButton')"
:label="is_editing ? $t('shared.label.save') : $t('shared.label.update')"
/>
</div>
</q-form>

View File

@ -46,14 +46,14 @@
type="text"
class="col"
:is-editing="is_editing"
:label-string="$t('profilePage.personalInfo.firstName')"
:label-string="$t('profile.personal.first_name')"
/>
<ProfileInputField
v-model="personal_form_data.last_name"
class="col"
type="text"
:is-editing="is_editing"
:label-string="$t('profilePage.personalInfo.lastName')"
:label-string="$t('profile.personal.last_name')"
/>
</div>
@ -63,7 +63,7 @@
class="col"
type="text"
:is-editing="is_editing"
:label-string="$t('profilePage.personalInfo.phoneNumber')"
:label-string="$t('profile.personal.phone_number')"
/>
<ProfileInputField
v-model="personal_form_data.birth_date"
@ -71,7 +71,7 @@
mask="#### / ## / ##"
hint="ex: 1970 / 01 / 01"
:is-editing="is_editing"
:label-string="$t('profilePage.personalInfo.birthDate')"
:label-string="$t('profile.personal.birthdate')"
/>
</div>
@ -80,8 +80,8 @@
v-model="personal_form_data.residence"
class="col"
:is-editing="is_editing"
:label-string="$t('profilePage.personalInfo.address')"
:hint="$t('profilePage.personalInfo.addressPlaceholder')"
:label-string="$t('profile.personal.address')"
:hint="$t('profile.personal.address_hint')"
/>
</div>
@ -104,7 +104,7 @@
type="submit"
:icon="is_editing ? 'save_alt' : 'create'"
class="q-ma-sm"
:label="is_editing ? $t('timesheet.saveButton') : $t('shiftsTemplate.updateButton')"
:label="is_editing ? $t('shared.label.save') : $t('shared.label.update')"
/>
</div>
</q-form>

View File

@ -23,7 +23,7 @@
filled
debounce="500"
label-color="primary"
class="q-ma-xs"
class="q-ma-xs text-uppercase"
input-class="text-weight-medium text-h6"
:hide-hint="hint === ''"
:hint="isEditing ? hint : ''"

View File

@ -14,7 +14,7 @@
<template>
<q-form class="q-pa-md column fit">
<div class="col-auto text-uppercase rounded-5" style="line-height: 1em;">{{ $t('profilePage.preferences.display_options') }}</div>
<div class="col-auto text-uppercase rounded-5" style="line-height: 1em;">{{ $t('profile.preferences.display_options') }}</div>
<q-card
flat
class="col-auto column justify-center items-center content-center q-mb-lg q-pa-md"
@ -38,7 +38,7 @@
</div>
<div class="bg-primary col-1"></div>
</div>
<span class="col-auto text-subtitle2 text-primary text-center text-uppercase">{{$t('profilePage.preferences.light_mode')}}</span>
<span class="col-auto text-subtitle2 text-primary text-center text-uppercase">{{$t('profile.preferences.light_mode')}}</span>
</q-card>
<q-toggle
@ -66,12 +66,12 @@
</div>
<div class="bg-primary col-1"></div>
</div>
<span class="col-auto text-subtitle2 text-primary text-center text-uppercase">{{$t('profilePage.preferences.dark_mode')}}</span>
<span class="col-auto text-subtitle2 text-primary text-center text-uppercase">{{$t('profile.preferences.dark_mode')}}</span>
</q-card>
</div>
</q-card>
<div class="col-auto text-uppercase rounded-5" style="line-height: 1em;">{{ $t('profilePage.preferences.language_options') }}</div>
<div class="col-auto text-uppercase rounded-5" style="line-height: 1em;">{{ $t('profile.preferences.language_options') }}</div>
<q-card
flat
class="col-auto column justify-center items-center content-center q-mb-lg q-pa-md"

View File

@ -18,7 +18,7 @@
:stack-label="!isEditing"
filled
label-color="primary"
class="q-ma-xs text-h6"
class="q-ma-xs text-h6 text-uppercase"
popup-content-class="text-weight-medium text-h6"
input-class="text-weight-medium"
:options="options"

View File

@ -28,17 +28,17 @@
<q-tab
:name='PanelNames.PERSONAL_INFO'
icon='person_outline'
:label="$q.screen.lt.md ? '' : $t('profilePage.personalInfo.title')"
:label="$q.screen.lt.md ? '' : $t('profile.personal.tab_title')"
/>
<q-tab
:name="PanelNames.EMPLOYEE_INFO"
icon="work_outline"
:label="$q.screen.lt.md ? '' : $t('profilePage.employeeInfo.title')"
:label="$q.screen.lt.md ? '' : $t('profile.employee.tab_title')"
/>
<q-tab
:name="PanelNames.PREFERENCES"
icon="display_settings"
:label="$q.screen.lt.md ? '' : $t('profilePage.preferences.title')"
:label="$q.screen.lt.md ? '' : $t('profile.preferences.tab_title')"
/>
</template>

View File

@ -3,15 +3,17 @@
import { colors } from 'quasar';
import { Bar } from 'vue-chartjs';
import { useI18n } from 'vue-i18n';
import { useQuasar } from 'quasar';
import { Chart as ChartJS, Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale, type ChartData, type ChartOptions, type Plugin, type ChartDataset } from 'chart.js';
import type { PayPeriodEmployeeDetails } from 'src/modules/timesheet-approval/types/timesheet-approval-pay-period-employee-details-interface';
const { t } = useI18n();
const $q = useQuasar();
ChartJS.register(Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale);
ChartJS.defaults.font.family = '"Roboto", sans-serif';
ChartJS.defaults.maintainAspectRatio = false;
ChartJS.defaults.color = $q.dark.isActive ? '#F5F5F5' : '#616161';
const props = defineProps<{
rawData: PayPeriodEmployeeDetails | undefined;
@ -29,22 +31,22 @@
const datasetConfig = [
{
key: 'regular_hours',
label: t('timeSheetValidations.hoursWorkedRegular'),
label: t('shared.shift_type.regular'),
color: colors.getPaletteColor('green-5'),
},
{
key: 'evening_hours',
label: t('timeSheetValidations.hoursWorkedEvening'),
label: t('shared.shift_type.evening'),
color: colors.getPaletteColor('green-9'),
},
{
key: 'emergency_hours',
label: t('timeSheetValidations.hoursWorkedEmergency'),
label: t('shared.shift_type.emergency'),
color: getComputedStyle(document.body).getPropertyValue('--q-warning').trim(),
},
{
key: 'overtime_hours',
label: t('timeSheetValidations.hoursWorkedOvertime'),
label: t('shared.shift_type.overtime'),
color: getComputedStyle(document.body).getPropertyValue('--q-negative').trim(),
},
] as const;
@ -67,33 +69,34 @@
</script>
<template>
<Bar
:data="getHoursWorkedData()"
:options="({
indexAxis: $q.screen.lt.md? 'y' : 'x',
plugins: {
legend: {
labels: {
boxWidth: 15,
<div>
<Bar
:data="getHoursWorkedData()"
:options="({
indexAxis: $q.screen.lt.md? 'y' : 'x',
plugins: {
legend: {
labels: {
boxWidth: 15,
},
},
title: {
display: true,
text: t('timesheet_approvals.chart.hours_worked_title'),
}
},
title: {
display: true,
text: t('timeSheetValidations.hoursWorkedChartTitle'),
color: '#616161'
scales: {
x: {
stacked: true,
},
y: {
stacked: true,
suggestedMin: 0,
suggestedMax: 10,
}
}
},
scales: {
x: {
stacked: true,
},
y: {
stacked: true,
suggestedMin: 0,
suggestedMax: 10,
}
}
})"
/>
})"
/>
</div>
</template>

View File

@ -3,15 +3,18 @@
import { ref } from 'vue';
import { colors } from 'quasar';
import { useI18n } from 'vue-i18n';
import { useQuasar } from 'quasar';
import { Doughnut } from 'vue-chartjs';
import { Chart as ChartJS, Title, Tooltip, Legend, ArcElement, CategoryScale, LinearScale, type ChartData, type ChartOptions, type Plugin, type ChartDataset } from 'chart.js';
import { Chart as ChartJS, Title, Tooltip, Legend, ArcElement, CategoryScale, LinearScale, type ChartDataset } from 'chart.js';
import type { PayPeriodOverviewEmployee } from 'src/modules/timesheet-approval/types/timesheet-approval-pay-period-overview-employee-interface';
const { t } = useI18n();
const $q = useQuasar();
ChartJS.register(Title, Tooltip, Legend, ArcElement, CategoryScale, LinearScale);
ChartJS.defaults.font.family = '"Roboto", sans-serif';
ChartJS.defaults.maintainAspectRatio = false;
ChartJS.defaults.color = $q.dark.isActive ? '#F5F5F5' : '#616161';
const props = defineProps<{
rawData: PayPeriodOverviewEmployee | undefined;
@ -52,16 +55,18 @@
</script>
<template>
<Doughnut
:data="data"
:options="({
plugins:{
legend:{
labels:{
boxWidth: 15,
<div>
<Doughnut
:data="data"
:options="({
plugins:{
legend:{
labels:{
boxWidth: 15,
}
}
}
}
})"
/>
})"
/>
</div>
</template>

View File

@ -1,17 +1,19 @@
<script setup lang="ts">
/*eslint-disable*/
import { ref } from 'vue';
import { Bar } from 'vue-chartjs';
import { useI18n } from 'vue-i18n';
import { Chart as ChartJS, Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale, TimeScale, type ChartData, type ChartOptions, type Plugin, type ChartDataset } from 'chart.js';
import { useQuasar } from 'quasar';
import { Chart as ChartJS, Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale, TimeScale, type ChartData, type ChartDataset } from 'chart.js';
import type { PayPeriodEmployeeDetails } from 'src/modules/timesheet-approval/types/timesheet-approval-pay-period-employee-details-interface';
import type { Expense } from 'src/modules/timesheets/types/timesheet-details-interface';
const { t } = useI18n();
const $q = useQuasar();
ChartJS.register(Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale, TimeScale);
ChartJS.defaults.font.family = '"Roboto", sans-serif';
ChartJS.defaults.maintainAspectRatio = false;
ChartJS.defaults.color = $q.dark.isActive ? '#F5F5F5' : '#616161';
const props = defineProps<{
rawData: PayPeriodEmployeeDetails | undefined;
@ -32,12 +34,12 @@
expenses_dataset.value = [
{
label: t('timesheet.refund'),
label: t('timesheet_approvals.table.expenses'),
data: all_costs,
backgroundColor: getComputedStyle(document.body).getPropertyValue('--q-primary').trim(),
},
{
label: t('timesheet.mileage'),
label: t('timesheet_approvals.table.mileage'),
data: all_mileage,
backgroundColor: getComputedStyle(document.body).getPropertyValue('--q-info').trim(),
}
@ -64,33 +66,34 @@
</script>
<template>
<Bar
:data="getExpensesData()"
:options="({
indexAxis: $q.screen.lt.md? 'y' : 'x',
plugins: {
title: {
display: true,
text: t('timeSheetValidations.reportFilterExpenses'),
color: '#616161'
<div>
<Bar
:data="getExpensesData()"
:options="({
indexAxis: $q.screen.lt.md? 'y' : 'x',
plugins: {
title: {
display: true,
text: t('timesheet_approvals.chart.expenses_title'),
},
legend:{
labels:{
boxWidth: 15,
}
}
},
legend:{
labels:{
boxWidth: 15,
scales: {
x: {
stacked: true
},
y: {
suggestedMin: 0,
suggestedMax: 100,
stacked: true
}
}
},
scales: {
x: {
stacked: true
},
y: {
suggestedMin: 0,
suggestedMax: 100,
stacked: true
}
}
})"
:style="$q.screen.lt.md ? 'min-height: 300px;': '' "
/>
})"
/>
</div>
</template>

View File

@ -9,7 +9,7 @@
<!-- punch-in timestamps -->
<q-card-section class="col q-pa-none">
<q-item-label class="text-weight-bolder text-primary" style="font-size: 0.7em;">
{{ $t('shiftColumns.labelIn') }}
{{ $t('shared.misc.in') }}
</q-item-label>
</q-card-section>
@ -20,7 +20,7 @@
<!-- punch-out timestamps -->
<q-card-section class="col q-pa-none">
<q-item-label class="text-weight-bolder text-primary" style="font-size: 0.7em;">
{{ $t('shiftColumns.labelOut') }}
{{ $t('shared.misc.out') }}
</q-item-label>
</q-card-section>

View File

@ -30,32 +30,32 @@
const shift_type_legend: shiftColor[] = [
{
type: t('timesheet.shift_types.REGULAR'),
type: t('shared.shift_type.regular'),
color: 'secondary',
text_color: 'grey-8',
text_color: '',
},
{
type: t('timesheet.shift_types.EVENING'),
type: t('shared.shift_type.evening'),
color: 'warning',
},
{
type: t('timesheet.shift_types.EMERGENCY'),
type: t('shared.shift_type.emergency'),
color: 'amber-10',
},
{
type: t('timeSheetValidations.hoursWorkedOvertime'),
type: t('shared.shift_type.overtime'),
color: 'negative',
},
{
type: t('timesheet.shift_types.VACATION'),
type: t('shared.shift_type.vacation'),
color: 'purple-10',
},
{
type: t('timesheet.shift_types.HOLIDAY'),
type: t('shared.shift_type.holiday'),
color: 'purple-8',
},
{
type: t('timesheet.shift_types.SICK'),
type: t('shared.shift_type.sick'),
color: 'grey-8',
},
]
@ -64,7 +64,7 @@
<template>
<q-card
class="q-pa-sm shadow-12 rounded-15 column no-wrap relative"
:style="$q.screen.gt.sm ? 'width: 70vw !important; height: 90vh !important;' : '' "
:style="$q.screen.lt.md ? '' : 'width: 60vw !important; height: 70vh !important;' "
>
<!-- loader -->
<q-card-section
@ -88,7 +88,7 @@
>
{{ props.employeeName }}
<q-separator class="q-mb-sm" size="2px" />
<q-separator spaced size="2px" />
<q-card-actions align="center" class="q-pa-none">
<q-card flat class="bg-secondary rounded-5 q-pa-xs">
<q-btn-toggle
@ -134,33 +134,30 @@
</q-card-section>
</q-card-section>
<!-- employee timesheet details, but look at these graphs -->
<!-- employee timesheet details with graphs -->
<q-card-section v-if="!props.isLoading && is_showing_graph" class="q-pa-md col column full-width no-wrap">
<q-card-section class="q-pa-none col no-wrap" style="min-height: 300px;">
<q-card-section :horizontal="!$q.screen.lt.md" class="q-pa-none col no-wrap" style="min-height: 300px;">
<TimesheetApprovalEmployeeDetailsHoursWorkedChart
:raw-data="props.employeeDetails"
class="col-7"
/>
</q-card-section>
<q-separator class="q-ma-sm"/>
<q-card-section
:horizontal="$q.screen.gt.sm"
class="justify-center no-wrap col full-width q-pa-none"
>
<q-card-section class="q-pa-none q-ma-none col-4">
<q-separator vertical spaced />
<div class="column col justify-center no-wrap q-pa-none">
<TimesheetApprovalEmployeeDetailsShiftTypesChart
:raw-data="props.employeeOverview"
class="col-5"
/>
</q-card-section>
<q-separator :vertical="$q.screen.gt.sm" class="q-ma-md" />
<q-card-section class="q-pa-none q-ma-none col" :class="$q.screen.lt.md ? 'full-width' : ''">
<q-separator :vertical="$q.screen.lt.md" spaced />
<TimesheetApprovalEmployeeExpensesChart
:raw-data="props.employeeDetails"
class="col"
/>
</q-card-section>
</div>
</q-card-section>
</q-card-section>
</q-card>

View File

@ -19,13 +19,11 @@ export const timesheetApprovalService = {
getPayPeriodEmployeeOverviews: async (year: number, period_number: number, supervisor_email: string): Promise<PayPeriodOverview> => {
// TODO: REMOVE MOCK DATA PEFORE PUSHING TO PROD
const response = await api.get(`pay-periods/${year}/${period_number}/${supervisor_email}`);
console.log('pay period data: ', response.data);
return response.data;
},
getTimesheetsByPayPeriodAndEmail: async (year: number, period_no: number, email: string): Promise<PayPeriodEmployeeDetails> => {
const response = await api.get('timesheets', { params: { year, period_no, email, }});
console.log('employee details: ', response.data);
return response.data;
},

View File

@ -31,7 +31,6 @@ export default defineRouter(function (/* { store, ssrContext } */) {
const authStore = useAuthStore();
if (destinationPage.meta.requiresAuth && !authStore.isAuthorizedUser) {
console.log("access denied!")
return { name: 'login' };
}
})

View File

@ -27,7 +27,6 @@ export const useEmployeeStore = defineStore('employee', () => {
isLoadingEmployeeProfile.value = true;
try {
const response = await EmployeeListService.getEmployeeDetails(email);
console.log("Employee details: ", response);
employee.value = response;
} catch (error) {

View File

@ -3,6 +3,7 @@ import { ref } from 'vue';
export const useUiStore = defineStore('ui', () => {
const isRightDrawerOpen = ref(true);
const toggleRightDrawer = () => {
isRightDrawerOpen.value = !isRightDrawerOpen.value;
}