import 'package:Intaleq/constant/colors.dart'; import 'package:Intaleq/constant/links.dart'; import 'package:Intaleq/constant/style.dart'; import 'package:Intaleq/controller/home/map_passenger_controller.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; import 'package:intl/intl.dart'; import '../../../constant/box_name.dart'; import '../../../controller/firebase/notification_service.dart'; import '../../../controller/functions/launch.dart'; import '../../../main.dart'; class ApplyOrderWidget extends StatelessWidget { const ApplyOrderWidget({super.key}); @override Widget build(BuildContext context) { Color parseColor(String colorHex) { if (colorHex.isEmpty) return Colors.grey; try { String processedHex = colorHex.replaceFirst('#', '').trim(); if (processedHex.length == 6) processedHex = 'FF$processedHex'; return Color(int.parse('0x$processedHex')); } catch (e) { return Colors.grey; } } return Obx(() { final controller = Get.find(); final bool isVisible = controller.currentRideState.value == RideState.driverApplied || controller.currentRideState.value == RideState.driverArrived; return AnimatedPositioned( duration: const Duration(milliseconds: 500), curve: Curves.elasticOut, // تغيير: جعلنا الإخفاء للأسفل أقل حدة ليكون التحريك أسرع bottom: isVisible ? 0 : -400, left: 0, right: 0, child: Container( decoration: BoxDecoration( color: Theme.of(context).cardColor, borderRadius: const BorderRadius.vertical(top: Radius.circular(25)), boxShadow: [ BoxShadow( blurRadius: 20, spreadRadius: 1, color: Colors.black.withOpacity(0.1), offset: const Offset(0, -3), ) ], ), // تغيير: تقليل الحواف الخارجية بشكل كبير padding: const EdgeInsets.fromLTRB(16, 8, 16, 16), child: GetBuilder( builder: (c) { return Column( mainAxisSize: MainAxisSize.min, // مهم جداً: يأخذ أقل مساحة ممكنة children: [ // مقبض صغير Container( width: 40, height: 4, decoration: BoxDecoration( color: Colors.grey.withOpacity(0.3), borderRadius: BorderRadius.circular(10), ), ), const SizedBox(height: 10), // تقليل المسافة // 1. [تغيير جوهري] دمج السعر مع الحالة في صف واحد لتوفير المساحة _buildCompactHeaderRow(context, c), const SizedBox(height: 10), // مسافة مضغوطة // 2. كرت المعلومات المضغوط _buildCompactInfoCard(context, c, parseColor), const SizedBox(height: 10), // مسافة مضغوطة // 3. أزرار الاتصال (Slim) _buildCompactButtonsRow(context, c), const SizedBox(height: 10), // مسافة مضغوطة // 4. شريط الوقت c.currentRideState.value == RideState.driverArrived ? const DriverArrivePassengerAndWaitMinute() : const TimeDriverToPassenger(), ], ); }, ), ), ); }); } // --------------------------------------------------------------------------- // [NEW] 1. صف الرأس المضغوط (يحتوي الحالة + الإحصائيات + السعر) // --------------------------------------------------------------------------- Widget _buildCompactHeaderRow( BuildContext context, MapPassengerController controller) { // تنسيق السعر final formatter = NumberFormat("#,###"); String formattedPrice = formatter.format(controller.totalPassenger); // حساب الدقائق int minutes = (controller.timeToPassengerFromDriverAfterApplied / 60).ceil(); if (minutes < 1) minutes = 1; // تنسيق المسافة String distanceDisplay = ""; try { double distMeters = double.parse(controller.distanceByPassenger); if (distMeters >= 1000) { distanceDisplay = "${(distMeters / 1000).toStringAsFixed(1)} km"; } else { distanceDisplay = "${distMeters.toInt()} m"; } } catch (e) { distanceDisplay = controller.distanceByPassenger; } return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, children: [ // القسم الأيسر: الحالة + Chips Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Driver is on the way'.tr, style: AppStyle.subtitle.copyWith( color: Colors.grey[600], fontWeight: FontWeight.w600, fontSize: 13, // تصغير الخط ), ), const SizedBox(height: 6), Row( children: [ _buildMiniStatChip( icon: Icons.access_time_filled_rounded, text: "$minutes ${'min'.tr}", color: AppColor.primaryColor, bgColor: AppColor.primaryColor.withOpacity(0.1), ), const SizedBox(width: 8), _buildMiniStatChip( icon: Icons.near_me_rounded, text: distanceDisplay, color: Colors.orange[800]!, bgColor: Colors.orange.withOpacity(0.1), ), ], ), ], ), ), // القسم الأيمن: السعر (كبير وواضح في الزاوية) Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( formattedPrice, style: AppStyle.title.copyWith( fontSize: 24, // تصغير من 32 إلى 24 fontWeight: FontWeight.w900, color: AppColor.primaryColor, height: 1.0, ), ), Text( 'SYP'.tr, style: TextStyle( fontSize: 12, fontWeight: FontWeight.bold, color: Colors.grey[600], ), ), ], ), ], ); } Widget _buildMiniStatChip({ required IconData icon, required String text, required Color color, required Color bgColor, }) { return Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: bgColor, borderRadius: BorderRadius.circular(12), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon(icon, size: 12, color: color), // تصغير الأيقونة const SizedBox(width: 4), Text( text, style: TextStyle( color: color, fontWeight: FontWeight.bold, fontSize: 12, // تصغير الخط ), ), ], ), ); } // --------------------------------------------------------------------------- // [MODIFIED] 2. كرت المعلومات المضغوط جداً // --------------------------------------------------------------------------- Widget _buildCompactInfoCard(BuildContext context, MapPassengerController controller, Color Function(String) parseColor) { return Container( // تقليل الحواف الداخلية للكرت padding: const EdgeInsets.all(10), decoration: BoxDecoration( color: Theme.of(context).scaffoldBackgroundColor, borderRadius: BorderRadius.circular(16), border: Border.all(color: Colors.grey.withOpacity(0.1)), ), child: Column( children: [ // الصف العلوي: سائق + سيارة Row( children: [ // صورة السائق (أصغر) Container( decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all( color: AppColor.primaryColor.withOpacity(0.2), width: 2), ), child: CircleAvatar( radius: 22, // تصغير من 28 إلى 22 backgroundColor: Colors.grey[200], backgroundImage: NetworkImage( '${AppLink.server}/portrate_captain_image/${controller.driverId}.jpg'), onBackgroundImageError: (_, __) => const Icon(Icons.person, color: Colors.grey, size: 20), ), ), const SizedBox(width: 10), // معلومات نصية Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( controller.driverName, style: const TextStyle( fontSize: 15, // تصغير الخط fontWeight: FontWeight.bold, ), maxLines: 1, overflow: TextOverflow.ellipsis, ), const SizedBox(height: 2), Row( children: [ const Icon(Icons.star_rounded, color: Colors.amber, size: 14), Text( " ${controller.driverRate} • ${controller.model}", style: TextStyle( fontSize: 12, color: Colors.grey[700], fontWeight: FontWeight.w500, ), maxLines: 1, overflow: TextOverflow.ellipsis, ), ], ), ], ), ), // أيقونة السيارة (أصغر) _buildMicroCarIcon(controller, parseColor), ], ), const SizedBox(height: 8), // لوحة السيارة (شريط نحيف جداً) _buildSlimLicensePlate(controller.licensePlate), ], ), ); } Widget _buildMicroCarIcon( MapPassengerController controller, Color Function(String) parseColor) { Color carColor = parseColor(controller.colorHex); return Container( height: 40, // تصغير من 50 width: 40, decoration: BoxDecoration( color: carColor.withOpacity(0.1), borderRadius: BorderRadius.circular(8), ), padding: const EdgeInsets.all(4), child: ColorFiltered( colorFilter: ColorFilter.mode(carColor, BlendMode.srcIn), child: Image.asset( box.read(BoxName.carType) == 'Scooter' || box.read(BoxName.carType) == 'Pink Bike' ? 'assets/images/moto.png' : 'assets/images/car3.png', fit: BoxFit.contain, ), ), ); } Widget _buildSlimLicensePlate(String plateNumber) { return Container( width: double.infinity, padding: const EdgeInsets.symmetric(vertical: 2, horizontal: 8), decoration: BoxDecoration( color: const Color(0xFFF5F5F5), borderRadius: BorderRadius.circular(6), border: Border.all(color: Colors.grey.withOpacity(0.3)), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( plateNumber, style: const TextStyle( fontFamily: 'RobotoMono', fontSize: 18, // تصغير الرقم fontWeight: FontWeight.w900, color: Colors.black87, letterSpacing: 1.5, ), ), const Text("SYR", style: TextStyle( fontSize: 10, fontWeight: FontWeight.bold, color: Colors.black54)), ], ), ); } // --------------------------------------------------------------------------- // [MODIFIED] 3. أزرار الاتصال (Slim Buttons) // --------------------------------------------------------------------------- Widget _buildCompactButtonsRow( BuildContext context, MapPassengerController controller) { return SizedBox( height: 40, // تحديد ارتفاع ثابت وصغير للأزرار child: Row( children: [ Expanded( child: _buildSlimButton( label: 'Message'.tr, // اختصار الكلمة icon: Icons.chat_bubble_outline_rounded, color: AppColor.blueColor, bgColor: AppColor.blueColor.withOpacity(0.08), onTap: () => _showContactOptionsDialog(context, controller), ), ), const SizedBox(width: 10), // تقليل المسافة Expanded( child: _buildSlimButton( label: 'Call'.tr, // اختصار الكلمة icon: Icons.phone_rounded, color: Colors.white, bgColor: AppColor.greenColor, onTap: () { HapticFeedback.heavyImpact(); makePhoneCall(controller.driverPhone); }, isPrimary: true, ), ), ], ), ); } Widget _buildSlimButton({ required String label, required IconData icon, required Color color, required Color bgColor, required VoidCallback onTap, bool isPrimary = false, }) { return ElevatedButton( onPressed: onTap, style: ElevatedButton.styleFrom( backgroundColor: bgColor, foregroundColor: color, elevation: isPrimary ? 2 : 0, padding: EdgeInsets.zero, // إزالة الحواشي الداخلية shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(icon, size: 18, color: color), // تصغير الأيقونة const SizedBox(width: 6), Text( label, style: TextStyle( fontWeight: FontWeight.bold, fontSize: 14, // تصغير الخط color: color, ), ), ], ), ); } // --- النوافذ المنبثقة للرسائل (نفس الكود السابق مع تحسين بسيط) --- void _showContactOptionsDialog( BuildContext context, MapPassengerController controller) { Get.bottomSheet( Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: Theme.of(context).cardColor, borderRadius: const BorderRadius.vertical(top: Radius.circular(20)), ), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('Quick Message'.tr, style: AppStyle.title.copyWith(fontSize: 16)), const SizedBox(height: 15), ..._buildPredefinedMessages(controller), const Divider(height: 20), _buildCustomMessageInput(controller, context), SizedBox(height: MediaQuery.of(context).viewInsets.bottom), ], ), ), isScrollControlled: true, ); } List _buildPredefinedMessages(MapPassengerController controller) { const messages = [ 'Hello, I\'m at the agreed-upon location', 'I\'m waiting for you', "How much longer will you be?", ]; return messages .map((message) => Padding( padding: const EdgeInsets.only(bottom: 8.0), child: InkWell( onTap: () { _sendMessage(controller, message.tr); Get.back(); }, child: Container( padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 12), decoration: BoxDecoration( color: Colors.grey.withOpacity(0.08), borderRadius: BorderRadius.circular(8), border: Border.all(color: Colors.grey.withOpacity(0.1)), ), child: Row( children: [ Icon(Icons.chat_bubble_outline, size: 16, color: AppColor.primaryColor), const SizedBox(width: 10), Expanded( child: Text(message.tr, style: AppStyle.subtitle.copyWith(fontSize: 13))), ], ), ), ), )) .toList(); } Widget _buildCustomMessageInput( MapPassengerController controller, BuildContext context) { return Row( children: [ Expanded( child: Container( height: 40, padding: const EdgeInsets.symmetric(horizontal: 12), decoration: BoxDecoration( color: Colors.grey.withOpacity(0.08), borderRadius: BorderRadius.circular(20), ), child: Form( key: controller.messagesFormKey, child: TextFormField( controller: controller.messageToDriver, decoration: InputDecoration( hintText: 'Type your message...'.tr, hintStyle: TextStyle(color: Colors.grey[500], fontSize: 13), border: InputBorder.none, contentPadding: const EdgeInsets.only(bottom: 10), ), ), ), ), ), const SizedBox(width: 8), InkWell( onTap: () { if (controller.messagesFormKey.currentState!.validate()) { _sendMessage(controller, controller.messageToDriver.text); controller.messageToDriver.clear(); Get.back(); } }, child: CircleAvatar( backgroundColor: AppColor.primaryColor, radius: 20, child: const Icon(Icons.send_rounded, color: Colors.white, size: 16), ), ), ], ); } void _sendMessage(MapPassengerController controller, String text) { NotificationService.sendNotification( category: 'MSG_FROM_PASSENGER', target: controller.driverToken.toString(), title: text.tr, body: text.tr, isTopic: false, tone: 'ding', driverList: [], ); } } // ----------------------------------------------------------------------------- // مؤشرات الانتظار والوقت (مضغوطة) // ----------------------------------------------------------------------------- class DriverArrivePassengerAndWaitMinute extends StatelessWidget { const DriverArrivePassengerAndWaitMinute({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return GetBuilder(builder: (controller) { return Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('Waiting...'.tr, style: const TextStyle( fontWeight: FontWeight.bold, fontSize: 12, color: Colors.orange)), Text( controller.stringRemainingTimeDriverWaitPassenger5Minute, style: const TextStyle( fontWeight: FontWeight.bold, color: Colors.orange, fontSize: 12), ), ], ), const SizedBox(height: 4), ClipRRect( borderRadius: BorderRadius.circular(2), child: LinearProgressIndicator( backgroundColor: Colors.orange.withOpacity(0.2), color: Colors.orange, minHeight: 4, value: controller.progressTimerDriverWaitPassenger5Minute.toDouble(), ), ), ], ); }); } } class TimeDriverToPassenger extends StatelessWidget { const TimeDriverToPassenger({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return GetBuilder(builder: (controller) { if (controller.timeToPassengerFromDriverAfterApplied <= 0) { return const SizedBox(); } return Column( children: [ // شريط التقدم فقط لأن الوقت والمسافة موجودان بالأعلى ClipRRect( borderRadius: BorderRadius.circular(2), child: LinearProgressIndicator( backgroundColor: AppColor.primaryColor.withOpacity(0.1), color: AppColor.primaryColor, minHeight: 4, value: controller.progressTimerToPassengerFromDriverAfterApplied .toDouble() .clamp(0.0, 1.0), ), ), ], ); }); } }