support new fields in adding
All checks were successful
All checks were successful
This commit is contained in:
@@ -27,10 +27,6 @@ class _TripsPageState extends State<TripsPage> {
|
||||
_tripLocoStatsFutures.clear();
|
||||
final data = context.read<DataService>();
|
||||
await data.fetchTripDetails();
|
||||
if (!mounted) return;
|
||||
for (final trip in data.tripDetails) {
|
||||
_tripStatsFuture(trip.id);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _renameTrip(TripDetail trip, String newName) async {
|
||||
@@ -42,10 +38,7 @@ class _TripsPageState extends State<TripsPage> {
|
||||
"trip_id": trip.id,
|
||||
"trip_name": newName,
|
||||
});
|
||||
await Future.wait([
|
||||
data.fetchTripDetails(),
|
||||
data.fetchTrips(),
|
||||
]);
|
||||
await data.fetchTripDetails();
|
||||
} catch (e) {
|
||||
messenger?.showSnackBar(
|
||||
SnackBar(content: Text('Failed to rename trip: $e')),
|
||||
@@ -54,10 +47,24 @@ class _TripsPageState extends State<TripsPage> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<TripLocoStat>> _tripStatsFuture(int tripId) {
|
||||
List<TripLocoStat> _cachedTripStats(
|
||||
TripDetail trip,
|
||||
TripSummary? summary,
|
||||
) {
|
||||
if (trip.locoStats.isNotEmpty) return trip.locoStats;
|
||||
if (summary?.locoStats.isNotEmpty == true) return summary!.locoStats;
|
||||
return const [];
|
||||
}
|
||||
|
||||
Future<List<TripLocoStat>> _loadTripStats(
|
||||
TripDetail trip,
|
||||
TripSummary? summary,
|
||||
) {
|
||||
final cached = _cachedTripStats(trip, summary);
|
||||
if (cached.isNotEmpty) return Future.value(cached);
|
||||
return _tripLocoStatsFutures.putIfAbsent(
|
||||
tripId,
|
||||
() => context.read<DataService>().fetchTripLocoStats(tripId),
|
||||
trip.id,
|
||||
() => context.read<DataService>().fetchTripLocoStats(trip.id),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -93,7 +100,10 @@ class _TripsPageState extends State<TripsPage> {
|
||||
Widget build(BuildContext context) {
|
||||
final data = context.watch<DataService>();
|
||||
final tripDetails = data.tripDetails;
|
||||
final tripSummaries = data.trips;
|
||||
final tripSummaries = data.tripList;
|
||||
final summaryById = {
|
||||
for (final summary in tripSummaries) summary.tripId: summary,
|
||||
};
|
||||
final showLoading = data.isTripDetailsLoading && tripDetails.isEmpty;
|
||||
|
||||
return RefreshIndicator(
|
||||
@@ -184,18 +194,25 @@ class _TripsPageState extends State<TripsPage> {
|
||||
}
|
||||
|
||||
final trip = tripDetails[index - 1];
|
||||
return _buildTripCard(context, trip);
|
||||
final summary = summaryById[trip.id];
|
||||
return _buildTripCard(context, trip, summary);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildTripCard(BuildContext context, TripDetail trip) {
|
||||
Widget _buildTripCard(
|
||||
BuildContext context,
|
||||
TripDetail trip,
|
||||
TripSummary? summary,
|
||||
) {
|
||||
final legs = trip.legs;
|
||||
final legCount = trip.legCount > 0 ? trip.legCount : legs.length;
|
||||
final legCount =
|
||||
trip.legCount > 0 ? trip.legCount : summary?.legCount ?? legs.length;
|
||||
final dateRange = _formatDateRange(legs);
|
||||
final endpoints = _formatEndpoints(legs);
|
||||
final statsFuture = _tripStatsFuture(trip.id);
|
||||
final stats = _cachedTripStats(trip, summary);
|
||||
final winnerCount = stats.where((e) => e.won).length;
|
||||
|
||||
return Card(
|
||||
child: Padding(
|
||||
@@ -245,50 +262,25 @@ class _TripsPageState extends State<TripsPage> {
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
FutureBuilder<List<TripLocoStat>>(
|
||||
future: statsFuture,
|
||||
builder: (context, snapshot) {
|
||||
final chips = <Widget>[
|
||||
_buildMetaChip(context, Icons.timeline, '$legCount legs'),
|
||||
if (dateRange != null)
|
||||
_buildMetaChip(context, Icons.calendar_month, dateRange),
|
||||
if (endpoints != null)
|
||||
_buildMetaChip(context, Icons.route, endpoints),
|
||||
];
|
||||
|
||||
final stats = snapshot.data ?? const [];
|
||||
final hasStats = stats.isNotEmpty;
|
||||
final loading =
|
||||
snapshot.connectionState == ConnectionState.waiting;
|
||||
|
||||
if (loading && !hasStats) {
|
||||
chips.add(
|
||||
_buildMetaChip(context, Icons.train, 'Loading traction...'),
|
||||
);
|
||||
} else if (hasStats) {
|
||||
final winnerCount = stats.where((e) => e.won).length;
|
||||
chips.add(
|
||||
_buildMetaChip(context, Icons.train, '${stats.length} had'),
|
||||
);
|
||||
chips.add(
|
||||
_buildMetaChip(
|
||||
context,
|
||||
Icons.emoji_events_outlined,
|
||||
'$winnerCount winners',
|
||||
),
|
||||
);
|
||||
} else if (snapshot.connectionState == ConnectionState.done) {
|
||||
chips.add(
|
||||
_buildMetaChip(context, Icons.train, 'No traction yet'),
|
||||
);
|
||||
}
|
||||
|
||||
return Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
children: chips,
|
||||
);
|
||||
},
|
||||
Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
children: [
|
||||
_buildMetaChip(context, Icons.timeline, '$legCount legs'),
|
||||
if (dateRange != null)
|
||||
_buildMetaChip(context, Icons.calendar_month, dateRange),
|
||||
if (endpoints != null)
|
||||
_buildMetaChip(context, Icons.route, endpoints),
|
||||
if (stats.isNotEmpty) ...[
|
||||
_buildMetaChip(context, Icons.train, '${stats.length} had'),
|
||||
_buildMetaChip(
|
||||
context,
|
||||
Icons.emoji_events_outlined,
|
||||
'$winnerCount winners',
|
||||
),
|
||||
] else
|
||||
_buildMetaChip(context, Icons.train, 'No traction yet'),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Align(
|
||||
@@ -301,7 +293,7 @@ class _TripsPageState extends State<TripsPage> {
|
||||
OutlinedButton.icon(
|
||||
icon: const Icon(Icons.train),
|
||||
label: const Text('Locos'),
|
||||
onPressed: () => _showTripWinners(context, trip),
|
||||
onPressed: () => _showTripWinners(context, trip, summary),
|
||||
),
|
||||
FilledButton.icon(
|
||||
icon: const Icon(Icons.open_in_new),
|
||||
@@ -532,14 +524,19 @@ class _TripsPageState extends State<TripsPage> {
|
||||
);
|
||||
}
|
||||
|
||||
void _showTripWinners(BuildContext context, TripDetail trip) {
|
||||
void _showTripWinners(
|
||||
BuildContext context,
|
||||
TripDetail trip,
|
||||
TripSummary? summary,
|
||||
) {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
builder: (_) {
|
||||
return SafeArea(
|
||||
child: FutureBuilder<List<TripLocoStat>>(
|
||||
future: _tripStatsFuture(trip.id),
|
||||
future: _loadTripStats(trip, summary),
|
||||
initialData: _cachedTripStats(trip, summary),
|
||||
builder: (ctx, snapshot) {
|
||||
final items = snapshot.data ?? [];
|
||||
final loading =
|
||||
|
||||
Reference in New Issue
Block a user