import 'package:flutter/material.dart'; import '../services/database_helper.dart'; import '../theme/theme_controller.dart'; import '../widgets/brand_mark.dart'; import 'analysis_screen.dart'; import 'live_analysis_screen.dart'; import 'static_capture_screen.dart'; import 'history_screen.dart'; class HomeScreen extends StatefulWidget { const HomeScreen({super.key}); @override State createState() => _HomeScreenState(); } class _HomeScreenState extends State { int? _totalScans; @override void initState() { super.initState(); _loadStats(); } Future _loadStats() async { final records = await DatabaseHelper().getAllRecords(); if (mounted) setState(() => _totalScans = records.length); } @override Widget build(BuildContext context) { final colorScheme = Theme.of(context).colorScheme; return Scaffold( body: SafeArea( child: SingleChildScrollView( padding: const EdgeInsets.all(20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ const BrandMark(size: 44), const SizedBox(width: 12), Expanded( child: Text( 'Palm Oil Ripeness AI', style: TextStyle( fontSize: 20, fontWeight: FontWeight.bold, color: colorScheme.onSurface, ), ), ), ValueListenableBuilder( valueListenable: ThemeController.themeMode, builder: (context, mode, _) { return IconButton( icon: Icon(_themeModeIcon(mode), color: colorScheme.onSurface), tooltip: 'Theme', onPressed: () => _showThemePicker(context, mode), ); }, ), ], ), const SizedBox(height: 20), _buildStatCard(colorScheme), const SizedBox(height: 24), GridView.count( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), crossAxisCount: 2, mainAxisSpacing: 16, crossAxisSpacing: 16, childAspectRatio: 0.95, children: [ _buildTile( context, title: 'Analyze Gallery', subtitle: 'Detect ripeness from photos', icon: Icons.photo_library, background: colorScheme.primary, foreground: colorScheme.onPrimary, onTap: () => Navigator.push( context, MaterialPageRoute(builder: (context) => const AnalysisScreen()), ), ), _buildTile( context, title: 'Snap & Analyze', subtitle: 'Manual high-res capture', icon: Icons.camera_alt, background: colorScheme.secondary, foreground: colorScheme.onSecondary, onTap: () => Navigator.push( context, MaterialPageRoute(builder: (context) => const StaticCaptureScreen()), ), ), _buildTile( context, title: 'Live Inference', subtitle: 'Real-time "Point-and-Scan"', icon: Icons.camera, background: colorScheme.primaryContainer, foreground: colorScheme.onPrimaryContainer, onTap: () => Navigator.push( context, MaterialPageRoute(builder: (context) => const LiveAnalysisScreen()), ), ), _buildTile( context, title: 'History Vault', subtitle: 'View previous detections', icon: Icons.history, background: colorScheme.surfaceContainerHighest, foreground: colorScheme.onSurface, bordered: true, onTap: () => Navigator.push( context, MaterialPageRoute(builder: (context) => const HistoryScreen()), ), ), ], ), ], ), ), ), ); } IconData _themeModeIcon(ThemeMode mode) { switch (mode) { case ThemeMode.light: return Icons.light_mode; case ThemeMode.dark: return Icons.dark_mode; case ThemeMode.system: return Icons.brightness_auto; } } Future _showThemePicker(BuildContext context, ThemeMode current) async { await showModalBottomSheet( context: context, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(20)), ), builder: (sheetContext) { return SafeArea( child: Column( mainAxisSize: MainAxisSize.min, children: [ const Padding( padding: EdgeInsets.fromLTRB(20, 20, 20, 8), child: Align( alignment: Alignment.centerLeft, child: Text("Theme", style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), ), ), _themeOptionTile(sheetContext, "Light", Icons.light_mode, ThemeMode.light, current), _themeOptionTile(sheetContext, "Dark", Icons.dark_mode, ThemeMode.dark, current), _themeOptionTile(sheetContext, "System", Icons.brightness_auto, ThemeMode.system, current), const SizedBox(height: 8), ], ), ); }, ); } Widget _themeOptionTile(BuildContext context, String label, IconData icon, ThemeMode mode, ThemeMode current) { final selected = mode == current; return ListTile( leading: Icon(icon), title: Text(label), trailing: selected ? const Icon(Icons.check) : null, onTap: () { ThemeController.setThemeMode(mode); Navigator.pop(context); }, ); } Widget _buildStatCard(ColorScheme colorScheme) { return Container( width: double.infinity, padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: colorScheme.surfaceContainerHighest, borderRadius: BorderRadius.circular(16), border: Border.all(color: colorScheme.primary.withOpacity(0.15)), ), child: Row( children: [ Icon(Icons.analytics_outlined, color: colorScheme.primary, size: 28), const SizedBox(width: 12), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( _totalScans == null ? '—' : '$_totalScans', style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold, color: colorScheme.onSurface), ), Text( 'Total Scans', style: TextStyle(fontSize: 13, color: colorScheme.onSurface.withOpacity(0.6)), ), ], ), ], ), ); } Widget _buildTile( BuildContext context, { required String title, required String subtitle, required IconData icon, required Color background, required Color foreground, required VoidCallback onTap, bool bordered = false, }) { return GestureDetector( onTap: onTap, child: Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: background, borderRadius: BorderRadius.circular(20), border: bordered ? Border.all(color: foreground.withOpacity(0.15)) : null, ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Icon(icon, color: foreground, size: 32), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title, style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: foreground), ), const SizedBox(height: 4), Text( subtitle, style: TextStyle(fontSize: 12, color: foreground.withOpacity(0.85)), ), ], ), ], ), ), ); } }