Admin : CRUD des scénarios de didacticiel + analytics de complétion #44
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?
Contexte
Suite à l'issue #42
(tutoriel guidé) : permettre à un admin de créer/modifier/supprimer les
scénarios de didacticiel depuis l'interface admin, plutôt que de les avoir
codés en dur. Bonus : analytics sur leur taux de complétion.
Ça révise directement la conception de #42, qui prévoyait un registre
TourDefinition[]statique en code (fichier TypeScript) avec des titres/contenus en clés i18n. Une fois éditable depuis un formulaire admin, le
contenu d'une étape ne peut plus raisonnablement être une clé i18n (un admin
ne va pas éditer
translation.jsonà la main) — il doit devenir du textelibre stocké en base, exactement comme le nom/la description d'une recette
sont déjà du texte libre plutôt que des clés i18n (la règle "tout texte
affiché vient d'i18next" concerne le chrome de l'UI codé en dur, pas le
contenu généré/administré dynamiquement — même distinction déjà appliquée
partout ailleurs dans ce repo). #42 doit être implémenté après ou avec
cette issue-ci, en consommant ce modèle plutôt que le registre statique
initialement prévu — un commentaire sera ajouté sur #42 pour le signaler.
Modèle de données
Suppression d'un scénario → cascade sur ses étapes et sur les lignes de
progression (cohérent : si le scénario n'existe plus, son statut "vu" par
tel ou tel utilisateur n'a plus de sens).
API admin (
/admin/api/tours,requireAdmin, même agrégateur queadmin.routes.ts'sadminRouter.use("/catalog", ...)etc.)GET /admin/api/toursGET /admin/api/tours/targetsTourTarget(pour le select du formulaire)POST /admin/api/tourskey,name)PATCH /admin/api/tours/:idname/enabledet remplace la liste d'étapes en bloc — même convention querecipe.service.ts'supdateRecipe, qui supprime/recrée tous lesStepd'une recette plutôt qu'un patch partiel, pas une nouveauté à inventerDELETE /admin/api/tours/:idAPI publique (lecture, pour le moteur de tour de #42)
GET /reference/tours(public, sansrequireAuth— même famille que/reference/diets//allergies/etc.) → scénarios activés avec leursétapes, forme consommée directement par
useTour()(#42) au lieu de sonregistre statique initialement prévu.
Interface admin
Nouvelle page
/admin/didacticiels(+ entrée dansAdminLayout.tsx'sNAV_ITEMS, même array que Dashboard/Monitoring/Corrections/Catalogue) :liste des scénarios (nom, activé/désactivé, nombre d'étapes) → éditeur par
scénario (nom, activé, liste d'étapes réordonnables avec route/cible/titre/
contenu, ajout/suppression d'étape). Nouveau scénario = mêmes champs,
keysaisie une fois à la création.
Bonus — analytics de complétion
Coût quasi nul, l'infrastructure existe déjà en quasi-totalité :
admin-metrics.service.ts'sgetMetrics()agrège déjà toutAnalyticsEventpartypeen séries temporelles journalières(
events: MetricsEventSeries[], lignes 190-204), etDashboardPage.tsx(lignes 120-135) rend déjà cette liste génériquement(
metrics.events.map(...)) — un type d'événement inédit apparaît sur ledashboard sans aucun changement frontend. Il suffit donc d'émettre,
côté
POST /profile/tours/:key/complete(#42) :et pareillement
"tour.skipped"si un tour est passé plutôt que terminé(distinction utile pour juger si un tour est trop long) — même fonction
analytics.recordEventqueplanning.item_added/tech_step.correction_submittedetc., rien de neuf à construire à ce niveau.
Fichiers à toucher
apps/api/prisma/schema.prisma—TourTarget/TourScenario/TourScenarioStep,TourProgressrévisé + migration + seed initial desTourTargetcorrespondant auxdata-tour-*posés par #42.apps/api/src/modules/admin/admin-tours.routes.ts/.service.ts(nouveaux)admin.routes.ts.apps/api/src/modules/reference/— ajouteGET /reference/tours.apps/web/src/pages/admin/tours/(nouveau) — page CRUD.apps/web/src/layouts/AdminLayout.tsx— entrée de nav.analytics.recordEvent("tour.completed"/"tour.skipped", ...)dans le endpoint de complétion de #42.
Tests
bloc, suppression en cascade) ;
GET /reference/toursne renvoie que lesscénarios activés.
(mock
cy.intercept, même convention que le reste de la suite admin).Hors scope
voir le rendu réel) — juste l'édition des données pour cette itération.
historique n'existe avant que #42 ne soit codé de toute façon).
🤖 Filed by Claude Code