import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../app/app_state.dart'; import '../services/order_polling_service.dart'; /// In-app notification banner that shows order status updates class OrderStatusNotification extends StatefulWidget { const OrderStatusNotification({super.key}); @override State createState() => _OrderStatusNotificationState(); } class _OrderStatusNotificationState extends State with SingleTickerProviderStateMixin { OrderStatusUpdate? _latestUpdate; bool _isVisible = false; AnimationController? _animationController; Animation? _slideAnimation; @override void initState() { super.initState(); _animationController = AnimationController( vsync: this, duration: const Duration(milliseconds: 300), ); _slideAnimation = CurvedAnimation( parent: _animationController!, curve: Curves.easeOut, ); } @override void dispose() { _animationController?.dispose(); super.dispose(); } void _showNotification(OrderStatusUpdate update) { setState(() { _latestUpdate = update; _isVisible = true; }); _animationController?.forward(); // Auto-hide after 5 seconds Future.delayed(const Duration(seconds: 5), () { _hideNotification(); }); } void _hideNotification() { _animationController?.reverse().then((_) { if (mounted) { setState(() { _isVisible = false; _latestUpdate = null; }); } }); } Color _getStatusColor(int statusId) { switch (statusId) { case 1: // Submitted return Colors.blue; case 2: // Preparing return Colors.orange; case 3: // Ready return Colors.green; case 4: // Completed return Colors.purple; default: return Colors.grey; } } IconData _getStatusIcon(int statusId) { switch (statusId) { case 1: // Submitted return Icons.receipt_long; case 2: // Preparing return Icons.restaurant; case 3: // Ready return Icons.notifications_active; case 4: // Completed return Icons.check_circle; default: return Icons.info; } } @override Widget build(BuildContext context) { // Listen for status updates context.select((state) => state.activeOrderStatusId); if (!_isVisible || _latestUpdate == null) { return const SizedBox.shrink(); } final statusColor = _getStatusColor(_latestUpdate!.statusId); final statusIcon = _getStatusIcon(_latestUpdate!.statusId); return SlideTransition( position: Tween( begin: const Offset(0, -1), end: Offset.zero, ).animate(_slideAnimation!), child: Material( elevation: 8, color: Colors.transparent, child: Container( width: double.infinity, padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), decoration: BoxDecoration( color: statusColor, boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.2), blurRadius: 8, offset: const Offset(0, 2), ), ], ), child: SafeArea( child: Row( children: [ Icon( statusIcon, color: Colors.white, size: 28, ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ Text( _latestUpdate!.statusName, style: const TextStyle( color: Colors.white, fontSize: 16, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 4), Text( _latestUpdate!.message, style: const TextStyle( color: Colors.white, fontSize: 14, ), ), ], ), ), IconButton( icon: const Icon(Icons.close, color: Colors.white), onPressed: _hideNotification, ), ], ), ), ), ), ); } /// Static method to show notification from anywhere static void show(BuildContext context, OrderStatusUpdate update) { final state = context.findAncestorStateOfType<_OrderStatusNotificationState>(); state?._showNotification(update); } } /// Global key to access notification from anywhere final GlobalKey<_OrderStatusNotificationState> orderNotificationKey = GlobalKey();