# TODO — Parité visitapp-web vs mymuseum-visitapp > Suivi des features Flutter (`mymuseum-visitapp`) à porter sur la version web (`visitapp-web`). > Légende : ❌ Non implémenté · ⚠️ Partiel · ✅ Fait · 🚫 Hors scope web (natif uniquement) Référence Flutter : `c:\Users\ThomasFransolet\Documents\Documents\Perso\GITEA\mymuseum-visitapp\lib\` --- ## Sections | Section | Flutter | Web | Statut | |---|---|---|---| | Article | `Sections/Article/article_page.dart` | `ArticleSection.tsx` | ✅ | | Agenda | `Sections/Agenda/agenda_page.dart` | `AgendaSection.tsx` | ⚠️ Partiel — popup à enrichir | | Menu | `Sections/Menu/menu_page.dart` | `MenuSection.tsx` | ✅ | | Slider | `Sections/Slider/` | `SliderSection.tsx` | ✅ | | Video | `Sections/Video/` | `VideoSection.tsx` | ✅ | | Map (+ parcours) | `Sections/Map/` | `MapSection.tsx` | ✅ | | PDF | `Sections/PDF/` | `PdfSection.tsx` | ✅ | | Weather | `Sections/Weather/` | `WeatherSection.tsx` | ✅ | | Quiz | `Sections/Quiz/` | `QuizSection.tsx` | ✅ | | Web | `Sections/Web/` | `WebSection.tsx` | ✅ | | Game (Puzzle / Sliding / Escape) | `Sections/Game/` | `GameSection.tsx` + `EscapeProgression.tsx` | ✅ | | GuidedPath (intégré Map / Game Escape) | `Sections/GuidedPath/` | `MapSection.tsx` + `EscapeProgression.tsx` | ✅ | | **Event** | `Sections/Event/event_page.dart`, `event_map_full_page.dart` | `EventSection.tsx` + `event/EventMap.tsx` | ✅ | --- ## ✅ Section Event — fait Page dédiée pour les sections de type Event ([EventSection.tsx](visitapp-web/src/components/sections/EventSection.tsx) + [event/EventMap.tsx](visitapp-web/src/components/sections/event/EventMap.tsx)). **Implémenté** : - Layout vertical scrollable (pas de TabBar — aligné avec le Flutter) - Hero : image + gradient + titre + badge dates `startDate…endDate` + back button - Section **Programme** : timeline verticale des `ProgrammeBlock` (triés par `startTime`), bloc actif (heure courante dans `startTime…endTime`) mis en évidence (badge "EN COURS", bordure primaire, dot avec halo), tap → bottom sheet détail + liste des annotations spatiales du bloc - Section **Carte** : mini-carte Leaflet (220px) avec annotations globales en couleur primaire + annotations du bloc actif en orange superposées. Bouton "Plein écran" overlay - Section **Parcours** : chips horizontaux (parcours guidés liés à l'event), tap → navigation vers la section Map associée (`baseSectionMapId`) qui héberge la progression existante - Section **À propos** : description HTML - Bottom sheet block detail : titre + horaire + description + liste annotations (badge orange + label) - Pré-fetch server-side des `guidedPaths` via le même endpoint polymorphe `/api/SectionMap/{eventId}/GuidedPath` **Types ajoutés** : `EventDTO`, `ProgrammeBlock`, `MapAnnotationDTO` dans [types.ts](visitapp-web/src/lib/api/types.ts) **Reste à faire** (nice-to-have) : - [ ] Mise en avant home : si `applicationInstanceDTO.sectionEventId != null`, afficher un bloc "à la une" en haut de la grille de configurations. Nécessite d'étendre `ApplicationInstanceDTO` (champ `sectionEventDTO?`) et de lui dédier un widget sur `[slug]/page.tsx`. --- ## ✅ Agenda — popup événement enrichi **Bug fix bonus** : le type web `EventAgendaDTO` était désynchronisé du backend (`title`/`startDate` au lieu de `label`/`dateFrom`). Type aligné dans [types.ts](visitapp-web/src/lib/api/types.ts). **Implémenté dans [AgendaSection.tsx](visitapp-web/src/components/sections/AgendaSection.tsx) + [agenda/EventMiniMap.tsx](visitapp-web/src/components/sections/agenda/EventMiniMap.tsx)** : - Mini-carte Leaflet centrée sur `address.geometry.coordinates` - Vidéo embarquée : iframe YouTube (`idVideoYoutube` ou `videoLink` YouTube), lecteur HTML5 natif (`videoLink` direct ou `videoResource.url`) - Liens cliquables : email (`mailto:`), téléphone (`tel:`), site web (target="_blank") - Adresse postale formatée → lien Google Maps --- ## ✅ Statistiques — tracking visiteur **Endpoint backend** : `POST /api/Stats/event` (anonyme, accepte `appType: "Web"`). **Implémenté** : - [src/lib/stats.ts](visitapp-web/src/lib/stats.ts) : `trackEvent()` + sessionId persistant (`sessionStorage`) - [src/hooks/useSectionTracking.ts](visitapp-web/src/hooks/useSectionTracking.ts) : hook auto qui émet `SectionView` au mount + `SectionLeave` au unmount avec durée - [src/components/TrackedSection.tsx](visitapp-web/src/components/TrackedSection.tsx) : wrapper appliqué au dispatcher → toutes les sections trackées sans toucher leur code - `instanceId` propagé via `VisitorContext` (depuis le layout `[slug]`) - Events spécifiques branchés : `MapPoiTap`, `QuizComplete`, `GameComplete`, `AgendaEventTap`, `QrScan` **Reste à brancher (rapide)** : - [ ] `ArticleRead` quand l'article est scrollé jusqu'à un seuil (~80%) - [ ] `MenuItemTap` au tap sur un item de menu --- --- ## ✅ Event "à la une" sur la home **Implémenté** : - `ApplicationInstanceDTO.sectionEventDTO` ajouté aux types - [src/components/FeaturedEvent.tsx](visitapp-web/src/components/FeaturedEvent.tsx) : carte hero (220px) avec image, badge "À LA UNE", badge dates, titre HTML - Branché dans [src/app/[slug]/page.tsx](visitapp-web/src/app/[slug]/page.tsx) : si `instance.sectionEventDTO` est rempli côté backend, le bloc s'affiche au-dessus de la grille de configurations --- ## ✅ Scanner QR code **Implémenté** : - Lib : `qr-scanner` (MIT, ~13kb gzip, cross-browser via `getUserMedia`) - [src/components/QRScannerButton.tsx](visitapp-web/src/components/QRScannerButton.tsx) : - Bouton flottant en bas-droite sur la home `/[slug]` - Modal fullscreen avec aperçu caméra + animation de scan - Parser regex qui extrait un path `/{slug}/{configId}/sections/{sectionId}` depuis le payload (URL absolue ou relative) - Sur match → `router.push()` vers le path - Émet l'event `QrScan` (avec payload + path parsé) - Gère les erreurs de permission caméra avec message visuel - Nécessite HTTPS en production (sauf localhost) **Reste à faire (nice-to-have)** : - [ ] Bouton scanner aussi accessible depuis `ConfigurationGrid` ou `SectionList` (actuellement seulement sur la home) --- ## 🚫 Hors scope (décision produit ou natif uniquement) Ces features ne sont **pas portées sur le web** : - **Assistant IA / Chat** — décision produit : feature premium réservée à l'app mobile native, pas portée côté web - **Mode offline / cache local** — décision produit : pas dans le scope web pour le moment, l'app web suppose une connexion - **Push notifications Firebase FCM** — réservées à l'app native (mobile installée) - **Beacons BLE** — Web Bluetooth pas supporté sur iOS Safari, et l'usage réel suppose un device mobile dédié - **Lecteur audio avancé** (just_audio Flutter) — l'audio HTML5 natif suffit, pas besoin d'aller plus loin - **Téléchargement caméra natif pour QR** — remplaçable par `getUserMedia` si on en a besoin (voir section QR ci-dessus) --- ## Suivi | Feature | Priorité | Statut | |---|---|---| | **Event Section** | Haute (gap fonctionnel) | ✅ Fait | | **Agenda popup enrichi** | Moyenne | ✅ Fait | | **Stats tracking** | Moyenne (besoin métier) | ✅ Fait (à compléter : ArticleRead, MenuItemTap) | | **Event "à la une" sur la home** | Basse (UX) | ✅ Fait | | **QR Scanner** | Basse | ✅ Fait | --- ## Référence — fichiers Flutter clés à consulter - Home + scanner : `lib/Screens/Home/home.dart`, `lib/Components/ScannerDialog.dart` - Event : `lib/Screens/Sections/Event/event_page.dart`, `event_map_full_page.dart` - Agenda popup : `lib/Screens/Sections/Agenda/event_popup.dart` - Services : `lib/Services/statisticsService.dart`, `assistantService.dart` - Cache local : `lib/Helpers/DatabaseHelper.dart`, `lib/Services/downloadConfiguration.dart` - Composants chat : `lib/Components/AssistantChatSheet.dart`