implemented RMV public transit module including trip search, station departures, and nearby stop lookup, added "Marianum Connect" API integration with bearer token authentication and auto-refresh logic, integrated geolocator for location-based station search, added persistent storage for favorite stations and recent trip queries, and implemented comprehensive UI for journey details, trip results, and disruption alerts
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../../../extensions/date_time.dart';
|
||||
|
||||
/// Returns the "depart at / arrive by" time and the AB/AN-toggle. `null` for
|
||||
/// [value] means "now" — the API treats an empty `when` parameter as the
|
||||
/// current time.
|
||||
class WhenPicker extends StatelessWidget {
|
||||
final DateTime? value;
|
||||
final bool byArrival;
|
||||
final ValueChanged<DateTime?> onValueChanged;
|
||||
final ValueChanged<bool> onByArrivalChanged;
|
||||
|
||||
const WhenPicker({
|
||||
super.key,
|
||||
required this.value,
|
||||
required this.byArrival,
|
||||
required this.onValueChanged,
|
||||
required this.onByArrivalChanged,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final label = value == null
|
||||
? 'Jetzt'
|
||||
: value!.formatDateRelativeShort() == 'Heute'
|
||||
? value!.formatHm()
|
||||
: '${value!.formatDateRelativeShort()} ${value!.formatHm()}';
|
||||
return Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: OutlinedButton.icon(
|
||||
icon: const Icon(Icons.schedule),
|
||||
label: Text(label),
|
||||
onPressed: () => _pick(context),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
SegmentedButton<bool>(
|
||||
segments: const [
|
||||
ButtonSegment(value: false, label: Text('Ab')),
|
||||
ButtonSegment(value: true, label: Text('An')),
|
||||
],
|
||||
selected: {byArrival},
|
||||
onSelectionChanged: (s) => onByArrivalChanged(s.first),
|
||||
),
|
||||
if (value != null) ...[
|
||||
const SizedBox(width: 4),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.close),
|
||||
tooltip: 'Zurück auf "Jetzt"',
|
||||
onPressed: () => onValueChanged(null),
|
||||
),
|
||||
],
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _pick(BuildContext context) async {
|
||||
final now = DateTime.now();
|
||||
final initial = value ?? now;
|
||||
final date = await showDatePicker(
|
||||
context: context,
|
||||
initialDate: initial,
|
||||
firstDate: now.subtract(const Duration(days: 7)),
|
||||
lastDate: now.add(const Duration(days: 365)),
|
||||
);
|
||||
if (date == null) return;
|
||||
if (!context.mounted) return;
|
||||
final time = await showTimePicker(
|
||||
context: context,
|
||||
initialTime: TimeOfDay(hour: initial.hour, minute: initial.minute),
|
||||
);
|
||||
if (time == null) return;
|
||||
onValueChanged(
|
||||
DateTime(date.year, date.month, date.day, time.hour, time.minute),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user