// food_cart_page.dart — مراجعة السلة، عرض السعر الموقّع، وإنشاء الطلب import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:geolocator/geolocator.dart'; import '../../constant/box_name.dart'; import '../../constant/colors.dart'; import '../../constant/style.dart'; import '../../main.dart'; import '../../views/widgets/error_snakbar.dart'; import '../../controller/food/food_controller.dart'; import '../../controller/food/food_models.dart'; import '../widgets/my_scafold.dart'; import 'food_order_tracking_page.dart'; class FoodCartPage extends StatefulWidget { const FoodCartPage({super.key}); @override State createState() => _FoodCartPageState(); } class _FoodCartPageState extends State { final TextEditingController _addressController = TextEditingController(); final TextEditingController _noteController = TextEditingController(); String _paymentMethod = 'wallet'; Position? _position; bool _isFetchingLocation = false; bool get _isAr => box.read(BoxName.lang) == 'ar'; @override void initState() { super.initState(); _fetchLocation(); } Future _fetchLocation() async { setState(() => _isFetchingLocation = true); try { final permission = await Geolocator.checkPermission(); if (permission == LocationPermission.denied) { await Geolocator.requestPermission(); } _position = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high); } catch (_) { _position = null; } if (mounted) setState(() => _isFetchingLocation = false); } @override Widget build(BuildContext context) { return GetBuilder( builder: (c) => MyScafolld( title: _isAr ? 'السلة' : 'Cart', isleading: true, body: [ c.cartLines.isEmpty ? _emptyCart() : _cartContent(c), ], ), ); } Widget _emptyCart() { return Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.shopping_cart_outlined, size: 72, color: AppColor.grayColor), const SizedBox(height: 16), Text(_isAr ? 'سلتك فارغة' : 'Your cart is empty', style: AppStyle.title), ], ), ); } Widget _cartContent(FoodController c) { return Column( children: [ Expanded( child: ListView( padding: const EdgeInsets.all(16), children: [ ...c.cartLines.map((line) => _cartLineTile(c, line)), const SizedBox(height: 16), _summaryRow(_isAr ? 'المجموع الفرعي' : 'Subtotal', foodFormatPrice(c.cartTotal)), if (c.currentQuote != null) ...[ _summaryRow(_isAr ? 'رسوم التوصيل' : 'Delivery fee', foodFormatPrice(c.currentQuote!.deliveryFee)), const Divider(), _summaryRow(_isAr ? 'الإجمالي' : 'Total', foodFormatPrice(c.currentQuote!.grandTotal), bold: true), ], const SizedBox(height: 20), TextField( controller: _addressController, decoration: InputDecoration( labelText: _isAr ? 'عنوان التوصيل' : 'Delivery address', border: OutlineInputBorder(borderRadius: BorderRadius.circular(12)), suffixIcon: _isFetchingLocation ? const Padding( padding: EdgeInsets.all(12), child: SizedBox(width: 16, height: 16, child: CircularProgressIndicator(strokeWidth: 2)), ) : Icon(_position != null ? Icons.my_location_rounded : Icons.location_off_rounded, color: _position != null ? AppColor.greenColor : AppColor.redColor), ), ), const SizedBox(height: 12), TextField( controller: _noteController, decoration: InputDecoration( labelText: _isAr ? 'ملاحظات (اختياري)' : 'Notes (optional)', border: OutlineInputBorder(borderRadius: BorderRadius.circular(12)), ), ), const SizedBox(height: 16), _paymentMethodPicker(), ], ), ), Padding( padding: EdgeInsets.fromLTRB(16, 8, 16, MediaQuery.of(context).padding.bottom + 16), child: SizedBox( width: double.infinity, height: 52, child: ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: AppColor.primaryColor, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(14)), ), onPressed: c.isQuoting || c.isPlacingOrder ? null : () => _onCheckoutPressed(c), child: c.isPlacingOrder ? const CircularProgressIndicator(color: Colors.white) : Text( c.currentQuote == null ? (_isAr ? 'احسب السعر' : 'Get Quote') : '${_isAr ? "اطلب الآن" : "Place Order"} · ${foodFormatPrice(c.currentQuote!.grandTotal)}', style: const TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 16), ), ), ), ), ], ); } Future _onCheckoutPressed(FoodController c) async { if (c.currentQuote == null) { await c.refreshQuote(); return; } if (_addressController.text.trim().isEmpty) { mySnackbarWarning(_isAr ? 'أدخل عنوان التوصيل' : 'Enter a delivery address'); return; } if (_position == null) { mySnackbarWarning(_isAr ? 'تعذّر تحديد موقعك — فعّل خدمة الموقع' : 'Could not get your location — enable location services'); return; } final orderId = await c.placeOrder( deliveryAddress: _addressController.text.trim(), deliveryLat: _position!.latitude, deliveryLng: _position!.longitude, paymentMethod: _paymentMethod, customerNote: _noteController.text.trim(), ); if (orderId != null) { Get.offAll(() => FoodOrderTrackingPage(orderId: orderId)); } } Widget _cartLineTile(FoodController c, FoodCartLine line) { return Card( margin: const EdgeInsets.only(bottom: 10), color: AppColor.cardColor, elevation: 0, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(14), side: BorderSide(color: AppColor.borderColor), ), child: Padding( padding: const EdgeInsets.all(12), child: Row( children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(line.item.nameAr, style: AppStyle.title.copyWith(fontWeight: FontWeight.bold)), const SizedBox(height: 4), Text(foodFormatPrice(line.lineTotal), style: AppStyle.subtitle.copyWith(color: AppColor.accentColor)), ], ), ), IconButton( icon: const Icon(Icons.remove_circle_outline_rounded), onPressed: () => c.updateQuantity(line.lineKey, line.quantity - 1), ), Text(line.quantity.toString(), style: AppStyle.title), IconButton( icon: const Icon(Icons.add_circle_outline_rounded), onPressed: () => c.updateQuantity(line.lineKey, line.quantity + 1), ), ], ), ), ); } Widget _summaryRow(String label, String value, {bool bold = false}) { final style = bold ? AppStyle.title.copyWith(fontWeight: FontWeight.bold, fontSize: 18) : AppStyle.subtitle; return Padding( padding: const EdgeInsets.symmetric(vertical: 4), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [Text(label, style: style), Text(value, style: style)], ), ); } Widget _paymentMethodPicker() { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(_isAr ? 'طريقة الدفع' : 'Payment method', style: AppStyle.title.copyWith(fontWeight: FontWeight.bold)), RadioListTile( contentPadding: EdgeInsets.zero, value: 'wallet', groupValue: _paymentMethod, title: Text(_isAr ? 'المحفظة' : 'Wallet'), onChanged: (v) => setState(() => _paymentMethod = v!), ), RadioListTile( contentPadding: EdgeInsets.zero, value: 'cash', groupValue: _paymentMethod, title: Text(_isAr ? 'نقداً عند الاستلام' : 'Cash on delivery'), onChanged: (v) => setState(() => _paymentMethod = v!), ), ], ); } }