import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:youmazgestion/Components/app_bar.dart'; import 'package:youmazgestion/Components/appDrawer.dart'; import 'package:youmazgestion/Services/stock_managementDatabase.dart'; class AjoutPointDeVentePage extends StatefulWidget { const AjoutPointDeVentePage({super.key}); @override _AjoutPointDeVentePageState createState() => _AjoutPointDeVentePageState(); } class _AjoutPointDeVentePageState extends State { final AppDatabase _appDatabase = AppDatabase.instance; final _formKey = GlobalKey(); bool _isLoading = false; // Contrôleurs final TextEditingController _nomController = TextEditingController(); final TextEditingController _codeController = TextEditingController(); // Liste des points de vente List> _pointsDeVente = []; final TextEditingController _searchController = TextEditingController(); @override void initState() { super.initState(); _loadPointsDeVente(); _searchController.addListener(_filterPointsDeVente); } Future _loadPointsDeVente() async { setState(() { _isLoading = true; }); try { final points = await _appDatabase.getPointsDeVente(); setState(() { _pointsDeVente = points; _isLoading = false; }); } catch (e) { setState(() { _isLoading = false; }); Get.snackbar( 'Erreur', 'Impossible de charger les points de vente: ${e.toString()}', snackPosition: SnackPosition.BOTTOM, backgroundColor: Colors.red, colorText: Colors.white, ); } } void _filterPointsDeVente() { final query = _searchController.text.toLowerCase(); if (query.isEmpty) { _loadPointsDeVente(); return; } setState(() { _pointsDeVente = _pointsDeVente.where((point) { final nom = point['nom']?.toString().toLowerCase() ?? ''; return nom.contains(query); }).toList(); }); } Future _submitForm() async { if (_formKey.currentState!.validate()) { setState(() { _isLoading = true; }); try { await _appDatabase.createPointDeVente( _nomController.text.trim(), _codeController.text.trim(), ); // Réinitialiser le formulaire _nomController.clear(); _codeController.clear(); // Recharger la liste await _loadPointsDeVente(); Get.snackbar( 'Succès', 'Point de vente ajouté avec succès', snackPosition: SnackPosition.BOTTOM, backgroundColor: Colors.green, colorText: Colors.white, ); } catch (e) { Get.snackbar( 'Erreur', 'Impossible d\'ajouter le point de vente: ${e.toString()}', snackPosition: SnackPosition.BOTTOM, backgroundColor: Colors.red, colorText: Colors.white, ); } finally { setState(() { _isLoading = false; }); } } } Future _deletePointDeVente(int id) async { final confirmed = await Get.dialog( AlertDialog( title: const Text('Confirmer la suppression'), content: const Text('Voulez-vous vraiment supprimer ce point de vente ?'), actions: [ TextButton( onPressed: () => Get.back(result: false), child: const Text('Annuler'), ), TextButton( onPressed: () => Get.back(result: true), child: const Text('Supprimer', style: TextStyle(color: Colors.red)), ), ], ), ); if (confirmed == true) { setState(() { _isLoading = true; }); try { await _appDatabase.deletePointDeVente(id); await _loadPointsDeVente(); Get.snackbar( 'Succès', 'Point de vente supprimé avec succès', snackPosition: SnackPosition.BOTTOM, backgroundColor: Colors.green, colorText: Colors.white, ); } catch (e) { Get.snackbar( 'Erreur', 'Impossible de supprimer le point de vente: ${e.toString()}', snackPosition: SnackPosition.BOTTOM, backgroundColor: Colors.red, colorText: Colors.white, ); } finally { setState(() { _isLoading = false; }); } } } @override Widget build(BuildContext context) { return Scaffold( appBar: CustomAppBar(title: 'Gestion des points de vente'), drawer: CustomDrawer(), body: Column( children: [ // Formulaire d'ajout Card( margin: const EdgeInsets.all(16), elevation: 4, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), child: Padding( padding: const EdgeInsets.all(16.0), child: Form( key: _formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ const Text( 'Ajouter un point de vente', style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: Color.fromARGB(255, 9, 56, 95), ), ), const SizedBox(height: 16), // Champ Nom TextFormField( controller: _nomController, decoration: InputDecoration( labelText: 'Nom du point de vente', prefixIcon: const Icon(Icons.store), border: OutlineInputBorder( borderRadius: BorderRadius.circular(8), ), filled: true, fillColor: Colors.grey.shade50, ), validator: (value) { if (value == null || value.isEmpty) { return 'Veuillez entrer un nom'; } return null; }, ), const SizedBox(height: 12), // Champ Code TextFormField( controller: _codeController, decoration: InputDecoration( labelText: 'Code (optionnel)', prefixIcon: const Icon(Icons.code), border: OutlineInputBorder( borderRadius: BorderRadius.circular(8), ), filled: true, fillColor: Colors.grey.shade50, ), ), const SizedBox(height: 16), // Bouton de soumission ElevatedButton( onPressed: _isLoading ? null : _submitForm, style: ElevatedButton.styleFrom( padding: const EdgeInsets.symmetric(vertical: 16), backgroundColor: Colors.blue.shade800, foregroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), child: _isLoading ? const SizedBox( width: 20, height: 20, child: CircularProgressIndicator( strokeWidth: 2, color: Colors.white, ), ) : const Text( 'Ajouter le point de vente', style: TextStyle(fontSize: 16), ), ), ], ), ), ), ), // Liste des points de vente Expanded( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Column( children: [ // Barre de recherche Padding( padding: const EdgeInsets.only(bottom: 8), child: TextField( controller: _searchController, decoration: InputDecoration( labelText: 'Rechercher un point de vente', prefixIcon: const Icon(Icons.search), border: OutlineInputBorder( borderRadius: BorderRadius.circular(8), ), filled: true, fillColor: Colors.grey.shade50, suffixIcon: _searchController.text.isNotEmpty ? IconButton( icon: const Icon(Icons.clear), onPressed: () { _searchController.clear(); _loadPointsDeVente(); }, ) : null, ), ), ), // En-tête de liste Padding( padding: const EdgeInsets.symmetric(vertical: 8), child: Row( children: [ const Expanded( flex: 2, child: Text( 'Nom', style: TextStyle( fontWeight: FontWeight.bold, color: Color.fromARGB(255, 9, 56, 95), ), ), ), const Expanded( child: Text( 'Code', style: TextStyle( fontWeight: FontWeight.bold, color: Color.fromARGB(255, 9, 56, 95), ), ), ), SizedBox( width: 40, child: Text( 'Actions', style: TextStyle( fontWeight: FontWeight.bold, color: Color.fromARGB(255, 9, 56, 95), ), ), ), ], ), ), // Liste Expanded( child: _isLoading && _pointsDeVente.isEmpty ? const Center(child: CircularProgressIndicator()) : _pointsDeVente.isEmpty ? const Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.store_mall_directory_outlined, size: 60, color: Colors.grey), SizedBox(height: 16), Text( 'Aucun point de vente trouvé', style: TextStyle( fontSize: 16, color: Colors.grey), ), ], ), ) : ListView.builder( itemCount: _pointsDeVente.length, itemBuilder: (context, index) { final point = _pointsDeVente[index]; return Card( margin: const EdgeInsets.only(bottom: 8), elevation: 2, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), child: Padding( padding: const EdgeInsets.all(8.0), child: Row( children: [ Expanded( flex: 2, child: Text( point['nom'] ?? 'N/A', style: const TextStyle( fontWeight: FontWeight.w500), ), ), Expanded( child: Text( point['code'] ?? 'N/A', style: TextStyle( color: Colors.grey.shade600), ), ), SizedBox( width: 40, child: IconButton( icon: const Icon(Icons.delete, size: 20, color: Colors.red), onPressed: () => _deletePointDeVente(point['id']), ), ), ], ), ), ); }, ), ), ], ), ), ), ], ), ); } @override void dispose() { _nomController.dispose(); _codeController.dispose(); _searchController.dispose(); super.dispose(); } }