import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../../../../api/connect/rmv/rmv_models.dart'; import '../../../../api/errors/error_mapper.dart'; import '../../../../routing/app_routes.dart'; import '../../../../state/app/modules/rmv/repository/rmv_repository.dart'; import '../../../../state/app/modules/settings/bloc/settings_cubit.dart'; import '../../../../widget/app_progress_indicator.dart'; import '../favorites_controller.dart'; import '../widgets/departure_arrival_tile.dart'; enum _Direction { departures, arrivals } class StationDetailView extends StatefulWidget { final StopLocation station; const StationDetailView({super.key, required this.station}); @override State createState() => _StationDetailViewState(); } class _StationDetailViewState extends State { final RmvRepository _repo = RmvRepository(); _Direction _direction = _Direction.departures; List? _departures; List? _arrivals; bool _loading = false; Object? _error; @override void initState() { super.initState(); _load(); } Future _load() async { setState(() { _loading = true; _error = null; }); try { if (_direction == _Direction.departures) { final result = await _repo.departures(widget.station.id); if (!mounted) return; setState(() { _departures = result; _loading = false; }); } else { final result = await _repo.arrivals(widget.station.id); if (!mounted) return; setState(() { _arrivals = result; _loading = false; }); } } catch (e) { if (!mounted) return; setState(() { _error = e; _loading = false; }); } } void _switch(_Direction d) { if (d == _direction) return; setState(() { _direction = d; _departures = null; _arrivals = null; }); _load(); } @override Widget build(BuildContext context) { final settings = context.watch(); final favCtrl = RmvFavoritesController(settings); final isFav = favCtrl.isFavorite(widget.station); return Scaffold( appBar: AppBar( title: Text(widget.station.name), actions: [ IconButton( tooltip: isFav ? 'Favorit entfernen' : 'Als Favorit speichern', icon: Icon(isFav ? Icons.star : Icons.star_border), onPressed: () => favCtrl.toggleFavorite(widget.station), ), ], ), body: Column( children: [ Padding( padding: const EdgeInsets.fromLTRB(16, 12, 16, 8), child: SegmentedButton<_Direction>( segments: const [ ButtonSegment( value: _Direction.departures, icon: Icon(Icons.north_east), label: Text('Abfahrten'), ), ButtonSegment( value: _Direction.arrivals, icon: Icon(Icons.south_west), label: Text('Ankünfte'), ), ], selected: {_direction}, onSelectionChanged: (s) => _switch(s.first), ), ), Expanded(child: _body()), ], ), ); } Widget _body() { if (_loading) { return const Center(child: AppProgressIndicator.large()); } final err = _error; if (err != null) { return Center( child: Padding( padding: const EdgeInsets.all(24), child: Column( mainAxisSize: MainAxisSize.min, children: [ Text( errorToUserMessage(err), textAlign: TextAlign.center, style: TextStyle(color: Theme.of(context).colorScheme.error), ), const SizedBox(height: 12), FilledButton.icon( icon: const Icon(Icons.refresh), onPressed: _load, label: const Text('Erneut versuchen'), ), ], ), ), ); } if (_direction == _Direction.departures) { final list = _departures ?? const []; if (list.isEmpty) return _emptyState('Keine Abfahrten gefunden.'); return RefreshIndicator( onRefresh: _load, child: ListView.separated( itemCount: list.length, separatorBuilder: (_, _) => const Divider(height: 1), itemBuilder: (_, i) => DepartureArrivalTile.fromDeparture( list[i], onTap: () => _openJourney(list[i].journeyRef), ), ), ); } final list = _arrivals ?? const []; if (list.isEmpty) return _emptyState('Keine Ankünfte gefunden.'); return RefreshIndicator( onRefresh: _load, child: ListView.separated( itemCount: list.length, separatorBuilder: (_, _) => const Divider(height: 1), itemBuilder: (_, i) => DepartureArrivalTile.fromArrival( list[i], onTap: () => _openJourney(list[i].journeyRef), ), ), ); } Widget _emptyState(String text) => RefreshIndicator( onRefresh: _load, child: ListView( physics: const AlwaysScrollableScrollPhysics(), children: [ Padding( padding: const EdgeInsets.symmetric(vertical: 80, horizontal: 24), child: Center( child: Text(text, style: Theme.of(context).textTheme.bodyLarge), ), ), ], ), ); void _openJourney(String? ref) { if (ref == null) return; AppRoutes.openRmvJourneyDetail(context, ref); } }