Browse Source

01082025_01

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

589
lib/Views/Dashboard.dart

@ -1568,6 +1568,9 @@ void _showPointVenteDetails(Map<String, dynamic> 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<int> dialogExpandedCommandes = <int>{};
showDialog(
context: context,
builder: (context) => StatefulBuilder(
@ -1575,7 +1578,7 @@ void _showPointVenteDetails(Map<String, dynamic> 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<String, dynamic> 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<String, dynamic> 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<String, dynamic> 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<String, dynamic> 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<String, dynamic> 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<String, dynamic> pointVenteData) async {
SizedBox(height: 8),
// ... (reste du code pour les sorties, inchangé)
FutureBuilder<List<Map<String, dynamic>>>(
future: _database.getHistoriqueSortiesPersonnelles(
pointDeVenteId: pointVenteId,
@ -1827,6 +1831,7 @@ void _showPointVenteDetails(Map<String, dynamic> 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<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 :
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<int> expandedCommandes, StateSetter setDialogState) {
final bool isExpanded = expandedCommandes.contains(commande.id);
return FutureBuilder<List<DetailCommande>>(
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:

Loading…
Cancel
Save