feat(ui): add search to stations

This commit is contained in:
fbachus
2026-07-30 20:03:08 +02:00
parent f8aa117c28
commit 0d67143be2
+61 -4
View File
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'api_handler.dart';
import 'transport_helper.dart';
import 'dart:async';
import 'package:sqflite_common_ffi/sqflite_ffi.dart'; //for testing on desktop
@@ -126,6 +127,7 @@ class ChooseStationPage extends StatefulWidget {
class _ChooseStationPageState extends State<ChooseStationPage> {
Station? _selectedStation;
List<Station> stationList = [];
Timer? _debounce;
void findNearbyStations() async {
stationList = await ApiHandler.nearbyStations(
@@ -148,6 +150,30 @@ class _ChooseStationPageState extends State<ChooseStationPage> {
setState(() {});
}
// Source - https://stackoverflow.com/a/52930197
// Posted by Jannie Theunissen, modified by community. See post 'Timeline' for change history
// Retrieved 2026-07-30, License - CC BY-SA 4.0
void _onSearchChanged(String? query) {
if (_debounce?.isActive ?? false) _debounce?.cancel();
_debounce = Timer(const Duration(milliseconds: 400), () {
_search(query);
});
}
void _search(String? query) {
if (query?.isEmpty ?? true) return;
// do something with query
setState(() {
findStationsByName(query!);
});
}
@override
void dispose() {
_debounce?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
@@ -155,11 +181,42 @@ class _ChooseStationPageState extends State<ChooseStationPage> {
body: Center(
child: Column(
children: [
ElevatedButton(
onPressed: () {
showResult(ApiHandler.findStations('S Biesdorf'));
// ElevatedButton(
// onPressed: () {
// showResult(ApiHandler.findStations('S Biesdorf'));
// },
// child: Text('Search for \'S Biesdorf\''),
// ),
SearchAnchor(
builder: (BuildContext context, SearchController controller) {
return SearchBar(
controller: controller,
hintText: 'Search for a Station',
padding: const WidgetStatePropertyAll<EdgeInsets>(
EdgeInsets.symmetric(horizontal: 16.0),
),
// onTap: () {
// controller.openView();
// },
onChanged: _onSearchChanged,
onSubmitted: _search,
leading: const Icon(Icons.search),
);
},
suggestionsBuilder:
(BuildContext context, SearchController controller) {
return List<ListTile>.generate(5, (int index) {
final String item = 'item $index';
return ListTile(
title: Text(item),
onTap: () {
setState(() {
controller.closeView(item);
});
},
);
});
},
child: Text('Search for \'S Biesdorf\''),
),
Expanded(
child: SizedBox(