Ce document complète le premier audit en se concentrant sur l'architecture, la logique métier, le couplage et l'accessibilité. Il propose un plan d'action découpé en 4 phases logiques et testables.
-
"God Object" Store (
useQuizStore) :- Ce store gère tout : sélection de configuration, état de la session, logique de jeu (score, réponse), persistance (appels DB directs), et même des bouts de navigation.
- Risque : Impossible de tester la logique de calcul de score sans mocker toute la DB et Pinia. Difficile d'ajouter de nouveaux modes de jeu.
-
Couplage Fort (Store <-> DB) :
- Les stores importent directement
sessionRepositoryetquestionRepository. - Risque : Si on change de backend (ex: Firebase au lieu d'IndexedDB), il faut réécrire tous les stores.
- Les stores importent directement
-
Fragilité du Routage ("Magic Strings") :
- Les noms de routes (
'quiz-active','summary','home') sont éparpillés danssrc/router/index.tset dans les composants/stores. - Risque : Une typo ou un renommage de route casse silencieusement la navigation.
- Les noms de routes (
-
Accessibilité & Sémantique :
QuestionCard.vueutilise des<div>avec@clickpour certaines interactions ou n'utilise pas assez les attributs ARIA pour décrire l'état (réponse sélectionnée vs correcte).- Les couleurs des catégories sont hardcodées dans le template (chaine
if/elsegéante), ce qui rend l'ajout de catégories pénible.
Objectif : Assainir la base de code sans toucher à la logique complexe.
- Centralisation des Routes :
- Créer
src/router/routes.tsexportant un objetAppRoutescontenant tous les noms de routes. - Remplacer toutes les chaînes
'quiz-active'parAppRoutes.Quiz.Active.
- Créer
- Consolidation des Constantes (Catégories) :
- Appliquer la recommandation de l'Audit v1 (fusionner
CATEGORY_CONFIG). - Refactoriser
QuestionCard.vuepour utiliser cette config dynamique pour les couleurs (supprimer le blocv-if/classgéant).
- Appliquer la recommandation de l'Audit v1 (fusionner
- Logger Service :
- Créer
src/utils/logger.tset remplacer lesconsole.log.
- Créer
Testabilité :
- Vérifier que l'application compile.
- Vérifier que la navigation fonctionne toujours.
- Vérifier qu'une nouvelle catégorie ajoutée dans
constants.tsapparaît bien avec sa couleur sans modifierQuestionCard.vue.
Objectif : Séparer la persistance de la logique métier.
- Abstraction des Repositories :
- S'assurer que les stores n'appellent pas directement
indexedDB(déjà partiellement fait, mais à renforcer).
- S'assurer que les stores n'appellent pas directement
- Validation des Données (Import) :
- Créer
src/utils/validators.tsavec des Type Guards (isValidQuestion). - Sécuriser
useDataStore.ts->importQuestions.
- Créer
- Standardisation des Clones :
- Remplacer
JSON.parse(JSON.stringify())parstructuredClone().
- Remplacer
Testabilité :
- Unit Test : Tester
isValidQuestionavec des JSON valides et invalides. - E2E : Tenter d'importer un fichier JSON corrompu via l'UI et vérifier que l'erreur est gérée proprement sans crash.
Objectif : Rendre le cœur du quiz testable unitairement sans Vue/Pinia.
- Création de
src/logic/quizEngine.ts:- Extraire la logique de calcul de score (
calculateScore(questions)) dans une fonction pure. - Extraire la logique de mélange (
shuffleAnswers,selectQuestions) dans des fonctions pures.
- Extraire la logique de calcul de score (
- Nettoyage de
useQuizStore:- Le store ne doit faire qu'orchestrer : appeler
quizEnginepour les calculs, puis sauvegarder le résultat via le Repository. - Déplacer la logique de "Sélection de configuration" (Categories, Difficulty) dans un petit store dédié
useQuizConfigStoreou garder séparé dans le state pour ne pas polluer la session active.
- Le store ne doit faire qu'orchestrer : appeler
Testabilité :
- Unit Test : Créer
src/logic/quizEngine.spec.ts. TestercalculateScoreavec un tableau de questions mocké. Vérifier que le score est juste (1pt facile, 3pts difficile). - Ceci est impossible actuellement car la logique est enfouie dans
finishQuizdu store.
Objectif : Rendre l'app utilisable par tous et nettoyer les templates.
- Composables UI :
- Extraire la logique de style de
Active.vueverssrc/composables/useQuizStyles.ts.
- Extraire la logique de style de
- Accessibilité (ARIA) :
- Dans
AnswerOption.vue, utiliser<button type="button" :aria-pressed="isSelected" :aria-label="...">. - S'assurer que le focus est géré lors du passage à la question suivante (pour les lecteurs d'écran).
- Dans
- Animations :
- Déplacer les
@keyframesdanstailwind.config.js.
- Déplacer les
Testabilité :
- Audit Lighthouse/Axe pour vérifier le score d'accessibilité.
- Vérifier la navigation au clavier (Tab / Enter).
Actuellement (useQuizStore.ts) :
// Difficile à tester
async function finishQuiz() {
// ... accès state ...
activeSession.value.questions.forEach((q) => {
const points = DIFFICULTY_POINTS[q.difficulte] || 1
// ... mutation state ...
})
}Cible (src/logic/scoring.ts) :
// Facile à tester (Fonction pure)
export function calculateSessionScore(questions: SessionQuestion[]): QuizScoreResult {
let score = 0;
let max = 0;
// ... calcul ...
return { score, max, percentage };
}Nouveau Store :
import { calculateSessionScore } from '@/logic/scoring';
async function finishQuiz() {
const result = calculateSessionScore(activeSession.value.questions);
activeSession.value.scorePondere = result.score;
// ... save ...
}