import 'package:flutter/material.dart'; import 'package:wetter/models/location_model.dart'; import 'package:wetter/services/openstreetmap_api_service.dart'; import 'package:wetter/services/utils.dart'; class AddLocationBySearchForm extends StatefulWidget { final Function saveNewLocation; const AddLocationBySearchForm({Key? key, required this.saveNewLocation}) : super(key: key); @override State createState() => _AddLocationBySearchFormState(); } class _AddLocationBySearchFormState extends State { final _formKey = GlobalKey(); final searchLocationFormController = TextEditingController(); final _debouncer = Debouncer(milliseconds: 500); bool _showResults = false; bool _locationSearchHasFocus = false; List? _locations; @override Widget build(BuildContext context) { return Form( key: _formKey, child: Column( children: [ FocusScope( child: Focus( onFocusChange: (focus) { setState(() { _locationSearchHasFocus = !_locationSearchHasFocus; }); }, child: TextFormField( onChanged: (value) { _debouncer.run(() { OpenStreetMapAPI.getLocationsFromSearch(value) .then((l) { setState(() { _locations = l; _showResults = true; }); }); }); }, decoration: const InputDecoration( border: UnderlineInputBorder(), labelText: "Location Name"), ))), if (_showResults && _locationSearchHasFocus) _showResultList(), ], )); } Column _showResultList() { if (_locations == null) { return Column( children: const [], ); } if (_locations!.isEmpty) { return Column( children: [_singleResult(name: "No result")], ); } return Column(children: [ for (LocationModel location in _locations!.getRange(0, 3)) _singleResult(name: location.name, location: location) ]); } Widget _singleResult({required String name, LocationModel? location}) { return GestureDetector( onTap: () { if (location != null) { widget.saveNewLocation( location.name, location.latitude, location.longitude); } }, child: Card( child: Padding( padding: const EdgeInsets.all(5), child: Row(children: [ Flexible( child: Text(name, style: Theme.of(context).textTheme.titleMedium)) ])))); } }