import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:country_picker/country_picker.dart'; import '../generated/i18n/app_localizations.dart'; class CountryField extends StatelessWidget { const CountryField({ super.key, required this.value, required this.onChanged, this.enabled = true, }); final String value; final ValueChanged onChanged; final bool enabled; @override Widget build(BuildContext context) { final l = AppLocalizations.of(context)!; final country = CountryService().findByCode(value); return Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Text(l.kycCountry, style: Theme.of(context).textTheme.labelLarge), const SizedBox(height: 8), Semantics( label: l.kycCountry, child: OutlinedButton( onPressed: !enabled ? null : () async { final code = await showDialog( context: context, builder: (_) => _CountrySearch(selected: value), ); if (context.mounted && code != null) onChanged(code); }, style: OutlinedButton.styleFrom( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(14), ), ), child: Row( children: [ Expanded( child: Text( country == null ? l.kycCountrySelect : _name(context, country), ), ), const SizedBox(width: 8), const Icon(Icons.expand_more), ], ), ), ), ], ); } } String _name(BuildContext context, Country country) => country.getTranslatedName(context) ?? country.name; class _CountrySearch extends StatefulWidget { const _CountrySearch({required this.selected}); final String selected; @override State<_CountrySearch> createState() => _CountrySearchState(); } class _CountrySearchState extends State<_CountrySearch> { final _query = TextEditingController(); final _countries = { for (final country in CountryService().getAll()) country.countryCode: country, }.values.toList(); @override void dispose() { _query.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final l = AppLocalizations.of(context)!; return Focus( autofocus: true, onKeyEvent: (_, event) { if (event is KeyDownEvent && event.logicalKey == LogicalKeyboardKey.escape) { Navigator.of(context).pop(); return KeyEventResult.handled; } return KeyEventResult.ignored; }, child: Dialog.fullscreen( child: Scaffold( appBar: AppBar( leading: BackButton(onPressed: () => Navigator.of(context).pop()), title: TextField( key: const ValueKey('country-search'), controller: _query, autofocus: true, decoration: InputDecoration( labelText: l.kycCountrySearch, prefixIcon: const Icon(Icons.search), ), onChanged: (_) => setState(() {}), ), toolbarHeight: 96, actions: [ if (_query.text.isNotEmpty) IconButton( tooltip: l.kycCountryClearSearch, icon: const Icon(Icons.clear), onPressed: () => setState(_query.clear), ), ], ), body: _list(context), ), ), ); } Widget _list(BuildContext context) { final search = _query.text.trim().toLowerCase(); final countries = _countries.where((country) { return _name(context, country).toLowerCase().contains(search) || country.name.toLowerCase().contains(search) || country.countryCode.toLowerCase() == search; }).toList()..sort((a, b) => _name(context, a).compareTo(_name(context, b))); if (countries.isEmpty) { return Center( child: Padding( padding: const EdgeInsets.all(24), child: Text(AppLocalizations.of(context)!.kycCountryEmpty), ), ); } return ListView.builder( itemCount: countries.length, itemBuilder: (context, index) { final country = countries[index]; final isSelected = country.countryCode == widget.selected; return ListTile( title: Text(_name(context, country)), selected: isSelected, trailing: isSelected ? const Icon(Icons.check) : null, onTap: () => Navigator.of(context).pop(country.countryCode), ); }, ); } }