Repository navigation
feat(admin): tableau de bord, lieux, parcours et import CSV - #398
Nascimento95 wants to merge 25 commits into
Conversation
228b5ae to
5282768
Compare
c38073a to
f2ccb57
Compare
|
Branche remise à jour sur la modération (#365), elle-même sur le socle rebasé sur Adaptations au rebase : le client API reprend celui de |
5282768 to
6135674
Compare
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…users (A-05) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…first name Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…to the team Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…eason dialog Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…sort (A-04) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… (A-04) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…urnal Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rnal Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…es address Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s (A-04) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… API Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-04) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s (A-04) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
f2ccb57 to
52d1d10
Compare
|
Branche remise à jour sur la modération (#365), elle-même sur le socle rebasé sur |
Résultat et problème
L'équipe n'avait ni tableau de bord ni moyen de gérer le catalogue. Cette PR ajoute le tableau de bord (A-05) et la section « Lieux et parcours » (A-04) : parcours, lieux et import CSV, côté API et côté admin.
Ce qui est fait :
GET /admin/countersetGET /admin/stats; tuiles « à traiter » selon le rôle, chacune ouvre sa liste filtrée ; chiffres du catalogue et des utilisateurs ; liens vers PostHog et RevenueCat.GET /admin/routes(recherche, filtres, tri, pages) ; fiche en lecture ; Dépublier et Republier avec motif, Réassigner à l'équipe (admin), chaque action journalisée.GET/POST /admin/places,GET/PATCH /admin/places/:id; liste, fiche dans le panneau de détail, création et édition dans un formulaire (éditeurs et admins ; un modérateur lit). La ville est déduite de la position.POST /admin/places/import, avec aperçu (dryRun) puis création ; modèle à télécharger ; chaque ligne affichée avec son résultat (prêt, créé, invalide avec les champs à corriger, doublon, hors zone) ; doublon = même nom à moins de 50 m, dans le catalogue ou plus haut dans le fichier ; une ligne au journal par lieu créé.mapbox-gl) : dans le formulaire d'un lieu, une épingle à déplacer ou un clic sur la carte renseigne la latitude et la longitude, et la saisie des champs déplace l'épingle. Sans jetonNEXT_PUBLIC_MAPBOX_TOKEN, le formulaire garde ses deux champs seuls.Critères d'acceptation :
Limites, et le ticket qui les lève :
Lien partenaire d'un lieu : demandé par ce ticket, non fait ici, et porté par Admin : affiliation et clics de réservation (A-09) #344 (affiliation, A-09), qui n'est pas encore réalisé et reste bloqué par Admin : socle Next.js, coque, connexion, rôles et journal (A-01) #52. Ce ticket prévoit lui-même le champ (
partner_booking_url,partner_program_id), les programmes d'affiliation et le comptage des clics : le faire ici créerait la colonne deux fois. Aucune colonne ni aucun champ n'existe pour l'instant. Le critère d'acceptation de ce ticket ne le couvre pas.Ouvrir dans l'app : l'écran du parcours de l'app est encore provisoire (Construire la fiche parcours (E-05) #37) ; le lien n'ouvre pas encore la fiche. Sur ordinateur il ne fait rien.
Lieu hors de toute ville : refusé (création, édition, import) tant que les villes ne se créent pas depuis la position (Ouvrir la création à toutes les villes : ville déduite de la position, recherche sans filtre de ville #340).
Tuiles à zéro : signalements de parcours (Migration : table route_reports et notifications.kind report_resolved #184), avis et support (Admin : signalements de lieux et de parcours, avis (A-03) #54), révisions (Gérer PUT /routes/:id/steps, submit, statuts et lien privé #48) : l'API répond 0 depuis une seule expression par compteur.
Horaires saisonniers d'un lieu : gardés à l'édition, mais ni affichés dans le formulaire ni importables.
Import : 500 lignes au plus par fichier (choix de cette PR, le ticket ne fixe pas de limite) ; chaque lieu est créé dans sa propre transaction, donc un import interrompu garde les lieux déjà créés, et le relancer les signale en doublons.
Pas de suppression de lieu : non demandée par le ticket.
Jeton Mapbox web : à créer dans le compte Mapbox de Widoo, public (
pk.), restreint aux adresses de l'admin ; à renseigner commeNEXT_PUBLIC_MAPBOX_TOKENdu build de staging et de production (argument de build deinfra/admin.Dockerfile).Questions pour Ilan :
Fixes #55
Écrans : A-04, A-05
Dépendance : empilée sur #365 (modération, #53), elle-même sur #363.
Comment vérifier
Montage local de #363, base locale, comptes
admin,editoretmoderator.Testé par Marco les 2026-10-12, 2026-10-13 et 2026-10-14, en local (base locale, Firebase de staging pour la connexion), face aux planches A-05 et aux modèles de
Ecranspour A-04 :La carte n'a pas de planche : elle suit la phrase du wiki (« épingle déplaçable »). Rien n'a été testé contre un environnement déployé. Pas de test à 150 % de texte ni au lecteur d'écran sur ces écrans.
pnpm lint && pnpm typecheck && pnpm testverts en localFormatage mécanique : non
Risque
Niveau : 2 — nouveaux endpoints authentifiés qui écrivent dans le catalogue (lieux, statut des parcours, import en lot) ; aucune migration.
Taille : deux commits au-dessus de 400 lignes.
56b6289(451) : la liste des parcours, ses filtres, son tableau, sa configuration et ses textes.4c58c56(427) : les composants du tableau de bord, son conteneur et ses textes.Revue OWASP (Top 10) :
requireAdminSection('catalog'); écriture d'un lieu parrequireRole('editor'); import, Republier et Réassigner parrequireRole('admin'). Refus testés par rôle (403, rien d'écrit). Les gardes de l'admin ne sont qu'un confort : l'API décide.place.create,place.import,place.updateet les actions de parcours gardent l'auteur et l'état.Nouvelle dépendance :
mapbox-gl3.32, chargée avec le formulaire de lieu seulement ; choisie parce que le wiki fixe Mapbox pour les cartes de Widoo (Architecture-Technique). Écartée :maplibre-gl, qui aurait demandé un autre fournisseur de tuiles. CSP de l'admin :api.mapbox.com,events.mapbox.comet un workerblob:ne sont autorisés que lorsqu'un jeton est configuré ; un jeton secret (sk.) est refusé au démarrage.Retour arrière
Le revert de la PR suffit pour le code, sans migration à annuler. Les lieux créés ou importés restent en base ; un import fait par erreur se retrouve par le journal (
admin_actions, actionplace.import).🤖 Generated with Claude Code