Compare commits
No commits in common. "f74b14c2039a5980b2e55cec360702150e070f6a" and "5ab8ae3423c92caa3e105ea9139bd2fab8f392e4" have entirely different histories.
f74b14c203
...
5ab8ae3423
@ -8,7 +8,6 @@ import 'package:p_tits_pas/models/pending_family.dart';
|
|||||||
import 'package:p_tits_pas/models/dossier_unifie.dart';
|
import 'package:p_tits_pas/models/dossier_unifie.dart';
|
||||||
import 'package:p_tits_pas/services/api/api_config.dart';
|
import 'package:p_tits_pas/services/api/api_config.dart';
|
||||||
import 'package:p_tits_pas/services/api/tokenService.dart';
|
import 'package:p_tits_pas/services/api/tokenService.dart';
|
||||||
import 'package:p_tits_pas/utils/am_vigilance.dart';
|
|
||||||
|
|
||||||
class DocumentActifInfo {
|
class DocumentActifInfo {
|
||||||
final String id;
|
final String id;
|
||||||
@ -689,24 +688,7 @@ class UserService {
|
|||||||
if (response.statusCode != 200 && response.statusCode != 201) {
|
if (response.statusCode != 200 && response.statusCode != 201) {
|
||||||
throw Exception(_extractErrorMessage(response.body, 'Erreur rattachement enfant'));
|
throw Exception(_extractErrorMessage(response.body, 'Erreur rattachement enfant'));
|
||||||
}
|
}
|
||||||
final am = _amModelFromBody(response.body);
|
return _amModelFromBody(response.body);
|
||||||
// Recalcule toujours places_available (capacité − enfants) après attachement.
|
|
||||||
return syncAmPlacesAvailable(am);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Aligne `places_available` sur capacité − enfants rattachés.
|
|
||||||
static Future<AssistanteMaternelleModel> syncAmPlacesAvailable(
|
|
||||||
AssistanteMaternelleModel am,
|
|
||||||
) async {
|
|
||||||
final expected = amExpectedPlacesAvailable(
|
|
||||||
maxChildren: am.maxChildren,
|
|
||||||
childrenCount: am.children.length,
|
|
||||||
);
|
|
||||||
if (expected == null || am.placesAvailable == expected) return am;
|
|
||||||
return updateAmFiche(
|
|
||||||
amUserId: am.user.id,
|
|
||||||
body: {'places_available': expected},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<AssistanteMaternelleModel> detachEnfantFromAm({
|
static Future<AssistanteMaternelleModel> detachEnfantFromAm({
|
||||||
|
|||||||
@ -9,18 +9,6 @@ int? amExpectedPlacesAvailable({
|
|||||||
return (maxChildren - childrenCount).clamp(0, maxChildren);
|
return (maxChildren - childrenCount).clamp(0, maxChildren);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// True s'il reste au moins une place d'accueil (capacité − enfants).
|
|
||||||
bool amHasFreePlace(AssistanteMaternelleModel am) {
|
|
||||||
final expected = amExpectedPlacesAvailable(
|
|
||||||
maxChildren: am.maxChildren,
|
|
||||||
childrenCount: am.children.length,
|
|
||||||
);
|
|
||||||
if (expected != null) return expected > 0;
|
|
||||||
final places = am.placesAvailable;
|
|
||||||
if (places != null) return places > 0;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// True si la valeur déclarée par l'AM ne correspond pas au calcul métier.
|
/// True si la valeur déclarée par l'AM ne correspond pas au calcul métier.
|
||||||
bool amHasPlacesInconsistency({
|
bool amHasPlacesInconsistency({
|
||||||
required int? maxChildren,
|
required int? maxChildren,
|
||||||
|
|||||||
@ -9,7 +9,6 @@ import 'package:p_tits_pas/utils/enfant_status_utils.dart';
|
|||||||
import 'package:p_tits_pas/widgets/admin/common/admin_am_edit_modal.dart';
|
import 'package:p_tits_pas/widgets/admin/common/admin_am_edit_modal.dart';
|
||||||
import 'package:p_tits_pas/widgets/admin/common/admin_am_photo_frame.dart';
|
import 'package:p_tits_pas/widgets/admin/common/admin_am_photo_frame.dart';
|
||||||
import 'package:p_tits_pas/widgets/admin/common/admin_parent_edit_modal.dart';
|
import 'package:p_tits_pas/widgets/admin/common/admin_parent_edit_modal.dart';
|
||||||
import 'package:p_tits_pas/widgets/admin/common/admin_select_am_modal.dart';
|
|
||||||
import 'package:p_tits_pas/widgets/admin/common/validation_detail_section.dart';
|
import 'package:p_tits_pas/widgets/admin/common/validation_detail_section.dart';
|
||||||
import 'package:p_tits_pas/widgets/admin/validation_modal_theme.dart';
|
import 'package:p_tits_pas/widgets/admin/validation_modal_theme.dart';
|
||||||
import 'package:p_tits_pas/widgets/common/auth_network_image.dart';
|
import 'package:p_tits_pas/widgets/common/auth_network_image.dart';
|
||||||
@ -400,25 +399,49 @@ class _AdminChildDetailModalState extends State<AdminChildDetailModal> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _attachAm() async {
|
Future<void> _attachAm() async {
|
||||||
|
List<AssistanteMaternelleModel> all;
|
||||||
|
try {
|
||||||
|
all = await UserService.getAssistantesMaternelles();
|
||||||
|
} catch (e) {
|
||||||
|
if (!mounted) return;
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(content: Text(e.toString().replaceFirst('Exception: ', ''))),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (_linkedAm != null && !_isSansGarde) {
|
if (_linkedAm != null && !_isSansGarde) {
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
const SnackBar(
|
const SnackBar(
|
||||||
content: Text(
|
content: Text('Détachez l\'assistante actuelle avant d\'en choisir une autre'),
|
||||||
'Détachez l\'assistante actuelle avant d\'en choisir une autre',
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (all.isEmpty) {
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
final selected = await AdminSelectAmModal.show(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
context,
|
const SnackBar(content: Text('Aucune assistante maternelle disponible')),
|
||||||
excludeIds: {
|
);
|
||||||
if (_linkedAm != null) _linkedAm!.user.id,
|
return;
|
||||||
},
|
}
|
||||||
title: 'Choisir une assistante maternelle',
|
|
||||||
|
if (!mounted) return;
|
||||||
|
final selected = await showDialog<AssistanteMaternelleModel>(
|
||||||
|
context: context,
|
||||||
|
builder: (ctx) => SimpleDialog(
|
||||||
|
title: const Text('Choisir une assistante maternelle'),
|
||||||
|
children: all
|
||||||
|
.map(
|
||||||
|
(am) => SimpleDialogOption(
|
||||||
|
onPressed: () => Navigator.pop(ctx, am),
|
||||||
|
child: Text(am.user.fullName),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
if (selected == null || !mounted) return;
|
if (selected == null || !mounted) return;
|
||||||
|
|
||||||
|
|||||||
@ -1,218 +0,0 @@
|
|||||||
import 'package:flutter/gestures.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:p_tits_pas/models/assistante_maternelle_model.dart';
|
|
||||||
import 'package:p_tits_pas/services/user_service.dart';
|
|
||||||
import 'package:p_tits_pas/utils/am_vigilance.dart';
|
|
||||||
import 'package:p_tits_pas/widgets/admin/common/admin_am_edit_modal.dart';
|
|
||||||
import 'package:p_tits_pas/widgets/admin/common/admin_select_list_modal.dart';
|
|
||||||
import 'package:p_tits_pas/widgets/admin/common/admin_user_card.dart';
|
|
||||||
import 'package:p_tits_pas/widgets/admin/validation_modal_theme.dart';
|
|
||||||
|
|
||||||
List<String> _amSelectSubtitleLines(AssistanteMaternelleModel am) {
|
|
||||||
final lines = <String>[];
|
|
||||||
final zone = (am.residenceCity ?? '').trim();
|
|
||||||
if (zone.isNotEmpty) lines.add('Zone : $zone');
|
|
||||||
final agrement = (am.approvalNumber ?? '').trim();
|
|
||||||
if (agrement.isNotEmpty) lines.add('Agrément : $agrement');
|
|
||||||
final max = am.maxChildren;
|
|
||||||
final free = amExpectedPlacesAvailable(
|
|
||||||
maxChildren: max,
|
|
||||||
childrenCount: am.children.length,
|
|
||||||
) ??
|
|
||||||
am.placesAvailable;
|
|
||||||
if (free != null || max != null) {
|
|
||||||
lines.add('Places libres : ${free ?? '–'} / capa. ${max ?? '–'}');
|
|
||||||
}
|
|
||||||
lines.add('${am.children.length} enfant(s)');
|
|
||||||
return lines;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sélection d'une AM à rattacher (fiche enfant) — ticket #147.
|
|
||||||
/// S'appuie sur [AdminSelectListModal] (shell partagé avec #146).
|
|
||||||
class AdminSelectAmModal {
|
|
||||||
AdminSelectAmModal._();
|
|
||||||
|
|
||||||
static Future<AssistanteMaternelleModel?> show(
|
|
||||||
BuildContext context, {
|
|
||||||
Set<String> excludeIds = const {},
|
|
||||||
String title = 'Choisir une assistante maternelle',
|
|
||||||
}) {
|
|
||||||
return AdminSelectListModal.show<AssistanteMaternelleModel>(
|
|
||||||
context,
|
|
||||||
title: title,
|
|
||||||
searchHint: 'Rechercher par nom, prénom ou zone…',
|
|
||||||
emptyMessage: 'Aucune assistante maternelle disponible',
|
|
||||||
noResultsMessage: 'Aucune AM avec place libre pour cette recherche',
|
|
||||||
toggleFilter: const AdminSelectToggleFilter<AssistanteMaternelleModel>(
|
|
||||||
label: 'Libre',
|
|
||||||
initialValue: true,
|
|
||||||
whenEnabled: amHasFreePlace,
|
|
||||||
),
|
|
||||||
loadItems: () async {
|
|
||||||
final list = await UserService.getAssistantesMaternelles();
|
|
||||||
return list
|
|
||||||
.where((am) => !excludeIds.contains(am.user.id))
|
|
||||||
.toList()
|
|
||||||
..sort(
|
|
||||||
(a, b) => a.user.fullName
|
|
||||||
.toLowerCase()
|
|
||||||
.compareTo(b.user.fullName.toLowerCase()),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
matchesQuery: (am, q) {
|
|
||||||
final u = am.user;
|
|
||||||
final name = u.fullName.toLowerCase();
|
|
||||||
final fn = (u.prenom ?? '').toLowerCase();
|
|
||||||
final ln = (u.nom ?? '').toLowerCase();
|
|
||||||
final zone = (am.residenceCity ?? '').toLowerCase();
|
|
||||||
final agrement = (am.approvalNumber ?? '').toLowerCase();
|
|
||||||
return name.contains(q) ||
|
|
||||||
fn.contains(q) ||
|
|
||||||
ln.contains(q) ||
|
|
||||||
zone.contains(q) ||
|
|
||||||
agrement.contains(q);
|
|
||||||
},
|
|
||||||
resolveSelect: (ctx, am, reload) =>
|
|
||||||
_resolveAmSelection(ctx, am, reload),
|
|
||||||
itemBuilder: (context, am, onSelect) {
|
|
||||||
final full = !amHasFreePlace(am);
|
|
||||||
return AdminUserCard(
|
|
||||||
title: am.user.fullName,
|
|
||||||
avatarUrl: am.user.photoUrl,
|
|
||||||
fallbackIcon: Icons.face,
|
|
||||||
subtitleLines: _amSelectSubtitleLines(am),
|
|
||||||
vigilanceTooltip: amPlacesVigilanceMessage(am),
|
|
||||||
onCardTap: onSelect,
|
|
||||||
margin: const EdgeInsets.only(bottom: 4),
|
|
||||||
contentPadding: const EdgeInsets.symmetric(
|
|
||||||
horizontal: 10,
|
|
||||||
vertical: 5,
|
|
||||||
),
|
|
||||||
backgroundColor: full ? const Color(0xFFFFEBEE) : null,
|
|
||||||
borderColor: full ? Colors.red.shade200 : null,
|
|
||||||
actions: [
|
|
||||||
IconButton(
|
|
||||||
icon: const Icon(Icons.add_link),
|
|
||||||
tooltip: 'Rattacher',
|
|
||||||
onPressed: onSelect,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Future<AssistanteMaternelleModel?> _resolveAmSelection(
|
|
||||||
BuildContext context,
|
|
||||||
AssistanteMaternelleModel am,
|
|
||||||
Future<void> Function() reloadList,
|
|
||||||
) async {
|
|
||||||
if (amHasFreePlace(am)) return am;
|
|
||||||
|
|
||||||
final selected = await showDialog<AssistanteMaternelleModel>(
|
|
||||||
context: context,
|
|
||||||
builder: (ctx) => _AmNoPlaceWarningDialog(initialAm: am),
|
|
||||||
);
|
|
||||||
await reloadList();
|
|
||||||
return selected;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Avertissement AM saturée + lien vers la fiche pour ajuster les places.
|
|
||||||
class _AmNoPlaceWarningDialog extends StatefulWidget {
|
|
||||||
final AssistanteMaternelleModel initialAm;
|
|
||||||
|
|
||||||
const _AmNoPlaceWarningDialog({required this.initialAm});
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<_AmNoPlaceWarningDialog> createState() =>
|
|
||||||
_AmNoPlaceWarningDialogState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _AmNoPlaceWarningDialogState extends State<_AmNoPlaceWarningDialog> {
|
|
||||||
late AssistanteMaternelleModel _am;
|
|
||||||
TapGestureRecognizer? _linkRecognizer;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
_am = widget.initialAm;
|
|
||||||
_linkRecognizer = TapGestureRecognizer()..onTap = _openAmFiche;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
_linkRecognizer?.dispose();
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _openAmFiche() async {
|
|
||||||
if (!mounted) return;
|
|
||||||
await showDialog<void>(
|
|
||||||
context: context,
|
|
||||||
builder: (ctx) => AdminAmEditModal(
|
|
||||||
assistante: _am,
|
|
||||||
onSaved: () async {
|
|
||||||
try {
|
|
||||||
final fresh =
|
|
||||||
await UserService.getAssistanteMaternelle(_am.user.id);
|
|
||||||
if (mounted) setState(() => _am = fresh);
|
|
||||||
} catch (_) {}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
if (!mounted) return;
|
|
||||||
|
|
||||||
try {
|
|
||||||
final fresh = await UserService.getAssistanteMaternelle(_am.user.id);
|
|
||||||
if (!mounted) return;
|
|
||||||
setState(() => _am = fresh);
|
|
||||||
if (amHasFreePlace(fresh)) {
|
|
||||||
Navigator.of(context).pop(fresh);
|
|
||||||
}
|
|
||||||
} catch (_) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final name = _am.user.fullName.trim().isNotEmpty
|
|
||||||
? _am.user.fullName.trim()
|
|
||||||
: 'Cette assistante maternelle';
|
|
||||||
const linkColor = ValidationModalTheme.primaryActionBackground;
|
|
||||||
|
|
||||||
return AlertDialog(
|
|
||||||
title: const Text('Plus de place disponible'),
|
|
||||||
content: Text.rich(
|
|
||||||
TextSpan(
|
|
||||||
style: const TextStyle(fontSize: 14, color: Colors.black87, height: 1.4),
|
|
||||||
children: [
|
|
||||||
TextSpan(
|
|
||||||
text: '$name n\'a plus de place libre pour accueillir '
|
|
||||||
'un enfant supplémentaire.\n\n',
|
|
||||||
),
|
|
||||||
const TextSpan(text: 'Vous pouvez '),
|
|
||||||
TextSpan(
|
|
||||||
text: 'ouvrir sa fiche',
|
|
||||||
style: TextStyle(
|
|
||||||
color: linkColor,
|
|
||||||
decoration: TextDecoration.underline,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
),
|
|
||||||
recognizer: _linkRecognizer,
|
|
||||||
),
|
|
||||||
const TextSpan(
|
|
||||||
text: ' pour modifier la capacité ou les places, '
|
|
||||||
'puis la sélectionner si une place se libère.',
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
actions: [
|
|
||||||
TextButton(
|
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
|
||||||
child: const Text('Fermer'),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -18,7 +18,7 @@ class AdminSelectToggleFilter<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Shell générique « rechercher + liste + sélection » pour les modales admin.
|
/// Shell générique « rechercher + liste + sélection » pour les modales admin.
|
||||||
/// Utilisé par la sélection d'enfant (#146) et la sélection d'AM (#147).
|
/// Utilisé par la sélection d'enfant (#146) et prévu pour la sélection d'AM (#147).
|
||||||
class AdminSelectListModal<T> extends StatefulWidget {
|
class AdminSelectListModal<T> extends StatefulWidget {
|
||||||
final String title;
|
final String title;
|
||||||
final String searchHint;
|
final String searchHint;
|
||||||
@ -39,17 +39,9 @@ class AdminSelectListModal<T> extends StatefulWidget {
|
|||||||
/// Nombre minimum de cartes visibles dans la zone scrollable.
|
/// Nombre minimum de cartes visibles dans la zone scrollable.
|
||||||
final int minVisibleCards;
|
final int minVisibleCards;
|
||||||
|
|
||||||
/// Switch optionnel à droite du champ de recherche (ex. « Sans garde », « Libre »).
|
/// Switch optionnel à droite du champ de recherche (ex. « Sans garde »).
|
||||||
final AdminSelectToggleFilter<T>? toggleFilter;
|
final AdminSelectToggleFilter<T>? toggleFilter;
|
||||||
|
|
||||||
/// Si fourni, appelé avant de valider la sélection.
|
|
||||||
/// Retourne l'élément à pop (éventuellement rafraîchi), ou `null` pour annuler.
|
|
||||||
final Future<T?> Function(
|
|
||||||
BuildContext context,
|
|
||||||
T item,
|
|
||||||
Future<void> Function() reload,
|
|
||||||
)? resolveSelect;
|
|
||||||
|
|
||||||
const AdminSelectListModal({
|
const AdminSelectListModal({
|
||||||
super.key,
|
super.key,
|
||||||
required this.title,
|
required this.title,
|
||||||
@ -63,7 +55,6 @@ class AdminSelectListModal<T> extends StatefulWidget {
|
|||||||
this.cardExtent = 52,
|
this.cardExtent = 52,
|
||||||
this.minVisibleCards = 8,
|
this.minVisibleCards = 8,
|
||||||
this.toggleFilter,
|
this.toggleFilter,
|
||||||
this.resolveSelect,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
static Future<T?> show<T>(
|
static Future<T?> show<T>(
|
||||||
@ -83,11 +74,6 @@ class AdminSelectListModal<T> extends StatefulWidget {
|
|||||||
double cardExtent = 52,
|
double cardExtent = 52,
|
||||||
int minVisibleCards = 8,
|
int minVisibleCards = 8,
|
||||||
AdminSelectToggleFilter<T>? toggleFilter,
|
AdminSelectToggleFilter<T>? toggleFilter,
|
||||||
Future<T?> Function(
|
|
||||||
BuildContext context,
|
|
||||||
T item,
|
|
||||||
Future<void> Function() reload,
|
|
||||||
)? resolveSelect,
|
|
||||||
}) {
|
}) {
|
||||||
return showDialog<T>(
|
return showDialog<T>(
|
||||||
context: context,
|
context: context,
|
||||||
@ -103,7 +89,6 @@ class AdminSelectListModal<T> extends StatefulWidget {
|
|||||||
cardExtent: cardExtent,
|
cardExtent: cardExtent,
|
||||||
minVisibleCards: minVisibleCards,
|
minVisibleCards: minVisibleCards,
|
||||||
toggleFilter: toggleFilter,
|
toggleFilter: toggleFilter,
|
||||||
resolveSelect: resolveSelect,
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -119,7 +104,6 @@ class _AdminSelectListModalState<T> extends State<AdminSelectListModal<T>> {
|
|||||||
bool _loading = true;
|
bool _loading = true;
|
||||||
String? _error;
|
String? _error;
|
||||||
late bool _toggleOn;
|
late bool _toggleOn;
|
||||||
bool _resolving = false;
|
|
||||||
|
|
||||||
double get _listHeight =>
|
double get _listHeight =>
|
||||||
widget.cardExtent * widget.minVisibleCards;
|
widget.cardExtent * widget.minVisibleCards;
|
||||||
@ -159,23 +143,6 @@ class _AdminSelectListModalState<T> extends State<AdminSelectListModal<T>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _handleSelect(T item) async {
|
|
||||||
if (_resolving) return;
|
|
||||||
final resolve = widget.resolveSelect;
|
|
||||||
if (resolve == null) {
|
|
||||||
Navigator.of(context).pop(item);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setState(() => _resolving = true);
|
|
||||||
try {
|
|
||||||
final chosen = await resolve(context, item, _load);
|
|
||||||
if (!mounted || chosen == null) return;
|
|
||||||
Navigator.of(context).pop(chosen);
|
|
||||||
} finally {
|
|
||||||
if (mounted) setState(() => _resolving = false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
List<T> get _filtered {
|
List<T> get _filtered {
|
||||||
var list = _all;
|
var list = _all;
|
||||||
final toggle = widget.toggleFilter;
|
final toggle = widget.toggleFilter;
|
||||||
@ -359,7 +326,7 @@ class _AdminSelectListModalState<T> extends State<AdminSelectListModal<T>> {
|
|||||||
return widget.itemBuilder(
|
return widget.itemBuilder(
|
||||||
context,
|
context,
|
||||||
item,
|
item,
|
||||||
() => _handleSelect(item),
|
() => Navigator.of(context).pop(item),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user