Parcours de démarrage : socle des étapes de visite (huit lignes, « J'ai compris », cochage d'office) #425
Labels
No labels
autopilot:pending-human
source:analyste
source:defenseur
source:human
source:medic
status:approved
status:blocked
status:in-progress
status:needs-clarification
status:needs-fix
status:ready
status:review
status:triage
type:bug
type:feature
type:infra
type:refactor
type:schema
type:security
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: maximus/Simpl-Resultat#425
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Le parcours gagne deux étapes de visite, sans action que la base puisse compter : « Parcourir les catégories et les mots-clés » (5ᵉ, avant le classement) et « Parcourir les rapports » (8ᵉ). Elles se cochent par un bouton « J'ai compris » ; un profil qui avait déjà terminé le parcours les trouve faites. Cette issue pose le socle (types, préférences, fournisseur, bouton, liste, docs) ; les cartes des deux pages viennent avec #432. Retours de Max sur la v0.17.1 (#422).
Contexte
getOnboardingSnapshot,src/services/onboardingService.ts). Les étapes passées vivent dansonboarding_skipped_<clé>(:35-37), la règle D9 dansonboarding_guided_initialized(initializeGuidedPath).src/hooks/useOnboardingChecklist.ts) a des actions locales prioritaires sur le snapshot d'un chargement parti avant elles (HIDE,SHOW,SKIP,RESUME) ;SKIPlibère aussi le verrou de carte (:120-128).OnboardingBanner.tsx), le rang de la carte (OnboardingStepCard.tsx:62) et la fin de parcours (bannerMode,cardNextdansonboardingPath.ts) attendentbudgetReady.Travail à faire
src/shared/types/index.ts) :ChecklistItemKeyajoute"categories"et"reports";CHECKLIST_ITEM_KEYS=profile, importFolder, source, import, categories, manualCategory, budget, reports; nouvelle constanteVISIT_STEP_KEYS = ["categories", "reports"].computeChecklist(src/utils/onboardingChecklist.ts) : optionsacknowledged?: readonly ChecklistItemKey[]etvisitStepsInitialized: boolean; lignescategories(to: "/categories") etreports(to: "/reports"), faites quand reconnues. Tant quevisitStepsInitializedest faux, ces deux lignes sont verrouillées (hors du total, decompleteet denextStep), comme Budget avantbudgetReady, et leurtoreste la page.onboardingService.ts:acknowledgedStepKey(key)=onboarding_acknowledged_<clé>; lecture en une requête (LIKE 'onboarding_acknowledged_%'), filtrée surVISIT_STEP_KEYSet la valeur « 1 » ;acknowledgeStep(key)=setPreference(acknowledgedStepKey(key), "1");ONBOARDING_VISIT_STEPS_INITIALIZED_KEY = "onboarding_visit_steps_initialized";getOnboardingSnapshotrend aussiacknowledgedetvisitStepsInitialized(seule la valeur « 1 » compte) ;initializeVisitSteps(acknowledge: boolean): sans transaction ; siacknowledge,acknowledgeStep("categories")puisacknowledgeStep("reports"), puissetPreference(ONBOARDING_VISIT_STEPS_INITIALIZED_KEY, "1"). Les écritures sont idempotentes : un arrêt entre deux refait le même calcul au lancement suivant. Aucune ne notifie le canal de données.shouldAcknowledgeVisitSteps(checklist)(dansonboardingChecklist.ts) : vrai quand chaque ligne déverrouillée horsVISIT_STEP_KEYSest faite ou passée.src/hooks/useOnboardingChecklist.ts,src/contexts/OnboardingContext.tsx) :ACKNOWLEDGE: ajoute la clé àacknowledgedavec unacknowledgedSetAtqui prime sur le snapshot d'un chargement parti avant elle, commeskippedSetAt; elle gardecardPage(contrairement àSKIP), pour que la carte annonce « Fait. » puis l'étape suivante ;acknowledge(key)exposé parOnboardingContext, qui écrit paracknowledgeStep;budgetReadyest vrai etvisitStepsInitializedfaux, appelerinitializeVisitSteps(shouldAcknowledgeVisitSteps(checklist))puis relire ; garde contre le double montage de StrictMode sur le modèle du chargeur de D9 (createOnboardingLoader, promesse partagée) ;visitStepsInitialized;OnboardingBanner,OnboardingStepCardet le calcul du mode (bannerMode,cardNext) reçoiventbudgetReady && visitStepsInitializedlà où ils reçoiventbudgetReadyaujourd'hui ; l'état « en attente » de la ligne Budget gardebudgetReadyseul.StepCard(src/components/onboarding/StepCard.tsx) : proponAcknowledge?: () => void; quand elle est fournie et que l'étape n'est pas faite, bouton « J'ai compris » avant « Passer cette étape ».OnboardingStepCardla passe quandVISIT_STEP_KEYScontient l'étape de la carte.OnboardingChecklist(src/components/dashboard/OnboardingChecklist.tsx) : huit lignes ;rowStaterend « en attente » pour une ligne de visite tant quevisitStepsInitializedest faux (pas « verrouillée », qui afficherait le badge de l'édition Base).Textes (FR | EN)
onboarding.checklist.items.categoriesonboarding.checklist.items.reportsonboarding.card.acknowledgeDocs
docs.gettingStarted.steps,docs.gettingStarted.subsections[0].steps[0]et[1],docs.gettingStarted.subsections[0].note,docs.dashboard.features[6]: mêmes changements, FR et EN.docs/adr/0022-canal-evenements-donnees.md:acknowledgeStepetinitializeVisitStepsentrent dans la liste « Ne notifient pas » (§2) ; au §5, le cochage d'office est admis comme D9 : une écriture unique par profil après un chargement réussi, qui relit elle-même.docs/architecture.md, section Onboarding : huit lignes ; l'invariant « Chaque case est cochée par une donnée, jamais par un clic » devient « Les six étapes de données se cochent par une donnée, jamais par un clic ; les deux étapes de visite par « J'ai compris » (et, pour Rapports, l'ouverture de la carte Tendances mise en évidence) » ; préférencesonboarding_acknowledged_<clé>etonboarding_visit_steps_initializeddans le tableau des préférences et dans la ligneuser_preferencesdu tableau des tables.docs/qa-onboarding.html: huit lignes, « J'ai compris », cochage d'office d'un profil complet, lignes de visite « en attente » avant l'initialisation.Fichiers concernés
src/shared/types/index.ts,src/utils/onboardingChecklist.ts,src/services/onboardingService.ts,src/hooks/useOnboardingChecklist.ts,src/contexts/OnboardingContext.tsx,src/components/onboarding/StepCard.tsx,src/components/onboarding/OnboardingStepCard.tsx,src/components/onboarding/OnboardingBanner.tsx,src/components/dashboard/OnboardingChecklist.tsx,src/utils/onboardingPath.tssrc/utils/onboardingChecklist.test.ts,src/services/onboardingService.test.ts,src/hooks/useOnboardingChecklist.test.ts,src/hooks/useOnboardingChecklist.wiring.test.ts,src/contexts/OnboardingContext.render.test.tsx,src/components/onboarding/StepCard.render.test.tsx,src/components/onboarding/OnboardingStepCard.test.tsx,src/components/onboarding/OnboardingBanner.render.test.tsx,src/components/dashboard/OnboardingChecklist.test.tsx,src/utils/onboardingPath.test.tsuseOnboardingà compléter, ou totaux et rangs à décaler) :src/components/layout/AppShell.render.test.tsx,src/components/layout/AppShell.slot.test.tsx,src/components/dashboard/DashboardEmptyState.render.test.tsx,src/pages/DashboardPage.render.test.tsx,src/pages/ImportPage.render.test.tsx,src/pages/TransactionsPage.render.test.tsx,src/pages/BudgetPage.render.test.tsx,src/pages/BudgetPage.wiring.test.ts,src/components/budget/BudgetTable.wiring.test.ts,src/pages/settings/UsersSettingsPage.test.tsxsrc/i18n/locales/fr.json,src/i18n/locales/en.json,docs/guide-utilisateur.md,docs/architecture.md,docs/adr/0022-canal-evenements-donnees.md,docs/qa-onboarding.html,CHANGELOG.md,CHANGELOG.fr.mdRègle des gabarits de test. Tout gabarit de parcours fini, et tout gabarit arrêté après l'étape d'import, reconnaît les deux étapes de visite et a
visitStepsInitializedvrai (sinonnextStepdevientcategories). Rangs :manualCategorypasse de 5 à 6 etbudgetde 6 à 7 ; totaux : 6 → 8 (Base+) et 5 → 7 (Gratuite).Depends on
Tests
computeChecklist: huit lignes dans l'ordre ; totaux 8 (Base+) et 7 (Gratuite) ; une étape reconnue est faite, pas passée ; une étape de visite peut être passée ; avant l'initialisation, les deux lignes de visite sont hors du total et denextStep.shouldAcknowledgeVisitSteps: vrai pour six lignes faites ou passées (Base+) ; vrai en Gratuite avec Budget verrouillé et les cinq autres faites ; faux s'il en reste une ; les lignes de visite n'entrent pas dans le calcul.acknowledgeStepécrit la bonne clé ; le snapshot ne garde que les clés de visite à « 1 » ;initializeVisitSteps(true)écrit les deux reconnues puis le drapeau,initializeVisitSteps(false)le drapeau seul ; aucun appel àwithTransaction.ACKNOWLEDGEprime sur un chargement parti avant lui et gardecardPage; le cochage d'office ne s'exécute qu'une fois, et pas avantbudgetReady; premier rendu d'un profil au parcours fini : pas de bandeau « Étape suivante ».StepCard: « J'ai compris » seulement aveconAcknowledge, jamais sur une étape faite.OnboardingChecklist: une ligne de visite non initialisée s'affiche « en attente », sans badge d'édition.Critères d'acceptation
/categoriesn'a pas encore de carte, donc ni « J'ai compris » ni « Passer cette étape ». Admis : la pile est mergée d'un bloc avant toute release.npm run buildetnpm testverts.Review caveats
acknowledgeStepou ungetPreferencedans le rappel d'unwithTransactionbloquerait toute la base, à chaque lancement puisque le drapeau ne serait jamais écrit ; les tests de service simulentwithTransactionet ne le verraient pas. Max a retenu une initialisation sans transaction (CWE-833, CWE-362).npm run buildvérifie les types des fichiers de test ; unacknowledgeobligatoire et les nouveaux champs du snapshot cassent les fauxuseOnboardingde dix fichiers, et le passage à huit lignes casse les totaux et rangs affirmés ailleurs. Fichiers listés et règle des gabarits.ACKNOWLEDGEécrit « commeSKIP» aurait fait disparaître la carte au clic ; il garde le verrou de carte.Décisions prises en planification
Conventions
src/i18n/locales/fr.json,en.json) ; les textes de ce corps s'écrivent mot pour mot (FR validé par Max le 2026-10-12, EN rédigé sur le même contenu).## [Unreleased]dansCHANGELOG.mdetCHANGELOG.fr.md.renderToStaticMarkup(pas de jsdom) et le fauxtpartagé livré par #389.user_preferences(ADR 0016).npm run build(il vérifie aussi les types des fichiers de test) etnpm testverts.docs/guide-utilisateur.md) : repérer une ligne par son texte cité, pas par son numéro.CHANGELOG
Added / Ajouté : FR « Parcours de démarrage : deux étapes de visite, « Parcourir les catégories et les mots-clés » (avant le classement) et « Parcourir les rapports » (en dernier), cochées par « J'ai compris » ; un profil qui avait terminé le parcours les trouve déjà faites. » EN "Getting started: two visit steps, “Browse categories and keywords” (before categorizing) and “Browse the reports” (last), checked with “Got it”; a profile that had finished the path finds them already done." (#432 complète cette entrée.)
Spec source
spec-plan-retours-onboarding-v0171.md(local, ignoré par git) ; décisions dansspec-decisions-retours-onboarding-v0171.md.Planification du 2026-10-12 (
/plan-run, jalonplanned-2026-10-12-retours-onboarding-v0171) : le corps est réécrit pour être autosuffisant (décisions de Max, constats de/review-specintégrés) ; les cartes des deux pages passent dans #432. Corps précédent ci-dessous.Corps précédent (titre : Parcours de démarrage : deux étapes de visite, Catégories et mots-clés (avant le classement) puis Rapports (en dernier), cochées par « J'ai compris »)
Contexte
Issu des retours de Max sur la v0.17.1 (#422, analysée le 2026-10-12 sur
mainà1954502) : « ajouter une étape pour parcourir la section catégorie et mots clés fait plus tôt, et parcours rapide de la page rapport ».La spec de la phase 2 excluait de changer les six lignes de la liste (
spec-decisions-onboarding-parcours-guide.md, section OUT). Cette issue lève l'exclusion, à la demande de Max.Aujourd'hui, chaque étape se coche par un compteur SQL (
getOnboardingSnapshot,src/services/onboardingService.ts). Aucune ne se coche par une visite, et les deux nouvelles n'ont rien que la base puisse compter.Décisions (Max, 2026-10-12)
user_preferences, comme les étapes passées : aucune migration. Une visite sans clic ne coche rien.Nouvel ordre :
/categories)/reports)Défauts retenus par l'analyse
/categorieset le hub/reportsne sont derrière aucunRequireFeature(src/App.tsx). Total : 8 en Base+, 7 en Gratuite, où Budget reste verrouillé.onboarding_acknowledged_<clé>= « 1 », sur le modèle deonboarding_skipped_<clé>(onboardingService.ts:35-37), lue dansgetOnboardingSnapshotet filtrée sur les clés valides.categories.allKeywords,src/pages/CategoriesPage.tsx:47-57), présent sur tout profil.reinitializeCategories,src/services/categoryService.ts:215).src/pages/ReportsPage.tsx,src/shared/entitlements.ts:26).Travail à faire
ChecklistItemKeyetCHECKLIST_ITEM_KEYS(src/shared/types/index.ts:970-986) aveccategoriesetreports, dans l'ordre ci-dessus.computeChecklist(src/utils/onboardingChecklist.ts:35-69) : huit lignes, et une optionacknowledged(étapes cochées par « J'ai compris ») qui fait ledonedes deux étapes de visite.onboardingService.ts:acknowledgeStep(clé), et lecture des préférencesonboarding_acknowledged_<clé>dansgetOnboardingSnapshot.useOnboardingChecklist,OnboardingContext) : actionacknowledge(clé), qui prime commeSKIPsur le snapshot d'un chargement parti avant elle.onboardingPath.ts:/categorieset/reportsdansCARD_PAGESetPAGE_STEPS; modèlescategoriesCardModeletreportsCardModel.StepCard: « J'ai compris » pour une étape de visite (nouvelle prop) ; après le clic, « Fait. » puis l'étape suivante, comme les autres cartes.CategoriesPageetReportsPage: la carte connectée, et la mise en évidence de la cible paronboardingTargetAttributes.onboarding.checklist.items.categorieset.reports, phrases des cartes, libellé « J'ai compris ».docs.gettingStartedFR et EN ;docs/architecture.md, section Onboarding : huit lignes, préférenceonboarding_acknowledged_<clé>, ligneuser_preferencesdu tableau des tables ;docs/qa-onboarding.html;Fichiers concernés
src/shared/types/index.ts,src/utils/onboardingChecklist.ts,src/utils/onboardingPath.tssrc/services/onboardingService.ts,src/hooks/useOnboardingChecklist.ts,src/contexts/OnboardingContext.tsxsrc/components/onboarding/StepCard.tsx,src/components/onboarding/OnboardingStepCard.tsx,src/components/dashboard/OnboardingChecklist.tsxsrc/pages/CategoriesPage.tsx,src/pages/ReportsPage.tsx(et le composant qui porte la carte Tendances)src/i18n/locales/fr.json,src/i18n/locales/en.jsondocs/guide-utilisateur.md,docs/architecture.md,docs/qa-onboarding.html,CHANGELOG.md,CHANGELOG.fr.mdSurface de test
src/utils/onboardingChecklist.test.ts,src/utils/onboardingPath.test.ts,src/services/onboardingService.test.ts,src/hooks/useOnboardingChecklist.test.tset.wiring.test.ts,src/contexts/OnboardingContext.render.test.tsx,src/components/onboarding/StepCard.render.test.tsx,src/components/onboarding/OnboardingStepCard.test.tsx,src/components/dashboard/OnboardingChecklist.test.tsx.acknowledgeStepécrit la bonne clé, etgetOnboardingSnapshotne garde que les clés valides à « 1 » ;ACKNOWLEDGEprime sur un chargement parti avant lui ;cardStepetcardNextsur/categorieset/reports: la carte Catégories mène à « Classer une transaction à la main », la carte Rapports à la fin ;tdes tests de rendu rend la clé brute, untoublié passe inaperçu.Critères d'acceptation
/categories; la carte explique les mots-clés, entoure « Tous les mots-clés » et annonce l'ajout d'un mot-clé à l'étape suivante./reports; « J'ai compris » y termine le parcours (« Démarrage terminé »)./categoriesou/reportssans cliquer ne coche rien.npm testetnpm run buildverts.Complexité estimée
Moyenne à complexe : une nouvelle sorte d'étape, de visite, à travers le service, le reducer, le modèle pur, la carte et deux pages, plus les docs et la liste QA.
Dépendances
Après #422 : mêmes fichiers (
fr.json,en.json,onboardingPath.ts, guide, CHANGELOG, liste QA), et la carte Catégories annonce ce que la carte Transactions de #422 explique. À enchaîner, pas en parallèle.Questions ouvertes
Aucune ; les défauts ci-dessus sont tranchés pour l'implémentation.
Parcours de démarrage : deux étapes de visite, Catégories et mots-clés (avant le classement) puis Rapports (en dernier), cochées par « J'ai compris »to Parcours de démarrage : socle des étapes de visite (huit lignes, « J'ai compris », cochage d'office)