From 2eeaeaa4c41cbefc7aa1c78b8ddd33cad92ec17e Mon Sep 17 00:00:00 2001 From: andrymodeste Date: Fri, 1 Aug 2025 07:15:02 +0200 Subject: [PATCH] 01082025_01 --- lib/Views/Dashboard.dart | 589 ++++++++++++++++++++------------------- 1 file changed, 300 insertions(+), 289 deletions(-) diff --git a/lib/Views/Dashboard.dart b/lib/Views/Dashboard.dart index e1f7687..e522292 100644 --- a/lib/Views/Dashboard.dart +++ b/lib/Views/Dashboard.dart @@ -1568,6 +1568,9 @@ void _showPointVenteDetails(Map pointVenteData) async { final pointVenteId = pointVenteData['point_vente_id'] as int; final pointVenteNom = pointVenteData['point_vente_nom'] as String; + // VARIABLE LOCALE pour gérer l'expansion des cartes dans ce dialog uniquement + Set dialogExpandedCommandes = {}; + showDialog( context: context, builder: (context) => StatefulBuilder( @@ -1575,7 +1578,7 @@ void _showPointVenteDetails(Map pointVenteData) async { title: Text('Détails - $pointVenteNom'), content: Container( width: double.maxFinite, - height: 600, // Augmenté pour inclure les commandes + height: 600, child: SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -1595,7 +1598,7 @@ void _showPointVenteDetails(Map pointVenteData) async { _showOnlyToday = !_showOnlyToday; if (_showOnlyToday) _dateRange = null; }); - setState(() {}); + setState(() {}); // Pour rafraîchir le dashboard principal aussi }, icon: Icon( _showOnlyToday ? Icons.today : Icons.calendar_today, @@ -1633,7 +1636,7 @@ void _showPointVenteDetails(Map pointVenteData) async { _dateRange = picked; _showOnlyToday = false; }); - setState(() {}); + setState(() {}); // Pour rafraîchir le dashboard principal aussi } }, icon: const Icon(Icons.date_range, size: 20), @@ -1658,7 +1661,7 @@ void _showPointVenteDetails(Map pointVenteData) async { _showOnlyToday = false; _dateRange = null; }); - setState(() {}); + setState(() {}); // Pour rafraîchir le dashboard principal aussi }, icon: const Icon(Icons.clear, size: 20), label: Text('Reset', style: TextStyle(fontSize: 12)), @@ -1742,8 +1745,7 @@ void _showPointVenteDetails(Map pointVenteData) async { SizedBox(height: 12), - - // NOUVELLE SECTION: Liste des commandes + // SECTION: Liste des commandes SizedBox(height: 16), Divider(), @@ -1781,15 +1783,18 @@ void _showPointVenteDetails(Map pointVenteData) async { return Text(message, style: TextStyle(color: Colors.grey)); } - final commandes = snapshot.data! - .map((map) => Commande.fromMap(map)) - .toList(); + final commandes = snapshot.data! + .map((map) => Commande.fromMap(map)) + .toList(); - return Column( - children: commandes.map(_buildCommandeCardForDialog).toList(), - ); + return Column( + children: commandes.map((commande) => + _buildCommandeCardForDialog(commande, dialogExpandedCommandes, setDialogState) + ).toList(), + ); }, ), + // Section des sorties personnelles SizedBox(height: 16), Divider(), @@ -1799,7 +1804,6 @@ void _showPointVenteDetails(Map pointVenteData) async { SizedBox(height: 8), - // ... (reste du code pour les sorties, inchangé) FutureBuilder>>( future: _database.getHistoriqueSortiesPersonnelles( pointDeVenteId: pointVenteId, @@ -1827,6 +1831,7 @@ void _showPointVenteDetails(Map pointVenteData) async { } return Text(message, style: TextStyle(color: Colors.grey)); } + final sorties = snapshot.data!; return Column( children: sorties.map((sortie) => Card( @@ -1934,12 +1939,10 @@ void _showPointVenteDetails(Map pointVenteData) async { ), ); } -// Ajoutez cette variable d'état dans votre classe _DashboardPageState -Set _expandedCommandes = {}; -// Remplacez votre méthode _buildCommandeCardForDialog par celle-ci : -Widget _buildCommandeCardForDialog(Commande commande) { - final bool isExpanded = _expandedCommandes.contains(commande.id); +// NOUVELLE VERSION de _buildCommandeCardForDialog qui utilise les paramètres du dialog +Widget _buildCommandeCardForDialog(Commande commande, Set expandedCommandes, StateSetter setDialogState) { + final bool isExpanded = expandedCommandes.contains(commande.id); return FutureBuilder>( future: _database.getDetailsCommande(commande.id!), @@ -1957,326 +1960,335 @@ Widget _buildCommandeCardForDialog(Commande commande) { return AnimatedContainer( duration: Duration(milliseconds: 300), curve: Curves.easeInOut, - child: InkWell( - onTap: () { - setState(() { - if (isExpanded) { - _expandedCommandes.remove(commande.id); - } else { - _expandedCommandes.add(commande.id!); - } - }); - }, + margin: EdgeInsets.symmetric(vertical: 4), + child: Material( + elevation: isExpanded ? 4 : 2, borderRadius: BorderRadius.circular(8), - child: Card( - margin: EdgeInsets.symmetric(vertical: 4), - elevation: isExpanded ? 4 : 2, - shape: RoundedRectangleBorder( + child: Container( + decoration: BoxDecoration( + color: isExpanded + ? Colors.grey.shade100 + : Colors.grey.shade200, borderRadius: BorderRadius.circular(8), - side: aDesRemises - ? BorderSide(color: Colors.orange.shade300, width: 1) - : BorderSide.none, + border: aDesRemises + ? Border.all(color: Colors.orange.shade300, width: 1) + : null, ), - child: Padding( - padding: EdgeInsets.all(12), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // En-tête de la commande (toujours visible) - Row( - children: [ - Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: _getStatutColor(commande.statut).withOpacity(0.1), - borderRadius: BorderRadius.circular(20), - border: aDesRemises - ? Border.all(color: Colors.orange.shade300, width: 1) - : null, - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon( - aDesRemises - ? Icons.discount - : _getStatutIcon(commande.statut), - size: 16, - color: aDesRemises - ? Colors.teal.shade700 - : commande.statut == StatutCommande.annulee - ? Colors.red - : Colors.blue.shade600, - ), - Text( - '#${commande.id}', - style: TextStyle( - fontSize: 8, - fontWeight: FontWeight.bold, - ), - ), - ], - ), - ), - SizedBox(width: 12), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - commande.clientNomComplet, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.bold, - ), - overflow: TextOverflow.ellipsis, - ), - SizedBox(height: 2), - Row( - children: [ - Icon(Icons.calendar_today, size: 12, color: Colors.grey), - SizedBox(width: 4), - Text( - DateFormat('dd/MM/yyyy').format(commande.dateCommande), - style: TextStyle(fontSize: 11, color: Colors.grey), - ), - SizedBox(width: 12), - Container( - padding: EdgeInsets.symmetric(horizontal: 6, vertical: 2), - decoration: BoxDecoration( - color: _getStatutColor(commande.statut).withOpacity(0.2), - borderRadius: BorderRadius.circular(10), - ), - child: Text( - commande.statutLibelle, - style: TextStyle( - fontSize: 10, - fontWeight: FontWeight.w600, - color: commande.statut == StatutCommande.annulee - ? Colors.red - : Colors.blue.shade700, - ), - ), - ), - ], - ), - ], - ), - ), - // Icône d'expansion - AnimatedRotation( - turns: isExpanded ? 0.5 : 0, - duration: Duration(milliseconds: 300), - child: Icon( - Icons.expand_more, - color: Colors.grey[600], - ), - ), - ], - ), - - SizedBox(height: 8), - - // Montant (toujours visible) - Row( - children: [ - Icon(Icons.attach_money, size: 14, color: Colors.green.shade600), - SizedBox(width: 4), - Text( - '${NumberFormat('#,##0', 'fr_FR').format(commande.montantTotal)} MGA', - style: TextStyle( - fontSize: 13, - fontWeight: FontWeight.bold, - color: Colors.green.shade700, - ), - ), - if (totalRemises > 0) ...[ - SizedBox(width: 8), + + child: InkWell( + onTap: () { + print('Card tapped! Current state: $isExpanded'); + // UTILISER setDialogState au lieu de setState + setDialogState(() { + if (isExpanded) { + expandedCommandes.remove(commande.id); + print('Removed commande ${commande.id}'); + } else { + expandedCommandes.add(commande.id!); + print('Added commande ${commande.id}'); + } + print('Current expanded: $expandedCommandes'); + }); + }, + borderRadius: BorderRadius.circular(8), + child: Padding( + padding: EdgeInsets.all(12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // En-tête de la commande (toujours visible) + Row( + children: [ Container( - padding: EdgeInsets.symmetric(horizontal: 4, vertical: 2), + width: 40, + height: 40, decoration: BoxDecoration( - color: Colors.orange.shade100, - borderRadius: BorderRadius.circular(8), + color: _getStatutColor(commande.statut).withOpacity(0.1), + borderRadius: BorderRadius.circular(20), + border: aDesRemises + ? Border.all(color: Colors.orange.shade300, width: 1) + : null, ), - child: Row( - mainAxisSize: MainAxisSize.min, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, children: [ - Icon(Icons.discount, size: 10, color: Colors.teal.shade700), - SizedBox(width: 2), + Icon( + aDesRemises + ? Icons.discount + : _getStatutIcon(commande.statut), + size: 16, + color: aDesRemises + ? Colors.teal.shade700 + : commande.statut == StatutCommande.annulee + ? Colors.red + : Colors.blue.shade600, + ), Text( - '-${NumberFormat('#,##0', 'fr_FR').format(totalRemises)}', + '#${commande.id}', style: TextStyle( - fontSize: 9, + fontSize: 8, fontWeight: FontWeight.bold, - color: Colors.teal.shade700, ), ), ], ), ), + SizedBox(width: 12), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + commande.clientNomComplet, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.bold, + ), + overflow: TextOverflow.ellipsis, + ), + SizedBox(height: 2), + Row( + children: [ + Icon(Icons.calendar_today, size: 12, color: Colors.grey), + SizedBox(width: 4), + Text( + DateFormat('dd/MM/yyyy').format(commande.dateCommande), + style: TextStyle(fontSize: 11, color: Colors.grey), + ), + SizedBox(width: 12), + Container( + padding: EdgeInsets.symmetric(horizontal: 6, vertical: 2), + decoration: BoxDecoration( + color: _getStatutColor(commande.statut).withOpacity(0.2), + borderRadius: BorderRadius.circular(10), + ), + child: Text( + commande.statutLibelle, + style: TextStyle( + fontSize: 10, + fontWeight: FontWeight.w600, + color: commande.statut == StatutCommande.annulee + ? Colors.red + : Colors.blue.shade700, + ), + ), + ), + ], + ), + ], + ), + ), + // Icône d'expansion + AnimatedRotation( + turns: isExpanded ? 0.5 : 0, + duration: Duration(milliseconds: 300), + child: Icon( + Icons.expand_more, + color: Colors.grey[600], + ), + ), ], - ], - ), - - // Détails étendus (visibles seulement si expanded) - AnimatedCrossFade( - duration: Duration(milliseconds: 300), - crossFadeState: isExpanded - ? CrossFadeState.showSecond - : CrossFadeState.showFirst, - firstChild: SizedBox.shrink(), - secondChild: Column( - crossAxisAlignment: CrossAxisAlignment.start, + ), + + SizedBox(height: 8), + + // Montant (toujours visible) + Row( children: [ - SizedBox(height: 12), - Divider(color: Colors.grey[300]), - SizedBox(height: 8), - - // Informations du commandeur - if (commande.commandeurnom != null && commande.commandeurnom!.isNotEmpty) + Icon(Icons.attach_money, size: 14, color: Colors.green.shade600), + SizedBox(width: 4), + Text( + '${NumberFormat('#,##0', 'fr_FR').format(commande.montantTotal)} MGA', + style: TextStyle( + fontSize: 13, + fontWeight: FontWeight.bold, + color: Colors.green.shade700, + ), + ), + if (totalRemises > 0) ...[ + SizedBox(width: 8), Container( - padding: EdgeInsets.all(8), + padding: EdgeInsets.symmetric(horizontal: 4, vertical: 2), decoration: BoxDecoration( - color: Colors.blue.shade50, - borderRadius: BorderRadius.circular(6), + color: Colors.orange.shade100, + borderRadius: BorderRadius.circular(8), ), child: Row( + mainAxisSize: MainAxisSize.min, children: [ - Icon(Icons.person, size: 16, color: Colors.blue[600]), - SizedBox(width: 8), + Icon(Icons.discount, size: 10, color: Colors.teal.shade700), + SizedBox(width: 2), Text( - 'Commandeur: ', + '-${NumberFormat('#,##0', 'fr_FR').format(totalRemises)}', style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: Colors.grey[700], - ), - ), - Expanded( - child: Text( - '${commande.commandeurnom ?? ''} ${commande.commandeurPrenom ?? ''}', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - color: Colors.blue[700], - ), + fontSize: 9, + fontWeight: FontWeight.bold, + color: Colors.teal.shade700, ), ), ], ), ), - - SizedBox(height: 8), - - // Statut détaillé - Container( - padding: EdgeInsets.all(8), - decoration: BoxDecoration( - color: _getStatutColor(commande.statut).withOpacity(0.1), - borderRadius: BorderRadius.circular(6), - ), - child: Row( - children: [ - Icon( - _getStatutIcon(commande.statut), - size: 16, - color: commande.statut == StatutCommande.annulee - ? Colors.red - : Colors.blue[600], - ), - SizedBox(width: 8), - Text( - 'Statut: ', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: Colors.grey[700], - ), + ], + ], + ), + + // Détails étendus avec AnimatedSize + AnimatedSize( + duration: Duration(milliseconds: 300), + curve: Curves.easeInOut, + child: isExpanded ? Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox(height: 12), + Divider(color: Colors.grey[300]), + SizedBox(height: 8), + + // Informations du commandeur + if (commande.commandeurnom != null && commande.commandeurnom!.isNotEmpty) + Container( + padding: EdgeInsets.all(8), + decoration: BoxDecoration( + color: Colors.blue.shade50, + borderRadius: BorderRadius.circular(6), ), - Text( - commande.statutLibelle, - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - color: commande.statut == StatutCommande.annulee - ? Colors.red - : Colors.blue[700], - ), + child: Row( + children: [ + Icon(Icons.person, size: 16, color: Colors.blue[600]), + SizedBox(width: 8), + Text( + 'Commandeur: ', + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w500, + color: Colors.grey[700], + ), + ), + Expanded( + child: Text( + '${commande.commandeurnom ?? ''} ${commande.commandeurPrenom ?? ''}', + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.bold, + color: Colors.blue[700], + ), + ), + ), + ], ), - ], - ), - ), - - SizedBox(height: 8), - - // Liste des produits commandés - if (snapshot.hasData && snapshot.data!.isNotEmpty) ...[ + ), + + SizedBox(height: 8), + + // Statut détaillé Container( padding: EdgeInsets.all(8), decoration: BoxDecoration( - color: Colors.green.shade50, + color: _getStatutColor(commande.statut).withOpacity(0.1), borderRadius: BorderRadius.circular(6), ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + child: Row( children: [ - Row( - children: [ - Icon(Icons.shopping_cart, size: 16, color: Colors.green[600]), - SizedBox(width: 8), - Text( - 'Produits commandés:', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - color: Colors.green[700], - ), - ), - ], + Icon( + _getStatutIcon(commande.statut), + size: 16, + color: commande.statut == StatutCommande.annulee + ? Colors.red + : Colors.blue[600], + ), + SizedBox(width: 8), + Text( + 'Statut: ', + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w500, + color: Colors.grey[700], + ), ), - SizedBox(height: 6), - ...snapshot.data!.map((detail) => Padding( - padding: EdgeInsets.only(left: 24, bottom: 4), - child: Row( + Text( + commande.statutLibelle, + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.bold, + color: commande.statut == StatutCommande.annulee + ? Colors.red + : Colors.blue[700], + ), + ), + ], + ), + ), + + SizedBox(height: 8), + + // Liste des produits commandés + if (snapshot.hasData && snapshot.data!.isNotEmpty) ...[ + Container( + padding: EdgeInsets.all(8), + decoration: BoxDecoration( + color: Colors.green.shade50, + borderRadius: BorderRadius.circular(6), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( children: [ - Container( - width: 4, - height: 4, - decoration: BoxDecoration( - color: Colors.green[600], - borderRadius: BorderRadius.circular(2), - ), - ), + Icon(Icons.shopping_cart, size: 16, color: Colors.green[600]), SizedBox(width: 8), - Expanded( - child: Text( - '${detail.produitNom} (x${detail.quantite})', - style: TextStyle( - fontSize: 11, - color: Colors.green[700], - ), - ), - ), Text( - '${NumberFormat('#,##0', 'fr_FR').format(detail.sousTotal)} MGA', + 'Produits commandés:', style: TextStyle( - fontSize: 11, - fontWeight: FontWeight.w500, + fontSize: 12, + fontWeight: FontWeight.bold, color: Colors.green[700], ), ), ], ), - )).toList(), - ], + SizedBox(height: 6), + ...snapshot.data!.map((detail) => Padding( + padding: EdgeInsets.only(left: 24, bottom: 4), + child: Row( + children: [ + Container( + width: 4, + height: 4, + decoration: BoxDecoration( + color: Colors.green[600], + borderRadius: BorderRadius.circular(2), + ), + ), + SizedBox(width: 8), + Expanded( + child: Text( + '${detail.produitNom} (x${detail.quantite})', + style: TextStyle( + fontSize: 11, + color: Colors.green[700], + ), + ), + ), + Text( + '${NumberFormat('#,##0', 'fr_FR').format(detail.sousTotal)} MGA', + style: TextStyle( + fontSize: 11, + fontWeight: FontWeight.w500, + color: Colors.green[700], + ), + ), + ], + ), + )).toList(), + ], + ), ), - ), + ], ], - ], + ) : SizedBox.shrink(), ), - ), - ], + ], + ), ), ), ), @@ -2285,7 +2297,6 @@ Widget _buildCommandeCardForDialog(Commande commande) { }, ); } - Color _getStatutColor(StatutCommande statut) { switch (statut) { case StatutCommande.enAttente: