Files
mobile/documentation/CDC_App_Flutter.md
2026-07-04 22:48:14 +02:00

16 KiB

Cahier des Charges — Application Utilisateur Mobile & Web

Projet : Laverie Connectée — App Flutter

Version : 1.0
Date : 2026-06-27
Stack principale : Flutter 3.x (Android / iOS / Web)


1. Contexte & Objectifs

1.1 Contexte

Application grand public permettant aux utilisateurs de :

  • Localiser les laveries disponibles
  • Gérer leur porte-monnaie électronique
  • Réserver un créneau machine
  • Déclencher un lavage par QR code
  • Suivre leurs lavages et consulter leur historique

1.2 Cibles plateformes

Plateforme Version minimale Distribution
Android 8.0 (API 26) Google Play Store
iOS 15.0 Apple App Store
Web Chrome 100+, Safari 15+, Firefox 100+ PWA hébergée

1.3 Contraintes

  • L'app doit rester utilisable hors-ligne pour les fonctions de consultation (solde en cache, historique)
  • Respect strict du RGPD : collecte minimale, consentements explicites, droit à l'effacement
  • L'application doit rester connectée en arrière-plan pour recevoir les notifications push

2. Stack Technique

Composant Technologie Version Justification
Framework UI Flutter 3.x (stable) Codebase unique Android/iOS/Web
Langage Dart 3.x Null-safety, typage fort
State management Riverpod 2.x Réactivité, testabilité, pas de BuildContext dependency
Navigation GoRouter 13.x Deep links, routing déclaratif
HTTP Client Dio 5.x Intercepteurs JWT, retry automatique
Cache local Hive 2.x Clé-valeur rapide, offline-first
Auth persistence flutter_secure_storage 9.x Stockage sécurisé tokens (Keychain / Keystore)
Notifications push firebase_messaging 15.x FCM Android/Web + APNs iOS
QR Code scan mobile_scanner 5.x Caméra native, performant
Paiement in-app flutter_stripe 10.x Stripe SDK officiel
Géolocalisation geolocator 13.x Localisation établissements
Cartes flutter_map + OpenStreetMap Affichage carte sans coût API Google
Internationalisation flutter_localizations (Flutter) fr / en au minimum
Tests flutter_test + Mockito Unit + widget + integration tests
CI/CD GitHub Actions + Fastlane Build, test, déploiement stores
Monitoring Firebase Crashlytics Crashes prod
Analytics Firebase Analytics Entonnoirs, rétention

3. Architecture de l'Application

3.1 Pattern architectural : Clean Architecture + Feature-first

lib/
├── core/
│   ├── api/
│   │   ├── api_client.dart          # Instance Dio configurée
│   │   ├── interceptors/
│   │   │   ├── auth_interceptor.dart    # Injection Bearer token
│   │   │   └── retry_interceptor.dart   # Retry sur 401 avec refresh
│   │   └── api_exception.dart
│   ├── cache/
│   │   └── hive_service.dart        # Abstraction cache local
│   ├── router/
│   │   └── app_router.dart          # GoRouter centralisé
│   ├── theme/
│   │   ├── app_theme.dart
│   │   └── app_colors.dart
│   └── utils/
│       ├── currency_formatter.dart
│       └── date_formatter.dart
│
├── features/
│   ├── auth/
│   │   ├── data/
│   │   │   ├── auth_repository.dart
│   │   │   └── models/auth_token.dart
│   │   ├── domain/
│   │   │   └── providers/auth_provider.dart
│   │   └── presentation/
│   │       ├── login_screen.dart
│   │       └── register_screen.dart
│   │
│   ├── wallet/
│   │   ├── data/
│   │   ├── domain/
│   │   └── presentation/
│   │       ├── wallet_screen.dart
│   │       ├── transaction_history_screen.dart
│   │       └── top_up_screen.dart
│   │
│   ├── establishments/
│   │   ├── data/
│   │   ├── domain/
│   │   └── presentation/
│   │       ├── map_screen.dart
│   │       ├── establishment_list_screen.dart
│   │       └── establishment_detail_screen.dart
│   │
│   ├── machines/
│   │   ├── data/
│   │   ├── domain/
│   │   └── presentation/
│   │       ├── machine_card_widget.dart
│   │       └── machine_detail_screen.dart
│   │
│   ├── booking/
│   │   ├── data/
│   │   ├── domain/
│   │   └── presentation/
│   │       ├── slot_picker_screen.dart
│   │       ├── booking_confirm_screen.dart
│   │       └── my_bookings_screen.dart
│   │
│   ├── wash/
│   │   ├── data/
│   │   ├── domain/
│   │   └── presentation/
│   │       ├── qr_scanner_screen.dart
│   │       ├── wash_confirm_screen.dart
│   │       └── wash_active_screen.dart
│   │
│   ├── notifications/
│   │   └── notification_service.dart
│   │
│   └── profile/
│       └── presentation/
│           ├── profile_screen.dart
│           └── gdpr_settings_screen.dart
│
└── main.dart

