import 'package:flutter/material.dart'; import '../services/odoo_service.dart'; import '../theme/app_theme.dart'; import '../utils/safe_cast.dart'; class OrdersScreen extends StatefulWidget { const OrdersScreen({super.key}); @override State createState() => _OrdersScreenState(); } class _OrdersScreenState extends State { List _history = []; bool _isLoading = true; @override void initState() { super.initState(); _fetchHistory(); } Future _fetchHistory() async { if (mounted) setState(() => _isLoading = true); try { final history = await OdooService().getOrderHistory(); if (mounted) { setState(() { _history = history; _isLoading = false; }); } } catch (e) { if (mounted) { setState(() => _isLoading = false); final errStr = e.toString().toLowerCase(); final isSessionExpired = e.runtimeType.toString().contains('SessionExpired') || errStr.contains('session expired') || errStr.contains('session_expired'); if (!isSessionExpired) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Failed to load order history. Please try again.')), ); } } } } String _formatDate(String rawDate) { if (rawDate.isEmpty) return ''; try { final parsed = DateTime.parse(rawDate); final months = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec', ]; final year = parsed.year; final month = months[parsed.month - 1]; final day = parsed.day.toString().padLeft(2, '0'); final hour = parsed.hour.toString().padLeft(2, '0'); final minute = parsed.minute.toString().padLeft(2, '0'); return '$day $month $year, $hour:$minute'; } catch (_) { return rawDate; } } @override Widget build(BuildContext context) { final theme = Theme.of(context); if (_isLoading) { return const Scaffold(body: Center(child: CircularProgressIndicator())); } return Scaffold( appBar: AppBar(title: const Text('Order & Points History')), body: RefreshIndicator( onRefresh: _fetchHistory, child: _history.isEmpty ? CustomScrollView( physics: const AlwaysScrollableScrollPhysics(), slivers: [ SliverFillRemaining( hasScrollBody: false, child: Center( child: Padding( padding: const EdgeInsets.all(40), child: Column( mainAxisSize: MainAxisSize.min, children: [ Container( padding: const EdgeInsets.all(28), decoration: const BoxDecoration( color: AppTheme.surfaceContainerLow, shape: BoxShape.circle, ), child: const Icon( Icons.receipt_long_rounded, size: 56, color: AppTheme.secondary, ), ), const SizedBox(height: 28), Text( 'No Orders Yet', style: theme.textTheme.headlineMedium, ), const SizedBox(height: 12), Text( 'Your order history and points transactions will show up here after you make purchases.', style: theme.textTheme.bodyLarge?.copyWith( color: AppTheme.onSurfaceVariant, height: 1.6, ), textAlign: TextAlign.center, ), ], ), ), ), ), ], ) : ListView.builder( padding: const EdgeInsets.symmetric(vertical: 16), itemCount: _history.length, itemBuilder: (context, index) { final item = _history[index]; final isEarn = item['type'] == 'earn'; final orderRef = safeString(item['order_ref']) ?? ''; final rawDate = safeString(item['date']) ?? ''; final posName = safeString(item['pos_name']) ?? ''; final programType = safeString(item['program_type']) ?? 'loyalty'; final isSubscription = programType == 'subscription'; final programName = safeString(item['program_name']) ?? ''; return Card( margin: const EdgeInsets.symmetric( horizontal: 16, vertical: 6, ), color: AppTheme.surfaceContainerLow, child: ListTile( contentPadding: const EdgeInsets.symmetric( horizontal: 20, vertical: 12, ), leading: Container( padding: const EdgeInsets.all(10), decoration: BoxDecoration( color: (isEarn ? const Color(0xFF2E7D32) : const Color(0xFFC62828)) .withValues(alpha: 0.1), shape: BoxShape.circle, ), child: Icon( isEarn ? Icons.add_card_rounded : Icons.payment_rounded, color: isEarn ? const Color(0xFF2E7D32) : const Color(0xFFC62828), size: 24, ), ), title: Text( orderRef.isNotEmpty ? orderRef : 'Point Adjustment', style: theme.textTheme.titleMedium?.copyWith( fontWeight: FontWeight.bold, color: AppTheme.onSurface, ), ), subtitle: Padding( padding: const EdgeInsets.only(top: 6.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ if (posName.isNotEmpty) ...[ Row( children: [ Icon( Icons.storefront_rounded, size: 14, color: theme.colorScheme.primary, ), const SizedBox(width: 4), Text( posName, style: theme.textTheme.bodySmall?.copyWith( fontWeight: FontWeight.w600, color: theme.colorScheme.primary, ), ), ], ), const SizedBox(height: 4), ], Text( _formatDate(rawDate), style: theme.textTheme.bodySmall?.copyWith( color: AppTheme.onSurfaceVariant, ), ), const SizedBox(height: 6), Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3), decoration: BoxDecoration( color: isSubscription ? const Color(0xFF1B5E20).withValues(alpha: 0.08) : theme.colorScheme.primary.withValues(alpha: 0.08), borderRadius: BorderRadius.circular(12), border: Border.all( color: isSubscription ? const Color(0xFF1B5E20).withValues(alpha: 0.2) : theme.colorScheme.primary.withValues(alpha: 0.2), width: 0.5, ), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon( isSubscription ? Icons.local_activity_rounded : Icons.card_membership_rounded, size: 10, color: isSubscription ? const Color(0xFF2E7D32) : theme.colorScheme.primary, ), const SizedBox(width: 4), Text( isSubscription ? 'Subscription Claim' : (programName.isNotEmpty ? programName : 'Loyalty Program'), style: TextStyle( fontSize: 9, fontWeight: FontWeight.bold, letterSpacing: 0.5, color: isSubscription ? const Color(0xFF2E7D32) : theme.colorScheme.primary, ), ), ], ), ), ], ), ), trailing: Text( '${isEarn ? '+' : ''}${item['points']} pts', style: theme.textTheme.titleMedium?.copyWith( fontWeight: FontWeight.bold, color: isEarn ? const Color(0xFF2E7D32) : const Color(0xFFC62828), fontSize: 16, ), ), ), ); }, ), ), ); } }