Implementiert den kompletten Kern-Flow der Emergency App gemäß docs/plan.md: - Notrufnummern-Datenbasis für 199 Länder + Modelle/Repository (AP1) - DialerService für tel:-Notrufe ohne Auto-Dial (AP2) - Statisches UI mit Panik-Button-Fallback (AP3) - Priorisierte Ländererkennung: SIM/Netz -> GPS/Geocoding -> Cache (AP4) - EmergencyProvider verdrahtet Repository/LocationService mit der UI (AP5) - Manuelle Länderauswahl als Fallback samt eigener Priorität (AP6) - UI-Lokalisierung (de/en/fr/es), an erkanntes Land gekoppelt (AP7) Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
94 lines
3.1 KiB
Dart
94 lines
3.1 KiB
Dart
import 'package:flutter/material.dart';
|
||
import 'package:provider/provider.dart';
|
||
|
||
import '../../l10n/app_localizations.dart';
|
||
import '../../models/country.dart';
|
||
import '../../providers/emergency_provider.dart';
|
||
|
||
/// Durchsuchbare Länderliste zur manuellen Länderauswahl
|
||
/// (`docs/plan.md`, Abschnitt 7 + 8, AP6).
|
||
///
|
||
/// Tap auf ein Land ruft [EmergencyProvider.selectCountryManually] auf –
|
||
/// das persistiert die Auswahl und stößt die Ermittlungskette danach sofort
|
||
/// erneut an – und schließt den Screen.
|
||
class CountryPickerScreen extends StatefulWidget {
|
||
const CountryPickerScreen({super.key});
|
||
|
||
@override
|
||
State<CountryPickerScreen> createState() => _CountryPickerScreenState();
|
||
}
|
||
|
||
class _CountryPickerScreenState extends State<CountryPickerScreen> {
|
||
final _searchController = TextEditingController();
|
||
String _query = '';
|
||
|
||
@override
|
||
void dispose() {
|
||
_searchController.dispose();
|
||
super.dispose();
|
||
}
|
||
|
||
List<Country> _filtered(List<Country> countries) {
|
||
final query = _query.trim().toLowerCase();
|
||
if (query.isEmpty) return countries;
|
||
return countries
|
||
.where(
|
||
(country) =>
|
||
country.nameDe.toLowerCase().contains(query) ||
|
||
country.nameEn.toLowerCase().contains(query) ||
|
||
country.isoCode.toLowerCase().contains(query),
|
||
)
|
||
.toList(growable: false);
|
||
}
|
||
|
||
Future<void> _select(BuildContext context, Country country) async {
|
||
await context.read<EmergencyProvider>().selectCountryManually(country.isoCode);
|
||
if (context.mounted) Navigator.of(context).pop();
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
final repository = context.read<EmergencyProvider>().repository;
|
||
final countries = _filtered(repository.allCountries);
|
||
final l10n = AppLocalizations.of(context)!;
|
||
|
||
return Scaffold(
|
||
appBar: AppBar(title: Text(l10n.pickerTitle)),
|
||
body: Column(
|
||
children: [
|
||
Padding(
|
||
padding: const EdgeInsets.all(16),
|
||
child: TextField(
|
||
controller: _searchController,
|
||
autofocus: true,
|
||
decoration: InputDecoration(
|
||
prefixIcon: const Icon(Icons.search),
|
||
hintText: l10n.pickerSearchHint,
|
||
border: const OutlineInputBorder(),
|
||
),
|
||
onChanged: (value) => setState(() => _query = value),
|
||
),
|
||
),
|
||
Expanded(
|
||
child: countries.isEmpty
|
||
? Center(child: Text(l10n.pickerNoResults))
|
||
: ListView.builder(
|
||
itemCount: countries.length,
|
||
itemBuilder: (context, index) {
|
||
final country = countries[index];
|
||
return ListTile(
|
||
key: ValueKey(country.isoCode),
|
||
leading: Text(country.flag, style: const TextStyle(fontSize: 24)),
|
||
title: Text(country.nameDe),
|
||
subtitle: Text(country.isoCode),
|
||
onTap: () => _select(context, country),
|
||
);
|
||
},
|
||
),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
}
|