Browse Source

01082025_01

28062025_02
andrymodeste 4 months ago
parent
commit
2eeaeaa4c4
  1. 579
      lib/Views/Dashboard.dart

579
lib/Views/Dashboard.dart

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

Loading…
Cancel
Save