// food_home_page.dart — الصفحة الرئيسية لتبويب "طعام": تصفح المطاعم import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../../constant/box_name.dart'; import '../../constant/colors.dart'; import '../../constant/style.dart'; import '../../main.dart'; import '../../controller/food/food_controller.dart'; import '../../controller/food/food_models.dart'; import '../widgets/my_scafold.dart'; import 'food_merchant_page.dart'; import 'food_cart_page.dart'; import 'food_order_history_page.dart'; class FoodHomePage extends StatelessWidget { const FoodHomePage({super.key}); bool get _isAr => box.read(BoxName.lang) == 'ar'; @override Widget build(BuildContext context) { final c = Get.put(FoodController()); c.fetchMerchants(); return GetBuilder( builder: (c) => MyScafolld( title: _isAr ? 'طعام' : 'Food', isleading: true, action: Row( mainAxisSize: MainAxisSize.min, children: [ IconButton( icon: Icon(Icons.history_rounded, color: AppColor.primaryColor), onPressed: () => Get.to(() => const FoodOrderHistoryPage()), ), Stack( clipBehavior: Clip.none, children: [ IconButton( icon: Icon(Icons.shopping_cart_rounded, color: AppColor.primaryColor), onPressed: () => Get.to(() => const FoodCartPage()), ), if (c.cartItemsCount > 0) Positioned( right: 4, top: 4, child: Container( padding: const EdgeInsets.all(4), decoration: const BoxDecoration(color: AppColor.redColor, shape: BoxShape.circle), constraints: const BoxConstraints(minWidth: 18, minHeight: 18), child: Text( c.cartItemsCount.toString(), textAlign: TextAlign.center, style: const TextStyle(color: Colors.white, fontSize: 11, fontWeight: FontWeight.bold), ), ), ), ], ), ], ), body: [ Column( children: [ Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: _citySearchBar(c), ), Expanded( child: RefreshIndicator( onRefresh: () => c.fetchMerchants(), child: c.isLoadingMerchants ? const Center(child: CircularProgressIndicator()) : c.merchants.isEmpty ? _emptyState() : ListView.builder( padding: const EdgeInsets.fromLTRB(16, 4, 16, 24), itemCount: c.merchants.length, itemBuilder: (_, i) => _merchantCard(c.merchants[i]), ), ), ), ], ), ], ), ); } Widget _citySearchBar(FoodController c) { return Row( children: [ Expanded( child: InkWell( onTap: () => _showCityPicker(c), child: Container( padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 12), decoration: BoxDecoration( color: AppColor.cardColor, borderRadius: BorderRadius.circular(12), border: Border.all(color: AppColor.borderColor), ), child: Row( children: [ Icon(Icons.location_on_rounded, color: AppColor.accentColor, size: 20), const SizedBox(width: 8), Expanded( child: Text(c.city, style: AppStyle.title, overflow: TextOverflow.ellipsis), ), Icon(Icons.keyboard_arrow_down_rounded, color: AppColor.grayColor), ], ), ), ), ), const SizedBox(width: 8), InkWell( onTap: () => _showSearchDialog(c), child: Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: AppColor.cardColor, borderRadius: BorderRadius.circular(12), border: Border.all(color: AppColor.borderColor), ), child: Icon(Icons.search_rounded, color: AppColor.primaryColor), ), ), ], ); } void _showCityPicker(FoodController c) { final controller = TextEditingController(text: c.city); Get.dialog( AlertDialog( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), title: Text(_isAr ? 'اختر المدينة' : 'Select City'), content: TextField( controller: controller, decoration: InputDecoration(hintText: _isAr ? 'اسم المدينة' : 'City name'), ), actions: [ TextButton(onPressed: () => Get.back(), child: Text(_isAr ? 'إلغاء' : 'Cancel')), ElevatedButton( onPressed: () { Get.back(); c.setCity(controller.text); }, child: Text(_isAr ? 'تم' : 'Done'), ), ], ), ); } void _showSearchDialog(FoodController c) { final controller = TextEditingController(); Get.dialog( AlertDialog( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), title: Text(_isAr ? 'بحث عن مطعم أو صنف' : 'Search restaurant or dish'), content: TextField( controller: controller, autofocus: true, decoration: InputDecoration(hintText: _isAr ? 'اكتب هنا...' : 'Type here...'), ), actions: [ TextButton(onPressed: () => Get.back(), child: Text(_isAr ? 'إلغاء' : 'Cancel')), ElevatedButton( onPressed: () { Get.back(); c.searchMerchants(controller.text); }, child: Text(_isAr ? 'بحث' : 'Search'), ), ], ), ); } Widget _emptyState() { return ListView( padding: const EdgeInsets.all(24), children: [ const SizedBox(height: 60), Icon(Icons.restaurant_menu_rounded, size: 72, color: AppColor.grayColor), const SizedBox(height: 16), Text( _isAr ? 'لا توجد مطاعم متاحة في هذه المدينة حالياً' : 'No restaurants available in this city yet', textAlign: TextAlign.center, style: AppStyle.title.copyWith(fontWeight: FontWeight.bold), ), ], ); } Widget _merchantCard(FoodMerchant m) { return Card( margin: const EdgeInsets.only(bottom: 12), color: AppColor.cardColor, elevation: 0, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), side: BorderSide(color: AppColor.borderColor), ), clipBehavior: Clip.antiAlias, child: InkWell( onTap: () => Get.to(() => FoodMerchantPage(merchantId: m.id)), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ if (m.coverUrl != null && m.coverUrl!.isNotEmpty) Image.network(m.coverUrl!, height: 120, width: double.infinity, fit: BoxFit.cover, errorBuilder: (_, __, ___) => Container(height: 120, color: AppColor.borderColor)), Padding( padding: const EdgeInsets.all(12), child: Row( children: [ CircleAvatar( radius: 24, backgroundColor: AppColor.accentColor.withOpacity(0.15), backgroundImage: (m.logoUrl != null && m.logoUrl!.isNotEmpty) ? NetworkImage(m.logoUrl!) : null, child: (m.logoUrl == null || m.logoUrl!.isEmpty) ? Icon(Icons.restaurant_rounded, color: AppColor.accentColor) : null, ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(m.nameAr, style: AppStyle.title.copyWith(fontWeight: FontWeight.bold)), const SizedBox(height: 4), Row( children: [ const Icon(Icons.star_rounded, color: Color(0xFFF59E0B), size: 16), const SizedBox(width: 2), Text(m.ratingAvg.toStringAsFixed(1), style: AppStyle.subtitle), const SizedBox(width: 10), Icon(Icons.access_time_rounded, size: 14, color: AppColor.grayColor), const SizedBox(width: 2), Text('${m.avgPrepMinutes} ${_isAr ? "د" : "min"}', style: AppStyle.subtitle), ], ), ], ), ), if (!m.isOpen) Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: AppColor.redColor.withOpacity(0.1), borderRadius: BorderRadius.circular(8), ), child: Text(_isAr ? 'مغلق' : 'Closed', style: TextStyle(color: AppColor.redColor, fontSize: 11, fontWeight: FontWeight.bold)), ), ], ), ), ], ), ), ); } }