import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import '../../database/database.dart'; import '../../models/motorcycle_models.dart'; import '../../core/theme/evolution_theme_config.dart'; import 'garage_providers.dart'; import 'widgets/motorcycle_photo.dart'; import '../../services/entitlements/entitlement_providers.dart'; import '../../services/entitlements/feature_access_service.dart'; import '../entitlements/widgets/pro_lock_badge.dart'; class GarageScreen extends ConsumerWidget { const GarageScreen({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final bikesAsync = ref.watch(garageMotorcyclesStreamProvider); final themeMode = ref.watch(dashboardThemeModeProvider); return Scaffold( backgroundColor: themeMode == DashboardThemeMode.evolution ? Colors.black : null, appBar: AppBar( backgroundColor: themeMode == DashboardThemeMode.evolution ? Colors.transparent : null, elevation: 0, title: Text( 'My Garage', style: TextStyle( fontFamily: themeMode == DashboardThemeMode.evolution ? 'Sora' : null, fontWeight: FontWeight.bold, ), ), actions: [ IconButton( icon: const Icon( Icons.add_circle_outline, color: Color(0xFF00E5FF), ), tooltip: 'Add Motorcycle', onPressed: () => _onAddMotorcycle(context, ref, bikesAsync.value), ), ], ), body: bikesAsync.when( loading: () => const Center(child: CircularProgressIndicator()), error: (err, stack) => Center(child: Text('Error loading garage: $err')), data: (bikes) { if (bikes.isEmpty) return _buildEmptyState(context); return ListView.builder( padding: const EdgeInsets.all(16.0), itemCount: bikes.length, itemBuilder: (context, index) { return _buildMotorcycleCard( context, ref, bikes[index], themeMode, ); }, ); }, ), floatingActionButton: bikesAsync.value != null && bikesAsync.value!.isNotEmpty ? FloatingActionButton.extended( backgroundColor: Colors.cyanAccent, foregroundColor: Colors.black, icon: const Icon(Icons.two_wheeler), label: const Text( 'ADD MOTORCYCLE', style: TextStyle(fontWeight: FontWeight.bold), ), onPressed: () => _onAddMotorcycle(context, ref, bikesAsync.value), ) : null, ); } void _onAddMotorcycle( BuildContext context, WidgetRef ref, List? bikes, ) { if (bikes != null && bikes.isNotEmpty) { final canAddMore = ref .read(featureAccessProvider) .canAccess(MotorSignalFeature.useMultipleMotorcycles); if (!canAddMore) { showProUpgradeSheet( context, ref, feature: MotorSignalFeature.useMultipleMotorcycles, ); return; } } context.push('/garage/add'); } Widget _buildEmptyState(BuildContext context) { return Center( child: Padding( padding: const EdgeInsets.all(32.0), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.two_wheeler, size: 80, color: Colors.white24), const SizedBox(height: 24), const Text( 'YOUR GARAGE IS EMPTY', style: TextStyle( fontSize: 20, fontWeight: FontWeight.bold, letterSpacing: 1.5, ), ), const SizedBox(height: 12), const Text( 'Add your motorcycle to personalize your ride history and performance data.', textAlign: TextAlign.center, style: TextStyle(color: Colors.white70, height: 1.4), ), const SizedBox(height: 32), ElevatedButton.icon( style: ElevatedButton.styleFrom( backgroundColor: Colors.cyanAccent, foregroundColor: Colors.black, padding: const EdgeInsets.symmetric( horizontal: 24, vertical: 14, ), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), ), icon: const Icon(Icons.add), label: const Text( 'ADD MOTORCYCLE', style: TextStyle( fontWeight: FontWeight.bold, letterSpacing: 1.2, ), ), onPressed: () => context.push('/garage/add'), ), ], ), ), ); } Widget _buildMotorcycleCard( BuildContext context, WidgetRef ref, GarageMotorcycle bike, DashboardThemeMode themeMode, ) { MotorcycleSpecification? spec; if (bike.specificationJson != null) { try { spec = MotorcycleSpecification.fromJson( json.decode(bike.specificationJson!), ); } catch (_) {} } final displayName = bike.nickname != null && bike.nickname!.isNotEmpty ? '${bike.nickname} (${bike.year} ${bike.makeName} ${bike.modelName})' : '${bike.year} ${bike.makeName} ${bike.modelName}'; final isEvolution = themeMode == DashboardThemeMode.evolution; return Container( margin: const EdgeInsets.only(bottom: 16), decoration: BoxDecoration( color: isEvolution ? const Color(0xFF0D0D0D) : null, borderRadius: BorderRadius.circular(isEvolution ? 14 : 12), border: Border.all( color: bike.isDefault ? const Color(0xFF00E5FF) : (isEvolution ? const Color(0xFF1F1F1F) : Colors.white12), width: bike.isDefault ? 1.8 : 1.0, ), ), child: Material( color: Colors.transparent, child: InkWell( borderRadius: BorderRadius.circular(isEvolution ? 14 : 12), onTap: () => context.push('/garage/${bike.id}'), child: Padding( padding: const EdgeInsets.all(12.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ MotorcyclePhoto( year: bike.year, make: bike.makeName, model: bike.modelName, height: 190, borderRadius: BorderRadius.circular(isEvolution ? 10 : 8), ), const SizedBox(height: 14), Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Expanded( child: Text( displayName, style: TextStyle( fontFamily: isEvolution ? 'Sora' : null, fontSize: 17, fontWeight: FontWeight.w800, color: Colors.white, ), ), ), if (bike.isDefault) Container( padding: const EdgeInsets.symmetric( horizontal: 8, vertical: 2, ), decoration: BoxDecoration( color: const Color( 0xFF00E5FF, ).withValues(alpha: 0.15), borderRadius: BorderRadius.circular(4), border: Border.all( color: const Color(0xFF00E5FF), ), ), child: const Text( 'CURRENT', style: TextStyle( fontFamily: 'Inter', fontSize: 10, fontWeight: FontWeight.w900, color: Color(0xFF00E5FF), letterSpacing: 0.5, ), ), ), ], ), const SizedBox(height: 6), Text( spec != null ? '${spec.displacementCc?.toStringAsFixed(0) ?? "—"} cc • ${spec.horsepower?.toStringAsFixed(0) ?? "—"} hp' : '${bike.year} • ${bike.makeName}', style: TextStyle( fontFamily: isEvolution ? 'JetBrains Mono' : null, color: isEvolution ? const Color(0xFF00E5FF) : Colors.white70, fontSize: 13, fontWeight: isEvolution ? FontWeight.w700 : FontWeight.normal, ), ), ], ), ), ], ), const SizedBox(height: 12), Wrap( alignment: WrapAlignment.spaceBetween, crossAxisAlignment: WrapCrossAlignment.center, spacing: 8, runSpacing: 4, children: [ TextButton.icon( icon: const Icon(Icons.directions_bike, size: 18), label: const Text('View Specs & Stats'), onPressed: () => context.push('/garage/${bike.id}'), ), if (!bike.isDefault) OutlinedButton( style: OutlinedButton.styleFrom( foregroundColor: Colors.white, side: const BorderSide(color: Colors.white30), ), onPressed: () { ref .read(garageControllerProvider) .setDefaultMotorcycle(bike.id); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text( 'Set ${bike.makeName} ${bike.modelName} as current motorcycle.', ), ), ); }, child: const Text('Set as Current'), ), ], ), ], ), ), ), ), ); } }