import 'package:aves/widgets/dialogs/aves_dialog.dart'; import 'package:aves/widgets/dialogs/selection_dialogs/common.dart'; import 'package:aves/widgets/dialogs/selection_dialogs/radio_list_tile.dart'; import 'package:flutter/material.dart'; // do not use as `T` a record containing a collection // because radio value comparison will fail without deep equality class AvesSingleSelectionDialog extends StatefulWidget { static const routeName = '/dialog/selection'; final T initialValue; final Map options; final TextBuilder? optionSubtitleBuilder; final String? title, message, confirmationButtonLabel; final bool? dense; const AvesSingleSelectionDialog({ super.key, required this.initialValue, required this.options, this.optionSubtitleBuilder, this.title, this.message, this.confirmationButtonLabel, this.dense, }); @override State> createState() => _AvesSingleSelectionDialogState(); } class _AvesSingleSelectionDialogState extends State> { late T _selectedValue; @override void initState() { super.initState(); _selectedValue = widget.initialValue; } @override Widget build(BuildContext context) { final title = widget.title; final message = widget.message; final verticalPadding = (title == null && message == null) ? AvesDialog.cornerRadius.y / 2 : .0; final confirmationButtonLabel = widget.confirmationButtonLabel; final needConfirmation = confirmationButtonLabel != null; return AvesDialog( title: title, scrollableContent: [ RadioGroup( groupValue: _selectedValue, onChanged: (v) { // always update the group value even when popping afterwards, // so that the group value can be used in pop handlers // as well as the regular return value from navigation _selectedValue = v as T; if (!needConfirmation) { // validate without confirmation Navigator.maybeOf(context)?.pop(v); } else { setState(() {}); } }, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ if (verticalPadding != 0) SizedBox(height: verticalPadding), if (message != null) Padding( padding: const EdgeInsets.all(16), child: Text(message), ), ...widget.options.entries.map((kv) { final radioValue = kv.key; final radioTitle = kv.value; return SelectionRadioListTile( value: radioValue, title: radioTitle, optionSubtitleBuilder: widget.optionSubtitleBuilder, dense: widget.dense, ); }), if (verticalPadding != 0) SizedBox(height: verticalPadding), ], ), ), ], actions: [ const CancelButton(), if (needConfirmation) TextButton( onPressed: () => Navigator.maybeOf(context)?.pop(_selectedValue), child: Text(confirmationButtonLabel), ), ], ); } }