3.2 Flux d'authentification

App start
  └── AuthProvider.check()
        ├── Token valide → HomeScreen
        ├── Token expiré → RefreshToken()
        │       ├── Succès → HomeScreen
        │       └── Échec → LoginScreen
        └── Pas de token → OnboardingScreen

3.3 Gestion du token JWT

  • AuthInterceptor (Dio) : inject Authorization: Bearer <token> sur chaque requête
  • Sur 401 : appel automatique à /auth/refresh → retry de la requête originale
  • Tokens stockés dans flutter_secure_storage (Keychain iOS / Keystore Android)
  • Sur Web : stockage en sessionStorage chiffré (pas de localStorage pour les tokens)

4. Écrans & Parcours Utilisateur

4.1 Navigation principale (Bottom Navigation Bar)

┌─────────────────────────────────────────────┐
│  🗺 Carte  │  💰 Wallet  │  📅 Réservations  │  👤 Profil │
└─────────────────────────────────────────────┘

4.2 Onboarding & Inscription

Écran 1 — Bienvenue

  • Logo + baseline
  • CTA : "Se connecter" / "Créer un compte"

Écran 2 — Inscription (multi-étapes)

  • Étape 1 : Email + mot de passe (+ confirmation)
  • Étape 2 : Prénom, nom, téléphone, date de naissance
  • Étape 3 : Consentements RGPD (cases à cocher individuelles, non pré-cochées)
    • Traitement des données (obligatoire)
    • Communications marketing (optionnel)
    • Analyse d'utilisation (optionnel)
  • Étape 4 : Code parrainage (optionnel)
  • Confirmation email requise avant accès complet

Règles de validation :

  • Email : format RFC 5322
  • Mot de passe : 8 caractères minimum, 1 majuscule, 1 chiffre
  • Téléphone : format E.164 (+33XXXXXXXXX)
  • Date de naissance : 16 ans minimum

4.3 Carte & Établissements

Écran Carte (MapScreen)

  • Carte OpenStreetMap centrée sur la position utilisateur
  • Marqueurs pour chaque établissement (couleur selon disponibilité)
    • 🟢 Machines disponibles
    • 🟡 Toutes occupées, créneaux libres
    • 🔴 Toutes occupées, aucun créneau proche
  • Tap sur marqueur → sheet inférieure avec résumé
  • Bouton liste (switch vue liste / carte)

Écran Détail Établissement

  • Nom, adresse, horaires
  • Liste des machines avec statut temps réel (polling 30s ou WebSocket si dispo)
  • Pour chaque machine : type, statut, prochain créneau libre, tarif actuel
  • CTA : "Réserver" ou "Scanner & Lancer"

4.4 Porte-monnaie

Écran Wallet

  • Solde affiché en grand (avec animation de mise à jour)
  • Bouton "Recharger" bien visible
  • Historique des 10 dernières transactions
  • Lien "Voir tout"

Écran Historique

  • Liste paginée (infinite scroll)
  • Filtres : Type (débit/crédit), Période
  • Chaque entrée : icône type, montant coloré, source, date/heure, solde après
  • Export CSV (optionnel, v2)

