You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
411 lines
17 KiB
411 lines
17 KiB
// Components/newCommandComponents/CadeauDialog.dart
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:youmazgestion/Models/client.dart';
|
|
import 'package:youmazgestion/Models/produit.dart';
|
|
import 'package:youmazgestion/Services/stock_managementDatabase.dart';
|
|
|
|
class CadeauDialog extends StatefulWidget {
|
|
final Product product;
|
|
final int quantite;
|
|
final DetailCommande? detailExistant;
|
|
|
|
const CadeauDialog({
|
|
Key? key,
|
|
required this.product,
|
|
required this.quantite,
|
|
this.detailExistant,
|
|
}) : super(key: key);
|
|
|
|
@override
|
|
_CadeauDialogState createState() => _CadeauDialogState();
|
|
}
|
|
|
|
class _CadeauDialogState extends State<CadeauDialog> {
|
|
final AppDatabase _database = AppDatabase.instance;
|
|
List<Product> _produitsDisponibles = [];
|
|
Product? _produitCadeauSelectionne;
|
|
int _quantiteCadeau = 1;
|
|
bool _isLoading = true;
|
|
String _searchQuery = '';
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_loadProduitsDisponibles();
|
|
}
|
|
|
|
Future<void> _loadProduitsDisponibles() async {
|
|
try {
|
|
final produits = await _database.getProducts();
|
|
setState(() {
|
|
_produitsDisponibles = produits.where((p) =>
|
|
p.id != widget.product.id && // Exclure le produit principal
|
|
(p.stock == null || p.stock! > 0) // Seulement les produits en stock
|
|
).toList();
|
|
_isLoading = false;
|
|
});
|
|
} catch (e) {
|
|
setState(() {
|
|
_isLoading = false;
|
|
});
|
|
Get.snackbar(
|
|
'Erreur',
|
|
'Impossible de charger les produits: $e',
|
|
snackPosition: SnackPosition.BOTTOM,
|
|
backgroundColor: Colors.red,
|
|
colorText: Colors.white,
|
|
);
|
|
}
|
|
}
|
|
|
|
List<Product> get _produitsFiltres {
|
|
if (_searchQuery.isEmpty) {
|
|
return _produitsDisponibles;
|
|
}
|
|
return _produitsDisponibles.where((p) =>
|
|
p.name.toLowerCase().contains(_searchQuery.toLowerCase()) ||
|
|
(p.reference?.toLowerCase().contains(_searchQuery.toLowerCase()) ?? false)
|
|
).toList();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final isMobile = MediaQuery.of(context).size.width < 600;
|
|
|
|
return AlertDialog(
|
|
title: Row(
|
|
children: [
|
|
Container(
|
|
padding: const EdgeInsets.all(8),
|
|
decoration: BoxDecoration(
|
|
color: Colors.green.shade100,
|
|
borderRadius: BorderRadius.circular(8),
|
|
),
|
|
child: Icon(Icons.card_giftcard, color: Colors.green.shade700),
|
|
),
|
|
const SizedBox(width: 12),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
'Ajouter un cadeau',
|
|
style: TextStyle(fontSize: isMobile ? 16 : 18),
|
|
),
|
|
Text(
|
|
'Pour: ${widget.product.name}',
|
|
style: TextStyle(
|
|
fontSize: isMobile ? 12 : 14,
|
|
color: Colors.grey.shade600,
|
|
fontWeight: FontWeight.normal,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
content: Container(
|
|
width: isMobile ? double.maxFinite : 500,
|
|
constraints: BoxConstraints(
|
|
maxHeight: MediaQuery.of(context).size.height * 0.7,
|
|
),
|
|
child: _isLoading
|
|
? const Center(child: CircularProgressIndicator())
|
|
: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
// Information sur le produit principal
|
|
Container(
|
|
padding: const EdgeInsets.all(12),
|
|
decoration: BoxDecoration(
|
|
color: Colors.blue.shade50,
|
|
borderRadius: BorderRadius.circular(8),
|
|
border: Border.all(color: Colors.blue.shade200),
|
|
),
|
|
child: Row(
|
|
children: [
|
|
Icon(Icons.shopping_bag, color: Colors.blue.shade700),
|
|
const SizedBox(width: 8),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
'Produit acheté',
|
|
style: TextStyle(
|
|
fontSize: 12,
|
|
color: Colors.blue.shade700,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
Text(
|
|
'${widget.quantite}x ${widget.product.name}',
|
|
style: const TextStyle(
|
|
fontSize: 14,
|
|
fontWeight: FontWeight.w500,
|
|
),
|
|
),
|
|
Text(
|
|
'Prix: ${widget.product.price.toStringAsFixed(2)} MGA',
|
|
style: TextStyle(
|
|
fontSize: 12,
|
|
color: Colors.grey.shade600,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
|
|
const SizedBox(height: 16),
|
|
|
|
// Barre de recherche
|
|
TextField(
|
|
decoration: InputDecoration(
|
|
labelText: 'Rechercher un produit cadeau',
|
|
prefixIcon: Icon(Icons.search, color: Colors.green.shade600),
|
|
border: OutlineInputBorder(
|
|
borderRadius: BorderRadius.circular(8),
|
|
),
|
|
filled: true,
|
|
fillColor: Colors.green.shade50,
|
|
),
|
|
onChanged: (value) {
|
|
setState(() {
|
|
_searchQuery = value;
|
|
});
|
|
},
|
|
),
|
|
|
|
const SizedBox(height: 16),
|
|
|
|
// Liste des produits disponibles
|
|
Expanded(
|
|
child: _produitsFiltres.isEmpty
|
|
? Center(
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
Icon(
|
|
Icons.card_giftcard_outlined,
|
|
size: 48,
|
|
color: Colors.grey.shade400,
|
|
),
|
|
const SizedBox(height: 8),
|
|
Text(
|
|
'Aucun produit disponible',
|
|
style: TextStyle(
|
|
color: Colors.grey.shade600,
|
|
fontSize: 14,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
)
|
|
: ListView.builder(
|
|
itemCount: _produitsFiltres.length,
|
|
itemBuilder: (context, index) {
|
|
final produit = _produitsFiltres[index];
|
|
final isSelected = _produitCadeauSelectionne?.id == produit.id;
|
|
|
|
return Card(
|
|
margin: const EdgeInsets.only(bottom: 8),
|
|
elevation: isSelected ? 4 : 1,
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(8),
|
|
side: BorderSide(
|
|
color: isSelected
|
|
? Colors.green.shade300
|
|
: Colors.grey.shade200,
|
|
width: isSelected ? 2 : 1,
|
|
),
|
|
),
|
|
child: ListTile(
|
|
contentPadding: const EdgeInsets.all(12),
|
|
leading: Container(
|
|
width: 40,
|
|
height: 40,
|
|
decoration: BoxDecoration(
|
|
color: isSelected
|
|
? Colors.green.shade100
|
|
: Colors.grey.shade100,
|
|
borderRadius: BorderRadius.circular(8),
|
|
),
|
|
child: Icon(
|
|
Icons.card_giftcard,
|
|
color: isSelected
|
|
? Colors.green.shade700
|
|
: Colors.grey.shade600,
|
|
),
|
|
),
|
|
title: Text(
|
|
produit.name,
|
|
style: TextStyle(
|
|
fontWeight: isSelected
|
|
? FontWeight.bold
|
|
: FontWeight.normal,
|
|
),
|
|
),
|
|
subtitle: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
'Prix normal: ${produit.price.toStringAsFixed(2)} MGA',
|
|
style: TextStyle(
|
|
fontSize: 12,
|
|
color: Colors.grey.shade600,
|
|
decoration: TextDecoration.lineThrough,
|
|
),
|
|
),
|
|
Row(
|
|
children: [
|
|
Icon(
|
|
Icons.card_giftcard,
|
|
size: 14,
|
|
color: Colors.green.shade600,
|
|
),
|
|
const SizedBox(width: 4),
|
|
Text(
|
|
'GRATUIT',
|
|
style: TextStyle(
|
|
fontSize: 12,
|
|
color: Colors.green.shade700,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
if (produit.stock != null)
|
|
Text(
|
|
'Stock: ${produit.stock}',
|
|
style: TextStyle(
|
|
fontSize: 11,
|
|
color: Colors.grey.shade500,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
trailing: isSelected
|
|
? Icon(
|
|
Icons.check_circle,
|
|
color: Colors.green.shade700,
|
|
)
|
|
: null,
|
|
onTap: () {
|
|
setState(() {
|
|
_produitCadeauSelectionne = produit;
|
|
});
|
|
},
|
|
),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
|
|
// Sélection de la quantité si un produit est sélectionné
|
|
if (_produitCadeauSelectionne != null) ...[
|
|
const SizedBox(height: 16),
|
|
Container(
|
|
padding: const EdgeInsets.all(12),
|
|
decoration: BoxDecoration(
|
|
color: Colors.green.shade50,
|
|
borderRadius: BorderRadius.circular(8),
|
|
border: Border.all(color: Colors.green.shade200),
|
|
),
|
|
child: Row(
|
|
children: [
|
|
Icon(Icons.card_giftcard, color: Colors.green.shade700),
|
|
const SizedBox(width: 8),
|
|
Expanded(
|
|
child: Text(
|
|
'Quantité de ${_produitCadeauSelectionne!.name}',
|
|
style: TextStyle(
|
|
fontWeight: FontWeight.w500,
|
|
color: Colors.green.shade700,
|
|
),
|
|
),
|
|
),
|
|
Container(
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.circular(20),
|
|
border: Border.all(color: Colors.green.shade300),
|
|
),
|
|
child: Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
IconButton(
|
|
icon: const Icon(Icons.remove, size: 16),
|
|
onPressed: _quantiteCadeau > 1
|
|
? () {
|
|
setState(() {
|
|
_quantiteCadeau--;
|
|
});
|
|
}
|
|
: null,
|
|
),
|
|
Text(
|
|
_quantiteCadeau.toString(),
|
|
style: const TextStyle(
|
|
fontWeight: FontWeight.bold,
|
|
fontSize: 14,
|
|
),
|
|
),
|
|
IconButton(
|
|
icon: const Icon(Icons.add, size: 16),
|
|
onPressed: () {
|
|
final maxStock = _produitCadeauSelectionne!.stock ?? 99;
|
|
if (_quantiteCadeau < maxStock) {
|
|
setState(() {
|
|
_quantiteCadeau++;
|
|
});
|
|
}
|
|
},
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
],
|
|
),
|
|
),
|
|
actions: [
|
|
TextButton(
|
|
onPressed: () => Get.back(),
|
|
child: const Text('Annuler'),
|
|
),
|
|
ElevatedButton.icon(
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: Colors.green.shade700,
|
|
foregroundColor: Colors.white,
|
|
padding: EdgeInsets.symmetric(
|
|
horizontal: isMobile ? 16 : 20,
|
|
vertical: isMobile ? 10 : 12,
|
|
),
|
|
),
|
|
icon: const Icon(Icons.card_giftcard),
|
|
label: Text(
|
|
isMobile ? 'Offrir' : 'Offrir le cadeau',
|
|
style: TextStyle(fontSize: isMobile ? 12 : 14),
|
|
),
|
|
onPressed: _produitCadeauSelectionne != null
|
|
? () {
|
|
Get.back(result: {
|
|
'produit': _produitCadeauSelectionne!,
|
|
'quantite': _quantiteCadeau,
|
|
});
|
|
}
|
|
: null,
|
|
),
|
|
],
|
|
);
|
|
}
|
|
}
|