import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:geosector_app/core/data/models/amicale_model.dart'; import 'package:geosector_app/core/repositories/user_repository.dart'; import 'package:geosector_app/core/repositories/region_repository.dart'; import 'package:provider/provider.dart'; import 'custom_text_field.dart'; class EntiteForm extends StatefulWidget { final AmicaleModel? amicale; final Function(AmicaleModel)? onSubmit; final bool readOnly; const EntiteForm({ Key? key, this.amicale, this.onSubmit, this.readOnly = false, }) : super(key: key); @override State createState() => _EntiteFormState(); } class _EntiteFormState extends State { final _formKey = GlobalKey(); // Controllers late final TextEditingController _nameController; late final TextEditingController _adresse1Controller; late final TextEditingController _adresse2Controller; late final TextEditingController _codePostalController; late final TextEditingController _villeController; late final TextEditingController _phoneController; late final TextEditingController _mobileController; late final TextEditingController _emailController; late final TextEditingController _gpsLatController; late final TextEditingController _gpsLngController; late final TextEditingController _stripeIdController; // Form values int? _fkRegion; String? _libRegion; bool _chkDemo = false; bool _chkCopieMailRecu = false; bool _chkAcceptSms = false; bool _chkActive = true; bool _chkStripe = false; // Liste des régions (sera chargée depuis le store) List> _regions = []; @override void initState() { super.initState(); // Initialize controllers with amicale data if available final amicale = widget.amicale; _nameController = TextEditingController(text: amicale?.name ?? ''); _adresse1Controller = TextEditingController(text: amicale?.adresse1 ?? ''); _adresse2Controller = TextEditingController(text: amicale?.adresse2 ?? ''); _codePostalController = TextEditingController(text: amicale?.codePostal ?? ''); _villeController = TextEditingController(text: amicale?.ville ?? ''); _phoneController = TextEditingController(text: amicale?.phone ?? ''); _mobileController = TextEditingController(text: amicale?.mobile ?? ''); _emailController = TextEditingController(text: amicale?.email ?? ''); _gpsLatController = TextEditingController(text: amicale?.gpsLat ?? ''); _gpsLngController = TextEditingController(text: amicale?.gpsLng ?? ''); _stripeIdController = TextEditingController(text: amicale?.stripeId ?? ''); _fkRegion = amicale?.fkRegion; _libRegion = amicale?.libRegion; _chkDemo = amicale?.chkDemo ?? false; _chkCopieMailRecu = amicale?.chkCopieMailRecu ?? false; _chkAcceptSms = amicale?.chkAcceptSms ?? false; _chkActive = amicale?.chkActive ?? true; _chkStripe = amicale?.chkStripe ?? false; // Charger les régions depuis le repository WidgetsBinding.instance.addPostFrameCallback((_) { _loadRegions(); }); } void _loadRegions() { try { final regionRepository = Provider.of(context, listen: false); if (!regionRepository.isLoaded) { // Initialiser le repository si ce n'est pas déjà fait regionRepository.init().then((_) { setState(() { _regions = regionRepository.getRegionsForDropdown(); }); }); } else { setState(() { _regions = regionRepository.getRegionsForDropdown(); }); } } catch (e) { debugPrint('Erreur lors du chargement des régions: $e'); // Utiliser une liste vide en cas d'erreur setState(() { _regions = []; }); } } @override void dispose() { _nameController.dispose(); _adresse1Controller.dispose(); _adresse2Controller.dispose(); _codePostalController.dispose(); _villeController.dispose(); _phoneController.dispose(); _mobileController.dispose(); _emailController.dispose(); _gpsLatController.dispose(); _gpsLngController.dispose(); _stripeIdController.dispose(); super.dispose(); } void _submitForm() { if (_formKey.currentState!.validate()) { final amicale = widget.amicale?.copyWith( name: _nameController.text, adresse1: _adresse1Controller.text, adresse2: _adresse2Controller.text, codePostal: _codePostalController.text, ville: _villeController.text, fkRegion: _fkRegion, libRegion: _libRegion, phone: _phoneController.text, mobile: _mobileController.text, email: _emailController.text, gpsLat: _gpsLatController.text, gpsLng: _gpsLngController.text, stripeId: _stripeIdController.text, chkDemo: _chkDemo, chkCopieMailRecu: _chkCopieMailRecu, chkAcceptSms: _chkAcceptSms, chkActive: _chkActive, chkStripe: _chkStripe, ) ?? AmicaleModel( id: 0, // Sera remplacé par l'API name: _nameController.text, adresse1: _adresse1Controller.text, adresse2: _adresse2Controller.text, codePostal: _codePostalController.text, ville: _villeController.text, fkRegion: _fkRegion, libRegion: _libRegion, phone: _phoneController.text, mobile: _mobileController.text, email: _emailController.text, gpsLat: _gpsLatController.text, gpsLng: _gpsLngController.text, stripeId: _stripeIdController.text, chkDemo: _chkDemo, chkCopieMailRecu: _chkCopieMailRecu, chkAcceptSms: _chkAcceptSms, chkActive: _chkActive, ); if (widget.onSubmit != null) { widget.onSubmit!(amicale); } } } @override Widget build(BuildContext context) { final theme = Theme.of(context); final userRepository = Provider.of(context, listen: false); final userRole = userRepository.getUserRole(); // Déterminer si l'utilisateur peut modifier les champs restreints final bool canEditRestrictedFields = userRole > 2; // Lecture seule pour les champs restreints si l'utilisateur n'a pas les droits final bool restrictedFieldsReadOnly = widget.readOnly || !canEditRestrictedFields; // Calculer la largeur maximale du formulaire pour les écrans larges final screenWidth = MediaQuery.of(context).size.width; final formMaxWidth = screenWidth > 800 ? 600.0 : screenWidth; return Form( key: _formKey, child: Container( constraints: BoxConstraints(maxWidth: formMaxWidth), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Nom CustomTextField( controller: _nameController, label: "Nom", readOnly: widget.readOnly, validator: (value) { if (value == null || value.isEmpty) { return "Veuillez entrer un nom"; } return null; }, ), const SizedBox(height: 16), // Bloc Adresse Text( "Adresse", style: theme.textTheme.titleMedium?.copyWith( fontWeight: FontWeight.bold, color: theme.colorScheme.onBackground, ), ), const SizedBox(height: 8), // Adresse 1 CustomTextField( controller: _adresse1Controller, label: "Adresse ligne 1", readOnly: widget.readOnly, ), const SizedBox(height: 16), // Adresse 2 CustomTextField( controller: _adresse2Controller, label: "Adresse ligne 2", readOnly: widget.readOnly, ), const SizedBox(height: 16), // Code Postal et Ville Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Code Postal Expanded( flex: 1, child: CustomTextField( controller: _codePostalController, label: "Code Postal", keyboardType: TextInputType.number, inputFormatters: [ FilteringTextInputFormatter.digitsOnly, LengthLimitingTextInputFormatter(5), ], readOnly: widget.readOnly, validator: (value) { if (value != null && value.isNotEmpty && value.length < 5) { return "Le code postal doit contenir 5 chiffres"; } return null; }, ), ), const SizedBox(width: 16), // Ville Expanded( flex: 2, child: CustomTextField( controller: _villeController, label: "Ville", readOnly: widget.readOnly, ), ), ], ), const SizedBox(height: 16), // Région Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Région", style: theme.textTheme.titleSmall?.copyWith( fontWeight: FontWeight.w500, color: theme.colorScheme.onBackground, ), ), const SizedBox(height: 8), _buildRegionDropdown(restrictedFieldsReadOnly), ], ), const SizedBox(height: 16), // Contact Text( "Contact", style: theme.textTheme.titleMedium?.copyWith( fontWeight: FontWeight.bold, color: theme.colorScheme.onBackground, ), ), const SizedBox(height: 8), // Téléphone fixe et mobile sur la même ligne Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Téléphone fixe Expanded( child: CustomTextField( controller: _phoneController, label: "Téléphone fixe", keyboardType: TextInputType.phone, readOnly: widget.readOnly, inputFormatters: [ FilteringTextInputFormatter.digitsOnly, LengthLimitingTextInputFormatter(10), ], validator: (value) { if (value != null && value.isNotEmpty && value.length < 10) { return "Le numéro de téléphone doit contenir 10 chiffres"; } return null; }, ), ), const SizedBox(width: 16), // Téléphone mobile Expanded( child: CustomTextField( controller: _mobileController, label: "Téléphone mobile", keyboardType: TextInputType.phone, readOnly: widget.readOnly, inputFormatters: [ FilteringTextInputFormatter.digitsOnly, LengthLimitingTextInputFormatter(10), ], validator: (value) { if (value != null && value.isNotEmpty && value.length < 10) { return "Le numéro de mobile doit contenir 10 chiffres"; } return null; }, ), ), ], ), const SizedBox(height: 16), // Email CustomTextField( controller: _emailController, label: "Email", keyboardType: TextInputType.emailAddress, readOnly: widget.readOnly, validator: (value) { if (value == null || value.isEmpty) { return "Veuillez entrer l'adresse email"; } if (!value.contains('@') || !value.contains('.')) { return "Veuillez entrer une adresse email valide"; } return null; }, ), const SizedBox(height: 16), // Informations avancées (visibles uniquement pour les administrateurs) if (canEditRestrictedFields || (_gpsLatController.text.isNotEmpty || _gpsLngController.text.isNotEmpty || _stripeIdController.text.isNotEmpty)) ...[ Text( "Informations avancées", style: theme.textTheme.titleMedium?.copyWith( fontWeight: FontWeight.bold, color: theme.colorScheme.onBackground, ), ), const SizedBox(height: 8), // GPS Latitude et Longitude Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ // GPS Latitude Expanded( child: CustomTextField( controller: _gpsLatController, label: "GPS Latitude", keyboardType: const TextInputType.numberWithOptions(decimal: true), readOnly: restrictedFieldsReadOnly, ), ), const SizedBox(width: 16), // GPS Longitude Expanded( child: CustomTextField( controller: _gpsLngController, label: "GPS Longitude", keyboardType: const TextInputType.numberWithOptions(decimal: true), readOnly: restrictedFieldsReadOnly, ), ), ], ), const SizedBox(height: 16), // Stripe Checkbox et Stripe ID sur la même ligne Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ // Checkbox Stripe Checkbox( value: _chkStripe, onChanged: restrictedFieldsReadOnly ? null : (value) { setState(() { _chkStripe = value!; }); }, activeColor: const Color(0xFF20335E), ), Text( "Stripe activé", style: theme.textTheme.bodyMedium?.copyWith( color: theme.colorScheme.onBackground, fontWeight: FontWeight.w500, ), ), const SizedBox(width: 16), // Stripe ID Expanded( child: CustomTextField( controller: _stripeIdController, label: "Stripe ID", readOnly: restrictedFieldsReadOnly, ), ), ], ), const SizedBox(height: 16), ], // Options Text( "Options", style: theme.textTheme.titleMedium?.copyWith( fontWeight: FontWeight.bold, color: theme.colorScheme.onBackground, ), ), const SizedBox(height: 8), // Checkbox Demo _buildCheckboxOption( label: "Mode démo", value: _chkDemo, onChanged: restrictedFieldsReadOnly ? null : (value) { setState(() { _chkDemo = value!; }); }, ), const SizedBox(height: 8), // Checkbox Copie Mail Reçu _buildCheckboxOption( label: "Copie des mails reçus", value: _chkCopieMailRecu, onChanged: widget.readOnly ? null : (value) { setState(() { _chkCopieMailRecu = value!; }); }, ), const SizedBox(height: 8), // Checkbox Accept SMS _buildCheckboxOption( label: "Accepte les SMS", value: _chkAcceptSms, onChanged: widget.readOnly ? null : (value) { setState(() { _chkAcceptSms = value!; }); }, ), const SizedBox(height: 8), // Checkbox Active _buildCheckboxOption( label: "Actif", value: _chkActive, onChanged: restrictedFieldsReadOnly ? null : (value) { setState(() { _chkActive = value!; }); }, ), const SizedBox(height: 25), // Bouton Enregistrer if (!widget.readOnly) Center( child: ElevatedButton( onPressed: _submitForm, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF20335E), foregroundColor: Colors.white, padding: const EdgeInsets.symmetric( horizontal: 24, vertical: 16), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(50), ), minimumSize: const Size(200, 50), ), child: const Text( 'Enregistrer', style: TextStyle( fontSize: 18, fontWeight: FontWeight.w500, ), ), ), ), ], ), ), ); } Widget _buildCheckboxOption({ required String label, required bool value, required Function(bool?)? onChanged, }) { final theme = Theme.of(context); return Row( children: [ Checkbox( value: value, onChanged: onChanged, activeColor: const Color(0xFF20335E), ), Text( label, style: theme.textTheme.bodyMedium?.copyWith( color: theme.colorScheme.onBackground, fontWeight: FontWeight.w500, ), ), ], ); } Widget _buildRegionDropdown(bool readOnly) { final theme = Theme.of(context); // Si en lecture seule, afficher simplement le texte if (readOnly && _libRegion != null) { return Padding( padding: const EdgeInsets.symmetric(vertical: 8.0), child: Text( _libRegion!, style: theme.textTheme.bodyLarge?.copyWith( color: theme.colorScheme.onBackground, ), ), ); } return Container( padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 5), decoration: BoxDecoration( color: const Color(0xFFF4F5F6).withOpacity(0.85), borderRadius: BorderRadius.circular(8), border: Border.all( color: const Color(0xFF20335E).withOpacity(0.1), width: 1, ), ), child: DropdownButtonHideUnderline( child: DropdownButton( value: _fkRegion, isExpanded: true, hint: const Text("Sélectionnez une région"), icon: const Icon( Icons.keyboard_arrow_down, color: Color(0xFF20335E), ), style: theme.textTheme.bodyMedium?.copyWith( color: const Color(0xFF20335E), ), dropdownColor: Colors.white, items: _regions .map>((Map region) { return DropdownMenuItem( value: region['id'] as int, child: Text(region['name'] as String), ); }).toList(), onChanged: readOnly ? null : (int? newValue) { setState(() { _fkRegion = newValue; // Trouver le libellé correspondant if (newValue != null) { final selectedRegion = _regions.firstWhere( (region) => region['id'] == newValue, orElse: () => {'id': newValue, 'name': ''}, ); _libRegion = selectedRegion['name'] as String; } else { _libRegion = null; } }); }, ), ), ); } }