Parcours Rechargement

  1. Saisie du montant (suggestions : 10€, 20€, 50€)
  2. Sélection du fournisseur de paiement (si plusieurs disponibles)
  3. Redirection vers Stripe Checkout (WebView sécurisée) ou SDK natif
  4. Retour sur l'app via deep link laverie://wallet/topup-result
  5. Confirmation animée + mise à jour du solde
  6. Notification push de confirmation

Contraintes :

  • Montant minimum : 5€, maximum : 150€ par rechargement
  • Affichage du solde en cache si hors-ligne

4.5 Réservation d'un Créneau

Écran Sélection de Créneau (SlotPickerScreen)

  • Sélecteur de date (calendrier scrollable, 14 jours maximum)
  • Pour la date sélectionnée : grille horaire avec créneaux libres/occupés
  • Mise en évidence du prix par créneau (heure creuse / heure pleine)
  • Information : "Supplément réservation : +1.00€"

Écran Confirmation Réservation

  • Récapitulatif : machine, date/heure, durée, prix total
  • Solde actuel et solde après débit
  • Mention pénalité no-show
  • Bouton "Confirmer et débiter X.XX€"

Écran Mes Réservations

  • Onglets : À venir / Passées
  • Chaque réservation : statut badge, machine, créneau, montant
  • Actions possibles : "Annuler", "Déplacer" (si > 2h)
  • Countdown pour les réservations imminentes

Règles métier UI :

  • Créneau non réservable si solde insuffisant → CTA "Recharger d'abord"
  • Annulation : popup de confirmation avec montant remboursé affiché
  • Déplacement : ouvre SlotPickerScreen avec le même contexte machine

4.6 Déclenchement d'un Lavage par QR Code

Écran Scanner QR (QrScannerScreen)

  • Vue caméra plein écran avec cadre de scan
  • Feedback visuel à la détection (vibration + flash vert)
  • Fallback : saisie manuelle du code machine

Flux post-scan :

  1. Identification de la machine via le QR
  2. Appel API → vérification statut + tarif
  3. Affichage récap : machine, programme, prix estimé, solde après
  4. Bouton "Lancer le lavage"
  5. Animation de confirmation (spinner → ✓)
  6. Écran "Lavage en cours" avec countdown

Écran Lavage Actif (WashActiveScreen)

  • Machine + établissement
  • Barre de progression avec temps restant (mise à jour polling API 30s)
  • Montant débité
  • Notification push à la fin du cycle

4.7 Notifications Push

Configuration :

  • Demande de permission notifications à l'inscription (après onboarding)
  • Sur iOS : UNUserNotificationCenter.requestAuthorization
  • Sur Android 13+ : POST_NOTIFICATIONS permission
  • Token FCM/APNs envoyé à l'API à chaque démarrage de l'app (mise à jour si changé)

Gestion en foreground :

  • Affichage d'une bannière in-app (snackbar stylisée)
  • Tap → navigation vers l'écran pertinent

Deep links depuis notification :

Notification Deep link
Rechargement confirmé laverie://wallet
Réservation confirmée laverie://bookings/{uuid}
Rappel créneau laverie://bookings/{uuid}
Lavage terminé laverie://washes/{uuid}
Promo disponible laverie://establishments/{uuid}

4.8 Profil & Paramètres

Écran Profil

  • Informations personnelles (modifiables)
  • Mes statistiques : nombre de lavages, total dépensé, économies promos
  • Code parrainage personnel (copiable, partageable)
  • Gestion notifications (toggle par type)
  • Paramètres RGPD
  • Déconnexion

Écran Paramètres RGPD

  • Visualisation des consentements donnés (avec date)
  • Toggle individuel pour chaque consentement
  • Bouton "Télécharger mes données" (export JSON, v2)
  • Bouton "Supprimer mon compte" (confirmation en deux étapes + délai 30 jours)

5. Gestion de l'État (Riverpod)

5.1 Providers principaux

// Auth
final authProvider = StateNotifierProvider<AuthNotifier, AuthState>

