🎵 Concertothèque

Gestionnaire personnel de concerts — Flutter + Firebase

v1.0.0+1 Flutter 3.x / Dart 3 Firebase Windows · macOS · Android · iOS

📌 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

Gestion des artistes & lieux

Dashboard & statistiques

Notifications

Fonctionnalités Windows spécifiques

Paramètres & compte

🛠️ Stack technique

Flutter 3.xFramework UI multiplateforme
Dart 3Langage principal
Firebase AuthAuthentification email/password
Cloud FirestoreBase de données NoSQL temps réel
Firebase MessagingPush notifications (FCM)
Firebase CrashlyticsRapport de crash mobile
flutter_local_notificationsNotifications locales (Toast)
tray_managerIcône systray Windows
window_managerContrôle fenêtre desktop
shared_preferencesPersistance légère locale
file_pickerDialogue natif "Enregistrer sous"
Inno Setup 6Installeur Windows

📁 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

ChampTypeDescription
idStringIdentifiant Firestore (final)
nomStringNom de l'artiste
genreStringGenre musical
photoStringURL de la photo (peut être vide)
// Méthodes
factory Artiste.fromDoc(DocumentSnapshot doc)
Map<String, dynamic> toMap()

Evenement (Concert) — lib/models/concert.dart

ChampTypeDescription
idStringIdentifiant Firestore
nomEventStringNom de l'événement
dateDateTimeDate du concert
typeCodeStringCON / FES / SOI / SHO / COM
placementStringFOSS / GRAD / CAT1–4 / CARO
prixBilletdoublePrix du billet (€)
depenseSupdoubleDépenses supplémentaires (€)
afficheStringURL de l'affiche
coverStringURL de la bannière
lieuNomStringNom de la salle
villeStringVille du concert
paysStringPays du concert
artistesList<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

ChampTypeDescription
idStringIdentifiant Firestore
nomStringNom de la salle
villeStringVille
paysStringPays (défaut : France)
adresseStringAdresse complète
typeStringType de lieu (salle, plein air…)
capaciteintCapacité d'accueil
photoStringURL de la photo
siteWebStringURL du site officiel

⚙️ Services

Services de données Firestore

Les trois services (EvenementService, ArtisteService, LieuService) suivent le même patron :

MéthodeRetourDescription
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éthodeDescription
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 :

InboxService

Écoute la collection users/{uid}/inbox en temps réel :

ExportService

TrayService Windows

AutostartService Windows

CrashLogger

📱 Écrans (Screens)

Authentification

ÉcranFichierDescription
LoginScreenlogin_screen.dartEmail + mot de passe, option "Se souvenir de moi" (SharedPreferences)
RegisterScreenregister_screen.dartInscription avec validation des champs

Dashboard

DashboardScreen (dashboard_screen.dart) — page d'accueil après connexion :

Concerts

ÉcranFonctionnalités clés
ConcertsScreenRecherche multi-champs, filtres par type, tri multi-colonnes, multi-sélection + suppression groupée
ConcertDetailScreenAffiche + bannière, infos complètes, artistes avec photos, liens vers artiste/lieu, édition/suppression
EvenementEditScreenFormulaire complet avec sélecteur de salle (+ création inline), date picker, type/placement, multi-artiste, aperçu images

Artistes

ÉcranFonctionnalités clés
ArtistesScreenGrille paginée (25/page), recherche par nom/genre, avatar, édition/suppression, FAB d'ajout
ArtisteDetailScreenGrand avatar, badge genre, compteur concerts, liste des concerts par date desc avec badges statut
ArtisteEditScreenFormulaire création/édition (nom, genre, URL photo)

Lieux

ÉcranFonctionnalités clés
LieuxScreenListe paginée, recherche nom/ville, photo, capacité
LieuDetailScreenPhoto, type, capacité, adresse, lien site web, concerts associés
LieuEditScreenFormulaire complet (nom, ville, pays, adresse, type, capacité, photo, site web)

Paramètres

SettingsScreen est divisé en 4 sections :

  1. Apparence — sélecteur de thème (Système / Clair / Sombre)
  2. Notifications — activation/désactivation, vérification permission OS, bouton test
  3. Système — démarrage auto (Windows), minimiser dans systray (Windows)
  4. 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) :

ArtistePickerDialog — lib/widgets/artiste_picker_dialog.dart

Dialog modal pour la sélection multiple d'artistes :

🔥 Configuration Firebase

Projet Firebase : concertotheque

PlateformeApp ID
Android1:983582489419:android:9bed2591728c13721006ce
iOS / macOS1:983582489419:ios:31fd242362c790671006ce
Web1:983582489419:web:c7d022dc130a2dd31006ce
Windows1:983582489419:web:384cf9d6ca940c541006ce

Services activés

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

users/
  {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
Toutes les collections sont scoped sous 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 :

  1. 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).
  2. Inbox Firestore (InboxService)
    Listener temps réel sur users/{uid}/inbox. Tout document read: false déclenche une notification et est marqué read: true. Utile pour les campagnes depuis Firebase Console ou Cloud Functions.
  3. 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 via NotificationService.getToken().

Par plateforme

PlateformeImplémentation
Windowsflutter_local_notifications → Toast natif Windows
AndroidFCM + flutter_local_notifications (canal "concerts")
iOS / macOSFCM + flutter_local_notifications + permission explicite

🎨 Thème & Couleurs

Couleurs principales

#FF6B35 — Orange primaire
#E65100 — Orange sombre
#12121A — Fond dark
#1E1E2C — Surface card
#2A2A3C — Séparateur

Couleurs par type d'événement

#E91E63 — Concert
#43A047 — Festival
#7B1FA2 — Soirée
#0288D1 — Showcase
#E65100 — Comédie

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

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.

Le projet est distribué via Scoop (gestionnaire de paquets Windows). Le manifest Scoop pointe vers l'archive ZIP du release GitHub.

📦 Dépendances

Firebase

PackageVersionUsage
firebase_core^4.7.0Initialisation Firebase
firebase_auth^6.5.1Authentification
cloud_firestore^6.4.1Base de données
firebase_messaging^16.2.0Push notifications (FCM)
firebase_crashlytics^5.2.2Rapport de crash mobile

Notifications

PackageVersionUsage
flutter_local_notifications^21.0.0Toast Windows / canal Android

Desktop Windows

PackageVersionUsage
tray_manager^0.2.3Icône systray
window_manager^0.3.9Contrôle fenêtre

Utilitaires

PackageVersionUsage
shared_preferences^2.3.0Persistance légère locale
file_picker^8.0.0Dialogue "Enregistrer sous"
url_launcher^6.3.1Ouvrir liens dans navigateur
package_info_plus^8.0.2Version de l'app
cupertino_icons^1.0.2Icônes iOS-style