279 lines
9.7 KiB
Dart
279 lines
9.7 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:p_tits_pas/services/user_service.dart';
|
|
import 'package:p_tits_pas/widgets/admin/base_user_management.dart';
|
|
|
|
class AssistanteMaternelleManagementWidget extends StatelessWidget {
|
|
const AssistanteMaternelleManagementWidget({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return BaseUserManagementWidget(
|
|
config: UserDisplayConfig(
|
|
title: 'Assistantes Maternelles',
|
|
role: 'assistante_maternelle',
|
|
defaultIcon: Icons.face,
|
|
filterFields: [
|
|
FilterField(
|
|
label: 'Rechercher',
|
|
hint: 'Nom ou email',
|
|
type: FilterType.text,
|
|
filter: (user, query) {
|
|
final fullName = '${user['prenom'] ?? ''} ${user['nom'] ?? ''}'.toLowerCase();
|
|
final email = (user['email'] ?? '').toLowerCase();
|
|
return fullName.contains(query.toLowerCase()) ||
|
|
email.contains(query.toLowerCase());
|
|
},
|
|
),
|
|
FilterField(
|
|
label: 'Zone géographique',
|
|
hint: 'Ville ou département',
|
|
type: FilterType.text,
|
|
filter: (user, query) {
|
|
final zone = (user['zone'] ?? user['ville'] ?? user['code_postal'] ?? '').toLowerCase();
|
|
return zone.contains(query.toLowerCase());
|
|
},
|
|
),
|
|
FilterField(
|
|
label: 'Capacité minimum',
|
|
hint: 'Nombre d\'enfants',
|
|
type: FilterType.number,
|
|
filter: (user, query) {
|
|
final capacite = int.tryParse(user['capacite']?.toString() ?? '0') ?? 0;
|
|
final minCapacite = int.tryParse(query) ?? 0;
|
|
return capacite >= minCapacite;
|
|
},
|
|
),
|
|
FilterField(
|
|
label: 'Statut',
|
|
hint: 'Tous',
|
|
type: FilterType.dropdown,
|
|
options: ['actif', 'en attente', 'inactif'],
|
|
filter: (user, status) {
|
|
if (status.isEmpty) return true;
|
|
return user['statut']?.toString().toLowerCase() == status.toLowerCase();
|
|
},
|
|
),
|
|
],
|
|
actions: [
|
|
UserAction(
|
|
icon: Icons.edit,
|
|
color: Colors.orange,
|
|
tooltip: 'Modifier',
|
|
onPressed: _editAssistante,
|
|
),
|
|
UserAction(
|
|
icon: Icons.delete,
|
|
color: Colors.red,
|
|
tooltip: 'Supprimer',
|
|
onPressed: _deleteAssistante,
|
|
),
|
|
UserAction(
|
|
icon: Icons.location_on,
|
|
color: Colors.green,
|
|
tooltip: 'Voir zone',
|
|
onPressed: _showZone,
|
|
),
|
|
],
|
|
getSubtitle: (user) {
|
|
final email = user['email'] ?? '';
|
|
final numeroAgrement = user['numeroAgrement'] ?? user['agrement'] ?? 'N/A';
|
|
final zone = user['code_postal'] ?? user['ville'] ?? 'Non spécifiée';
|
|
final capacite = user['capacite'] ?? user['capaciteAccueil'] ?? 'N/A';
|
|
return '$email\nN° Agrément: $numeroAgrement\nZone: $zone | Capacité: $capacite';
|
|
},
|
|
getDisplayName: (user) => '${user['prenom'] ?? ''} ${user['nom'] ?? ''}',
|
|
),
|
|
);
|
|
}
|
|
|
|
static Future<void> _editAssistante(BuildContext context, Map<String, dynamic> assistante) async {
|
|
// TODO: Implémenter l'édition
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
const SnackBar(
|
|
content: Text('Fonctionnalité de modification à implémenter'),
|
|
backgroundColor: Colors.orange,
|
|
),
|
|
);
|
|
}
|
|
|
|
static Future<void> _deleteAssistante(BuildContext context, Map<String, dynamic> assistante) async {
|
|
final confirmed = await showDialog<bool>(
|
|
context: context,
|
|
builder: (context) => AlertDialog(
|
|
title: const Text('Confirmer la suppression'),
|
|
content: Text(
|
|
'Êtes-vous sûr de vouloir supprimer le compte de ${assistante['firstName']} ${assistante['lastName']} ?\n\n'
|
|
'Cette action supprimera également tous les contrats et données associés.'
|
|
),
|
|
actions: [
|
|
TextButton(
|
|
onPressed: () => Navigator.of(context).pop(false),
|
|
child: const Text('Annuler'),
|
|
),
|
|
TextButton(
|
|
onPressed: () => Navigator.of(context).pop(true),
|
|
style: TextButton.styleFrom(foregroundColor: Colors.red),
|
|
child: const Text('Supprimer'),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
|
|
if (confirmed == true) {
|
|
try {
|
|
final userService = UserService();
|
|
final success = await userService.deleteUser(assistante['id']);
|
|
|
|
if (success && context.mounted) {
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
SnackBar(
|
|
content: Text('${assistante['firstName']} ${assistante['lastName']} supprimé avec succès'),
|
|
backgroundColor: Colors.green,
|
|
),
|
|
);
|
|
// Le widget se rechargera automatiquement via le système de state
|
|
} else {
|
|
throw Exception('Erreur lors de la suppression');
|
|
}
|
|
} catch (e) {
|
|
if (context.mounted) {
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
SnackBar(
|
|
content: Text('Erreur: ${e.toString()}'),
|
|
backgroundColor: Colors.red,
|
|
),
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static Future<void> _showZone(BuildContext context, Map<String, dynamic> assistante) async {
|
|
final zone = assistante['zone'] ?? assistante['ville'] ?? 'Non spécifiée';
|
|
final adresse = assistante['adresse'] ?? assistante['address'] ?? '';
|
|
final codePostal = assistante['codePostal'] ?? assistante['zipCode'] ?? '';
|
|
|
|
showDialog(
|
|
context: context,
|
|
builder: (context) => AlertDialog(
|
|
title: Text('Zone d\'intervention - ${assistante['firstName']} ${assistante['lastName']}'),
|
|
content: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
if (zone.isNotEmpty) Text('Zone: $zone', style: const TextStyle(fontWeight: FontWeight.bold)),
|
|
const SizedBox(height: 8),
|
|
if (adresse.isNotEmpty) Text('Adresse: $adresse'),
|
|
if (codePostal.isNotEmpty) Text('Code postal: $codePostal'),
|
|
const SizedBox(height: 16),
|
|
Text('Capacité d\'accueil: ${assistante['capacite'] ?? assistante['capaciteAccueil'] ?? 'N/A'} enfants'),
|
|
Text('N° Agrément: ${assistante['numeroAgrement'] ?? assistante['agrement'] ?? 'N/A'}'),
|
|
],
|
|
),
|
|
actions: [
|
|
TextButton(
|
|
onPressed: () => Navigator.of(context).pop(),
|
|
child: const Text('Fermer'),
|
|
),
|
|
TextButton(
|
|
onPressed: () {
|
|
// TODO: Ouvrir dans Maps
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
const SnackBar(
|
|
content: Text('Intégration Maps à implémenter'),
|
|
),
|
|
);
|
|
},
|
|
child: const Text('Voir sur la carte'),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
// return Padding(
|
|
// padding: const EdgeInsets.all(16),
|
|
// child: Column(
|
|
// crossAxisAlignment: CrossAxisAlignment.start,
|
|
// children: [
|
|
// // 🔎 Zone de filtre
|
|
// _buildFilterSection(),
|
|
|
|
// const SizedBox(height: 16),
|
|
|
|
// // 📋 Liste des assistantes
|
|
// ListView.builder(
|
|
// shrinkWrap: true,
|
|
// physics: const NeverScrollableScrollPhysics(),
|
|
// itemCount: assistantes.length,
|
|
// itemBuilder: (context, index) {
|
|
// final assistante = assistantes[index];
|
|
// return Card(
|
|
// margin: const EdgeInsets.symmetric(vertical: 8),
|
|
// child: ListTile(
|
|
// leading: const Icon(Icons.face),
|
|
// title: Text(assistante['nom'].toString()),
|
|
// subtitle: Text(
|
|
// "N° Agrément : ${assistante['numeroAgrement']}\nZone : ${assistante['zone']} | Capacité : ${assistante['capacite']}"),
|
|
// trailing: Row(
|
|
// mainAxisSize: MainAxisSize.min,
|
|
// children: [
|
|
// IconButton(
|
|
// icon: const Icon(Icons.edit),
|
|
// onPressed: () {
|
|
// // TODO: Ajouter modification
|
|
// },
|
|
// ),
|
|
// IconButton(
|
|
// icon: const Icon(Icons.delete),
|
|
// onPressed: () {
|
|
// // TODO: Ajouter suppression
|
|
// },
|
|
// ),
|
|
// ],
|
|
// ),
|
|
// ),
|
|
// );
|
|
// },
|
|
// ),
|
|
// ],
|
|
// ),
|
|
// );
|
|
// }
|
|
|
|
// Widget _buildFilterSection() {
|
|
// return Wrap(
|
|
// spacing: 16,
|
|
// runSpacing: 8,
|
|
// children: [
|
|
// SizedBox(
|
|
// width: 200,
|
|
// child: TextField(
|
|
// decoration: const InputDecoration(
|
|
// labelText: "Zone géographique",
|
|
// border: OutlineInputBorder(),
|
|
// ),
|
|
// onChanged: (value) {
|
|
// // TODO: Ajouter logique de filtrage par zone
|
|
// },
|
|
// ),
|
|
// ),
|
|
// SizedBox(
|
|
// width: 200,
|
|
// child: TextField(
|
|
// decoration: const InputDecoration(
|
|
// labelText: "Capacité minimum",
|
|
// border: OutlineInputBorder(),
|
|
// ),
|
|
// keyboardType: TextInputType.number,
|
|
// onChanged: (value) {
|
|
// // TODO: Ajouter logique de filtrage par capacité
|
|
// },
|
|
// ),
|
|
// ),
|
|
// ],
|
|
// );
|
|
// }
|
|
// }
|