// Wallet
final walletProvider = FutureProvider<WalletData>
final transactionsProvider = StateNotifierProvider<TransactionsNotifier, TransactionsState>

// Establishments
final establishmentsProvider = FutureProvider.family<Establishment, String>  // by uuid
final nearbyEstablishmentsProvider = FutureProvider<List<Establishment>>

// Machines
final machineStatusProvider = StreamProvider.family<Machine, String>  // polling 30s

// Bookings
final bookingsProvider = StateNotifierProvider<BookingsNotifier, BookingsState>
final slotAvailabilityProvider = FutureProvider.family<List<TimeSlot>, SlotQuery>

// Active wash
final activeWashProvider = StreamProvider<Wash?>  // null si aucun lavage en cours

5.2 Stratégie offline-first (Hive)

Donnée Cache TTL
Solde wallet Oui Jusqu'au prochain refresh
Historique transactions Oui (50 dernières) 24h
Établissements (liste) Oui 1h
Disponibilités machines Non
Réservations Oui 30 min

En cas d'absence de réseau : affichage des données en cache avec badge "Données hors-ligne".


6. Sécurité

6.1 Stockage

  • Tokens JWT : flutter_secure_storage (AES-256 sur Android, Keychain sur iOS)
  • Aucune donnée sensible dans SharedPreferences
  • Sur Web : pas de localStorage, session uniquement

6.2 Réseau

  • Certificate pinning en production (via dio custom HttpClient)
  • Timeout : 10s connexion, 30s réception
  • Toutes les requêtes en HTTPS (TLS 1.3)

6.3 QR Code

  • Vérification côté serveur (le QR code seul ne suffit pas à déclencher un lavage)
  • Rate limiting API sur /washes/start : 3 req/min/user

7. Performance & UX

  • Splash screen natif (Android 12 Splash API, iOS UILaunchScreen)
  • Skeleton loaders sur toutes les listes et cartes pendant le chargement
  • Optimistic UI : affichage anticipé des mises à jour (ex: annulation réservation)
  • Pull-to-refresh sur toutes les listes
  • Pagination infinie sur l'historique des transactions
  • Animations : transitions de pages fluides (Hero, Fade), animation solde wallet

8. Tests

Type Outil Portée
Tests unitaires flutter_test Providers Riverpod, formatters, validators
Tests widgets flutter_test Tous les écrans principaux
Tests d'intégration integration_test Parcours critiques (inscription, rechargement, scan QR)
Tests golden golden_toolkit Composants UI clés (cohérence visuelle)

Parcours critiques à couvrir en intégration :

  1. Inscription complète → vérification email → connexion
  2. Rechargement porte-monnaie (mock Stripe)
  3. Réservation créneau → annulation → vérification remboursement
  4. Scan QR → lancement lavage → fin de cycle

9. CI/CD

9.1 Pipeline GitHub Actions

# Sur chaque PR :
- flutter analyze          # Linting strict
- flutter test             # Tests unitaires + widgets
- flutter build apk --release   # Vérification build Android
- flutter build ios --release   # Vérification build iOS (macOS runner)
- flutter build web             # Vérification build Web

# Sur merge main :
- Fastlane → TestFlight (iOS)
- Fastlane → Play Store Internal Track (Android)
- Deploy Web → hébergement (Firebase Hosting ou VPS)

9.2 Flavors

Flavor API URL Firebase projet Build suffix
dev http://localhost:8000 laverie-dev .dev
staging https://api-staging.laverie.app laverie-staging .staging
production https://api.laverie.app laverie-prod

10. Livrables attendus

  • Code source Flutter (GitHub, repository dédié)
  • Flavors configurés (dev / staging / prod)
  • README.md avec instructions setup complet
  • Fichiers de configuration Firebase (google-services.json, GoogleService-Info.plist)
  • Fichiers de signature Android (.keystore) documentés
  • Screenshots pour les stores (5 par plateforme minimum)
  • Suite de tests (couverture > 70% sur la logique métier)
  • Build release Android (.aab) + iOS (.ipa) prêts à soumettre