feat(help): a start of the personnalized help to navigate and use the app according to the user access

This commit is contained in:
Matthieu Haineault 2025-12-17 08:43:23 -05:00
parent 6606ebb992
commit f963570f45
11 changed files with 302 additions and 8 deletions

View File

@ -1,4 +1,48 @@
export default {
dashboard: {
welcome: "Welcome to the Targo App!",
},
help: {
label: "Centre d'aide",
tutorial: {
dashboard: "Home Page",
personal_profile: {
title: "Section << Personnal Profile >>",
personal_info: "Personal informations",
professional_info: "Professional informations",
},
timesheets: {
title: "Section << Timesheet >>",
create_shift: "Add a new shift",
update_shift: "Update an existing shift",
delete_shift: "Removing a shift from the timesheet",
create_expense: "Add a new expense",
update_expense: "Update an existing expense",
delete_expense: "Removing an expense from the list",
},
employee_list: {
title: "Section << Employee List >>",
terminated_employees: "Inactive employees",
},
employee_management: {
title: "Section << Employee Management >>",
create_employee: "Creating a new employee",
update_employee: "Updating an existing employee's informations",
module_access: "App managing access tool",
schedule_preset: "Schedule preset management",
terminate_employee: "terminate an employee",
},
timesheets_approval: {
title: "Section << Timesheets approval >>",
approval: "timesheet approvals",
inspect: "Inspect timesheets",
},
shared: {
search: "Advance search",
display: "Display mode",
},
},
},
employee_list: {
page_header: "Employee Directory",
table: {

View File

@ -1,4 +1,48 @@
export default {
dashboard: {
welcome: "Bienvenue dans l'application Targo!",
},
help: {
label: "Centre d'aide",
tutorial: {
dashboard: "Page d'accueil",
personal_profile: {
title: "Section << Profil >>",
personal_info: "Informations personnelles",
professional_info: "Informations professionnelles",
},
timesheets: {
title: "Section << Carte de temps >>",
create_shift: "Inscrire un nouveau quart de travail",
update_shift: "Modifier un quart de travail existant",
delete_shift: "Supprimer un quart de travail de la carte de temps",
create_expense: "Inscrire une dépense",
update_expense: "Modifier une dépense",
delete_expense: "Supprimer une dépense",
},
employee_list: {
title: "Section << Répertoire des employés >>",
terminated_employees: "Employés inactifs",
},
employee_management: {
title: "Section << Gestion des employés >>",
create_employee: "Création d'un nouvel employé",
update_employee: "Modifier les informations d'un employé",
module_access: "Outils de gestion des accès de l'application",
schedule_preset: "Gestion des horaires prédéterminés",
terminate_employee: "Rendre un employé inactif",
},
timesheets_approval: {
title: "Section << Validation de Carte de temps >>",
approval: "Validation des cartes de temps",
inspect: "Inspect timesheets",
},
shared: {
search: "Recherche avancée",
display: "Mode d'affichage",
},
},
},
employee_list: {
page_header: "Répertoire du personnel",
table: {

View File

@ -0,0 +1,53 @@
<script setup lang="ts">
import { useHelpStore } from 'src/stores/help-store';
const help_store = useHelpStore();
</script>
<template>
<q-card
class="column q-my-xs bg-secondary"
v-for="module, index of help_store.custom_help_module_options"
:key="index"
>
<!-- Card Header -->
<div class="row col-auto text-h5 q-pa-md text-accent bg-primary">
{{ $t(`${module}`) }}
</div>
<!-- Card Body -->
<div class="row col">
<!-- Object and descriptions zone -->
<div class="col-8">
<q-expansion-item
class="bg-gray-2 text-weight-bolder col-auto row "
group="help_page"
:label="($t(index.toString())).toUpperCase()"
switch-toggle-side
>
<div class="col">
description goes here
</div>
</q-expansion-item>
</div>
<!-- images of the related selected option -->
<div
v-for="option, index in (help_store.options)"
:key="index"
class="col-4"
>
<q-img
:src="option.toString()"
loading="lazy"
class="col-4"
>
<div class="absolute-top text-subtitle1 text-center">
needs to check with v-if to show only the right img
</div>
</q-img>
</div>
</div>
</q-card>
</template>

View File

@ -0,0 +1,55 @@
export interface HelpModule {
dashboard: string;
personal_profile: string;
timesheet: string;
employee_list: string;
employee_management: string;
timesheets_approval: string;
};
export const module_access_help: string[] = [
'help.tutorial.personal_profile.title',
'help.tutorial.timesheets.title',
'help.tutorial.employee_list.title',
'help.tutorial.employee_management.title',
'help.tutorial.timesheets_approval.title',
];
export const profile_options = [
{ label: 'help.tutorial.personal_profile.personal_info', path: "https://picsum.photos/500/300" },
{ label: 'help.tutorial.personal_profile.professional_info', path: "https://picsum.photos/500/300" },
{ label: 'help.tutorial.shared.display', path: "https://picsum.photos/500/300" },
];
export const timesheet_options = [
{ label: 'help.tutorial.timesheet.create_shift', path: "https://picsum.photos/500/300" },
{ label: 'help.tutorial.timesheet.update_shift', path: "https://picsum.photos/500/300" },
{ label: 'help.tutorial.timesheet.delete_shift', path: "https://picsum.photos/500/300" },
{ label: 'help.tutorial.timesheet.create_shift', path: "https://picsum.photos/500/300" },
{ label: 'help.tutorial.timesheet.update_shift', path: "https://picsum.photos/500/300" },
{ label: 'help.tutorial.timesheet.delete_shift', path: "https://picsum.photos/500/300" },
];
export const employee_list_options = [
{ label: 'help.tutorial.employee_list.terminated_employees', path: "https://picsum.photos/500/300" },
{ label: 'help.tutorial.shared.display', path: "https://picsum.photos/500/300" },
{ label: 'help.tutorial.shared.search', path: "https://picsum.photos/500/300" },
];
export const employee_management_options = [
{ label: 'help.tutorial.employee_list.terminated_employees', path: "https://picsum.photos/500/300" },
{ label: 'help.tutorial.employee_management.create_employee', path: "https://picsum.photos/500/300" },
{ label: 'help.tutorial.employee_management.update_employee', path: "https://picsum.photos/500/300" },
{ label: 'help.tutorial.employee_management.module_access', path: "https://picsum.photos/500/300" },
{ label: 'help.tutorial.employee_management.schedule_preset', path: "https://picsum.photos/500/300" },
{ label: 'help.tutorial.employee_management.terminate_employee', path: "https://picsum.photos/500/300" },
{ label: 'help.tutorial.shared.display', path: "https://picsum.photos/500/300" },
{ label: 'help.tutorial.shared.search', path: "https://picsum.photos/500/300" },
];
export const timesheets_approval = [
{ label: 'help.tutorial.timesheets_approval.approval', path: "https://picsum.photos/500/300" },
{ label: 'help.tutorial.timesheets_approval.inspect', path: "https://picsum.photos/500/300" },
{ label: 'help.tutorial.shared.display', path: "https://picsum.photos/500/300" },
{ label: 'help.tutorial.shared.search', path: "https://picsum.photos/500/300" },
]

View File

@ -0,0 +1,10 @@
import { api } from "src/boot/axios";
import type { HelpModule } from "src/modules/help/models/help-module.model";
import type { BackendResponse } from "src/modules/shared/models/backend-response.models";
export const HelpService = {
getHelpModules: async (): Promise<BackendResponse<HelpModule[]>> => {
const response = await api.get<BackendResponse<HelpModule[]>>(`/help`);
return response.data;
}
}

View File

@ -61,7 +61,7 @@
>
<q-img src="src/assets/line-truck-1.jpg" class="full-height">
<div class="absolute-bottom text-h5">
Welcome to App Targo!
{{ $t('dashboard.welcome') }}
</div>
</q-img>
<div class="q-mt-md text-center">

View File

@ -0,0 +1,24 @@
<script setup lang="ts">
import PageHeaderTemplate from 'src/modules/shared/components/page-header-template.vue';
import HelpModule from 'src/modules/help/components/help-module.vue';
import { onMounted } from 'vue';
import { useHelpStore } from 'src/stores/help-store';
const help_store = useHelpStore();
onMounted(async () => {
await help_store.getHelpModules();
});
</script>
<template>
<q-page
flat
class="bg-secondary"
>
<PageHeaderTemplate
:title="$t('help.label')"
class="text-accent"
/>
<help-module />
</q-page>
</template>

View File

@ -6,5 +6,6 @@ export enum RouteNames {
EMPLOYEE_LIST = 'employee_list',
EMPLOYEE_MANAGEMENT = 'employee_management',
PROFILE = 'personal_profile',
TIMESHEET = 'timesheets'
TIMESHEET = 'timesheets',
HELP = 'help',
}

View File

@ -3,12 +3,12 @@ import { RouteNames } from './router-constants';
const routes: RouteRecordRaw[] = [
{
path: '/',
path: '/',
component: () => import('src/layouts/main-layout.vue'),
meta: { requiresAuth: true },
children: [
{
path: '',
{
path: '',
name: RouteNames.DASHBOARD,
component: () => import('src/pages/dashboard-page.vue'),
},
@ -32,18 +32,23 @@ const routes: RouteRecordRaw[] = [
name: RouteNames.PROFILE,
component: () => import('src/pages/profile-page.vue'),
},
{
path: 'help',
name: RouteNames.HELP,
component: () => import('src/pages/help-page.vue'),
},
],
},
{
path: '/v1/login',
path: '/v1/login',
name: RouteNames.LOGIN,
component: () => import('src/pages/login-page.vue'),
meta: { requiresAuth: false },
},
{
path: '/login-success',
path: '/login-success',
name: RouteNames.LOGIN_SUCCESS,
component: () => import('src/modules/auth/pages/auth-login-popup-success.vue'),
meta: { requiresAuth: false },

View File

@ -4,9 +4,11 @@ import { AuthService } from "../modules/auth/services/services-auth";
import { CAN_APPROVE_PAY_PERIODS, type User } from "src/modules/shared/models/user.models";
import { useRouter } from "vue-router";
import { Notify } from "quasar";
import type { ModuleAccessName } from "src/modules/employee-list/models/employee-profile.models";
export const useAuthStore = defineStore('auth', () => {
const user = ref<User>();
const user_module_access = ref<ModuleAccessName>();
const authError = ref("");
const isAuthorizedUser = computed(() => CAN_APPROVE_PAY_PERIODS.includes(user.value?.role ?? 'GUEST'));
const router = useRouter();
@ -62,6 +64,15 @@ export const useAuthStore = defineStore('auth', () => {
return { status: 400, message: 'unknown error occured' };
}
return { user, authError, isAuthorizedUser, login, oidcLogin, logout, getProfile };
return {
user,
authError,
isAuthorizedUser,
user_module_access,
login,
oidcLogin,
logout,
getProfile
};
});

47
src/stores/help-store.ts Normal file
View File

@ -0,0 +1,47 @@
import { defineStore } from "pinia";
import { ref } from "vue";
import { HelpService } from "src/modules/help/services/help.service";
import type { HelpModule } from "src/modules/help/models/help-module.model";
export const useHelpStore = defineStore('help', () => {
const is_loading = ref(false);
const help_modules = ref<HelpModule[]>([]);
const custom_help_module_options: string[] = [];
const options: { label: string, path: string }[] = [];
const getHelpModules = async (): Promise<boolean> => {
try {
const response = await HelpService.getHelpModules();
if (response.success && response.data) help_modules.value = response.data;
for (const module in help_modules) {
if (module === 'personal_profile') {
custom_help_module_options.push(module);
}
if (module === 'timesheet') {
custom_help_module_options.push(module);
}
if (module === 'employee_list') {
custom_help_module_options.push(module);
}
if (module === 'employee_management') {
custom_help_module_options.push(module);
}
if (module === 'timesheets_approval') {
custom_help_module_options.push(module);
}
}
return response.success;
} catch (error) {
console.error('An error occured while fetching Help modules', error);
return false;
}
};
return {
is_loading,
help_modules,
options,
custom_help_module_options,
getHelpModules,
}
});