import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../providers/auth_provider.dart'; import '../providers/dashboard_provider.dart'; import '../providers/mark_list_provider.dart'; import 'mark_list_screen.dart'; class DashboardScreen extends StatefulWidget { const DashboardScreen({super.key}); @override State createState() => _DashboardScreenState(); } class _DashboardScreenState extends State { @override void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) async { final auth = Provider.of(context, listen: false); // STEP 1: Try refresh token BEFORE any API calls await auth.tryRefreshToken(context); // STEP 2: Now safe to load dashboard final dash = Provider.of(context, listen: false); dash.init(context); await dash.loadSummary(context); // STEP 3: Load marks AFTER refresh final marks = Provider.of(context, listen: false); marks.init(context); await marks.loadMarks(context); }); } void _showAddMarkForm() { final markCtrl = TextEditingController(); final originCtrl = TextEditingController(); final destCtrl = TextEditingController(); showModalBottomSheet( context: context, isScrollControlled: true, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(18)), builder: (_) { return Padding( padding: EdgeInsets.fromLTRB( 18, 18, 18, MediaQuery.of(context).viewInsets.bottom + 20, ), child: Column( mainAxisSize: MainAxisSize.min, children: [ const Text( "Add Mark No", style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), ), const SizedBox(height: 16), TextField(controller: markCtrl, decoration: const InputDecoration(labelText: "Mark No")), const SizedBox(height: 12), TextField(controller: originCtrl, decoration: const InputDecoration(labelText: "Origin")), const SizedBox(height: 12), TextField(controller: destCtrl, decoration: const InputDecoration(labelText: "Destination")), const SizedBox(height: 20), ElevatedButton( onPressed: () async { final mark = markCtrl.text.trim(); final origin = originCtrl.text.trim(); final dest = destCtrl.text.trim(); if (mark.isEmpty || origin.isEmpty || dest.isEmpty) { ScaffoldMessenger.of(context) .showSnackBar(const SnackBar(content: Text("All fields required"))); return; } final provider = Provider.of(context, listen: false); final res = await provider.addMark(context, mark, origin, dest); if (res['success'] == true) { Navigator.pop(context); } else { final msg = res['message'] ?? "Failed"; ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(msg))); } }, child: const Text("Submit"), ), ], ), ); }, ); } @override Widget build(BuildContext context) { final auth = Provider.of(context); final dash = Provider.of(context); final marks = Provider.of(context); final name = auth.user?['customer_name'] ?? 'User'; if (dash.loading) { return const Center(child: CircularProgressIndicator()); } return SingleChildScrollView( padding: const EdgeInsets.all(18), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // HEADER Text( "Welcome, $name 👋", style: const TextStyle(fontSize: 20, fontWeight: FontWeight.w600), ), const SizedBox(height: 20), // ORDER SUMMARY Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ _statBox("Active", dash.activeOrders, Colors.blue), _statBox("In Transit", dash.inTransitOrders, Colors.orange), _statBox("Delivered", dash.deliveredOrders, Colors.green), ], ), const SizedBox(height: 20), _valueCard("Total Value", dash.totalValue), const SizedBox(height: 10), _valueCard("Raw Amount", "₹${dash.totalRaw.toStringAsFixed(2)}"), const SizedBox(height: 30), // ADD + VIEW ALL BUTTONS SIDE BY SIDE Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ ElevatedButton.icon( icon: const Icon(Icons.add), label: const Text("Add Mark No"), onPressed: _showAddMarkForm, ), if (marks.marks.length > 0) TextButton( onPressed: () { Navigator.push( context, MaterialPageRoute(builder: (_) => const MarkListScreen()), ); }, child: const Text( "View All →", style: TextStyle( fontSize: 16, color: Colors.indigo, fontWeight: FontWeight.w600, ), ), ), ], ), const SizedBox(height: 20), // MARK LIST (only 10 latest) const Text( "Latest Mark Numbers", style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), ), const SizedBox(height: 10), if (marks.loading) const Center(child: CircularProgressIndicator()) else Column( children: List.generate( marks.marks.length > 10 ? 10 : marks.marks.length, (i) { final m = marks.marks[i]; return Card( child: ListTile( title: Text(m['mark_no']), subtitle: Text("${m['origin']} → ${m['destination']}"), trailing: Text( m['status'], style: const TextStyle(color: Colors.indigo), ), ), ); }, ), ), const SizedBox(height: 30), ], ), ); } // UI WIDGETS Widget _statBox(String title, int value, Color color) { return Container( width: 110, padding: const EdgeInsets.all(14), decoration: BoxDecoration( color: color.withOpacity(0.15), borderRadius: BorderRadius.circular(12), ), child: Column( children: [ Text(value.toString(), style: const TextStyle(fontSize: 22, fontWeight: FontWeight.bold)), const SizedBox(height: 4), Text(title, style: const TextStyle(fontSize: 14)), ], ), ); } Widget _valueCard(String title, String value) { return Container( width: double.infinity, padding: const EdgeInsets.all(18), decoration: BoxDecoration( color: Colors.indigo.shade50, borderRadius: BorderRadius.circular(12), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(title, style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: Colors.grey)), const SizedBox(height: 6), Text( value, style: const TextStyle( fontSize: 24, fontWeight: FontWeight.bold, color: Colors.indigo, ), ), ], ), ); } }