feat(login): refactor login page code, trim excess logic, refine UI, use innate Quasar and Vue utils and components

This commit is contained in:
Nicolas Drolet 2025-07-31 17:11:58 -04:00
parent 984ac83f67
commit 7317f35df3
29 changed files with 391 additions and 319 deletions

View File

@ -67,6 +67,12 @@ export default defineConfigWithVueTs(
rules: {
'prefer-promise-reject-errors': 'off',
// warn about unused but underscored variables
'no-unused-vars': [
'warn',
{ argsIgnorePattern: '^_' }
],
// allow debugger during development only
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
}

View File

@ -126,7 +126,9 @@ export default defineConfig((ctx) => {
// animations: 'all', // --- includes all animations
// https://v2.quasar.dev/options/animations
animations: [],
animations: [
'fadeInUp',
],
// https://v2.quasar.dev/quasar-cli-vite/quasar-config-file#sourcefiles
// sourceFiles: {
@ -219,7 +221,7 @@ export default defineConfig((ctx) => {
builder: {
// https://www.electron.build/configuration/configuration
appId: 'quasar-project'
appId: 'App Targo'
}
},

Binary file not shown.

After

Width:  |  Height:  |  Size: 938 KiB

View File

@ -14,7 +14,7 @@ declare module 'vue' {
// good idea to move this instance creation inside of the
// "export default () => {}" function below (which runs individually
// for each client)
const api = axios.create({ baseURL: 'https://api.example.com' });
const api = axios.create({ baseURL: import.meta.env.VITE_TARGO_BACKEND_URL });
export default defineBoot(({ app }) => {
// for use inside Vue files (Options API) through this.$axios and this.$api

View File

@ -1 +1,6 @@
// app global css in SCSS form
@each $size in (5, 10, 15, 20, 25) {
.rounded-#{$size} {
border-radius: #{$size}px;
}
}

View File

@ -13,13 +13,13 @@
// Tip: Use the "Theme Builder" on Quasar's documentation website.
$primary: #019547;
$secondary: #dadded;
$accent: #1976d2;
$secondary: #EFFFEF;
$accent: #ADEAC6;
$dark-font: #305530;
$dark: #111212;
$dark-page: #121212;
$dark: #323232;
$dark-page: #323232;
$positive: #21ba45;
$negative: #c10015;

View File

@ -1,7 +1,6 @@
export default {
mainLayout: {
backButton: 'Back to home',
clearFilter: 'Clear filter',
footerLayout: {
title: `Targo Communications, 2005 - 2025)}. All rights reserved.`,
},
helpPage: {
title_1: 'Contact Us',
@ -19,6 +18,10 @@ export default {
messageValidation: 'Message must be a valid email.',
submit: 'Send',
},
mainLayout: {
backButton: 'Back to home',
clearFilter: 'Clear filter',
},
navBar: {
navItem_1: 'Users list',
navItem_2: 'Shift validations',
@ -33,9 +36,6 @@ export default {
pageTitle: 'Oops. Nothing here...',
backButton: 'Go to the home page',
},
footerLayout: {
title: `Targo Communications, 2005 - 2025)}. All rights reserved.`,
},
loginPage: {
title: 'Log in to Targo',
forgotPassword: 'Forgot Password?',
@ -43,9 +43,10 @@ export default {
email: 'Email',
password: 'Password',
submit: 'Sign in ',
authentik: 'Targo authentication',
employeeLoginButton: 'Targo employee login',
emailValidation: 'Email must be a valid email.',
passwordValidation: 'Password must be a valid email.',
rememberMe: 'Remember me',
},
signUpPage: {
title: 'Create a new account',

View File

@ -1,102 +1,4 @@
export default {
mainLayout: {
backButton: 'Retour à la page daccueil',
clearFilter: 'Effacer le filtre',
},
helpPage: {
title_1: 'Contactez-nous',
title_2:
'Veuillez remplir le formulaire ci-dessous et nous vous communiquerons dès que possible.',
fullName: 'Nom complet*',
email: 'Adresse e-mail*',
phoneNumber: 'Numéro de téléphone*',
message:
'Comment pouvons-nous vous aider? Sil vous plaît utiliser cette zone pour fournir un message détaillé, Merci!*',
//form validation
fullNameValidation: 'Le nom complet doit être rempli.',
emailValidation: 'Le-mail doit être un e-mail valide.',
phoneNumberValidation: 'Le numéro de téléphone doit être rempli.',
messageValidation: 'Message doit être rempli.',
submit: 'Envoyer',
},
navBar: {
navItem_1: 'Liste des utilisateurs',
navItem_2: 'Validations des quarts de travail',
menuItem_1: 'Profil',
menuItem_2: 'Aide',
menuItem_3: 'Déconnexion',
menuItem_4: 'Carte de temps',
menuItem_5: 'Calendrier annuel',
mobileIndexTitle: 'Bonjour',
},
notFoundPage: {
pageTitle: 'Oops. Rien ici...',
backButton: 'Aller à la page daccueil',
},
footerLayout: {
title: `Targo Canada, 2005 - 2025. Tous droits réservés.`,
},
loginPage: {
title: 'Se connecter à Targo',
forgotPassword: 'Mot de passe oublié?',
signUp: 'Vous navez pas encore de compte?',
email: 'Email',
password: 'Mot de passe',
submit: 'Se connecter',
authentik: 'Authentification Targo',
emailValidation: 'Email doit être un e-mail valide.',
passwordValidation: 'Mot de passe doit être rempli.',
},
signUpPage: {
title: 'Créer un nouveau compte',
firstName: 'Prénom',
lastName: 'Nom de famille',
email: 'Email',
phoneNumber: 'Numéro de téléphone',
password: 'Nouveau mot de passe',
confirmedPassword: 'Confirmez votre mot de passe',
signIn: 'Vous avez déjà un compte?',
submit: 'Sinscrire',
firstNameValidation: 'Le prénom doit être rempli.',
lastNameValidation: 'Le nom de famille doit être rempli.',
emailValidation: 'Email doit être un e-mail valide.',
phoneNumberValidation: 'Numéro de téléphone doit être rempli.',
passwordValidationTitle: 'Critères de mot de passe :',
passwordValidation: 'Le mot de passe doit répondre à tous les critères.',
passwordLengthValidation: 'Doit être dau moins 8 caractères de long.',
passwordCapitalValidation: 'Doit contenir au moins une lettre majuscule.',
passwordNumberValidation: 'Doit contenir au moins un numéro.',
passwordSpecialCharacterValidation:
'Doit contenir au moins un caractère spécial : !@#$%^&*()-_+=',
confirmPasswordValidation:
'Le mot de passe doit correspondre au nouveau mot de passe.',
},
forgotPage: {
title:
'Veuillez saisir votre e-mail pour rechercher votre compte et envoyer un code de vérification.',
email: 'Email',
emailValidation: 'Email doit être un e-mail valide.',
submit: 'Envoyer code',
cancel: 'Annuler',
},
resetPage: {
title: 'Réinitialiser votre mot de passe',
code: 'code',
codeValidation: 'Le code doit être rempli avec 4 chiffres.',
newPassword: 'Nouveau mot de passe',
confirmedPassword: 'Confirmez votre mot de passe',
newPasswordValidation: 'Le mot de passe doit répondre à tous les critères.',
newPasswordLengthValidation: 'Doit être dau moins 8 caractères de long.',
newPasswordCapitalValidation:
'Doit contenir au moins une lettre majuscule.',
newPasswordNumberValidation: 'Doit contenir au moins un numéro.',
newPasswordSpecialCharacterValidation:
'Doit contenir au moins un caractère spécial : !@#$%^&*()-_+=',
confirmNewPasswordValidation:
'Le mot de passe doit correspondre au nouveau mot de passe.',
submit: 'Envoyer',
cancel: 'Annuler',
},
accountDialog: {
title: 'Plus',
item_1: 'Langue',
@ -105,97 +7,6 @@ export default {
item_4: 'Carte de temps',
item_5: 'Calendrier annuel',
},
notificationDialog: {
notice: 'Notification',
markAllRead: 'Marquer tout comme lu',
deleteAll: 'Supprimer tout',
close: 'Fermer',
},
profilePage: {
title: 'Profil',
firstName: 'Prénom',
lastName: 'Nom de famille',
email: 'Email',
phoneNumber: 'Numéro de téléphone',
job_title: 'Titre du poste',
company: 'Entreprise',
supervisor: 'Superviseur',
role: 'Role',
address: 'Adresse',
job_titleValidation: 'Le champ "titre du poste" doit être rempli.',
companyValidation: 'Le champ "entreprise" doit être rempli.',
supervisorValidation: 'Un employé qui na pas le rôle de superviseur doit être attribué à un superviseur.',
roleValidation: 'Le champ "rôle" doit être rempli.',
addressValidation: 'Le champ "adresse" doit être rempli.',
firstNameValidation: 'Le champ "prénom" doit être rempli.',
lastNameValidation: 'Le champ "nom de famille" doit être rempli.',
phoneNumberValidation: 'Le champ "numéro de téléphone" doit être rempli.',
submit: 'Modifier Profil',
},
indexAdminPage: {
card_1: 'Administrateurs',
card_2: 'Techniciens',
card_3: 'Marchand',
card_4: 'Clients',
},
usersListPage: {
tableHeader: 'Liste des utilisateurs',
search_input: 'Rechercher',
tableCol_1: 'État',
tableCol_2: 'Prénom',
tableCol_3: 'Nom de famille',
tableCol_4: 'Email',
tableCol_5: 'Numéro de téléphone',
tableCol_6: 'Type dutilisateur',
tableCol_7: 'Role',
tableCol_8: 'Créé par',
tableCol_9: 'Superviseur',
activeStatus: 'Actif',
unActiveStatus: 'Inactif',
addButton: 'Cliquez ici pour ajouter un nouvel utilisateur',
customer: 'Client',
dealer: 'Marchand',
employee: 'Employé',
technician: 'Technicien',
admin: 'Administrateur',
support: 'Support',
},
editUserPage: {
title: 'Modifier le compte',
passwordTitle: 'Réinitialiser le mot de passe',
firstName: 'Prénom',
lastName: 'Nom de famille',
email: 'Email',
phoneNumber: 'Numéro de téléphone',
type: 'Choisir un type',
role: 'Choisir un role',
job_title: 'Titre demploi',
company: 'Entreprise',
supervisor: 'Superviseur',
isSupervisor: 'Est un superviseur',
hours_bank_max: 'Maximum de banque dheures ',
address: 'Adresse',
verifiedAccountStatus: 'Compte vérifié',
unVerifiedAccountStatus: 'Compte non vérifié',
password: 'Nouveau mot de passe',
confirmedPassword: 'Confirmez votre mot de passe',
submit: 'Modifier le compte',
//Form Validaiton
firstNameValidation: 'Le prénom doit être rempli.',
lastNameValidation: 'Le nom de famille doit être rempli.',
emailValidation: 'Email doit être un e-mail valide.',
phoneNumberValidation: 'Numéro de téléphone doit être rempli.',
typeValidation: 'Type doit être rempli.',
roleValidation: 'Role doit être rempli.',
job_titleValidation: 'Le Titre demploi doit être rempli.',
companyValidation: 'Entreprise doit être rempli.',
supervisorValidation: 'Superviseur doit être rempli.',
hours_bank_maxValidation: 'Maximum de banque dheures doit être rempli.',
addressValidation: 'Adresse doit être rempli.',
passwordValidation: 'Le mot de passe doit répondre à tous les critères.',
confirmPasswordValidation:
'Le mot de passe doit correspondre au nouveau mot de passe.',
},
addUserPage: {
title: 'Créer un utilisateur',
firstName: 'Prénom',
@ -239,12 +50,243 @@ export default {
confirmPasswordValidation:
'Le mot de passe doit correspondre au nouveau mot de passe.',
},
autoLogout: {
title: 'Alerte',
message_start: 'Attention : vous serez automatiquement déconnecté dans',
message_end: 'secondes si vous ninteragissez pas avec lécran.',
},
daysOfWeek: {
Sunday: 'dimanche',
Monday: 'lundi',
Tuesday: 'mardi',
Wednesday: 'mercredi',
Thursday: 'jeudi',
Friday: 'vendredi',
Saturday: 'samedi',
},
editUserPage: {
title: 'Modifier le compte',
passwordTitle: 'Réinitialiser le mot de passe',
firstName: 'Prénom',
lastName: 'Nom de famille',
email: 'Email',
phoneNumber: 'Numéro de téléphone',
type: 'Choisir un type',
role: 'Choisir un role',
job_title: 'Titre demploi',
company: 'Entreprise',
supervisor: 'Superviseur',
isSupervisor: 'Est un superviseur',
hours_bank_max: 'Maximum de banque dheures ',
address: 'Adresse',
verifiedAccountStatus: 'Compte vérifié',
unVerifiedAccountStatus: 'Compte non vérifié',
password: 'Nouveau mot de passe',
confirmedPassword: 'Confirmez votre mot de passe',
submit: 'Modifier le compte',
//Form Validaiton
firstNameValidation: 'Le prénom doit être rempli.',
lastNameValidation: 'Le nom de famille doit être rempli.',
emailValidation: 'Email doit être un e-mail valide.',
phoneNumberValidation: 'Numéro de téléphone doit être rempli.',
typeValidation: 'Type doit être rempli.',
roleValidation: 'Role doit être rempli.',
job_titleValidation: 'Le Titre demploi doit être rempli.',
companyValidation: 'Entreprise doit être rempli.',
supervisorValidation: 'Superviseur doit être rempli.',
hours_bank_maxValidation: 'Maximum de banque dheures doit être rempli.',
addressValidation: 'Adresse doit être rempli.',
passwordValidation: 'Le mot de passe doit répondre à tous les critères.',
confirmPasswordValidation:
'Le mot de passe doit correspondre au nouveau mot de passe.',
},
expenseColumns: {
title: 'Dépenses',
column_1: 'Type',
column_2: 'Montant',
column_3: 'Attachement',
column_4: 'Description',
column_5: 'État',
column_6: 'Rapport du superviseur',
},
footerLayout: {
title: `Targo Canada, 2005 - 2025. Tous droits réservés.`,
},
forgotPage: {
title:
'Veuillez saisir votre e-mail pour rechercher votre compte et envoyer un code de vérification.',
email: 'Email',
emailValidation: 'Email doit être un e-mail valide.',
submit: 'Envoyer code',
cancel: 'Annuler',
},
helpPage: {
title_1: 'Contactez-nous',
title_2:
'Veuillez remplir le formulaire ci-dessous et nous vous communiquerons dès que possible.',
fullName: 'Nom complet*',
email: 'Adresse e-mail*',
phoneNumber: 'Numéro de téléphone*',
message:
'Comment pouvons-nous vous aider? Sil vous plaît utiliser cette zone pour fournir un message détaillé, Merci!*',
//form validation
fullNameValidation: 'Le nom complet doit être rempli.',
emailValidation: 'Le-mail doit être un e-mail valide.',
phoneNumberValidation: 'Le numéro de téléphone doit être rempli.',
messageValidation: 'Message doit être rempli.',
submit: 'Envoyer',
},
indexAdminPage: {
card_1: 'Administrateurs',
card_2: 'Techniciens',
card_3: 'Marchand',
card_4: 'Clients',
},
loginPage: {
title: 'Se connecter à Targo',
forgotPassword: 'Mot de passe oublié?',
signUp: 'Vous navez pas encore de compte?',
email: 'Email',
password: 'Mot de passe',
submit: 'Se connecter',
employeeLoginButton: 'Login employé Targo',
emailValidation: 'Email doit être un e-mail valide.',
passwordValidation: 'Mot de passe doit être rempli.',
rememberMe: 'Rester connecté',
},
mainLayout: {
backButton: 'Retour à la page daccueil',
clearFilter: 'Effacer le filtre',
},
navBar: {
navItem_1: 'Liste des utilisateurs',
navItem_2: 'Validations des quarts de travail',
menuItem_1: 'Profil',
menuItem_2: 'Aide',
menuItem_3: 'Déconnexion',
menuItem_4: 'Carte de temps',
menuItem_5: 'Calendrier annuel',
mobileIndexTitle: 'Bonjour',
},
notFoundPage: {
pageTitle: 'Oops. Rien ici...',
backButton: 'Aller à la page daccueil',
},
notificationDialog: {
notice: 'Notification',
markAllRead: 'Marquer tout comme lu',
deleteAll: 'Supprimer tout',
close: 'Fermer',
},
pagesTitles: {
newUserPageTitle: 'Nouvel utilisateur',
updateUserPageTitle: 'Mettre à jour lutilisateur',
timeSheetPageTitle: 'Carte de temps',
timeSheetValidationsIdPageTitle: 'Carte de temps',
},
profilePage: {
title: 'Profil',
firstName: 'Prénom',
lastName: 'Nom de famille',
email: 'Email',
phoneNumber: 'Numéro de téléphone',
job_title: 'Titre du poste',
company: 'Entreprise',
supervisor: 'Superviseur',
role: 'Role',
address: 'Adresse',
job_titleValidation: 'Le champ "titre du poste" doit être rempli.',
companyValidation: 'Le champ "entreprise" doit être rempli.',
supervisorValidation: 'Un employé qui na pas le rôle de superviseur doit être attribué à un superviseur.',
roleValidation: 'Le champ "rôle" doit être rempli.',
addressValidation: 'Le champ "adresse" doit être rempli.',
firstNameValidation: 'Le champ "prénom" doit être rempli.',
lastNameValidation: 'Le champ "nom de famille" doit être rempli.',
phoneNumberValidation: 'Le champ "numéro de téléphone" doit être rempli.',
submit: 'Modifier Profil',
},
resetPage: {
title: 'Réinitialiser votre mot de passe',
code: 'code',
codeValidation: 'Le code doit être rempli avec 4 chiffres.',
newPassword: 'Nouveau mot de passe',
confirmedPassword: 'Confirmez votre mot de passe',
newPasswordValidation: 'Le mot de passe doit répondre à tous les critères.',
newPasswordLengthValidation: 'Doit être dau moins 8 caractères de long.',
newPasswordCapitalValidation:
'Doit contenir au moins une lettre majuscule.',
newPasswordNumberValidation: 'Doit contenir au moins un numéro.',
newPasswordSpecialCharacterValidation:
'Doit contenir au moins un caractère spécial : !@#$%^&*()-_+=',
confirmNewPasswordValidation:
'Le mot de passe doit correspondre au nouveau mot de passe.',
submit: 'Envoyer',
cancel: 'Annuler',
},
shiftColumns: {
title: 'Quarts de travail',
column_1: 'Type',
column_2: 'Entrée',
column_3: 'Sortie',
column_4: 'Commentaire',
column_5: 'État',
column_6: 'Rapport du superviseur',
},
shiftsTemplate: {
tabTitle1: 'Quarts de travail',
tabTitle2: 'Modèles de quarts de travail',
saveButton: 'Enregistrer',
emptyShiftsMessage: 'Aucun modèle disponible.',
emptyTemplateMessage: 'Aucun quarts de travail disponible.',
selectTemplate: 'Sélectionnez un modèle',
selectTemplateNoResult: 'Aucun modele disponible.',
selectDay: 'Jour',
startTime: 'Heure de début',
endTime: 'Heure de fin',
templateTitle: 'Titre',
templateDescription: 'Description',
createButton: 'Créer',
updateButton: 'Mettre à jour',
deleteButton: 'Supprimer',
resetButton: 'Réinitialiser',
dayValidation: 'Jour doit être rempli.',
startTimeValidation: 'Heure de début doit être rempli.',
endTimeValidation: 'Heure de fin doit être rempli.',
startTimeAfterEndTimeValidation:
'Lheure de début ne peut pas être après lheure de fin',
endTimeBeforeStartTimeValidation:
'Lheure de fin ne peut pas être précédente à lheure de debut',
existingTimeShift: 'Ce temps est déjà utilisé',
},
signUpPage: {
title: 'Créer un nouveau compte',
firstName: 'Prénom',
lastName: 'Nom de famille',
email: 'Email',
phoneNumber: 'Numéro de téléphone',
password: 'Nouveau mot de passe',
confirmedPassword: 'Confirmez votre mot de passe',
signIn: 'Vous avez déjà un compte?',
submit: 'Sinscrire',
firstNameValidation: 'Le prénom doit être rempli.',
lastNameValidation: 'Le nom de famille doit être rempli.',
emailValidation: 'Email doit être un e-mail valide.',
phoneNumberValidation: 'Numéro de téléphone doit être rempli.',
passwordValidationTitle: 'Critères de mot de passe :',
passwordValidation: 'Le mot de passe doit répondre à tous les critères.',
passwordLengthValidation: 'Doit être dau moins 8 caractères de long.',
passwordCapitalValidation: 'Doit contenir au moins une lettre majuscule.',
passwordNumberValidation: 'Doit contenir au moins un numéro.',
passwordSpecialCharacterValidation:
'Doit contenir au moins un caractère spécial : !@#$%^&*()-_+=',
confirmPasswordValidation:
'Le mot de passe doit correspondre au nouveau mot de passe.',
},
table: {
recordsTitle: 'Enregistrements par page:',
noResultsLabel: 'Le filtre na révélé aucun résultat',
noDataLabel: 'Je nai rien trouvé pour toi',
},
timeSheet: {
timeSheetTab_1: 'Quarts de travail',
timeSheetTab_2: 'Dépenses',
@ -277,9 +319,7 @@ export default {
shiftTypeValidation: 'Le type doit être rempli.',
shiftStartTimeValidation: 'Entrée doit être rempli.',
shiftEndTimeValidation: 'Sortie doit être rempli.',
endTimeValidation:
'Lheure de fin ne peut pas être antérieure ou égale à lheure de début',
endTimeValidation:'Lheure de fin doit suivre lheure de début.',
expensesTile: 'Dépenses du jour',
expensesType: 'Type',
expensesValue: 'Montant',
@ -319,83 +359,37 @@ export default {
accumulatedVacationTotal: 'Accumulées de vacances',
consumedVacationTotal: 'Consommées de vacances',
maxVacationPerYear: 'Maximum de vacances par année',
accumulatedSicknessTotalValidation:
'Accumulées de maladies doit être positive.',
consumedSicknessTotalValidation:
'Consommées de maladies doit être positive.',
accumulatedVacationTotalValidation:
'Accumulées de vacances doit être positive.',
consumedVacationTotalValidation:
'Consommées de vacances doit être positive.',
maxVacationPerYearValidation:
'Le nombre maximum de vacances par an doit être positif.',
accumulatedSicknessTotalValidation: 'Cumulatif maladie doit être positif',
consumedSicknessTotalValidation: 'Maladie utilisé doit être positif',
accumulatedVacationTotalValidation: 'Cumulatif vacances doit être positif',
consumedVacationTotalValidation: 'Vacances utilisées doit être positif',
maxVacationPerYearValidation: 'Maximum vacances annuel doit être positif.',
resteVacationTotal: 'Reste des vacances',
validateToolTip: 'Valider',
unvalidateToolTip: 'Invalider',
lockToolTip: 'Verrouiller la semaine',
unlockToolTip: 'Déverrouiller la semaine',
},
shiftColumns: {
title: 'Quarts de travail',
column_1: 'Type',
column_2: 'Entrée',
column_3: 'Sortie',
column_4: 'Commentaire',
column_5: 'État',
column_6: 'Rapport du superviseur',
},
expenseColumns: {
title: 'Dépenses',
column_1: 'Type',
column_2: 'Montant',
column_3: 'Attachement',
column_4: 'Description',
column_5: 'État',
column_6: 'Rapport du superviseur',
},
table: {
recordsTitle: 'Enregistrements par page:',
noResultsLabel: 'Le filtre na révélé aucun résultat',
noDataLabel: 'Je nai rien trouvé pour toi',
},
autoLogout: {
title: 'Alerte',
message_start: 'Attention : vous serez automatiquement déconnecté dans',
message_end: 'secondes si vous ninteragissez pas avec lécran.',
},
daysOfWeek: {
Sunday: 'dimanche',
Monday: 'lundi',
Tuesday: 'mardi',
Wednesday: 'mercredi',
Thursday: 'jeudi',
Friday: 'vendredi',
Saturday: 'samedi',
},
shiftsTemplate: {
tabTitle1: 'Quarts de travail',
tabTitle2: 'Modèles de quarts de travail',
saveButton: 'Enregistrer',
emptyShiftsMessage: 'Aucun modèle disponible.',
emptyTemplateMessage: 'Aucun quarts de travail disponible.',
selectTemplate: 'Sélectionnez un modèle',
selectTemplateNoResult: 'Aucun modele disponible.',
selectDay: 'Jour',
startTime: 'Heure de début',
endTime: 'Heure de fin',
templateTitle: 'Titre',
templateDescription: 'Description',
createButton: 'Créer',
updateButton: 'Mettre à jour',
deleteButton: 'Supprimer',
resetButton: 'Réinitialiser',
dayValidation: 'Jour doit être rempli.',
startTimeValidation: 'Heure de début doit être rempli.',
endTimeValidation: 'Heure de fin doit être rempli.',
startTimeAfterEndTimeValidation:
'Lheure de début ne peut pas être après lheure de fin',
endTimeBeforeStartTimeValidation:
'Lheure de fin ne peut pas être précédente à lheure de debut',
existingTimeShift: 'Ce temps est déjà utilisé',
usersListPage: {
tableHeader: 'Liste des utilisateurs',
search_input: 'Rechercher',
tableCol_1: 'État',
tableCol_2: 'Prénom',
tableCol_3: 'Nom de famille',
tableCol_4: 'Email',
tableCol_5: 'Numéro de téléphone',
tableCol_6: 'Type dutilisateur',
tableCol_7: 'Role',
tableCol_8: 'Créé par',
tableCol_9: 'Superviseur',
activeStatus: 'Actif',
unActiveStatus: 'Inactif',
addButton: 'Cliquez ici pour ajouter un nouvel utilisateur',
customer: 'Client',
dealer: 'Marchand',
employee: 'Employé',
technician: 'Technicien',
admin: 'Administrateur',
support: 'Support',
},
};

View File

@ -1,12 +1,12 @@
<script lang="ts" setup>
import { RouterView } from 'vue-router';
import NavBar from 'src/pages/nav-bars/nav-bar.vue';
import FooterBar from 'src/pages/footer-bars/footer-bar.vue';
import HeaderBar from 'src/modules/shared/components/navigation/header-bars/header-bar.vue';
import FooterBar from 'src/modules/shared/components/navigation/footer-bars/footer-bar.vue';
</script>
<template>
<q-layout view="hHh lpR fFf">
<NavBar />
<HeaderBar />
<q-page-container>
<router-view class="q-pa-sm" />
</q-page-container>

View File

@ -1,6 +1,5 @@
/* eslint-disable */
import { defineStore } from "pinia";
import router from "src/router";
import { api } from "src/boot/axios";
import { User } from "src/modules/users/types/user-interface";
import { AuthState } from "./types/auth-interface";
@ -10,8 +9,8 @@ export const useAuthStore = defineStore('auth', {
state: (): AuthState => ({
token: "",
user: {
firstName: 'Guest',
lastName: 'Guest',
firstName: 'Unknown',
lastName: 'Unknown',
email: 'guest@guest.com',
role: 'guest'
} as User,
@ -25,7 +24,7 @@ export const useAuthStore = defineStore('auth', {
actions: {
async login() {
return "standard login";
api.get('v1/');
},
async oidcLogin() {
@ -44,8 +43,8 @@ export const useAuthStore = defineStore('auth', {
return "setting user info";
},
isAuthorizedUser(email: string) {
return "checking user authorization";
isAuthorizedUser(): boolean {
return this.$state.user.role.toLowerCase() != 'guest';
},
async forgotPassword(email: string) {

View File

@ -1,15 +1,11 @@
/* eslint-disable */
import { useAuthStore } from "src/modules/auth/auth-store";
export const useAuthAccess = () => {
const authStore = useAuthStore();
const isLoggedIn = async () => {
return authStore.hasAuthToken;
};
const isAuthorizedUser = async (email: string) => {
return authStore.isAuthorizedUser(email);
const isAuthorizedUser = async () => {
return authStore.isAuthorizedUser();
};
const forgotPassword = async (email: string) => {

View File

@ -1,11 +1,7 @@
/* eslint-disable */
import { useAuthStore } from "src/modules/auth/auth-store";
export const useAuthSession = () => {
const authStore = useAuthStore();
const login = async () => {
return authStore.login();
return {status: 200, message: 'sent a login request'};
};
const oidcLogin = async () => {

View File

@ -0,0 +1,55 @@
<script setup lang="ts">
import { ref, watch } from 'vue';
import { useAuthSession } from 'src/modules/auth/composables/use-auth-session';
const { login } = useAuthSession();
const email = ref('');
const isShowingEmployeeLoginButton = ref(false);
const isRemembered = ref(false);
watch(email, (value) => {
if (!isShowingEmployeeLoginButton.value && value.includes('@targoint')) {
isShowingEmployeeLoginButton.value = true;
}
});
</script>
<template>
<q-layout view="hHh lpR fFf" class="flex flex-center bg-secondary">
<q-img src="src/assets/login-background.png" fit="cover" position="50% 100%" class="absolute-full" />
<q-page-container>
<q-card class="rounded-20">
<q-card-section class="text-center bg-primary">
<q-img src="/src/assets/logo-targo-white.svg" ratio="4.6" fit="contain" class="full-width" />
</q-card-section>
<div class="q-pt-sm q-px-xl q-pb-lg">
<q-card-section class="text-center">
<div class="text-h6 text-grey-9 text-weight-bold">
{{ $t('loginPage.title') }}
</div>
</q-card-section>
<q-form class="q-gutter-sm" @submit="login">
<q-input dense outlined label-color="primary" v-model="email" :label="$t('loginPage.email')" />
<q-card-section class="q-ma-none q-pa-none">
<q-toggle v-model="isRemembered" :label="$t('loginPage.rememberMe')" color="primary" />
</q-card-section>
<q-card-section>
<q-btn :label="$t('loginPage.submit')" type="submit" color="primary" rounded size="md" class="full-width q-mt-md" />
</q-card-section>
</q-form>
<q-card-section class="text-center q-pt-none">
<RouterLink class="text-primary text-weight-bold" style="text-decoration: none" to="/signup">{{ $t('loginPage.signUp') }}</RouterLink>
</q-card-section>
<q-card-section v-if="isShowingEmployeeLoginButton">
<q-btn class="full-width" :label="$t('loginPage.employeeLoginButton')" icon="login" />
</q-card-section>
</div>
</q-card>
</q-page-container>
</q-layout>
</template>

View File

@ -4,7 +4,7 @@
import { useQuasar } from 'quasar';
// import { getInitials } from 'src/helpers/object';
import { useAuthStore } from 'src/modules/auth/auth-store';
import LanguageSwitch from 'src/shared/components/language-switch.vue';
import LanguageSwitch from 'src/modules/shared/components/language-switch.vue';
// import dialogs from 'src/components/dialogs';
// import authenticationApi from 'src/composables/useAuthentication';

View File

@ -0,0 +1,12 @@
<script lang="ts" setup>
// import HeaderBarMobile from './header-bar-mobile.vue';
import HeaderBarWeb from './header-bar-web.vue';
</script>
<template>
<q-header elevated>
<!-- <HeaderBarMobile /> -->
<HeaderBarWeb />
</q-header>
</template>

View File

@ -1,12 +0,0 @@
<script lang="ts" setup>
// import NavBarMobile from './nav-bar-mobile.vue';
import NavBarWeb from './nav-bar-web.vue';
</script>
<template>
<q-header elevated>
<!-- <NavBarMobile /> -->
<NavBarWeb />
</q-header>
</template>

View File

@ -1,11 +1,7 @@
import { defineRouter } from '#q-app/wrappers';
import {
createMemoryHistory,
createRouter,
createWebHashHistory,
createWebHistory,
} from 'vue-router';
import { createMemoryHistory, createRouter, createWebHashHistory, createWebHistory, } from 'vue-router';
import routes from './routes';
import { useAuthStore } from 'src/modules/auth/auth-store';
/*
* If not building with SSR mode, you can
@ -31,5 +27,13 @@ export default defineRouter(function (/* { store, ssrContext } */) {
history: createHistory(process.env.VUE_ROUTER_BASE),
});
Router.beforeEach((destinationPage) => {
const authStore = useAuthStore();
if (destinationPage.meta.requiresAuth && !authStore.isAuthorizedUser()) {
return { name: 'login' };
}
})
return Router;
});

View File

@ -2,9 +2,22 @@ import type { RouteRecordRaw } from 'vue-router';
const routes: RouteRecordRaw[] = [
{
path: '/',
path: '/',
component: () => import('src/layouts/main-layout.vue'),
children: [{ path: '', component: () => import('src/pages/test-page.vue') }],
meta: { requiresAuth: true },
children: [
{
path: '',
component: () => import('src/pages/test-page.vue'),
},
],
},
{
path: '/v1/login',
name: 'login',
component: () => import('src/modules/auth/pages/auth-login.vue'),
meta: { requiresAuth: false },
},
// Always leave this as last one,
@ -12,6 +25,7 @@ const routes: RouteRecordRaw[] = [
{
path: '/:catchAll(.*)*',
component: () => import('src/pages/error-page.vue'),
meta: { requiresAuth: false },
},
];