Restructuration majeure du projet: migration de flutt vers app, ajout de l'API et mise à jour du site web
This commit is contained in:
@@ -0,0 +1,141 @@
|
||||
# Documentation des Widgets Amicale
|
||||
|
||||
Cette documentation explique comment utiliser les widgets `AmicaleRowWidget` et `AmicaleTableWidget` pour afficher et gérer les données des amicales dans l'application.
|
||||
|
||||
## AmicaleRowWidget
|
||||
|
||||
Le widget `AmicaleRowWidget` représente une ligne dans un tableau d'amicales. Il affiche les informations d'une amicale avec les colonnes suivantes :
|
||||
|
||||
- ID
|
||||
- Nom
|
||||
- Code Postal
|
||||
- Région
|
||||
- Actions (boutons selon les droits de l'utilisateur)
|
||||
|
||||
### Propriétés
|
||||
|
||||
| Propriété | Type | Description |
|
||||
| ------------- | --------------- | ---------------------------------------------------------------------------------- |
|
||||
| `amicale` | `AmicaleModel` | **Obligatoire**. L'objet amicale à afficher. |
|
||||
| `onEdit` | `VoidCallback?` | Fonction appelée lorsque l'utilisateur clique sur le bouton d'édition. |
|
||||
| `onDelete` | `VoidCallback?` | Fonction appelée lorsque l'utilisateur clique sur le bouton de suppression. |
|
||||
| `isAlternate` | `bool` | Indique si la ligne doit avoir une couleur de fond alternée. Par défaut à `false`. |
|
||||
|
||||
### Gestion des droits d'accès
|
||||
|
||||
Le widget gère automatiquement l'affichage des boutons d'action en fonction du rôle de l'utilisateur :
|
||||
|
||||
- Le bouton d'édition (crayon) est visible pour tous les utilisateurs avec un rôle > 1
|
||||
- Le bouton de suppression (corbeille) est visible uniquement pour les utilisateurs avec un rôle > 2
|
||||
|
||||
### Exemple d'utilisation
|
||||
|
||||
```dart
|
||||
AmicaleRowWidget(
|
||||
amicale: amicale,
|
||||
isAlternate: index % 2 == 1, // Alterner les couleurs
|
||||
onEdit: () {
|
||||
// Code pour gérer l'édition
|
||||
},
|
||||
onDelete: () {
|
||||
// Code pour gérer la suppression
|
||||
},
|
||||
)
|
||||
```
|
||||
|
||||
## AmicaleTableWidget
|
||||
|
||||
Le widget `AmicaleTableWidget` affiche un tableau complet d'amicales avec un en-tête et des lignes. Il utilise le widget `AmicaleRowWidget` pour afficher chaque ligne.
|
||||
|
||||
### Propriétés
|
||||
|
||||
| Propriété | Type | Description |
|
||||
| -------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `amicales` | `List<AmicaleModel>` | **Obligatoire**. La liste des amicales à afficher. |
|
||||
| `onEdit` | `Function(AmicaleModel)?` | Fonction appelée lorsque l'utilisateur clique sur le bouton d'édition d'une amicale. |
|
||||
| `onDelete` | `Function(AmicaleModel)?` | Fonction appelée lorsque l'utilisateur clique sur le bouton de suppression d'une amicale. |
|
||||
| `isLoading` | `bool` | Indique si les données sont en cours de chargement. Affiche un indicateur de chargement si `true`. Par défaut à `false`. |
|
||||
| `emptyMessage` | `String?` | Message à afficher lorsque la liste des amicales est vide. |
|
||||
|
||||
### États du tableau
|
||||
|
||||
Le widget gère automatiquement différents états :
|
||||
|
||||
1. **Chargement** : Affiche un indicateur de chargement circulaire lorsque `isLoading` est `true`.
|
||||
2. **Liste vide** : Affiche un message lorsque la liste des amicales est vide.
|
||||
3. **Affichage normal** : Affiche la liste des amicales avec des lignes alternées.
|
||||
|
||||
### Exemple d'utilisation
|
||||
|
||||
```dart
|
||||
AmicaleTableWidget(
|
||||
amicales: _amicales,
|
||||
isLoading: _isLoading,
|
||||
onEdit: (amicale) {
|
||||
// Code pour gérer l'édition de l'amicale
|
||||
},
|
||||
onDelete: (amicale) {
|
||||
// Code pour gérer la suppression de l'amicale
|
||||
},
|
||||
emptyMessage: 'Aucune amicale trouvée. Veuillez en créer une nouvelle.',
|
||||
)
|
||||
```
|
||||
|
||||
## Intégration avec AmicaleRepository
|
||||
|
||||
Pour utiliser ces widgets avec le repository des amicales, vous devez :
|
||||
|
||||
1. Récupérer les amicales depuis le repository :
|
||||
|
||||
```dart
|
||||
final amicaleRepository = Provider.of<AmicaleRepository>(context, listen: false);
|
||||
final amicales = amicaleRepository.getAllAmicales();
|
||||
```
|
||||
|
||||
2. Gérer les actions d'édition et de suppression :
|
||||
|
||||
```dart
|
||||
void _handleEdit(AmicaleModel amicale) {
|
||||
// Naviguer vers la page d'édition ou afficher une boîte de dialogue
|
||||
}
|
||||
|
||||
Future<void> _handleDelete(AmicaleModel amicale) async {
|
||||
// Afficher une confirmation puis supprimer
|
||||
final amicaleRepository = Provider.of<AmicaleRepository>(context, listen: false);
|
||||
await amicaleRepository.deleteAmicale(amicale.id);
|
||||
|
||||
// Recharger la liste
|
||||
setState(() {
|
||||
_amicales = amicaleRepository.getAllAmicales();
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
## Exemple complet
|
||||
|
||||
Un exemple complet d'utilisation est disponible dans le fichier `app/lib/presentation/widgets/examples/amicale_table_example.dart`.
|
||||
|
||||
## Personnalisation
|
||||
|
||||
### Styles
|
||||
|
||||
Les widgets utilisent les styles du thème de l'application pour la cohérence visuelle. Vous pouvez personnaliser l'apparence en modifiant le thème ou en surchargeant les styles dans votre implémentation.
|
||||
|
||||
### Colonnes et flexibilité
|
||||
|
||||
Les colonnes du tableau ont des valeurs de flex prédéfinies pour une mise en page optimale :
|
||||
|
||||
- ID : flex 1
|
||||
- Nom : flex 4
|
||||
- Code Postal : flex 2
|
||||
- Région : flex 3
|
||||
- Actions : flex 2
|
||||
|
||||
Vous pouvez ajuster ces valeurs en modifiant le code source si nécessaire.
|
||||
|
||||
## Bonnes pratiques
|
||||
|
||||
1. **Gestion des erreurs** : Ajoutez toujours une gestion des erreurs lors de l'interaction avec le repository.
|
||||
2. **Confirmation des actions** : Demandez toujours une confirmation avant de supprimer une amicale.
|
||||
3. **Actualisation des données** : Prévoyez un moyen de rafraîchir les données (bouton ou pull-to-refresh).
|
||||
4. **Pagination** : Pour les grandes listes, envisagez d'implémenter une pagination.
|
||||
204
app/lib/presentation/widgets/docs/entite_form_documentation.md
Normal file
204
app/lib/presentation/widgets/docs/entite_form_documentation.md
Normal file
@@ -0,0 +1,204 @@
|
||||
# Documentation du Widget EntiteForm
|
||||
|
||||
Cette documentation décrit le widget `EntiteForm` créé pour la création et la modification des entités (amicales) dans l'application GeoSector.
|
||||
|
||||
## Description
|
||||
|
||||
Le widget `EntiteForm` est un formulaire complet permettant de créer ou modifier une entité (amicale). Il gère l'affichage de tous les champs nécessaires, la validation des données et les restrictions d'accès basées sur le rôle de l'utilisateur.
|
||||
|
||||
## Propriétés
|
||||
|
||||
- `amicale` (AmicaleModel?, optionnel) : Le modèle d'amicale à modifier. Si null, le formulaire sera en mode création.
|
||||
- `onSubmit` (Function(AmicaleModel)?, optionnel) : Callback appelé lorsque le formulaire est soumis avec succès.
|
||||
- `readOnly` (bool, défaut: false) : Si true, tous les champs du formulaire seront en lecture seule.
|
||||
|
||||
## Champs du formulaire
|
||||
|
||||
Le formulaire inclut les champs suivants :
|
||||
|
||||
### Informations générales
|
||||
|
||||
- **Nom** : Nom de l'amicale (obligatoire)
|
||||
|
||||
### Adresse
|
||||
|
||||
- **Adresse ligne 1** : Première ligne d'adresse
|
||||
- **Adresse ligne 2** : Seconde ligne d'adresse (optionnelle)
|
||||
- **Code Postal** : Code postal (validation pour 5 chiffres)
|
||||
- **Ville** : Nom de la ville
|
||||
- **Région** : Sélection de la région via un dropdown
|
||||
|
||||
### Contact
|
||||
|
||||
- **Téléphone fixe** : Numéro de téléphone fixe (validation pour 10 chiffres)
|
||||
- **Téléphone mobile** : Numéro de téléphone mobile (validation pour 10 chiffres)
|
||||
- **Email** : Adresse email (obligatoire, avec validation de format)
|
||||
|
||||
### Informations avancées (visibles uniquement pour les administrateurs ou si déjà remplies)
|
||||
|
||||
- **GPS Latitude** : Coordonnée GPS latitude
|
||||
- **GPS Longitude** : Coordonnée GPS longitude
|
||||
- **Stripe ID** : Identifiant Stripe pour les paiements
|
||||
|
||||
### Options
|
||||
|
||||
- **Mode démo** : Indique si l'amicale est en mode démo
|
||||
- **Copie des mails reçus** : Indique si l'amicale reçoit une copie des emails
|
||||
- **Accepte les SMS** : Indique si l'amicale accepte les SMS
|
||||
- **Actif** : Indique si l'amicale est active
|
||||
|
||||
## Restrictions d'accès
|
||||
|
||||
Certains champs sont soumis à des restrictions d'accès basées sur le rôle de l'utilisateur :
|
||||
|
||||
- Les champs suivants sont en lecture seule pour les utilisateurs avec un rôle ≤ 2 :
|
||||
- fkRegion/libRegion
|
||||
- gpsLat
|
||||
- gpsLng
|
||||
- stripeId
|
||||
- chkDemo
|
||||
- chkActive
|
||||
|
||||
## Exemple d'utilisation
|
||||
|
||||
Un exemple complet d'utilisation est disponible dans le fichier `app/lib/presentation/widgets/examples/entite_form_example.dart`.
|
||||
|
||||
### Utilisation simple
|
||||
|
||||
```dart
|
||||
// Création d'une nouvelle amicale
|
||||
EntiteForm(
|
||||
onSubmit: (amicale) {
|
||||
// Gérer la soumission
|
||||
print('Nouvelle amicale: ${amicale.name}');
|
||||
},
|
||||
)
|
||||
|
||||
// Modification d'une amicale existante
|
||||
EntiteForm(
|
||||
amicale: amicaleExistante,
|
||||
onSubmit: (amicale) {
|
||||
// Gérer la soumission
|
||||
print('Amicale modifiée: ${amicale.name}');
|
||||
},
|
||||
)
|
||||
|
||||
// Affichage en lecture seule
|
||||
EntiteForm(
|
||||
amicale: amicaleExistante,
|
||||
readOnly: true,
|
||||
)
|
||||
```
|
||||
|
||||
### Utilisation avec gestion d'état
|
||||
|
||||
```dart
|
||||
class _MyWidgetState extends State<MyWidget> {
|
||||
AmicaleModel? _amicale;
|
||||
bool _isLoading = true;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_loadAmicale();
|
||||
}
|
||||
|
||||
Future<void> _loadAmicale() async {
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
});
|
||||
|
||||
try {
|
||||
if (widget.amicaleId != null) {
|
||||
// Récupérer l'amicale depuis le repository
|
||||
final amicaleRepository = Provider.of<AmicaleRepository>(context, listen: false);
|
||||
final amicale = amicaleRepository.getAmicaleById(widget.amicaleId!);
|
||||
|
||||
setState(() {
|
||||
_amicale = amicale;
|
||||
_isLoading = false;
|
||||
});
|
||||
} else {
|
||||
// Création d'une nouvelle amicale
|
||||
setState(() {
|
||||
_amicale = null;
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint('Erreur lors du chargement de l\'amicale: $e');
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void _handleSubmit(AmicaleModel amicale) async {
|
||||
try {
|
||||
final amicaleRepository = Provider.of<AmicaleRepository>(context, listen: false);
|
||||
|
||||
// Sauvegarder l'amicale
|
||||
final savedAmicale = await amicaleRepository.saveAmicale(amicale);
|
||||
|
||||
// Afficher un message de confirmation
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Amicale ${savedAmicale.name} sauvegardée avec succès'),
|
||||
backgroundColor: Colors.green,
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
debugPrint('Erreur lors de la sauvegarde de l\'amicale: $e');
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Erreur lors de la sauvegarde: $e'),
|
||||
backgroundColor: Colors.red,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return _isLoading
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: EntiteForm(
|
||||
amicale: _amicale,
|
||||
onSubmit: _handleSubmit,
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Intégration avec le système de rôles
|
||||
|
||||
Le widget utilise le `UserRepository` pour déterminer le rôle de l'utilisateur actuel et appliquer les restrictions d'accès en conséquence. Assurez-vous que le `UserRepository` est disponible dans l'arbre des widgets via un `Provider`.
|
||||
|
||||
```dart
|
||||
// Dans le widget parent
|
||||
return MultiProvider(
|
||||
providers: [
|
||||
Provider<UserRepository>(
|
||||
create: (context) => userRepository,
|
||||
),
|
||||
Provider<AmicaleRepository>(
|
||||
create: (context) => amicaleRepository,
|
||||
),
|
||||
],
|
||||
child: MyWidget(),
|
||||
);
|
||||
```
|
||||
|
||||
## Personnalisation
|
||||
|
||||
Le widget utilise le thème de l'application pour le style. Vous pouvez personnaliser l'apparence en modifiant le thème ou en étendant le widget pour créer votre propre version personnalisée.
|
||||
|
||||
## Validation des données
|
||||
|
||||
Le formulaire inclut une validation pour les champs suivants :
|
||||
|
||||
- **Nom** : Ne peut pas être vide
|
||||
- **Code Postal** : Doit contenir 5 chiffres s'il est rempli
|
||||
- **Téléphone fixe** : Doit contenir 10 chiffres s'il est rempli
|
||||
- **Téléphone mobile** : Doit contenir 10 chiffres s'il est rempli
|
||||
- **Email** : Ne peut pas être vide et doit contenir un '@' et un '.'
|
||||
@@ -0,0 +1,160 @@
|
||||
# Documentation du Widget EntiteForm avec RegionRepository
|
||||
|
||||
Cette documentation explique comment utiliser le widget `EntiteForm` avec le `RegionRepository` pour afficher et gérer les régions dans le formulaire d'entité.
|
||||
|
||||
## Intégration du RegionRepository
|
||||
|
||||
Le widget `EntiteForm` est conçu pour fonctionner avec le `RegionRepository` afin de récupérer la liste des régions disponibles pour le champ de sélection de région. Voici comment l'intégrer :
|
||||
|
||||
### 1. Initialisation du RegionRepository
|
||||
|
||||
Le `RegionRepository` doit être initialisé et fourni au widget `EntiteForm` via un `Provider`. Voici un exemple d'initialisation :
|
||||
|
||||
```dart
|
||||
final regionRepository = RegionRepository();
|
||||
await regionRepository.init();
|
||||
```
|
||||
|
||||
### 2. Fournir le RegionRepository via Provider
|
||||
|
||||
Pour que le widget `EntiteForm` puisse accéder au `RegionRepository`, vous devez le fournir via un `Provider` :
|
||||
|
||||
```dart
|
||||
MultiProvider(
|
||||
providers: [
|
||||
ChangeNotifierProvider<RegionRepository>.value(value: regionRepository),
|
||||
// Autres providers si nécessaire
|
||||
],
|
||||
child: EntiteForm(
|
||||
amicale: amicale,
|
||||
onSubmit: handleSubmit,
|
||||
readOnly: false,
|
||||
),
|
||||
)
|
||||
```
|
||||
|
||||
### 3. Mise à jour des régions depuis l'API
|
||||
|
||||
Lorsque l'API renvoie les données des régions dans la réponse de login, vous devez les mettre à jour dans le `RegionRepository` :
|
||||
|
||||
```dart
|
||||
// Dans le service qui gère la connexion
|
||||
void handleLoginResponse(Map<String, dynamic> response) {
|
||||
// Autres traitements...
|
||||
|
||||
// Mise à jour des régions si présentes dans la réponse
|
||||
if (response.containsKey('regions') && response['regions'] is List) {
|
||||
final regionRepository = Provider.of<RegionRepository>(context, listen: false);
|
||||
regionRepository.updateRegionsFromApi(response['regions']);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Fonctionnement avec les restrictions d'accès
|
||||
|
||||
Le widget `EntiteForm` gère automatiquement les restrictions d'accès basées sur le rôle de l'utilisateur :
|
||||
|
||||
- Pour les utilisateurs avec un rôle ≤ 2, le champ de sélection de région est en lecture seule
|
||||
- Pour les utilisateurs avec un rôle > 2, le champ de sélection de région est modifiable
|
||||
|
||||
## Filtrage des régions selon le code postal
|
||||
|
||||
Le `RegionRepository` offre une méthode `getRegionByPostalCode` qui permet de filtrer les régions en fonction du code postal :
|
||||
|
||||
```dart
|
||||
// Récupérer la région correspondant au code postal
|
||||
final codePostal = '75001';
|
||||
final region = regionRepository.getRegionByPostalCode(codePostal);
|
||||
if (region != null) {
|
||||
// Utiliser la région trouvée
|
||||
print('Région trouvée : ${region.libelle}');
|
||||
}
|
||||
```
|
||||
|
||||
Cette fonctionnalité est particulièrement utile pour pré-remplir le champ de région lorsque l'utilisateur entre un code postal.
|
||||
|
||||
## Exemple complet d'utilisation
|
||||
|
||||
Un exemple complet d'utilisation est disponible dans le fichier `app/lib/presentation/widgets/examples/entite_form_with_regions_example.dart`.
|
||||
|
||||
### Exemple simplifié
|
||||
|
||||
```dart
|
||||
class MyWidget extends StatefulWidget {
|
||||
@override
|
||||
State<MyWidget> createState() => _MyWidgetState();
|
||||
}
|
||||
|
||||
class _MyWidgetState extends State<MyWidget> {
|
||||
late RegionRepository _regionRepository;
|
||||
AmicaleModel? _amicale;
|
||||
bool _isLoading = true;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_regionRepository = RegionRepository();
|
||||
_initData();
|
||||
}
|
||||
|
||||
Future<void> _initData() async {
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
});
|
||||
|
||||
try {
|
||||
// Initialiser le repository des régions
|
||||
await _regionRepository.init();
|
||||
|
||||
// Charger l'amicale si nécessaire
|
||||
// ...
|
||||
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
} catch (e) {
|
||||
debugPrint('Erreur lors de l\'initialisation: $e');
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void _handleSubmit(AmicaleModel amicale) {
|
||||
// Traiter la soumission du formulaire
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MultiProvider(
|
||||
providers: [
|
||||
ChangeNotifierProvider<RegionRepository>.value(value: _regionRepository),
|
||||
],
|
||||
child: Scaffold(
|
||||
appBar: AppBar(title: Text('Formulaire d\'entité')),
|
||||
body: _isLoading
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: EntiteForm(
|
||||
amicale: _amicale,
|
||||
onSubmit: _handleSubmit,
|
||||
readOnly: false,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Mise à jour du code postal et de la région
|
||||
|
||||
Pour mettre à jour automatiquement la région lorsque l'utilisateur change le code postal, vous pouvez étendre le widget `EntiteForm` ou créer un wrapper qui écoute les changements du champ de code postal et met à jour la région en conséquence.
|
||||
|
||||
## Remarques importantes
|
||||
|
||||
1. Assurez-vous que le `RegionRepository` est initialisé avant d'afficher le formulaire.
|
||||
2. Le widget `EntiteForm` s'adapte automatiquement au rôle de l'utilisateur pour les restrictions d'accès.
|
||||
3. Les régions sont filtrées en fonction du code postal de l'amicale pour les utilisateurs avec un rôle ≤ 2.
|
||||
4. Pour les utilisateurs avec un rôle > 2, toutes les régions sont disponibles dans le dropdown.
|
||||
@@ -0,0 +1,207 @@
|
||||
# Documentation des Widgets Membre
|
||||
|
||||
Cette documentation décrit les widgets créés pour afficher et gérer les données des membres dans l'application GeoSector.
|
||||
|
||||
## Widgets disponibles
|
||||
|
||||
### 1. MembreRowWidget
|
||||
|
||||
Widget qui représente une ligne individuelle dans un tableau de membres. Il affiche les informations d'un membre et des boutons d'action pour l'édition et la suppression.
|
||||
|
||||
#### Propriétés
|
||||
|
||||
- `membre` (MembreModel, requis) : Le modèle de membre à afficher
|
||||
- `onEdit` (Function()?, optionnel) : Callback appelé lorsque le bouton d'édition est pressé
|
||||
- `onDelete` (Function()?, optionnel) : Callback appelé lorsque le bouton de suppression est pressé
|
||||
|
||||
#### Colonnes affichées
|
||||
|
||||
- ID : Identifiant unique du membre
|
||||
- Prénom (firstName) : Prénom du membre
|
||||
- Nom (name) : Nom de famille du membre
|
||||
- Secteur (sectName) : Nom du secteur auquel le membre est associé
|
||||
- Rôle (fkRole) : Rôle du membre (affiché sous forme de texte : User, Admin, Super)
|
||||
- Actions : Boutons d'édition et de suppression
|
||||
|
||||
### 2. MembreTableWidget
|
||||
|
||||
Widget qui affiche un tableau complet de membres avec en-tête et lignes. Il utilise le widget `MembreRowWidget` pour afficher chaque ligne.
|
||||
|
||||
#### Propriétés
|
||||
|
||||
- `membres` (List<MembreModel>, requis) : La liste des membres à afficher
|
||||
- `onEdit` (Function(MembreModel)?, optionnel) : Callback appelé lorsque le bouton d'édition est pressé pour un membre
|
||||
- `onDelete` (Function(MembreModel)?, optionnel) : Callback appelé lorsque le bouton de suppression est pressé pour un membre
|
||||
- `showHeader` (bool, défaut: true) : Indique si l'en-tête du tableau doit être affiché
|
||||
- `height` (double?, optionnel) : Hauteur du tableau (null pour prendre toute la hauteur disponible)
|
||||
- `padding` (EdgeInsetsGeometry?, optionnel) : Padding du tableau
|
||||
|
||||
## Exemple d'utilisation
|
||||
|
||||
Un exemple complet d'utilisation est disponible dans le fichier `app/lib/presentation/widgets/examples/membre_table_example.dart`.
|
||||
|
||||
### Utilisation simple
|
||||
|
||||
```dart
|
||||
// S'assurer que la boîte Hive est ouverte
|
||||
if (!Hive.isBoxOpen(AppKeys.membresBoxName)) {
|
||||
await Hive.openBox<MembreModel>(AppKeys.membresBoxName);
|
||||
}
|
||||
|
||||
// Récupérer les membres depuis la boîte Hive
|
||||
final membresBox = Hive.box<MembreModel>(AppKeys.membresBoxName);
|
||||
final membres = membresBox.values.toList();
|
||||
|
||||
// Afficher le tableau
|
||||
return MembreTableWidget(
|
||||
membres: membres,
|
||||
onEdit: (membre) {
|
||||
// Gérer l'édition
|
||||
},
|
||||
onDelete: (membre) {
|
||||
// Gérer la suppression
|
||||
},
|
||||
);
|
||||
```
|
||||
|
||||
### Utilisation avec gestion d'état
|
||||
|
||||
```dart
|
||||
class _MyWidgetState extends State<MyWidget> {
|
||||
List<MembreModel> _membres = [];
|
||||
bool _isLoading = true;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_loadMembres();
|
||||
}
|
||||
|
||||
Future<void> _loadMembres() async {
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
});
|
||||
|
||||
try {
|
||||
// S'assurer que la boîte Hive est ouverte
|
||||
if (!Hive.isBoxOpen(AppKeys.membresBoxName)) {
|
||||
await Hive.openBox<MembreModel>(AppKeys.membresBoxName);
|
||||
}
|
||||
|
||||
// Récupérer les membres depuis la boîte Hive
|
||||
final membresBox = Hive.box<MembreModel>(AppKeys.membresBoxName);
|
||||
final membres = membresBox.values.toList();
|
||||
|
||||
setState(() {
|
||||
_membres = membres;
|
||||
_isLoading = false;
|
||||
});
|
||||
} catch (e) {
|
||||
debugPrint('Erreur lors du chargement des membres: $e');
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return _isLoading
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: MembreTableWidget(
|
||||
membres: _membres,
|
||||
onEdit: _handleEdit,
|
||||
onDelete: _handleDelete,
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Gestion des événements
|
||||
|
||||
### Édition d'un membre
|
||||
|
||||
```dart
|
||||
void _handleEdit(MembreModel membre) {
|
||||
// Exemple de gestion de l'événement d'édition
|
||||
debugPrint('Édition du membre: ${membre.firstName} ${membre.name} (ID: ${membre.id})');
|
||||
|
||||
// Ici, vous pourriez ouvrir une boîte de dialogue ou naviguer vers une page d'édition
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: const Text('Édition de membre'),
|
||||
content: Text('Vous avez demandé à éditer le membre ${membre.firstName} ${membre.name}'),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: const Text('Fermer'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Suppression d'un membre
|
||||
|
||||
```dart
|
||||
void _handleDelete(MembreModel membre) {
|
||||
// Exemple de gestion de l'événement de suppression
|
||||
debugPrint('Suppression du membre: ${membre.firstName} ${membre.name} (ID: ${membre.id})');
|
||||
|
||||
// Demander confirmation avant de supprimer
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: const Text('Confirmation de suppression'),
|
||||
content: Text('Êtes-vous sûr de vouloir supprimer le membre ${membre.firstName} ${membre.name} ?'),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: const Text('Annuler'),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
// Fermer la boîte de dialogue
|
||||
Navigator.of(context).pop();
|
||||
|
||||
try {
|
||||
// Supprimer le membre de la boîte Hive
|
||||
final membresBox = Hive.box<MembreModel>(AppKeys.membresBoxName);
|
||||
await membresBox.delete(membre.id);
|
||||
|
||||
// Mettre à jour l'état
|
||||
setState(() {
|
||||
_membres = _membres.where((m) => m.id != membre.id).toList();
|
||||
});
|
||||
|
||||
// Afficher un message de confirmation
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Membre ${membre.firstName} ${membre.name} supprimé'),
|
||||
backgroundColor: Colors.green,
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
debugPrint('Erreur lors de la suppression du membre: $e');
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Erreur lors de la suppression: $e'),
|
||||
backgroundColor: Colors.red,
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
child: const Text('Supprimer'),
|
||||
style: TextButton.styleFrom(foregroundColor: Colors.red),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Personnalisation
|
||||
|
||||
Les widgets utilisent le thème de l'application pour le style. Vous pouvez personnaliser l'apparence en modifiant le thème ou en étendant les widgets pour créer vos propres versions personnalisées.
|
||||
Reference in New Issue
Block a user