feat: Version 3.3.5 - Optimisations pages, améliorations ergonomie et affichages dynamiques stats

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
pierre
2025-10-06 15:32:32 +02:00
parent 570a1fa1f0
commit 21657a3820
31 changed files with 1982 additions and 1442 deletions

View File

@@ -950,6 +950,107 @@ Chaque amicale dispose de son **propre compte Stripe Connect** :
9. Vérification statut compte
10. Affichage "✅ Compte actif"
### 🔑 Configuration des clés API Stripe par environnement
GEOSECTOR utilise des **clés Stripe différentes** selon l'environnement pour séparer les données de test et de production.
#### **Fichier de configuration**
`/home/pierre/dev/geosector/api/src/Config/AppConfig.php`
#### **Répartition des clés par environnement**
| Environnement | URL | Plateforme Stripe | Clés utilisées | Mode | Usage |
|---------------|-----|-------------------|----------------|------|-------|
| **DEV** | `dapp.geosector.fr` | Test Pierre | `pk_test_51QwoVN...`<br>`sk_test_51QwoVN...` | `test` | Développement |
| **REC** | `rapp.geosector.fr` | Test Client | `CLIENT_PK_TEST_A_REMPLACER`<br>`CLIENT_SK_TEST_A_REMPLACER` | `test` | Recette |
| **PROD** | `app.geosector.fr` | Live Client | `CLIENT_PK_LIVE_A_REMPLACER`<br>`CLIENT_SK_LIVE_A_REMPLACER` | `live` | Production |
#### **Types de clés Stripe**
**Clés obligatoires (2) :**
| Clé | Format | Où la trouver | Utilisation |
|-----|--------|---------------|-------------|
| **Publishable key** | `pk_test_51XXXXX...` ou `pk_live_XXXXX...` | Dashboard → Developers → API Keys | Client-side (Flutter app) |
| **Secret key** | `sk_test_51XXXXX...` ou `sk_live_XXXXX...` | Dashboard → Developers → API Keys (révéler) | Server-side (API PHP) |
**Clé optionnelle :**
| Clé | Format | Où la trouver | Utilisation |
|-----|--------|---------------|-------------|
| **Webhook secret** | `whsec_test_XXXXX...` ou `whsec_live_XXXXX...` | Dashboard → Webhooks → Endpoint → Signing secret | Validation webhooks (non utilisé actuellement) |
#### **Récupération des clés client**
Pour configurer REC et PROD, le client doit fournir ses clés depuis son **Dashboard Stripe** :
**Pour REC (clés TEST) :**
1. Se connecter sur https://dashboard.stripe.com/test/apikeys
2. Copier la **Publishable key**`CLIENT_PK_TEST_A_REMPLACER`
3. Révéler et copier la **Secret key**`CLIENT_SK_TEST_A_REMPLACER`
**Pour PROD (clés LIVE) :**
1. Se connecter sur https://dashboard.stripe.com/apikeys (mode live)
2. Copier la **Publishable key**`CLIENT_PK_LIVE_A_REMPLACER`
3. Révéler et copier la **Secret key**`CLIENT_SK_LIVE_A_REMPLACER`
#### **Configuration dans AppConfig.php**
**Structure du fichier :**
```php
// Configuration DÉVELOPPEMENT (dapp.geosector.fr)
'stripe' => [
'public_key_test' => 'pk_test_51QwoVN...', // Clés Pierre (opérationnel)
'secret_key_test' => 'sk_test_51QwoVN...',
'mode' => 'test',
],
// Configuration RECETTE (rapp.geosector.fr)
'stripe' => [
'public_key_test' => 'CLIENT_PK_TEST_A_REMPLACER', // À remplacer
'secret_key_test' => 'CLIENT_SK_TEST_A_REMPLACER', // À remplacer
'mode' => 'test',
],
// Configuration PRODUCTION (app.geosector.fr)
'stripe' => [
'public_key_live' => 'CLIENT_PK_LIVE_A_REMPLACER', // À remplacer
'secret_key_live' => 'CLIENT_SK_LIVE_A_REMPLACER', // À remplacer
'mode' => 'live',
],
```
#### **Points importants**
⚠️ **Isolation des environnements** :
- DEV utilise la plateforme de test de Pierre (développement isolé)
- REC utilise la plateforme de test du client (tests en conditions réelles)
- PROD utilise la plateforme live du client (vraies transactions)
⚠️ **Sécurité** :
- Ne JAMAIS commiter les vraies clés dans Git
- Vérifier que `AppConfig.php` est dans `.gitignore`
- Les clés secrètes ne doivent jamais être exposées côté client
⚠️ **Mode de fonctionnement** :
- L'API détecte automatiquement l'environnement via l'URL
- Le `mode` (`test` ou `live`) détermine quelle paire de clés utiliser
- En mode `test` : utilise `public_key_test` et `secret_key_test`
- En mode `live` : utilise `public_key_live` et `secret_key_live`
#### **Déploiement après modification**
Après avoir remplacé les placeholders par les vraies clés :
```bash
cd /home/pierre/dev/geosector/api
./deploy-api.sh
```
L'API sera redéployée sur l'environnement correspondant avec les nouvelles clés.
### 📱 Tap to Pay V2 - Paiement sans contact
#### **Fonctionnalités prévues**

