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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user