Notrufnummern-Datenbasis, Ländererkennung, State-Management und Lokalisierung (AP1-AP7)
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>
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
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),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user