View File

@@ -1008,3 +1008,368 @@ Pour vérifier que le cache est désactivé en DEV/REC :
**Date d'ajout** : 2025-09-23
**Auteur** : Solution de gestion du cache
**Version** : 1.0.0
## ✅ Améliorations de l'interactivité des graphiques - v3.3.5
**Date** : 06/10/2025
**Version** : 3.3.5
**Statut** : ✅ Complété
### 📋 Vue d'ensemble
Amélioration majeure de l'expérience utilisateur avec l'ajout d'interactivité sur tous les graphiques et cartes du tableau de bord, permettant une navigation intelligente vers l'historique avec filtres pré-appliqués.
### 🎯 Modifications apportées
#### 1. **Réinitialisation des filtres lors des clics sur les graphiques**
**Fichiers modifiés** :
- `lib/presentation/widgets/charts/passage_summary_card.dart`
- `lib/presentation/widgets/charts/payment_summary_card.dart`
- `lib/presentation/widgets/sector_distribution_card.dart`
**Implémentation** :
```dart
// Réinitialiser TOUS les filtres avant de sauvegarder le nouveau
settingsBox.delete('history_selectedPaymentTypeId');
settingsBox.delete('history_selectedSectorId');
settingsBox.delete('history_selectedSectorName');
settingsBox.delete('history_selectedMemberId');
settingsBox.delete('history_startDate');
settingsBox.delete('history_endDate');
// Sauvegarder uniquement le critère sélectionné
settingsBox.put('history_selectedTypeId', typeId);
```
**Bénéfice** : L'utilisateur voit uniquement les passages correspondant au critère cliqué, sans interférence d'anciens filtres.
---
#### 2. **Navigation directe vers les pages d'historique**
**Correction** : Changement des routes de navigation de `/admin` et `/user` vers `/admin/history` et `/user/history`.
**Code** :
```dart
final bool isAdmin = CurrentUserService.instance.shouldShowAdminUI;
context.go(isAdmin ? '/admin/history' : '/user/history');
```
**Bénéfice** : Navigation immédiate vers la page cible sans étape intermédiaire.
---
#### 3. **Chargement des filtres pour tous les utilisateurs**
**Fichier** : `lib/presentation/pages/history_page.dart` (lignes 143-151)
**Problème** : La méthode `_loadPreselectedFilters()` n'était appelée que pour les admins.
**Solution** :
```dart
} else {
_loadPreselectedFilters(); // Maintenant appelé pour tous
if (!isAdmin) {
selectedMemberId = currentUserId;
}
}
```
**Bénéfice** : Les filtres fonctionnent correctement en mode utilisateur.
---
#### 4. **Correction du dropdown des membres (admin)**
**Fichier** : `lib/presentation/pages/history_page.dart` (lignes 537-542)
**Problème** : Utilisation de `Hive.box<UserModel>` qui ne contient que le currentUser.
**Solution** : Utiliser la liste `_users` construite depuis `membreRepository.getAllMembres()`.
```dart
..._users.map((UserModel user) {
return DropdownMenuItem<int?>(
value: user.id,
child: Text('${user.firstName ?? ''} ${user.name ?? ''}'),
);
}),
```
**Bénéfice** : Affichage correct de tous les membres de l'amicale.
---
#### 5. **Adaptation dynamique de la hauteur des cartes**
**Fichiers** :
- `lib/presentation/widgets/sector_distribution_card.dart`
- `lib/presentation/widgets/members_board_passages.dart`
**Modification** : Suppression des contraintes de hauteur fixe.
```dart
ListView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: sectorStats.length,
itemBuilder: (context, index) => ...,
)
```
**Bénéfice** : Les cartes s'adaptent à leur contenu sans espace vide inutile.
---
#### 6. **Correction du bug ActivityChart (secteurs utilisateur)**
**Fichier** : `lib/presentation/widgets/charts/activity_chart.dart` (lignes 196-201)
**Problème** : Logique incorrecte de récupération des secteurs utilisateur.
**Code AVANT (bugué)** :
```dart
userSectorIds = userSectorBox.values
.where((us) => us.id == currentUser.id)
.map((us) => us.fkSector)
.toSet();
```
**Code APRÈS (corrigé)** :
```dart
final userSectors = userRepository.getUserSectors();
userSectorIds = userSectors.map((sector) => sector.id).toSet();
```
**Bénéfice** : Le graphique affiche correctement les passages des secteurs assignés à l'utilisateur.
---
#### 7. **Ajout de boutons de période (7j/14j/21j)**
**Fichier** : `lib/presentation/widgets/charts/activity_chart.dart`
**Implémentation** :
- Ajout d'un état `_selectedDays` (par défaut 7 jours)
- Création de la méthode `_buildPeriodButton(int days)`
- Affichage conditionnel via paramètre `showPeriodButtons`
```dart
Row(
mainAxisSize: MainAxisSize.min,
children: [
_buildPeriodButton(7),
const SizedBox(width: 4),
_buildPeriodButton(14),
const SizedBox(width: 4),
_buildPeriodButton(21),
],
)
```
**Bénéfice** : L'utilisateur peut rapidement changer la période d'affichage.
---
#### 8. **Affichage conditionnel des boutons de période**
**Paramètre ajouté** : `showPeriodButtons` (par défaut `false`)
**Usage** :
- `home_page.dart` : `showPeriodButtons: true`
- `history_page.dart` : non utilisé (donc `false`)
**Bénéfice** : Les boutons n'apparaissent que sur la page d'accueil.
---
#### 9. **Passages type 2 éditables par tous les utilisateurs**
**Fichier** : `lib/presentation/pages/history_page.dart` (ligne 1606)
**Modification** :
```dart
if (isAdmin || passage.fkUser == currentUserId || passage.fkType == 2) {
_handlePassageEdit(passage);
}
```
**Bénéfice** : Tous les utilisateurs peuvent finaliser les passages de type 2 (À finaliser).
---
#### 10. **Noms de secteurs cliquables pour les utilisateurs**
**Fichier** : `lib/presentation/widgets/sector_distribution_card.dart` (lignes 321-342)
**Implémentation** :
```dart
Expanded(
child: InkWell(
onTap: () {
final settingsBox = Hive.box(AppKeys.settingsBoxName);
if (isAdmin) {
// Admin : naviguer vers la carte
settingsBox.put('selectedSectorId', sectorId);
settingsBox.put('selectedPageIndex', 4);
context.go('/admin');
} else {
// User : naviguer vers l'historique avec filtre secteur
settingsBox.delete('history_selectedTypeId');
settingsBox.delete('history_selectedPaymentTypeId');
// ... autres suppressions
settingsBox.put('history_selectedSectorId', sectorId);
settingsBox.put('history_selectedSectorName', name);
context.go('/user/history');
}
},
child: Text(name, ...),
),
),
```
**Bénéfice** : Les utilisateurs peuvent cliquer sur un nom de secteur pour voir ses passages dans l'historique.
---
#### 11. **Interactivité des segments de barres ActivityChart**
**Fichier** : `lib/presentation/widgets/charts/activity_chart.dart`
**Nouvelles dépendances** :
```dart
import 'package:geosector_app/core/services/current_user_service.dart';
import 'package:go_router/go_router.dart';
```
**Implémentation** :
##### a) Callback `onPointTap` dans StackedColumnSeries
```dart
onPointTap: widget.showPeriodButtons ? (ChartPointDetails details) {
_handlePointTap(details, typeId);
} : null,
```
##### b) Méthode `_handlePointTap` (lignes 532-573)
```dart
void _handlePointTap(ChartPointDetails details, int typeId) {
if (details.pointIndex == null || details.pointIndex! < 0) return;
final passageBox = Hive.box<PassageModel>(AppKeys.passagesBoxName);
final chartData = _calculateActivityData(passageBox, _selectedDays);
if (details.pointIndex! >= chartData.length) return;
final clickedData = chartData[details.pointIndex!];
final clickedDate = clickedData.date;
final settingsBox = Hive.box(AppKeys.settingsBoxName);
// Réinitialiser tous les autres filtres
settingsBox.delete('history_selectedPaymentTypeId');
settingsBox.delete('history_selectedSectorId');
settingsBox.delete('history_selectedSectorName');
settingsBox.delete('history_selectedMemberId');
// Appliquer le filtre de type
settingsBox.put('history_selectedTypeId', typeId);
// Définir la plage de dates pour la journée complète
final startDateTime = DateTime(
clickedDate.year,
clickedDate.month,
clickedDate.day,
0, 0, 0
);
settingsBox.put('history_startDate', startDateTime.millisecondsSinceEpoch);
final endDateTime = DateTime(
clickedDate.year,
clickedDate.month,
clickedDate.day,
23, 59, 59
);
settingsBox.put('history_endDate', endDateTime.millisecondsSinceEpoch);
// Naviguer vers l'historique
final bool isAdmin = CurrentUserService.instance.shouldShowAdminUI;
context.go(isAdmin ? '/admin/history' : '/user/history');
}
```
**Fonctionnalités** :
- Clic sur un segment de barre → filtre par type ET date exacte
- Date de début : jour cliqué à 00:00:00
- Date de fin : jour cliqué à 23:59:59
- Réinitialisation de tous les autres filtres
- Navigation contextuelle (admin/user)
**Bénéfice** : Navigation ultra-précise vers les passages d'un type spécifique pour une journée donnée.
---
### 📊 Impact UX
| Fonctionnalité | Avant | Après |
|----------------|-------|-------|
| **Clics sur graphiques** | Non fonctionnel | ✅ Navigation avec filtres |
| **Filtres utilisateurs** | ❌ Ne marchait pas | ✅ Fonctionnels |
| **Dropdown membres** | ❌ Vide en admin | ✅ Tous les membres |
| **Hauteur des cartes** | Fixe (espace vide) | ✅ Adaptative |
| **ActivityChart users** | ❌ Pas de données | ✅ Affichage correct |
| **Boutons de période** | Absents | ✅ 7j/14j/21j |
| **Édition type 2** | Admin seulement | ✅ Tous les users |
| **Secteurs cliquables** | Admin uniquement | ✅ Admin et users |
| **Segments de barres** | Non cliquables | ✅ Filtrage par type+date |
### 🎨 Expérience utilisateur améliorée
1. **Navigation intuitive** : Cliquer sur n'importe quel élément visuel (graphique, secteur, barre) filtre automatiquement l'historique
2. **Filtres intelligents** : Réinitialisation automatique pour éviter les conflits
3. **Contexte préservé** : Admin et utilisateurs ont des comportements adaptés
4. **Période flexible** : Choix rapide entre 7, 14 ou 21 jours
5. **Précision temporelle** : Sélection jour par jour via les segments de barres
### 🔍 Fichiers modifiés
```
lib/presentation/widgets/charts/
├── passage_summary_card.dart ✏️ Filtres + navigation
├── payment_summary_card.dart ✏️ Filtres + navigation
└── activity_chart.dart ✏️ Boutons période + clic segments
lib/presentation/widgets/
└── sector_distribution_card.dart ✏️ Filtres + hauteur + clics users
lib/presentation/pages/
├── home_page.dart ✏️ Paramètres ActivityChart
└── history_page.dart ✏️ Filtres users + dropdown membres
```
### 🧪 Tests effectués
- ✅ Clics sur PassageSummaryCard → historique filtré
- ✅ Clics sur PaymentSummaryCard → historique filtré
- ✅ Clics sur SectorDistributionCard → historique filtré
- ✅ Clics sur segments ActivityChart → historique avec type + date
- ✅ Boutons de période 7j/14j/21j fonctionnels
- ✅ Affichage correct en mode admin et user
- ✅ Dropdown membres affiche tous les membres
- ✅ Hauteur des cartes adaptative
- ✅ Édition passages type 2 par tous
### 🚀 Prochaines étapes suggérées
- [ ] Ajouter un indicateur visuel sur les éléments cliquables (cursor: pointer)
- [ ] Animation de transition lors de la navigation vers l'historique
- [ ] Tooltip sur les segments de barres pour prévisualiser les données
- [ ] Export des données filtrées depuis l'historique
- [ ] Mémorisation des périodes préférées par utilisateur
---
**Date de complétion** : 06/10/2025
**Testé par** : Équipe de développement
**Statut** : ✅ Prêt pour production

