import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import '../../core/menu_item_visual.dart'; import '../../core/utils/currency_utils.dart'; import '../public/public_api.dart'; import '../cart/cart_state.dart'; import '../table/table_context.dart'; final menuProvider = FutureProvider.autoDispose.family?, String>((ref, slug) { return ref.watch(publicApiProvider).getMenu(slug); }); int _salePrice(int price, num discountPercent) { if (discountPercent <= 0) return price; return (price * (1 - discountPercent / 100)).round(); } String? _imageUrl(String? path) { if (path == null || path.isEmpty) return null; if (path.startsWith('http')) return path; const base = String.fromEnvironment('API_BASE', defaultValue: 'http://10.0.2.2:5080'); return '$base$path'; } String _menuPrimaryName(Map item, String languageCode) { final fa = item['name'] as String? ?? ''; final en = item['nameEn'] as String? ?? ''; final ar = item['nameAr'] as String? ?? ''; if (languageCode == 'en') return en.isNotEmpty ? en : fa; if (languageCode == 'ar') return ar.isNotEmpty ? ar : fa; return fa; } String? _menuEnglishSubtitle(Map item, String languageCode) { final en = (item['nameEn'] as String?)?.trim() ?? ''; if (en.isEmpty || languageCode == 'en') return null; final primary = _menuPrimaryName(item, languageCode); if (primary == en) return null; return en; } class MenuScreen extends ConsumerStatefulWidget { const MenuScreen({super.key, required this.slug, this.tableId, this.tableNumber}); final String slug; final String? tableId; final String? tableNumber; @override ConsumerState createState() => _MenuScreenState(); } class _MenuScreenState extends ConsumerState { bool _contextSet = false; @override Widget build(BuildContext context) { final menuAsync = ref.watch(menuProvider(widget.slug)); final cart = ref.watch(cartProvider); final tableLabel = widget.tableNumber; return Directionality( textDirection: TextDirection.rtl, child: Scaffold( backgroundColor: const Color(0xFFF8FAFB), appBar: AppBar( backgroundColor: Colors.white, foregroundColor: const Color(0xFF0F6E56), elevation: 0, title: Text(tableLabel != null ? 'منو — میز $tableLabel' : 'منو'), actions: [ IconButton( icon: const Icon(Icons.event_seat_outlined), onPressed: () => context.push('/cafe/${widget.slug}/reserve'), ), if (cart.itemCount > 0) TextButton( onPressed: () => context.push('/cafe/${widget.slug}/cart'), child: Text('سبد (${cart.itemCount})'), ), ], ), body: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ if (tableLabel != null) Container( margin: const EdgeInsets.fromLTRB(16, 8, 16, 0), padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), decoration: BoxDecoration( color: const Color(0xFFE1F5EE), borderRadius: BorderRadius.circular(12), border: Border.all(color: const Color(0xFF0F6E56).withValues(alpha: 0.3)), ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.table_restaurant, color: Color(0xFF0F6E56), size: 20), const SizedBox(width: 8), Text( 'میز $tableLabel', style: const TextStyle( color: Color(0xFF0F6E56), fontWeight: FontWeight.w600, fontSize: 14, ), ), ], ), ), Expanded( child: menuAsync.when( data: (menu) { if (menu == null) return const Center(child: Text('منو یافت نشد')); if (!_contextSet) { _contextSet = true; WidgetsBinding.instance.addPostFrameCallback((_) { ref.read(cartProvider.notifier).setContext( slug: widget.slug, cafeName: menu['cafeName'] as String? ?? widget.slug, tableId: widget.tableId, tableNumber: tableLabel != null ? int.tryParse(tableLabel) : null, ); if (widget.tableId != null) { ref.read(tableContextProvider.notifier).setTable( tableId: widget.tableId!, tableNumber: tableLabel ?? '', cafeSlug: widget.slug, ); } }); } final categories = menu['categories'] as List? ?? []; final lang = Localizations.localeOf(context).languageCode; return ListView( padding: const EdgeInsets.all(16), children: [ for (final cat in categories) ...[ Padding( padding: const EdgeInsets.only(bottom: 8, top: 4), child: Text( _menuPrimaryName(cat as Map, lang), style: const TextStyle( fontSize: 11, fontWeight: FontWeight.w600, letterSpacing: 0.6, color: Color(0xFF64748B), ), ), ), ...((cat['items'] as List? ?? []).map((item) { final id = item['id'] as String; final catMap = cat as Map; final catId = catMap['id'] as String? ?? ''; final catName = _menuPrimaryName(catMap, lang); final name = _menuPrimaryName(item as Map, lang); final nameEnSub = _menuEnglishSubtitle(item as Map, lang); final price = (item['price'] as num).toInt(); final discount = (item['discountPercent'] as num?) ?? 0; final sale = _salePrice(price, discount); final img = _imageUrl(item['imageUrl'] as String?); final video = _imageUrl(item['videoUrl'] as String?); final visualKind = inferMenuItemKind( categoryId: catId, categoryName: catName, ); return Card( margin: const EdgeInsets.only(bottom: 12), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), side: BorderSide(color: Colors.grey.shade200), ), clipBehavior: Clip.antiAlias, child: InkWell( onTap: () { ref.read(cartProvider.notifier).addItem( CartLine( menuItemId: id, name: name, unitPrice: sale, ), ); ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('$name به سبد اضافه شد')), ); }, child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Stack( children: [ AspectRatio( aspectRatio: 16 / 9, child: img != null ? Image.network(img, fit: BoxFit.cover) : Container( color: visualKind == MenuItemVisualKind.drink ? const Color(0xFFE8F4F8) : const Color(0xFFF5F0EB), child: Icon( visualKind == MenuItemVisualKind.drink ? Icons.local_cafe_outlined : Icons.restaurant_outlined, size: 48, color: const Color(0xFF0F6E56).withValues(alpha: 0.45), ), ), ), if (video != null) Positioned( bottom: 8, right: 8, child: Container( padding: const EdgeInsets.symmetric( horizontal: 8, vertical: 4, ), decoration: BoxDecoration( color: Colors.black.withValues(alpha: 0.65), borderRadius: BorderRadius.circular(6), ), child: const Row( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.play_circle_outline, size: 14, color: Colors.white), SizedBox(width: 4), Text( 'ویدیو', style: TextStyle( fontSize: 11, color: Colors.white, ), ), ], ), ), ), if (discount > 0) Positioned( top: 8, left: 8, child: Container( padding: const EdgeInsets.symmetric( horizontal: 8, vertical: 4, ), decoration: BoxDecoration( color: const Color(0xFFFFF8E8), borderRadius: BorderRadius.circular(6), border: Border.all(color: const Color(0xFFBA7517)), ), child: Text( '${discount.toInt()}٪ تخفیف', style: const TextStyle( fontSize: 11, fontWeight: FontWeight.w600, color: Color(0xFFBA7517), ), ), ), ), ], ), Padding( padding: const EdgeInsets.all(12), child: Row( children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( name, style: const TextStyle( fontWeight: FontWeight.w600, fontSize: 14, ), ), if (nameEnSub != null) ...[ const SizedBox(height: 2), Text( nameEnSub, style: TextStyle( fontSize: 11, color: Colors.grey.shade600, ), ), ], const SizedBox(height: 4), Row( children: [ if (discount > 0) ...[ Text( formatToman(price), style: TextStyle( fontSize: 12, color: Colors.grey.shade500, decoration: TextDecoration.lineThrough, ), ), const SizedBox(width: 8), ], Text( formatToman(sale), style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: Color(0xFF0F6E56), ), ), ], ), ], ), ), const Icon( Icons.add_circle, color: Color(0xFF0F6E56), size: 32, ), ], ), ), ], ), ), ); })), const SizedBox(height: 8), ], ], ); }, loading: () => const Center(child: CircularProgressIndicator()), error: (e, _) => Center(child: Text('خطا: $e')), ), ), ], ), floatingActionButton: cart.itemCount > 0 ? FloatingActionButton.extended( backgroundColor: const Color(0xFF0F6E56), onPressed: () => context.push('/cafe/${widget.slug}/cart'), label: Text('سبد — ${formatToman(cart.subtotal)}'), icon: const Icon(Icons.shopping_cart), ) : null, ), ); } }