import 'package:flutter/material.dart'; import 'package:p_tits_pas/models/user.dart'; import 'package:p_tits_pas/services/user_service.dart'; class AdminCreateDialog extends StatefulWidget { final AppUser? initialUser; const AdminCreateDialog({ super.key, this.initialUser, }); @override State createState() => _AdminCreateDialogState(); } class _AdminCreateDialogState extends State { final _formKey = GlobalKey(); final _nomController = TextEditingController(); final _prenomController = TextEditingController(); final _emailController = TextEditingController(); final _passwordController = TextEditingController(); final _telephoneController = TextEditingController(); bool _isSubmitting = false; bool _obscurePassword = true; bool get _isEditMode => widget.initialUser != null; @override void initState() { super.initState(); final user = widget.initialUser; if (user != null) { _nomController.text = user.nom ?? ''; _prenomController.text = user.prenom ?? ''; _emailController.text = user.email; _telephoneController.text = user.telephone ?? ''; // En édition, on ne préremplit jamais le mot de passe. _passwordController.clear(); } } @override void dispose() { _nomController.dispose(); _prenomController.dispose(); _emailController.dispose(); _passwordController.dispose(); _telephoneController.dispose(); super.dispose(); } String? _required(String? value, String field) { if (value == null || value.trim().isEmpty) { return '$field est requis'; } return null; } String? _validateEmail(String? value) { final base = _required(value, 'Email'); if (base != null) return base; final email = value!.trim(); final ok = RegExp(r'^[^@]+@[^@]+\.[^@]+$').hasMatch(email); if (!ok) return 'Format email invalide'; return null; } String? _validatePassword(String? value) { if (_isEditMode && (value == null || value.trim().isEmpty)) { return null; } final base = _required(value, 'Mot de passe'); if (base != null) return base; if (value!.trim().length < 6) return 'Minimum 6 caractères'; return null; } Future _submit() async { if (_isSubmitting) return; if (!_formKey.currentState!.validate()) return; setState(() { _isSubmitting = true; }); try { if (_isEditMode) { await UserService.updateAdmin( adminId: widget.initialUser!.id, nom: _nomController.text.trim(), prenom: _prenomController.text.trim(), email: _emailController.text.trim(), telephone: _telephoneController.text.trim(), password: _passwordController.text.trim().isEmpty ? null : _passwordController.text, ); } else { await UserService.createAdmin( nom: _nomController.text.trim(), prenom: _prenomController.text.trim(), email: _emailController.text.trim(), password: _passwordController.text, telephone: _telephoneController.text.trim(), ); } if (!mounted) return; ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text( _isEditMode ? 'Administrateur modifié avec succès.' : 'Administrateur créé avec succès.', ), ), ); Navigator.of(context).pop(true); } catch (e) { if (!mounted) return; ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text( e.toString().replaceFirst('Exception: ', ''), ), backgroundColor: Colors.red.shade700, ), ); } finally { if (!mounted) return; setState(() { _isSubmitting = false; }); } } Future _delete() async { if (!_isEditMode || _isSubmitting) return; final confirmed = await showDialog( context: context, builder: (ctx) { return AlertDialog( title: const Text('Confirmer la suppression'), content: Text( 'Supprimer ${widget.initialUser!.fullName.isEmpty ? widget.initialUser!.email : widget.initialUser!.fullName} ?', ), actions: [ TextButton( onPressed: () => Navigator.of(ctx).pop(false), child: const Text('Annuler'), ), FilledButton( onPressed: () => Navigator.of(ctx).pop(true), style: FilledButton.styleFrom(backgroundColor: Colors.red.shade700), child: const Text('Supprimer'), ), ], ); }, ); if (confirmed != true) return; setState(() { _isSubmitting = true; }); try { await UserService.deleteUser(widget.initialUser!.id); if (!mounted) return; ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Administrateur supprimé.')), ); Navigator.of(context).pop(true); } catch (e) { if (!mounted) return; ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(e.toString().replaceFirst('Exception: ', '')), backgroundColor: Colors.red.shade700, ), ); setState(() { _isSubmitting = false; }); } } @override Widget build(BuildContext context) { return AlertDialog( title: Row( children: [ Expanded( child: Text( _isEditMode ? 'Modifier un administrateur' : 'Créer un administrateur', ), ), if (_isEditMode) IconButton( icon: const Icon(Icons.close), tooltip: 'Fermer', onPressed: _isSubmitting ? null : () => Navigator.of(context).pop(false), ), ], ), content: SizedBox( width: 620, child: Form( key: _formKey, child: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, children: [ Row( children: [ Expanded(child: _buildNomField()), const SizedBox(width: 12), Expanded(child: _buildPrenomField()), ], ), const SizedBox(height: 12), _buildEmailField(), const SizedBox(height: 12), Row( children: [ Expanded(child: _buildPasswordField()), const SizedBox(width: 12), Expanded(child: _buildTelephoneField()), ], ), ], ), ), ), ), actions: [ if (_isEditMode) ...[ OutlinedButton( onPressed: _isSubmitting ? null : _delete, style: OutlinedButton.styleFrom(foregroundColor: Colors.red.shade700), child: const Text('Supprimer'), ), FilledButton.icon( onPressed: _isSubmitting ? null : _submit, icon: _isSubmitting ? const SizedBox( width: 16, height: 16, child: CircularProgressIndicator(strokeWidth: 2), ) : const Icon(Icons.edit), label: Text(_isSubmitting ? 'Modification...' : 'Modifier'), ), ] else ...[ OutlinedButton( onPressed: _isSubmitting ? null : () => Navigator.of(context).pop(false), child: const Text('Annuler'), ), FilledButton.icon( onPressed: _isSubmitting ? null : _submit, icon: _isSubmitting ? const SizedBox( width: 16, height: 16, child: CircularProgressIndicator(strokeWidth: 2), ) : const Icon(Icons.person_add_alt_1), label: Text(_isSubmitting ? 'Création...' : 'Créer'), ), ], ], ); } Widget _buildNomField() { return TextFormField( controller: _nomController, textCapitalization: TextCapitalization.words, decoration: const InputDecoration( labelText: 'Nom', border: OutlineInputBorder(), ), validator: (v) => _required(v, 'Nom'), ); } Widget _buildPrenomField() { return TextFormField( controller: _prenomController, textCapitalization: TextCapitalization.words, decoration: const InputDecoration( labelText: 'Prénom', border: OutlineInputBorder(), ), validator: (v) => _required(v, 'Prénom'), ); } Widget _buildEmailField() { return TextFormField( controller: _emailController, keyboardType: TextInputType.emailAddress, decoration: const InputDecoration( labelText: 'Email', border: OutlineInputBorder(), ), validator: _validateEmail, ); } Widget _buildPasswordField() { return TextFormField( controller: _passwordController, obscureText: _obscurePassword, enableSuggestions: false, autocorrect: false, autofillHints: _isEditMode ? const [] : const [AutofillHints.newPassword], decoration: InputDecoration( labelText: _isEditMode ? 'Nouveau mot de passe' : 'Mot de passe', border: const OutlineInputBorder(), suffixIcon: IconButton( onPressed: () { setState(() { _obscurePassword = !_obscurePassword; }); }, icon: Icon( _obscurePassword ? Icons.visibility_off : Icons.visibility, ), ), ), validator: _validatePassword, ); } Widget _buildTelephoneField() { return TextFormField( controller: _telephoneController, keyboardType: TextInputType.phone, decoration: const InputDecoration( labelText: 'Téléphone', border: OutlineInputBorder(), ), validator: (v) => _required(v, 'Téléphone'), ); } }