feat: Mise à jour des interfaces mobiles v3.2.3
- Amélioration des interfaces utilisateur sur mobile - Optimisation de la responsivité des composants Flutter - Mise à jour des widgets de chat et communication - Amélioration des formulaires et tableaux - Ajout de nouveaux composants pour l'administration - Optimisation des thèmes et styles visuels 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -40,7 +40,8 @@ class _UserDashboardHomePageState extends State<UserDashboardHomePage> {
|
||||
if (operation != null) {
|
||||
return Text(
|
||||
'${operation.name} (${_formatDate(operation.dateDebut)}-${_formatDate(operation.dateFin)})',
|
||||
style: theme.textTheme.headlineMedium?.copyWith(
|
||||
style: TextStyle(
|
||||
fontSize: AppTheme.r(context, 20),
|
||||
fontWeight: FontWeight.bold,
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
@@ -48,7 +49,8 @@ class _UserDashboardHomePageState extends State<UserDashboardHomePage> {
|
||||
} else {
|
||||
return Text(
|
||||
'Tableau de bord',
|
||||
style: theme.textTheme.headlineMedium?.copyWith(
|
||||
style: TextStyle(
|
||||
fontSize: AppTheme.r(context, 20),
|
||||
fontWeight: FontWeight.bold,
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
@@ -88,46 +90,45 @@ class _UserDashboardHomePageState extends State<UserDashboardHomePage> {
|
||||
}
|
||||
|
||||
// Construction d'une carte combinée pour les règlements (liste + graphique)
|
||||
Widget _buildCombinedPaymentsCard(bool isDesktop) {
|
||||
return PaymentSummaryCard(
|
||||
title: 'Mes règlements',
|
||||
titleColor: AppTheme.accentColor,
|
||||
titleIcon: Icons.payments,
|
||||
height: 300,
|
||||
useValueListenable: true,
|
||||
userId: userRepository.getCurrentUser()?.id,
|
||||
showAllPayments: false,
|
||||
isDesktop: isDesktop,
|
||||
backgroundIcon: Icons.euro_symbol,
|
||||
backgroundIconColor: Colors.blue,
|
||||
backgroundIconOpacity: 0.07,
|
||||
backgroundIconSize: 180,
|
||||
customTotalDisplay: (totalAmount) {
|
||||
// Calculer le nombre de passages avec règlement pour le titre personnalisé
|
||||
final currentUser = userRepository.getCurrentUser();
|
||||
if (currentUser == null) return '${totalAmount.toStringAsFixed(2)} €';
|
||||
|
||||
final passagesBox = Hive.box<PassageModel>(AppKeys.passagesBoxName);
|
||||
int passagesCount = 0;
|
||||
|
||||
for (final passage in passagesBox.values) {
|
||||
if (passage.fkUser == currentUser.id) {
|
||||
double montant = 0.0;
|
||||
try {
|
||||
String montantStr = passage.montant.replaceAll(',', '.');
|
||||
montant = double.tryParse(montantStr) ?? 0.0;
|
||||
} catch (e) {
|
||||
// Ignorer les erreurs
|
||||
}
|
||||
if (montant > 0) passagesCount++;
|
||||
}
|
||||
}
|
||||
|
||||
return '${totalAmount.toStringAsFixed(2)} € sur $passagesCount passages';
|
||||
},
|
||||
);
|
||||
}
|
||||
Widget _buildCombinedPaymentsCard(bool isDesktop) {
|
||||
return PaymentSummaryCard(
|
||||
title: 'Mes règlements',
|
||||
titleColor: AppTheme.accentColor,
|
||||
titleIcon: Icons.payments,
|
||||
height: 300,
|
||||
useValueListenable: true,
|
||||
userId: userRepository.getCurrentUser()?.id,
|
||||
showAllPayments: false,
|
||||
isDesktop: isDesktop,
|
||||
backgroundIcon: Icons.euro_symbol,
|
||||
backgroundIconColor: Colors.blue,
|
||||
backgroundIconOpacity: 0.07,
|
||||
backgroundIconSize: 180,
|
||||
customTotalDisplay: (totalAmount) {
|
||||
// Calculer le nombre de passages avec règlement pour le titre personnalisé
|
||||
final currentUser = userRepository.getCurrentUser();
|
||||
if (currentUser == null) return '${totalAmount.toStringAsFixed(2)} €';
|
||||
|
||||
final passagesBox = Hive.box<PassageModel>(AppKeys.passagesBoxName);
|
||||
int passagesCount = 0;
|
||||
|
||||
for (final passage in passagesBox.values) {
|
||||
if (passage.fkUser == currentUser.id) {
|
||||
double montant = 0.0;
|
||||
try {
|
||||
String montantStr = passage.montant.replaceAll(',', '.');
|
||||
montant = double.tryParse(montantStr) ?? 0.0;
|
||||
} catch (e) {
|
||||
// Ignorer les erreurs
|
||||
}
|
||||
if (montant > 0) passagesCount++;
|
||||
}
|
||||
}
|
||||
|
||||
return '${totalAmount.toStringAsFixed(2)} € sur $passagesCount passages';
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// Construction d'une carte combinée pour les passages (liste + graphique)
|
||||
Widget _buildCombinedPassagesCard(BuildContext context, bool isDesktop) {
|
||||
@@ -136,8 +137,8 @@ Widget _buildCombinedPaymentsCard(bool isDesktop) {
|
||||
titleColor: AppTheme.primaryColor,
|
||||
titleIcon: Icons.route,
|
||||
height: 300,
|
||||
useValueListenable: true,
|
||||
userId: userRepository.getCurrentUser()?.id,
|
||||
useValueListenable: true,
|
||||
userId: userRepository.getCurrentUser()?.id,
|
||||
showAllPassages: false,
|
||||
excludePassageTypes: const [2], // Exclure "À finaliser"
|
||||
isDesktop: isDesktop,
|
||||
@@ -160,7 +161,9 @@ Widget _buildCombinedPaymentsCard(bool isDesktop) {
|
||||
height: 350,
|
||||
child: ActivityChart(
|
||||
useValueListenable: true, // Utiliser le système réactif
|
||||
excludePassageTypes: const [2], // Exclure les passages "À finaliser"
|
||||
excludePassageTypes: const [
|
||||
2
|
||||
], // Exclure les passages "À finaliser"
|
||||
daysToShow: 15,
|
||||
periodType: 'Jour',
|
||||
height: 350,
|
||||
@@ -178,27 +181,29 @@ Widget _buildCombinedPaymentsCard(bool isDesktop) {
|
||||
Widget _buildRecentPassages(BuildContext context, ThemeData theme) {
|
||||
// Utilisation directe du widget PassagesListWidget sans Card wrapper
|
||||
return ValueListenableBuilder(
|
||||
valueListenable: Hive.box<PassageModel>(AppKeys.passagesBoxName).listenable(),
|
||||
valueListenable:
|
||||
Hive.box<PassageModel>(AppKeys.passagesBoxName).listenable(),
|
||||
builder: (context, Box<PassageModel> passagesBox, child) {
|
||||
final recentPassages = _getRecentPassages(passagesBox);
|
||||
|
||||
|
||||
// Debug : afficher le nombre de passages récupérés
|
||||
debugPrint('UserDashboardHomePage: ${recentPassages.length} passages récents récupérés');
|
||||
|
||||
debugPrint(
|
||||
'UserDashboardHomePage: ${recentPassages.length} passages récents récupérés');
|
||||
|
||||
if (recentPassages.isEmpty) {
|
||||
return Card(
|
||||
elevation: 4,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
child: const Padding(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(32.0),
|
||||
child: Center(
|
||||
child: Text(
|
||||
'Aucun passage récent',
|
||||
style: TextStyle(
|
||||
color: Colors.grey,
|
||||
fontSize: 14,
|
||||
fontSize: AppTheme.r(context, 14),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -208,7 +213,8 @@ Widget _buildCombinedPaymentsCard(bool isDesktop) {
|
||||
|
||||
// Utiliser une hauteur fixe pour le widget dans le dashboard
|
||||
return SizedBox(
|
||||
height: 450, // Hauteur légèrement augmentée pour compenser l'absence de Card
|
||||
height:
|
||||
450, // Hauteur légèrement augmentée pour compenser l'absence de Card
|
||||
child: PassagesListWidget(
|
||||
passages: recentPassages,
|
||||
showFilters: false,
|
||||
@@ -217,8 +223,10 @@ Widget _buildCombinedPaymentsCard(bool isDesktop) {
|
||||
maxPassages: 20,
|
||||
// Ne pas appliquer de filtres supplémentaires car les passages
|
||||
// sont déjà filtrés dans _getRecentPassages
|
||||
excludePassageTypes: null, // Pas de filtre, déjà géré dans _getRecentPassages
|
||||
filterByUserId: null, // Pas de filtre, déjà géré dans _getRecentPassages
|
||||
excludePassageTypes:
|
||||
null, // Pas de filtre, déjà géré dans _getRecentPassages
|
||||
filterByUserId:
|
||||
null, // Pas de filtre, déjà géré dans _getRecentPassages
|
||||
periodFilter: null, // Pas de filtre de période
|
||||
// Le widget gère maintenant le flux conditionnel par défaut
|
||||
onPassageSelected: null,
|
||||
@@ -245,18 +253,19 @@ Widget _buildCombinedPaymentsCard(bool isDesktop) {
|
||||
/// Récupère les passages récents pour la liste
|
||||
List<Map<String, dynamic>> _getRecentPassages(Box<PassageModel> passagesBox) {
|
||||
final currentUserId = userRepository.getCurrentUser()?.id;
|
||||
|
||||
// Filtrer les passages :
|
||||
|
||||
// Filtrer les passages :
|
||||
// - Avoir une date passedAt
|
||||
// - Exclure le type 2 ("À finaliser")
|
||||
// - Appartenir à l'utilisateur courant
|
||||
final allPassages = passagesBox.values.where((p) {
|
||||
if (p.passedAt == null) return false;
|
||||
if (p.fkType == 2) return false; // Exclure les passages "À finaliser"
|
||||
if (currentUserId != null && p.fkUser != currentUserId) return false; // Filtrer par utilisateur
|
||||
if (currentUserId != null && p.fkUser != currentUserId)
|
||||
return false; // Filtrer par utilisateur
|
||||
return true;
|
||||
}).toList();
|
||||
|
||||
|
||||
// Trier par date décroissante
|
||||
allPassages.sort((a, b) => b.passedAt!.compareTo(a.passedAt!));
|
||||
|
||||
@@ -294,7 +303,10 @@ Widget _buildCombinedPaymentsCard(bool isDesktop) {
|
||||
'hasReceipt': passage.nomRecu.isNotEmpty,
|
||||
'hasError': passage.emailErreur.isNotEmpty,
|
||||
'fkUser': passage.fkUser,
|
||||
'isOwnedByCurrentUser': passage.fkUser == userRepository.getCurrentUser()?.id, // Ajout du champ pour le widget
|
||||
'isOwnedByCurrentUser': passage.fkUser ==
|
||||
userRepository
|
||||
.getCurrentUser()
|
||||
?.id, // Ajout du champ pour le widget
|
||||
};
|
||||
}).toList();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user