120 lines
3.1 KiB
Dart
120 lines
3.1 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
import '../../../../api/connect/rmv/rmv_models.dart';
|
|
import 'product_chip.dart';
|
|
import 'realtime_time.dart';
|
|
|
|
/// Renders a single departure or arrival row. Used in the station detail view.
|
|
class DepartureArrivalTile extends StatelessWidget {
|
|
final Product? product;
|
|
final String name;
|
|
|
|
/// Direction (for departures) or origin (for arrivals).
|
|
final String towards;
|
|
final DateTime scheduled;
|
|
final DateTime? realtime;
|
|
final int? delayMinutes;
|
|
final String? track;
|
|
final String? realTrack;
|
|
final bool cancelled;
|
|
final VoidCallback? onTap;
|
|
|
|
const DepartureArrivalTile({
|
|
super.key,
|
|
required this.product,
|
|
required this.name,
|
|
required this.towards,
|
|
required this.scheduled,
|
|
this.realtime,
|
|
this.delayMinutes,
|
|
this.track,
|
|
this.realTrack,
|
|
this.cancelled = false,
|
|
this.onTap,
|
|
});
|
|
|
|
factory DepartureArrivalTile.fromDeparture(
|
|
Departure d, {
|
|
VoidCallback? onTap,
|
|
}) => DepartureArrivalTile(
|
|
product: d.product,
|
|
name: d.name,
|
|
towards: 'nach ${d.direction}',
|
|
scheduled: d.scheduledTime,
|
|
realtime: d.realTime,
|
|
delayMinutes: d.delayMinutes,
|
|
track: d.track,
|
|
realTrack: d.realTrack,
|
|
cancelled: d.cancelled,
|
|
onTap: onTap,
|
|
);
|
|
|
|
factory DepartureArrivalTile.fromArrival(
|
|
Arrival a, {
|
|
VoidCallback? onTap,
|
|
}) => DepartureArrivalTile(
|
|
product: a.product,
|
|
name: a.name,
|
|
towards: 'von ${a.origin}',
|
|
scheduled: a.scheduledTime,
|
|
realtime: a.realTime,
|
|
delayMinutes: a.delayMinutes,
|
|
track: a.track,
|
|
realTrack: a.realTrack,
|
|
cancelled: a.cancelled,
|
|
onTap: onTap,
|
|
);
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final effectiveTrack = (realTrack?.isNotEmpty ?? false)
|
|
? realTrack!
|
|
: (track ?? '');
|
|
final trackChanged =
|
|
realTrack != null && track != null && realTrack != track;
|
|
return ListTile(
|
|
onTap: onTap,
|
|
leading: SizedBox(
|
|
width: 72,
|
|
child: ProductChip(product: product, fallbackLabel: name),
|
|
),
|
|
title: Text(
|
|
towards,
|
|
maxLines: 1,
|
|
overflow: TextOverflow.ellipsis,
|
|
style: TextStyle(
|
|
decoration: cancelled ? TextDecoration.lineThrough : null,
|
|
),
|
|
),
|
|
subtitle: effectiveTrack.isEmpty
|
|
? null
|
|
: Row(
|
|
children: [
|
|
Icon(
|
|
Icons.directions_transit,
|
|
size: 14,
|
|
color: Theme.of(context).colorScheme.secondary,
|
|
),
|
|
const SizedBox(width: 4),
|
|
Text(
|
|
'Gleis $effectiveTrack',
|
|
style: TextStyle(
|
|
color: trackChanged
|
|
? Colors.red
|
|
: Theme.of(context).colorScheme.secondary,
|
|
fontWeight: trackChanged ? FontWeight.bold : null,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
trailing: RealtimeTime(
|
|
scheduled: scheduled,
|
|
realtime: realtime,
|
|
delayMinutes: delayMinutes,
|
|
cancelled: cancelled,
|
|
style: Theme.of(context).textTheme.titleMedium,
|
|
),
|
|
);
|
|
}
|
|
}
|