🎵 Concertothèque
Gestionnaire personnel de concerts — Flutter + Firebase
📌 Aperçu du projet
Concertothèque est une application de bureau (Windows, prioritaire) et mobile (Android / iOS) développée avec Flutter. Elle permet à un utilisateur de tenir un journal personnel de tous les concerts qu'il a assistés ou prévoit d'assister, en gérant les artistes, les salles et les statistiques associées.
Les données sont synchronisées en temps réel via Cloud Firestore et l'authentification est assurée par Firebase Auth. Des notifications locales rappellent les concerts à venir (J-7 et J-1).
Concerts
Créez, éditez et archivez vos événements avec affiche, placement et tarif.
Artistes
Bibliothèque d'artistes avec genre musical et historique des concerts.
Lieux
Gérez salles et festivals avec adresse, capacité et site web.
Statistiques
Dashboard avec total dépenses, top artistes et prochains concerts.
Rappels
Notifications automatiques J-7 et J-1 avant chaque concert.
Export CSV
Export de concerts, artistes et lieux au format CSV UTF-8.
✨ Fonctionnalités
Gestion des concerts
- Création / édition / suppression avec confirmation
- Types d'événement : Concert, Festival, Soirée, Showcase, Comédie musicale
- Placements : Fosse, Gradin, Catégorie 1–4, Carré Or
- Liaison à une salle (avec création inline) et à des artistes (multi-sélection)
- Images : affiche et couverture par URL
- Archivage automatique lorsque la date est passée
- Filtres avancés (nom, ville, artiste, type) + tri multi-colonnes
- Sélection multiple pour suppression groupée
Gestion des artistes & lieux
- CRUD complet avec pagination (25 éléments / page)
- Recherche instantanée par nom / genre
- Page de détail avec liste des concerts associés
Dashboard & statistiques
- Nombre total de concerts, à venir, archivés
- Total des dépenses (billets + dépenses supplémentaires)
- Top 5 artistes les plus vus (barres de progression)
- Top 5 salles les plus visitées
- Prochains concerts à venir
Notifications
- Rappels automatiques J-7 et J-1 au démarrage de l'app
- Notifications depuis Firestore Inbox (Firebase Console / Cloud Functions)
- Windows : Toast natif via
flutter_local_notifications - Mobile : FCM +
flutter_local_notifications - Anti-doublon via
SharedPreferences
Fonctionnalités Windows spécifiques
- Icône dans la barre des tâches (system tray) avec menu contextuel
- Option "Minimiser dans le systray" au lieu de fermer
- Démarrage automatique au lancement de Windows (registre
HKCU\…\Run)
Paramètres & compte
- Sélecteur de thème : Système / Clair / Sombre
- Modification du profil (nom d'affichage)
- Suppression de compte avec ré-authentification
- Export CSV séparé pour chaque collection
- Journalisation des erreurs (Crashlytics mobile, Firestore desktop)
🛠️ Stack technique
📁 Structure des fichiers
concertotheque_app/ ├── lib/ │ ├── main.dart ← Point d'entrée, init Firebase & services │ ├── app_settings.dart ← État global (thème, notifications, tray) │ ├── firebase_options.dart ← Clés Firebase par plateforme │ │ │ ├── models/ │ │ ├── artiste.dart ← Modèle Artiste │ │ ├── concert.dart ← Modèle Evenement (concert) │ │ └── lieu.dart ← Modèle Lieu (salle) │ │ │ ├── screens/ │ │ ├── login_screen.dart ← Connexion email/password │ │ ├── register_screen.dart ← Inscription │ │ ├── dashboard_screen.dart ← Tableau de bord & statistiques │ │ ├── concerts_screen.dart ← Liste concerts (filtre, tri, multi-select) │ │ ├── concert_detail_screen.dart ← Détail d'un concert │ │ ├── evenement_edit_screen.dart ← Création / édition concert │ │ ├── artistes_screen.dart ← Liste artistes paginée │ │ ├── artiste_detail_screen.dart ← Détail artiste + concerts │ │ ├── artiste_edit_screen.dart ← Création / édition artiste │ │ ├── lieux_screen.dart ← Liste des salles │ │ ├── lieu_detail_screen.dart ← Détail salle + concerts │ │ ├── lieu_edit_screen.dart ← Création / édition salle │ │ ├── settings_screen.dart ← Paramètres app (4 sections) │ │ └── about_screen.dart ← À propos & debug │ │ │ ├── services/ │ │ ├── evenement_service.dart ← CRUD concerts (Firestore) │ │ ├── artiste_service.dart ← CRUD artistes (Firestore) │ │ ├── lieu_service.dart ← CRUD lieux (Firestore) │ │ ├── notification_service.dart ← Toast / FCM │ │ ├── reminder_service.dart ← Rappels J-7 / J-1 │ │ ├── inbox_service.dart ← Listener Firestore inbox │ │ ├── export_service.dart ← Export CSV │ │ ├── tray_service.dart ← Systray Windows │ │ ├── autostart_service.dart ← Démarrage auto Windows │ │ └── crash_logger.dart ← Crashlytics / Firestore logs │ │ │ └── widgets/ │ ├── main_layout.dart ← Sidebar + zone contenu │ └── artiste_picker_dialog.dart ← Sélecteur artistes multi-choix │ ├── android/ ← Config Android ├── ios/ ← Config iOS ├── macos/ ← Config macOS ├── windows/ ← Config Windows (runner, icône .ico) ├── web/ ← Config Web (limité) ├── linux/ ← Config Linux ├── docs/ ← Documentation technique │ ├── ARCHITECTURE.md │ ├── BUILD_RELEASE.md │ ├── FIREBASE.md │ └── notifications.md ├── pubspec.yaml ← Dépendances & métadonnées app ├── firebase.json ← Config FlutterFire CLI └── documentation.html ← Ce fichier
🗂️ Modèles de données
Artiste — lib/models/artiste.dart
| Champ | Type | Description |
|---|---|---|
| id | String | Identifiant Firestore (final) |
| nom | String | Nom de l'artiste |
| genre | String | Genre musical |
| photo | String | URL de la photo (peut être vide) |
// Méthodes factory Artiste.fromDoc(DocumentSnapshot doc) Map<String, dynamic> toMap()
Evenement (Concert) — lib/models/concert.dart
| Champ | Type | Description |
|---|---|---|
| id | String | Identifiant Firestore |
| nomEvent | String | Nom de l'événement |
| date | DateTime | Date du concert |
| typeCode | String | CON / FES / SOI / SHO / COM |
| placement | String | FOSS / GRAD / CAT1–4 / CARO |
| prixBillet | double | Prix du billet (€) |
| depenseSup | double | Dépenses supplémentaires (€) |
| affiche | String | URL de l'affiche |
| cover | String | URL de la bannière |
| lieuNom | String | Nom de la salle |
| ville | String | Ville du concert |
| pays | String | Pays du concert |
| artistes | List<String> | Noms des artistes |
// Getter calculé
bool get isArchive => date.isBefore(DateTime.now());
// Codes types → libellés
const typeLabels = {
'CON': 'Concert', 'FES': 'Festival',
'SOI': 'Soirée', 'SHO': 'Showcase', 'COM': 'Comédie musicale'
};
// Codes placement → libellés
const placementLabels = {
'FOSS': 'Fosse', 'GRAD': 'Gradin',
'CAT1': 'Catégorie 1', 'CAT2': 'Catégorie 2',
'CAT3': 'Catégorie 3', 'CAT4': 'Catégorie 4',
'CARO': 'Carré Or'
};
Lieu (Salle) — lib/models/lieu.dart
| Champ | Type | Description |
|---|---|---|
| id | String | Identifiant Firestore |
| nom | String | Nom de la salle |
| ville | String | Ville |
| pays | String | Pays (défaut : France) |
| adresse | String | Adresse complète |
| type | String | Type de lieu (salle, plein air…) |
| capacite | int | Capacité d'accueil |
| photo | String | URL de la photo |
| siteWeb | String | URL du site officiel |
⚙️ Services
Services de données Firestore
Les trois services (EvenementService, ArtisteService, LieuService)
suivent le même patron :
- Collection :
users/{uid}/{evenements|artistes|lieux} - Pagination curseur : 25 éléments par page
| Méthode | Retour | Description |
|---|---|---|
| fetchPage({cursor}) | Future<List> | Page paginée (cursor-based) |
| fetchAll() | Future<List> | Jeu complet (pour export) |
| stream() | Stream<List> | Temps réel (artistes, lieux) |
| add(item) | Future<void> | Créer un document |
| update(item) | Future<void> | Modifier un document |
| delete(id) | Future<void> | Supprimer un document |
NotificationService
Gère les notifications locales et push selon la plateforme :
| Méthode | Description |
|---|---|
| initialize() | Init platform-specific (Toast ou FCM) |
| canShow() | Vérifie paramètres app + permission OS |
| show(title, body, id) | Affiche une notification |
| isOsPermissionGranted() | Vérifie permission OS |
| getToken() | Token FCM (mobile uniquement) |
ReminderService
Au démarrage de l'app, interroge Firestore pour les concerts dans les 7 prochains jours :
- Rappel à J-7 (clé SharedPreferences :
{id}_j7) - Rappel à J-1 (clé SharedPreferences :
{id}_j1) - Anti-doublon : les rappels déjà envoyés ne sont plus réémis
InboxService
Écoute la collection users/{uid}/inbox en temps réel :
- Déclenchement sur tout document avec
read: false - Marque automatiquement le document
read: trueaprès affichage - Cycle de vie géré manuellement :
start()/stop()(login/logout)
ExportService
- Exports CSV avec BOM UTF-8 (compatibilité Excel)
- Dialogue natif "Enregistrer sous" via
file_picker - Séparateur : virgule, valeurs entre guillemets si nécessaire
- Format date : ISO 8601 (
YYYY-MM-DD)
TrayService Windows
- Singleton implémentant
TrayListeneretWindowListener - Menu contextuel : "Ouvrir Concertothèque" / "Quitter"
- Intercepte la fermeture si
minimizeToTrayest activé - Icône :
windows/runner/resources/concertotheque.ico
AutostartService Windows
- Registre :
HKCU\Software\Microsoft\Windows\CurrentVersion\Run - Commande
reg add/reg deleteviaProcess.run - Méthodes :
isEnabled(),setEnabled(bool)
CrashLogger
- Mobile : délègue à Firebase Crashlytics
- Desktop : écrit dans
users/{uid}/crash_logs(Firestore) - Champs : error, stack, platform, fatal, timestamp
- Intégré dans
runZonedGuarded(erreurs async non gérées)
📱 Écrans (Screens)
Authentification
| Écran | Fichier | Description |
|---|---|---|
| LoginScreen | login_screen.dart | Email + mot de passe, option "Se souvenir de moi" (SharedPreferences) |
| RegisterScreen | register_screen.dart | Inscription avec validation des champs |
Dashboard
DashboardScreen (dashboard_screen.dart) — page d'accueil après connexion :
- Compteurs : total concerts, à venir, archivés
- Total des dépenses (billets + dépenses supplémentaires)
- Artistes uniques et lieux uniques
- Top 5 artistes avec barres de progression (occurrences)
- Top 5 lieux visités
- Liste des prochains concerts (triés par date)
Concerts
| Écran | Fonctionnalités clés |
|---|---|
| ConcertsScreen | Recherche multi-champs, filtres par type, tri multi-colonnes, multi-sélection + suppression groupée |
| ConcertDetailScreen | Affiche + bannière, infos complètes, artistes avec photos, liens vers artiste/lieu, édition/suppression |
| EvenementEditScreen | Formulaire complet avec sélecteur de salle (+ création inline), date picker, type/placement, multi-artiste, aperçu images |
Artistes
| Écran | Fonctionnalités clés |
|---|---|
| ArtistesScreen | Grille paginée (25/page), recherche par nom/genre, avatar, édition/suppression, FAB d'ajout |
| ArtisteDetailScreen | Grand avatar, badge genre, compteur concerts, liste des concerts par date desc avec badges statut |
| ArtisteEditScreen | Formulaire création/édition (nom, genre, URL photo) |
Lieux
| Écran | Fonctionnalités clés |
|---|---|
| LieuxScreen | Liste paginée, recherche nom/ville, photo, capacité |
| LieuDetailScreen | Photo, type, capacité, adresse, lien site web, concerts associés |
| LieuEditScreen | Formulaire complet (nom, ville, pays, adresse, type, capacité, photo, site web) |
Paramètres
SettingsScreen est divisé en 4 sections :
- Apparence — sélecteur de thème (Système / Clair / Sombre)
- Notifications — activation/désactivation, vérification permission OS, bouton test
- Système — démarrage auto (Windows), minimiser dans systray (Windows)
- Données — export CSV (concerts, artistes, lieux), modification profil, suppression compte
À propos
AboutScreen — icône app, version, développeur (Julien Gournay), liens GitHub, stack technologique, bouton debug crash.
🧩 Widgets
MainLayout — lib/widgets/main_layout.dart
Disposition principale de l'application (après authentification) :
- Sidebar fixe de 250 px + zone contenu extensible
- Logo + 6 entrées de navigation (Dashboard, Concerts, Artistes, Lieux, Paramètres, À propos)
- Indicateur de route active : bordure gauche orange + fond teinté
- Carte utilisateur en bas (initiale + email) + dialogue de déconnexion au clic
- Couleurs adaptatives light/dark
- Transitions de page sans animation (
PageRouteBuilder)
ArtistePickerDialog — lib/widgets/artiste_picker_dialog.dart
Dialog modal pour la sélection multiple d'artistes :
- Champ de recherche filtrant par nom en temps réel
- Stream Firestore live (
ArtisteService.stream()) - Checkbox avec accent orange pour chaque artiste
- Sous-titre = genre musical
- Badge indiquant le nombre de sélections
- Retourne
List<String>(noms) ounullsi annulé
🔥 Configuration Firebase
Projet Firebase : concertotheque
| Plateforme | App ID |
|---|---|
| Android | 1:983582489419:android:9bed2591728c13721006ce |
| iOS / macOS | 1:983582489419:ios:31fd242362c790671006ce |
| Web | 1:983582489419:web:c7d022dc130a2dd31006ce |
| Windows | 1:983582489419:web:384cf9d6ca940c541006ce |
Services activés
- Firebase Authentication (email/password)
- Cloud Firestore
- Firebase Cloud Messaging (FCM)
- Firebase Crashlytics (mobile)
Règles Firestore recommandées
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId}/{document=**} {
allow read, write: if request.auth != null
&& request.auth.uid == userId;
}
}
}
🗄️ Structure Firestore
{uid}/
evenements/ ← concerts
{docId}
nomEvent string
date timestamp
typeCode string
placement string
prixBillet number
depenseSup number
affiche, cover string (URL)
lieuNom, ville, pays string
artistes array<string>
artistes/
{docId}
nom, genre, photo string
lieux/
{docId}
nom, ville, pays, adresse, type string
capacite number
photo, siteWeb string
inbox/ ← messages push
{docId}
title, body string
read boolean
crash_logs/ ← desktop uniquement
{docId}
error, stack, platform, fatal, timestamp
users/{uid}/ — un utilisateur ne peut
accéder qu'à ses propres données grâce aux règles Firestore.
🔔 Système de notifications
Architecture
Trois canaux de notification coexistent :
-
Rappels automatiques (ReminderService)
Au démarrage, interroge Firestore pour les concerts dans les 7 prochains jours. Envoie une notification J-7 et J-1. Résistant aux redémarrages grâce à SharedPreferences ({id}_j7/{id}_j1). -
Inbox Firestore (InboxService)
Listener temps réel surusers/{uid}/inbox. Tout documentread: falsedéclenche une notification et est marquéread: true. Utile pour les campagnes depuis Firebase Console ou Cloud Functions. -
Push mobile (FCM)
Firebase Cloud Messaging reçoit les messages push en arrière-plan sur Android/iOS. Le token FCM est récupérable viaNotificationService.getToken().
Par plateforme
| Plateforme | Implémentation |
|---|---|
| Windows | flutter_local_notifications → Toast natif Windows |
| Android | FCM + flutter_local_notifications (canal "concerts") |
| iOS / macOS | FCM + flutter_local_notifications + permission explicite |
🎨 Thème & Couleurs
Couleurs principales
Couleurs par type d'événement
Configuration Material 3
ColorScheme.fromSeed( seedColor: Color(0xFFFF6B35), brightness: Brightness.dark, // ou light selon le mode )
Le mode thème est piloté par AppSettings.themeMode (ChangeNotifier).
Il est appliqué via AnimatedBuilder dans main.dart et
n'est pas persisté entre les sessions (retour à "Système" au redémarrage).
🏗️ Compilation
Prérequis
- Flutter SDK ≥ 3.x (
flutter --version) - Dart ≥ 3.0
- FlutterFire CLI (
dart pub global activate flutterfire_cli) - Pour Windows : Visual Studio 2022 + workload "Desktop development with C++"
- Pour Android : Android Studio + NDK
- Inno Setup 6 (optionnel, pour l'installeur .exe)
Commandes
# Installer les dépendances flutter pub get # Lancer en développement flutter run -d windows flutter run -d android # Build release Windows flutter build windows --release # Build release Android (APK) flutter build apk --release # Build release Android (Bundle) flutter build appbundle --release # Regénérer les options Firebase flutterfire configure
Installeur Windows (Inno Setup)
Après flutter build windows --release, l'exécutable se trouve dans
build/windows/x64/runner/Release/. Inno Setup crée un installeur
.exe avec raccourci bureau et désinstalleur.
📦 Dépendances
Firebase
| Package | Version | Usage |
|---|---|---|
| firebase_core | ^4.7.0 | Initialisation Firebase |
| firebase_auth | ^6.5.1 | Authentification |
| cloud_firestore | ^6.4.1 | Base de données |
| firebase_messaging | ^16.2.0 | Push notifications (FCM) |
| firebase_crashlytics | ^5.2.2 | Rapport de crash mobile |
Notifications
| Package | Version | Usage |
|---|---|---|
| flutter_local_notifications | ^21.0.0 | Toast Windows / canal Android |
Desktop Windows
| Package | Version | Usage |
|---|---|---|
| tray_manager | ^0.2.3 | Icône systray |
| window_manager | ^0.3.9 | Contrôle fenêtre |
Utilitaires
| Package | Version | Usage |
|---|---|---|
| shared_preferences | ^2.3.0 | Persistance légère locale |
| file_picker | ^8.0.0 | Dialogue "Enregistrer sous" |
| url_launcher | ^6.3.1 | Ouvrir liens dans navigateur |
| package_info_plus | ^8.0.2 | Version de l'app |
| cupertino_icons | ^1.0.2 | Icônes iOS-style |