import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../providers/order_provider.dart'; import 'order_detail_screen.dart'; import 'order_invoice_screen.dart'; import 'order_track_screen.dart'; class OrdersScreen extends StatefulWidget { const OrdersScreen({super.key}); @override State createState() => _OrdersScreenState(); } class _OrdersScreenState extends State { String searchQuery = ""; @override void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) { Provider.of(context, listen: false).loadOrders(); }); } @override Widget build(BuildContext context) { final provider = Provider.of(context); if (provider.loading) { return const Center(child: CircularProgressIndicator()); } final screenWidth = MediaQuery.of(context).size.width; final scale = (screenWidth / 420).clamp(0.85, 1.1); final filteredOrders = provider.orders.where((o) { final q = searchQuery.toLowerCase(); return o["order_id"].toString().toLowerCase().contains(q) || o["status"].toString().toLowerCase().contains(q) || o["description"].toString().toLowerCase().contains(q); }).toList(); return Column( children: [ _searchBar(scale), Expanded( child: ListView.builder( padding: EdgeInsets.all(14 * scale), itemCount: filteredOrders.length, itemBuilder: (context, i) { return _orderCard(filteredOrders[i], scale); }, ), ), ], ); } Widget _searchBar(double scale) { return Container( margin: EdgeInsets.fromLTRB(14 * scale, 14 * scale, 14 * scale, 8 * scale), padding: EdgeInsets.symmetric(horizontal: 12 * scale), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(14 * scale), boxShadow: [ BoxShadow( color: Colors.black12.withOpacity(0.1), blurRadius: 8 * scale, offset: const Offset(0, 3), ), ], ), child: Row( children: [ Icon(Icons.search, size: 20 * scale, color: Colors.grey.shade700), SizedBox(width: 8 * scale), Expanded( child: TextField( onChanged: (v) => setState(() => searchQuery = v), decoration: const InputDecoration( hintText: "Search orders...", border: InputBorder.none, ), ), ), ], ), ); } Widget _orderCard(Map o, double scale) { final progress = getProgress(o['status']); final percent = (progress * 100).toInt(); return Card( elevation: 2, margin: EdgeInsets.only(bottom: 12 * scale), color: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(14), ), child: Padding( padding: EdgeInsets.all(12 * scale), // 👈 tighter padding child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // HEADER Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Order #${o['order_id']}", style: TextStyle( fontSize: 15 * scale, // 👈 slightly smaller fontWeight: FontWeight.w600, ), ), getStatusBadge(o['status'], scale), ], ), SizedBox(height: 6 * scale), Text( o['description'], style: TextStyle(fontSize: 13 * scale), ), SizedBox(height: 4 * scale), Text( "₹${o['amount']}", style: TextStyle( fontSize: 15 * scale, fontWeight: FontWeight.w600, ), ), SizedBox(height: 12 * scale), // PROGRESS HEADER Align( alignment: Alignment.centerRight, child: Text( "$percent%", style: TextStyle( fontWeight: FontWeight.w600, fontSize: 11 * scale, color: Colors.grey.shade700, ), ), ), _AnimatedProgressBar(progress: progress, scale: scale), SizedBox(height: 6 * scale), // PROGRESS LABELS Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: const [ Text("Shipment Ready", style: TextStyle(fontSize: 10, color: Colors.grey)), Text("Import Custom", style: TextStyle(fontSize: 10, color: Colors.grey)), Text("Delivered", style: TextStyle(fontSize: 10, color: Colors.grey)), ], ), SizedBox(height: 12 * scale), // ACTIONS Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ _btn(Icons.visibility, "View", Colors.green.shade700, Colors.green.shade50, () => _openOrderDetails(o['order_id']), scale), _btn(Icons.receipt_long, "Invoice", Colors.orange.shade700, Colors.orange.shade50, () => _openInvoice(o['order_id']), scale), _btn(Icons.local_shipping, "Track", Colors.blue.shade700, Colors.blue.shade50, () => _openTrack(o['order_id']), scale), ], ), ], ), ), ); } Widget _btn( IconData icon, String text, Color fg, Color bg, VoidCallback onTap, double scale, ) { return InkWell( onTap: onTap, borderRadius: BorderRadius.circular(10), child: Container( constraints: BoxConstraints( minWidth: 115 * scale, // 👈 makes button wider minHeight: 36 * scale, // 👈 makes button taller ), padding: EdgeInsets.symmetric( horizontal: 16 * scale, // slightly more horizontal space vertical: 8 * scale, ), decoration: BoxDecoration( color: bg, borderRadius: BorderRadius.circular(10), ), child: Row( mainAxisAlignment: MainAxisAlignment.center, // 👈 centers content children: [ Icon(icon, size: 16 * scale, color: fg), SizedBox(width: 6 * scale), Text( text, style: TextStyle( color: fg, fontWeight: FontWeight.w600, fontSize: 12 * scale, ), ), ], ), ), ); } // ================= STATUS BADGE ================= Widget getStatusBadge(String? status, double scale) { final config = statusConfig(status); final isDomestic = (status ?? '').toLowerCase().contains("domestic"); return Container( padding: EdgeInsets.symmetric(horizontal: 10, vertical: 6), decoration: BoxDecoration( color: config.bg, borderRadius: BorderRadius.circular(12), ), child: Text( isDomestic ? "Domestic\nDistribution" : formatStatusLabel(status), textAlign: TextAlign.center, maxLines: isDomestic ? 2 : 1, style: TextStyle( color: config.fg, fontWeight: FontWeight.w600, fontSize: 11, height: 1.2, ), ), ); } void _openOrderDetails(String id) => Navigator.push(context, MaterialPageRoute(builder: (_) => OrderDetailScreen(orderId: id))); void _openInvoice(String id) => Navigator.push(context, MaterialPageRoute(builder: (_) => OrderInvoiceScreen(orderId: id))); void _openTrack(String id) => Navigator.push(context, MaterialPageRoute(builder: (_) => OrderTrackScreen(orderId: id))); } // ================= PROGRESS BAR ================= class _AnimatedProgressBar extends StatelessWidget { final double progress; final double scale; const _AnimatedProgressBar({required this.progress, required this.scale}); @override Widget build(BuildContext context) { return LayoutBuilder(builder: (context, c) { return Stack( children: [ Container( height: 8, // 👈 thinner bar decoration: BoxDecoration( color: Colors.grey.shade300, borderRadius: BorderRadius.circular(20), ), ), AnimatedContainer( duration: const Duration(milliseconds: 600), height: 8, width: c.maxWidth * progress, decoration: BoxDecoration( borderRadius: BorderRadius.circular(20), gradient: const LinearGradient( colors: [Color(0xFF4F8CFF), Color(0xFF8A4DFF)], ), ), ), ], ); }); } } // ================= STATUS LOGIC ================= double getProgress(String? status) { final s = (status ?? '').toLowerCase(); if (s.contains("shipment ready")) return 0.05; if (s.contains("export")) return 0.10; if (s.contains("international")) return 0.20; if (s.contains("arrived")) return 0.30; if (s.contains("import")) return 0.40; if (s.contains("warehouse")) return 0.50; if (s.contains("domestic")) return 0.60; if (s.contains("out for")) return 0.90; if (s.contains("delivered")) return 1.0; return 0.05; } _StatusConfig statusConfig(String? status) { final s = (status ?? '').toLowerCase(); if (s.contains("shipment ready")) { return _StatusConfig(Colors.blue.shade800, Colors.blue.shade50); } if (s.contains("export")) { return _StatusConfig(Colors.purple.shade800, Colors.purple.shade50); } if (s.contains("international")) { return _StatusConfig(Colors.red.shade800, Colors.red.shade50); } if (s.contains("arrived")) { return _StatusConfig(Colors.orange.shade800, Colors.orange.shade50); } if (s.contains("import")) { return _StatusConfig(Colors.teal.shade800, Colors.teal.shade50); } if (s.contains("warehouse")) { return _StatusConfig(Colors.brown.shade800, Colors.brown.shade50); } if (s.contains("domestic")) { return _StatusConfig(Colors.indigo.shade800, Colors.indigo.shade50); } if (s.contains("out for")) { return _StatusConfig(Colors.pink.shade800, Colors.pink.shade50); } if (s.contains("delivered")) { return _StatusConfig(Colors.green.shade800, Colors.green.shade50); } return _StatusConfig(Colors.grey.shade800, Colors.grey.shade300); } class _StatusConfig { final Color fg; final Color bg; _StatusConfig(this.fg, this.bg); } // ================= STATUS LABEL MAP ================= const Map statusLabelMap = { 'shipment_ready': 'Shipment Ready', 'export_custom': 'Export Custom', 'international_transit': 'International Transit', 'arrived_at_port': 'Arrived At Port', 'import_custom': 'Import Custom', 'warehouse': 'Warehouse Processing', 'domestic_distribution': 'Domestic Distribution', 'out_for_delivery': 'Out For Delivery', 'delivered': 'Delivered', }; String formatStatusLabel(String? status) { if (status == null || status.isEmpty) return "Unknown"; return statusLabelMap[status.toLowerCase()] ?? status.replaceAll('_', ' ').toUpperCase(); }