MotorSignal-App/lib/features/history/history_screen.dart

114 lines
4.3 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'dart:math' as math;
import '../../database/database.dart';
import 'ride_detail_screen.dart';
class HistoryScreen extends ConsumerWidget {
const HistoryScreen({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final database = ref.watch(databaseProvider);
return Scaffold(
appBar: AppBar(title: const Text('Ride History')),
body: StreamBuilder<List<Ride>>(
stream: database.select(database.rides).watch(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(child: CircularProgressIndicator());
}
if (snapshot.hasError) {
return Center(child: Text('Error: ${snapshot.error}'));
}
final rides = snapshot.data ?? [];
// Sort by start time descending
rides.sort((a, b) => b.startTime.compareTo(a.startTime));
if (rides.isEmpty) {
return const Center(
child: Text(
'No recorded rides yet.',
style: TextStyle(fontSize: 18, color: Colors.grey),
),
);
}
return ListView.builder(
padding: const EdgeInsets.all(8),
itemCount: rides.length,
itemBuilder: (context, index) {
final ride = rides[index];
return Card(
elevation: 4,
margin: const EdgeInsets.symmetric(vertical: 8, horizontal: 4),
child: InkWell(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => RideDetailScreen(ride: ride),
),
);
},
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Ride ${ride.id}',
style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 18)
),
Text(
ride.startTime.toLocal().toString().split('.')[0],
style: const TextStyle(color: Colors.grey),
),
],
),
const Divider(),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_buildStatCol('TRIP', '${ride.distanceMiles.toStringAsFixed(1)} mi'),
_buildStatCol('TIME', '${(ride.movingTime / 60).toStringAsFixed(0)} min'),
_buildStatCol('TOP SPD', '${ride.topSpeedMph.toStringAsFixed(0)} mph'),
],
),
const SizedBox(height: 12),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_buildStatCol('MAX LEAN', '${math.max(ride.maxLeanLeft, ride.maxLeanRight).toStringAsFixed(0)}°'),
_buildStatCol('HARD BRK', '${ride.maxBrakingG.toStringAsFixed(2)}G'),
_buildStatCol('ELEV GAIN', '${ride.elevationGain.toStringAsFixed(0)}m'),
],
),
],
),
),
),
);
},
);
},
),
);
}
Widget _buildStatCol(String label, String val) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(label, style: const TextStyle(fontSize: 10, color: Colors.grey)),
Text(val, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
],
);
}
}