View File

@@ -356,11 +356,89 @@ _Bénéfice : Sécurité renforcée et meilleure traçabilité_
---
<div style="page-break-after: always;"></div>
## UPGRADES PACKAGES FLUTTER
### 📊 État des packages (Octobre 2025)
L'analyse `flutter pub outdated` a révélé plusieurs packages nécessitant des mises à jour, dont un package discontinué critique.
### 🔴 Phase 1 - Correction package discontinué (URGENT)
**Statut : ✅ TERMINÉ (06/10/2025)**
| Package | Action | Ancienne version | Nouvelle version |
|---------|--------|------------------|------------------|
| `dio_cache_interceptor_hive_store` | ❌ Suppression (discontinué) | 3.2.2 | - |
| `http_cache_hive_store` | ✅ Ajout (remplacement) | - | 5.0.0 |
| `flutter_map_cache` | ⬆️ Mise à jour | 1.5.2 | 2.0.0+1 |
**Fichiers modifiés :**
- `pubspec.yaml` : Remplacement des dépendances
- `lib/presentation/widgets/mapbox_map.dart` : Import mis à jour
**Tests requis :**
- [x] Affichage carte web
- [x] Affichage carte mobile
- [x] Cache des tuiles mobile
- [x] Mode terrain
### 🟡 Phase 2 - Mises à jour importantes (PLANIFIÉ)
**Statut : ⏳ EN ATTENTE**
#### Cartes et géolocalisation
| Package | Actuelle | Cible | Breaking Changes |
|---------|----------|-------|------------------|
| `flutter_map` | 6.2.1 | 8.2.2 | ⚠️ Oui (v7, v8) |
| `geolocator` | 12.0.0 | 14.0.2 | Possible |
#### Device Info & Permissions
| Package | Actuelle | Cible | Importance |
|---------|----------|-------|------------|
| `device_info_plus` | 9.1.2 | 12.1.0 | ⭐⭐⭐ Tap to Pay |
| `battery_plus` | 4.1.0 | 7.0.0 | ⭐⭐ |
| `connectivity_plus` | 5.0.2 | 7.0.0 | ⭐⭐ |
| `sensors_plus` | 3.1.0 | 7.0.0 | ⭐⭐⭐ Mode boussole |
| `permission_handler` | 11.4.0 | 12.0.1 | ⭐⭐⭐ |
**Points d'attention :**
- `flutter_map 8.x` : Breaking changes majeurs v6 → v8
- `device_info_plus` : Vérifier compatibilité DeviceInfoService
- Tests complets requis : cartes, géolocalisation, mode terrain
### 🟢 Phase 3 - Mises à jour secondaires (PLANIFIÉ)
**Statut : ⏳ EN ATTENTE**
| Package | Actuelle | Cible | Note |
|---------|----------|-------|------|
| `syncfusion_flutter_charts` | 30.2.7 | 31.1.22 | Mineure |
| `package_info_plus` | 4.2.0 | 8.3.1 | Vérifier compatibilité |
**Packages à jour :**
-`dio: 5.9.0`
-`go_router: 16.2.4`
-`hive: 2.2.3`
-`flutter_stripe: 12.0.2`
-`mek_stripe_terminal: 4.6.0`
### 📅 Planning des upgrades
| Phase | Période prévue | Priorité | Effort |
|-------|----------------|----------|--------|
| Phase 1 | ✅ 06/10/2025 | 🔴 Critique | 1h |
| Phase 2 | 10-15/10/2025 | 🟡 Important | 4-6h |
| Phase 3 | 20-25/10/2025 | 🟢 Mineur | 2-3h |
---
_Document généré le 11 septembre 2025_
_Dernière mise à jour le 04 octobre 2025_
_Dernière mise à jour le 06 octobre 2025_
_Ce document sera mis à jour régulièrement avec l'avancement des développements_
---
**GEOSECTOR** - Solution de gestion des distributions de calendriers Amicales de pompiers
**GEOSECTOR** - Solution de gestion des distributions de calendriers Amicales de pompiers
© 2025 - Tous droits réservés