import 'package:Intaleq/print.dart'; import 'package:Intaleq/views/widgets/my_textField.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:Intaleq/constant/box_name.dart'; import 'package:Intaleq/constant/style.dart'; import 'package:Intaleq/controller/home/map_passenger_controller.dart'; import 'package:Intaleq/main.dart'; import 'package:Intaleq/views/home/map_widget.dart/form_search_places_destenation.dart'; import 'package:Intaleq/views/widgets/elevated_btn.dart'; import 'package:maplibre_gl/maplibre_gl.dart'; import '../../../constant/colors.dart'; import '../../../constant/table_names.dart'; import '../../../controller/functions/toast.dart'; import '../../../controller/functions/tts.dart'; import '../../widgets/error_snakbar.dart'; import '../../widgets/mydialoug.dart'; import 'form_search_start.dart'; // ─── Design Tokens (Modern & Dynamic) ──────────────────────────────────────── class _D { // Radii - More rounded for modern feel static const double radiusCard = 28; static const double radiusChip = 20; static const double radiusBtn = 16; static const double radiusInner = 14; static const double radiusPill = 50; // Shadows - Layered depth with blur static List get cardShadow => [ BoxShadow( color: Colors.black.withOpacity(0.08), blurRadius: 40, spreadRadius: -8, offset: const Offset(0, 12), ), BoxShadow( color: Colors.black.withOpacity(0.04), blurRadius: 16, spreadRadius: -4, offset: const Offset(0, 4), ), ]; static List glowShadow(Color c, {double intensity = 0.4}) => [ BoxShadow( color: c.withOpacity(intensity), blurRadius: 24, spreadRadius: -4, offset: const Offset(0, 8), ), BoxShadow( color: c.withOpacity(intensity * 0.5), blurRadius: 12, spreadRadius: -2, offset: const Offset(0, 3), ), ]; static List innerGlow(Color c) => [ BoxShadow( color: c.withOpacity(0.15), blurRadius: 20, spreadRadius: -10, offset: const Offset(0, 0), ), ]; // Durations - Smoother animations static const Duration fast = Duration(milliseconds: 180); static const Duration medium = Duration(milliseconds: 420); static const Duration slow = Duration(milliseconds: 600); // Gradients static LinearGradient primaryGradient({ Alignment begin = Alignment.topLeft, Alignment end = Alignment.bottomRight, }) => LinearGradient( begin: begin, end: end, colors: [ AppColor.primaryColor, AppColor.primaryColor.withOpacity(0.85), AppColor.primaryColor.withOpacity(0.7), ], stops: const [0.0, 0.5, 1.0], ); static LinearGradient cardGradient() => LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ AppColor.secondaryColor.withOpacity(0.98), AppColor.secondaryColor .withBlue( (AppColor.secondaryColor.blue + 12).clamp(0, 255), ) .withOpacity(0.95), ], ); // Glassmorphism effect static BoxDecoration glassEffect({ required Color color, double opacity = 0.1, double borderOpacity = 0.2, }) => BoxDecoration( color: color.withOpacity(opacity), borderRadius: BorderRadius.circular(radiusInner), border: Border.all( color: color.withOpacity(borderOpacity), width: 1, ), backgroundBlendMode: BlendMode.overlay, ); } // ───────────────────────────────────────────────────────────────────────────── // MAIN BOTTOM MENU MAP - Modern Redesign // ───────────────────────────────────────────────────────────────────────────── class MainBottomMenuMap extends StatelessWidget { const MainBottomMenuMap({super.key}); @override Widget build(BuildContext context) { Get.put(MapPassengerController()); return GetBuilder( builder: (controller) { if (controller.isPickerShown) { return _MapPickerOverlay(controller: controller); } return Positioned( bottom: Get.height * .035, left: 16, right: 16, child: AnimatedContainer( duration: _D.medium, curve: Curves.easeOutQuint, height: controller.mainBottomMenuMapHeight, decoration: BoxDecoration( gradient: _D.cardGradient(), borderRadius: BorderRadius.circular(_D.radiusCard), boxShadow: _D.cardShadow, border: Border.all( color: Get.isDarkMode ? Colors.white.withOpacity(0.15) : Colors.white.withOpacity(0.65), width: 1.2, ), ), child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(_D.radiusCard), gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Colors.white.withOpacity(0.08), Colors.transparent, ], ), ), child: ClipRRect( borderRadius: BorderRadius.circular(_D.radiusCard), child: SingleChildScrollView( physics: const NeverScrollableScrollPhysics(), child: controller.isMainBottomMenuMap ? _CollapsedView(controller: controller) : _ExpandedView(controller: controller, context: context), ), ), ), ), ); }, ); } } // ───────────────────────────────────────────────────────────────────────────── // COLLAPSED VIEW - Modern & Elegant // ───────────────────────────────────────────────────────────────────────────── class _CollapsedView extends StatelessWidget { final MapPassengerController controller; const _CollapsedView({required this.controller}); @override Widget build(BuildContext context) { final String firstName = box.read(BoxName.name).toString().split(' ').first; return Column( mainAxisSize: MainAxisSize.min, children: [ // ── Animated drag handle ───────────────────────────────────────────── const SizedBox(height: 14), AnimatedContainer( duration: _D.fast, width: 44, height: 5, decoration: BoxDecoration( gradient: LinearGradient( colors: [ Colors.grey.shade400.withOpacity(0.6), Colors.grey.shade300, Colors.grey.shade400.withOpacity(0.6), ], ), borderRadius: BorderRadius.circular(3), ), ), const SizedBox(height: 16), // ── Main interactive search card ───────────────────────────────────── Semantics( button: true, label: 'Open destination search'.tr, hint: 'Double tap to open search or enter destination'.tr, child: Material( color: Colors.transparent, child: InkWell( onTap: controller.changeMainBottomMenuMap, borderRadius: BorderRadius.circular(_D.radiusInner), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 8), child: Row( children: [ // Animated search icon with glow AnimatedContainer( duration: _D.medium, width: 48, height: 48, decoration: BoxDecoration( gradient: _D.primaryGradient(), borderRadius: BorderRadius.circular(_D.radiusPill), boxShadow: _D.glowShadow(AppColor.primaryColor), ), child: const Icon( Icons.search_rounded, color: Colors.white, size: 22, ), ), const SizedBox(width: 16), // Dynamic text content Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text.rich( TextSpan( children: [ TextSpan( text: '${'Where to'.tr} ', style: AppStyle.title.copyWith( fontWeight: FontWeight.w600, fontSize: 16, color: Colors.grey.shade700, ), ), TextSpan( text: firstName, style: AppStyle.title.copyWith( fontWeight: FontWeight.w800, fontSize: 16.5, color: AppColor.primaryColor, letterSpacing: -0.3, ), ), const TextSpan(text: '؟'), ], ), ), const SizedBox(height: 2), if (!controller.noCarString) AnimatedOpacity( duration: _D.fast, opacity: 1, child: Text( 'Tap to search your destination'.tr, style: AppStyle.subtitle.copyWith( fontSize: 12, color: Colors.grey.shade500, fontWeight: FontWeight.w400, ), ), ), ], ), ), // Elegant expand indicator Container( padding: const EdgeInsets.symmetric( horizontal: 14, vertical: 8), decoration: BoxDecoration( gradient: LinearGradient( colors: [ AppColor.primaryColor.withOpacity(0.12), AppColor.primaryColor.withOpacity(0.06), ], ), borderRadius: BorderRadius.circular(_D.radiusPill), border: Border.all( color: AppColor.primaryColor.withOpacity(0.25), width: 1, ), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ AnimatedRotation( duration: _D.fast, turns: 0, child: Icon( Icons.keyboard_arrow_up_rounded, color: AppColor.primaryColor, size: 20, ), ), const SizedBox(width: 4), Text( 'Open'.tr, style: TextStyle( color: AppColor.primaryColor, fontSize: 12.5, fontWeight: FontWeight.w700, letterSpacing: 0.3, ), ), ], ), ), ], ), ), ), ), ), // ── Recent places - Modern horizontal chips ─────────────────────────── if (controller.recentPlaces.isNotEmpty) ...[ const SizedBox(height: 12), Container( height: 40, padding: const EdgeInsets.symmetric(horizontal: 18), child: ListView.separated( scrollDirection: Axis.horizontal, itemCount: controller.recentPlaces.length, separatorBuilder: (_, __) => const SizedBox(width: 10), itemBuilder: (context, index) => _RecentPlaceChip(controller: controller, index: index), ), ), const SizedBox(height: 16), ] else const SizedBox(height: 20), ], ); } } // ───────────────────────────────────────────────────────────────────────────── // EXPANDED VIEW - Dynamic Route Planner // ───────────────────────────────────────────────────────────────────────────── class _ExpandedView extends StatelessWidget { final MapPassengerController controller; final BuildContext context; const _ExpandedView({required this.controller, required this.context}); @override Widget build(BuildContext context) { return Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // ── Animated drag handle ───────────────────────────────────────────── const SizedBox(height: 14), Center( child: AnimatedContainer( duration: _D.fast, width: 44, height: 5, decoration: BoxDecoration( gradient: LinearGradient( colors: [ Colors.grey.shade400.withOpacity(0.6), Colors.grey.shade300, Colors.grey.shade400.withOpacity(0.6), ], ), borderRadius: BorderRadius.circular(3), ), ), ), // ── Modern Header with gradient ────────────────────────────────────── Container( padding: const EdgeInsets.fromLTRB(20, 18, 16, 14), decoration: BoxDecoration( gradient: LinearGradient( colors: [ Colors.transparent, Colors.grey.shade50.withOpacity(0.3), ], begin: Alignment.topCenter, end: Alignment.bottomCenter, ), ), child: Row( children: [ // Animated icon container AnimatedContainer( duration: _D.medium, width: 42, height: 42, decoration: BoxDecoration( gradient: _D.primaryGradient(), borderRadius: BorderRadius.circular(_D.radiusInner), boxShadow: _D.glowShadow(AppColor.primaryColor), ), child: const Icon( Icons.alt_route_rounded, color: Colors.white, size: 20, ), ), const SizedBox(width: 14), Text( 'Plan Your Route'.tr, style: AppStyle.title.copyWith( fontWeight: FontWeight.w800, fontSize: 18, letterSpacing: -0.5, height: 1.2, ), ), const Spacer(), // Elegant close button Semantics( button: true, label: 'Close panel'.tr, child: Material( color: Colors.transparent, child: InkWell( onTap: controller.changeMainBottomMenuMap, borderRadius: BorderRadius.circular(_D.radiusPill), child: AnimatedContainer( duration: _D.fast, width: 38, height: 38, decoration: BoxDecoration( color: Colors.grey.shade100, shape: BoxShape.circle, boxShadow: [ BoxShadow( color: Colors.grey.shade200.withOpacity(0.5), blurRadius: 8, offset: const Offset(0, 2), ), ], ), child: Icon( Icons.keyboard_arrow_down_rounded, size: 24, color: Colors.grey.shade600, ), ), ), ), ), ], ), ), // Subtle separator with gradient Container( height: 1, margin: const EdgeInsets.symmetric(horizontal: 20), decoration: BoxDecoration( gradient: LinearGradient( colors: [ Colors.transparent, Colors.grey.shade200, Colors.transparent, ], ), ), ), const SizedBox(height: 16), // ── Dynamic Route Timeline ─────────────────────────────────────────── // Start location row _buildTimelineItem( dotColor: AppColor.primaryColor, showTopLine: false, showBottomLine: true, isStart: true, child: !controller.isAnotherOreder ? _TimelineRow( icon: Icons.my_location_rounded, iconColor: AppColor.primaryColor, bgColor: AppColor.primaryColor, label: controller.currentLocationString, ) : Padding( padding: const EdgeInsets.only(right: 16), child: formSearchPlacesStart(), ), ), // Dynamic waypoints with color coding ...List.generate(controller.activeMenuWaypointCount, (index) { final wpName = controller.menuWaypointNames[index]; final isSet = controller.menuWaypoints[index] != null; final Color accent = index == 0 ? Colors.amber.shade600 : Colors.deepPurple.shade400; final Color soft = index == 0 ? Colors.amber.shade50 : Colors.deepPurple.shade50; return _buildTimelineItem( dotColor: accent, showTopLine: true, showBottomLine: true, child: Container( padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 12), decoration: BoxDecoration( gradient: LinearGradient( colors: [ soft.withOpacity(0.9), soft.withOpacity(0.6), ], ), borderRadius: BorderRadius.circular(_D.radiusInner), border: Border.all( color: isSet ? accent.withOpacity(0.35) : Colors.grey.shade200, width: 1, ), boxShadow: isSet ? [ BoxShadow( color: accent.withOpacity(0.08), blurRadius: 12, offset: const Offset(0, 3), ) ] : null, ), child: Row( children: [ // Animated waypoint number badge AnimatedContainer( duration: _D.fast, width: 26, height: 26, decoration: BoxDecoration( gradient: LinearGradient( colors: index == 0 ? [Colors.amber.shade400, Colors.amber.shade700] : [ Colors.deepPurple.shade300, Colors.deepPurple.shade500 ], begin: Alignment.topLeft, end: Alignment.bottomRight, ), shape: BoxShape.circle, boxShadow: [ BoxShadow( color: accent.withOpacity(0.35), blurRadius: 8, offset: const Offset(0, 3), ), ], ), child: Center( child: Text( '${index + 1}', style: const TextStyle( color: Colors.white, fontSize: 11, fontWeight: FontWeight.w800, letterSpacing: -0.3, ), ), ), ), const SizedBox(width: 12), Expanded( child: Semantics( button: true, label: isSet ? '${'Waypoint'.tr} $wpName' : '${'Stop'.tr} ${index + 1}', hint: 'Double tap to set or change this waypoint on the map' .tr, child: GestureDetector( onTap: () { controller.changeMainBottomMenuMap(); controller.startPickingWaypointOnMap(index); }, child: Text( isSet ? wpName : '${'Stop'.tr} ${index + 1}', style: TextStyle( fontSize: 13.5, color: isSet ? accent.withOpacity(0.9) : Colors.grey.shade400, fontWeight: isSet ? FontWeight.w600 : FontWeight.w400, fontStyle: isSet ? FontStyle.normal : FontStyle.italic, height: 1.3, ), maxLines: 1, overflow: TextOverflow.ellipsis, ), ), )), // Map button with hover effect simulation Semantics( button: true, label: 'Pick location on map'.tr, child: GestureDetector( onTap: () { controller.changeMainBottomMenuMap(); controller.startPickingWaypointOnMap(index); }, child: AnimatedContainer( duration: _D.fast, width: 34, height: 34, margin: const EdgeInsets.symmetric(horizontal: 4), decoration: BoxDecoration( color: accent.withOpacity(0.12), borderRadius: BorderRadius.circular(10), border: Border.all( color: accent.withOpacity(0.25), width: 1, ), ), child: Icon( Icons.map_outlined, color: accent, size: 17, ), ), ), ), // Remove button with subtle animation Semantics( button: true, label: 'Remove waypoint'.tr, child: GestureDetector( onTap: () => controller.removeMenuWaypoint(index), child: AnimatedContainer( duration: _D.fast, width: 28, height: 28, decoration: BoxDecoration( color: Colors.red.shade50, shape: BoxShape.circle, border: Border.all( color: Colors.red.shade100, width: 1, ), ), child: Icon( Icons.close_rounded, color: Colors.red.shade400, size: 15, ), ), ), ), ], ), ), ); }), // Add stop button - Modern CTA style if (controller.activeMenuWaypointCount < 2) _buildTimelineItem( dotColor: Colors.orange.shade300, isDotDashed: true, showTopLine: true, showBottomLine: true, child: Semantics( button: true, label: 'Add a new waypoint stop'.tr, child: Material( color: Colors.transparent, child: InkWell( onTap: () => controller.addMenuWaypoint(), borderRadius: BorderRadius.circular(_D.radiusInner), child: AnimatedContainer( duration: _D.fast, padding: const EdgeInsets.symmetric( horizontal: 16, vertical: 12), decoration: BoxDecoration( borderRadius: BorderRadius.circular(_D.radiusInner), border: Border.all( color: Colors.orange.shade200, style: BorderStyle.solid, width: 1.5, ), gradient: LinearGradient( colors: [ Colors.orange.shade50.withOpacity(0.6), Colors.orange.shade50.withOpacity(0.3), ], ), ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.add_location_alt_outlined, color: Colors.orange.shade500, size: 18, ), const SizedBox(width: 10), Text( 'Add a Stop'.tr, style: TextStyle( color: Colors.orange.shade700, fontSize: 13.5, fontWeight: FontWeight.w600, letterSpacing: 0.2, ), ), const SizedBox(width: 10), Container( padding: const EdgeInsets.symmetric( horizontal: 8, vertical: 3), decoration: BoxDecoration( color: Colors.orange.shade100, borderRadius: BorderRadius.circular(10), border: Border.all( color: Colors.orange.shade200, width: 1, ), ), child: Text( '+5 ${'min'.tr}', style: TextStyle( color: Colors.orange.shade700, fontSize: 10.5, fontWeight: FontWeight.w700, ), ), ), ], ), ), ), ), ), ), // Destination row with elegant styling _buildTimelineItem( dotColor: Colors.red.shade500, showTopLine: true, showBottomLine: false, isEnd: true, child: Padding( padding: const EdgeInsets.only(right: 16), child: formSearchPlacesDestenation(), ), ), // ── Smart Surcharge banner ─────────────────────────────────────────── if (controller.activeMenuWaypointCount > 0) AnimatedContainer( duration: _D.medium, margin: const EdgeInsets.fromLTRB(20, 8, 20, 0), padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10), decoration: BoxDecoration( gradient: LinearGradient( colors: [ Colors.orange.shade50.withOpacity(0.95), Colors.amber.shade50.withOpacity(0.85), ], ), borderRadius: BorderRadius.circular(_D.radiusInner), border: Border.all( color: Colors.orange.shade100.withOpacity(0.8), width: 1, ), boxShadow: [ BoxShadow( color: Colors.orange.shade100.withOpacity(0.3), blurRadius: 12, offset: const Offset(0, 4), ), ], ), child: Row( children: [ AnimatedContainer( duration: _D.fast, width: 30, height: 30, decoration: BoxDecoration( color: Colors.orange.shade100, borderRadius: BorderRadius.circular(10), boxShadow: [ BoxShadow( color: Colors.orange.shade200.withOpacity(0.4), blurRadius: 6, offset: const Offset(0, 2), ), ], ), child: Icon( Icons.schedule_rounded, size: 15, color: Colors.orange.shade700, ), ), const SizedBox(width: 12), Expanded( child: Text.rich( TextSpan( children: [ TextSpan( text: '${controller.activeMenuWaypointCount} ', style: TextStyle( fontSize: 13, color: Colors.orange.shade800, fontWeight: FontWeight.w700, ), ), TextSpan( text: '${'stop(s)'.tr} · +', style: TextStyle( fontSize: 12.5, color: Colors.orange.shade600, fontWeight: FontWeight.w500, ), ), TextSpan( text: '${controller.activeMenuWaypointCount * 5} ', style: TextStyle( fontSize: 13, color: Colors.orange.shade800, fontWeight: FontWeight.w700, ), ), TextSpan( text: 'min added to fare'.tr, style: TextStyle( fontSize: 12.5, color: Colors.orange.shade600, fontWeight: FontWeight.w500, ), ), ], ), ), ), ], ), ), const SizedBox(height: 14), // ── WhatsApp button - Modern card style ────────────────────────────── Padding( padding: const EdgeInsets.symmetric(horizontal: 18), child: _WhatsAppLinkButton(controller: controller), ), const SizedBox(height: 12), // ── Order type button - Dynamic toggle style ───────────────────────── Padding( padding: const EdgeInsets.symmetric(horizontal: 18), child: _OrderTypeButton(controller: controller), ), const SizedBox(height: 18), ], ); } Widget _buildTimelineItem({ required Color dotColor, required bool showTopLine, required bool showBottomLine, required Widget child, bool isDotDashed = false, bool isStart = false, bool isEnd = false, }) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 20), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox( width: 24, child: Column( children: [ if (showTopLine) AnimatedContainer( duration: _D.fast, width: 2.5, height: 12, decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Colors.grey.shade200.withOpacity(0.4), Colors.grey.shade300, ], ), borderRadius: const BorderRadius.vertical( top: Radius.circular(2), ), ), ), // Animated dot with pulse effect simulation AnimatedContainer( duration: _D.medium, width: isDotDashed ? 15 : 15, height: isDotDashed ? 15 : 15, decoration: BoxDecoration( color: isDotDashed ? Colors.transparent : dotColor.withOpacity(0.95), shape: BoxShape.circle, border: Border.all( color: isDotDashed ? dotColor : dotColor.withOpacity(0.3), width: isDotDashed ? 2 : 3, style: isDotDashed ? BorderStyle.solid : BorderStyle.solid, ), boxShadow: isDotDashed ? [] : [ BoxShadow( color: dotColor.withOpacity(0.35), blurRadius: 10, spreadRadius: 2, ), BoxShadow( color: dotColor.withOpacity(0.15), blurRadius: 20, spreadRadius: -5, ), ], ), child: isDotDashed ? Center( child: Container( width: 5, height: 5, decoration: BoxDecoration( color: dotColor, shape: BoxShape.circle, ), ), ) : null, ), if (showBottomLine) AnimatedContainer( duration: _D.fast, width: 2.5, height: 12, decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Colors.grey.shade300, Colors.grey.shade200.withOpacity(0.4), ], ), borderRadius: const BorderRadius.vertical( bottom: Radius.circular(2), ), ), ), ], ), ), const SizedBox(width: 14), Expanded(child: child), ], ), ); } } // ───────────────────────────────────────────────────────────────────────────── // MAP PICKER OVERLAY - Glassmorphism Design // ───────────────────────────────────────────────────────────────────────────── class _MapPickerOverlay extends StatelessWidget { final MapPassengerController controller; const _MapPickerOverlay({required this.controller}); String _getModeTitle(BuildContext context) { if (controller.isPickingWaypoint) { return 'Move map to set stop'.tr + ' ${controller.pickingWaypointIndex + 1}'.tr; } if (controller.passengerStartLocationFromMap) { return controller.isAnotherOreder ? 'Now set the pickup point for the other person'.tr : 'Move map to your pickup point'.tr; } else if (controller.startLocationFromMap) { return 'Move map to set start location'.tr; } else if (controller.workLocationFromMap) { return 'Move map to your work location'.tr; } else if (controller.homeLocationFromMap) { return 'Move map to your home location'.tr; } return 'Move map to select destination'.tr; } String _getConfirmLabel(BuildContext context) { if (controller.isPickingWaypoint) return 'Set as Stop'.tr; if (controller.passengerStartLocationFromMap) return 'Confirm Pickup Location'.tr; if (controller.workLocationFromMap) return 'Set as Work'.tr; if (controller.homeLocationFromMap) return 'Set as Home'.tr; return 'Set Destination'.tr; } IconData _getModeIcon() { if (controller.isPickingWaypoint) return Icons.add_location_alt_rounded; if (controller.passengerStartLocationFromMap) return Icons.person_pin_circle_rounded; if (controller.workLocationFromMap) return Icons.work_rounded; if (controller.homeLocationFromMap) return Icons.home_rounded; return Icons.location_on_rounded; } Color _getModeColor() { if (controller.isPickingWaypoint) return Colors.orange.shade600; if (controller.passengerStartLocationFromMap) return Colors.green.shade600; if (controller.workLocationFromMap) return Colors.blue.shade600; if (controller.homeLocationFromMap) return Colors.orange.shade600; return AppColor.primaryColor; } @override Widget build(BuildContext context) { final modeColor = _getModeColor(); return Positioned( bottom: Get.height * .035, left: 16, right: 16, child: Column( mainAxisSize: MainAxisSize.min, children: [ // ── Dynamic instruction banner with gradient ─────────────────────── AnimatedContainer( duration: _D.medium, padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 14), decoration: BoxDecoration( gradient: LinearGradient( colors: [ modeColor, modeColor.withOpacity(0.88), modeColor.withOpacity(0.75), ], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(_D.radiusCard), boxShadow: _D.glowShadow(modeColor, intensity: 0.5), border: Border.all( color: Get.isDarkMode ? Colors.white.withOpacity(0.15) : Colors.white.withOpacity(0.35), width: 1, ), ), child: Row( children: [ AnimatedContainer( duration: _D.fast, width: 38, height: 38, decoration: BoxDecoration( color: Colors.white.withOpacity(0.22), borderRadius: BorderRadius.circular(12), border: Border.all( color: Colors.white.withOpacity(0.3), width: 1, ), ), child: Icon( _getModeIcon(), color: Colors.white, size: 19, ), ), const SizedBox(width: 14), Expanded( child: Text( _getModeTitle(context), style: const TextStyle( color: Colors.white, fontWeight: FontWeight.w700, fontSize: 14, height: 1.3, letterSpacing: -0.2, ), ), ), ], ), ), const SizedBox(height: 12), // ── Glassmorphism coordinate card ───────────────────────────────── Container( decoration: BoxDecoration( color: AppColor.secondaryColor.withOpacity(0.98), borderRadius: BorderRadius.circular(_D.radiusCard), boxShadow: _D.cardShadow, border: Border.all( color: Get.isDarkMode ? Colors.white.withOpacity(0.1) : Colors.white.withOpacity(0.7), width: 1.3, ), ), child: ClipRRect( borderRadius: BorderRadius.circular(_D.radiusCard), child: Column( mainAxisSize: MainAxisSize.min, children: [ // Coordinate display with modern styling Padding( padding: const EdgeInsets.fromLTRB(20, 18, 20, 2), child: Row( children: [ AnimatedContainer( duration: _D.fast, width: 34, height: 34, decoration: BoxDecoration( color: modeColor.withOpacity(0.12), borderRadius: BorderRadius.circular(11), border: Border.all( color: modeColor.withOpacity(0.25), width: 1, ), ), child: Icon( Icons.gps_fixed_rounded, color: modeColor, size: 16, ), ), const SizedBox(width: 14), Expanded( child: Container( padding: const EdgeInsets.symmetric( horizontal: 12, vertical: 8), decoration: BoxDecoration( color: Colors.grey.shade50, borderRadius: BorderRadius.circular(10), border: Border.all( color: Colors.grey.shade200, width: 1, ), ), child: Text( '${controller.newMyLocation.latitude.toStringAsFixed(5)}, ' '${controller.newMyLocation.longitude.toStringAsFixed(5)}', style: TextStyle( fontSize: 12, color: Colors.grey.shade700, fontFeatures: const [ FontFeature.tabularFigures() ], letterSpacing: 0.3, fontWeight: FontWeight.w500, ), ), ), ), const SizedBox(width: 10), // Live indicator badge Container( padding: const EdgeInsets.symmetric( horizontal: 9, vertical: 4), decoration: BoxDecoration( gradient: LinearGradient( colors: [ Colors.green.shade100, Colors.green.shade50, ], ), borderRadius: BorderRadius.circular(10), border: Border.all( color: Colors.green.shade200, width: 1, ), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ AnimatedContainer( duration: const Duration(milliseconds: 500), width: 7, height: 7, decoration: BoxDecoration( color: Colors.green.shade500, shape: BoxShape.circle, boxShadow: [ BoxShadow( color: Colors.green.shade300 .withOpacity(0.6), blurRadius: 6, spreadRadius: 1, ), ], ), ), const SizedBox(width: 5), Text( 'Live', style: TextStyle( fontSize: 10.5, color: Colors.green.shade700, fontWeight: FontWeight.w700, letterSpacing: 0.5, ), ), ], ), ), ], ), ), const SizedBox(height: 16), // Elegant separator Container( height: 1, margin: const EdgeInsets.symmetric(horizontal: 20), decoration: BoxDecoration( gradient: LinearGradient( colors: [ Colors.transparent, Colors.grey.shade200, Colors.transparent, ], ), ), ), // Action buttons with modern styling Padding( padding: const EdgeInsets.fromLTRB(16, 14, 16, 18), child: Row( children: [ // Cancel button - Subtle outline style Expanded( flex: 2, child: AnimatedContainer( duration: _D.fast, child: OutlinedButton.icon( onPressed: () { controller.isPickerShown = false; controller.passengerStartLocationFromMap = false; controller.startLocationFromMap = false; controller.workLocationFromMap = false; controller.homeLocationFromMap = false; controller.isPickingWaypoint = false; controller.pickingWaypointIndex = -1; if (!controller.isMainBottomMenuMap) { controller.isMainBottomMenuMap = true; controller.mainBottomMenuMapHeight = Get.height * .22; } controller.update(); }, style: OutlinedButton.styleFrom( foregroundColor: Colors.grey.shade600, side: BorderSide( color: Colors.grey.shade200, width: 1.5), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(_D.radiusBtn), ), padding: const EdgeInsets.symmetric(vertical: 14), elevation: 0, ), icon: const Icon(Icons.close_rounded, size: 17), label: Text( 'Cancel'.tr, style: const TextStyle( fontSize: 13.5, fontWeight: FontWeight.w600), ), ), ), ), const SizedBox(width: 12), // Confirm button - Gradient with glow Expanded( flex: 3, child: AnimatedContainer( duration: _D.fast, child: ElevatedButton.icon( onPressed: () => _onConfirmTap(controller, context), style: ElevatedButton.styleFrom( backgroundColor: modeColor, foregroundColor: Colors.white, elevation: 0, shadowColor: Colors.transparent, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(_D.radiusBtn), ), padding: const EdgeInsets.symmetric(vertical: 14), ), icon: Icon(_getModeIcon(), size: 18), label: Text( _getConfirmLabel(context), style: const TextStyle( fontWeight: FontWeight.w700, fontSize: 13.5, letterSpacing: 0.2), ), ), ), ), ], ), ), ], ), ), ), ], ), ); } // ── confirm logic (unchanged) ───────────────────────────────────────────── Future _onConfirmTap( MapPassengerController controller, BuildContext context) async { await Future.delayed(const Duration(milliseconds: 280)); final LatLng currentCameraPosition = LatLng( controller.newMyLocation.latitude, controller.newMyLocation.longitude, ); Log.print( '🌐 MAP PICKER CENTER: ${currentCameraPosition.latitude}, ${currentCameraPosition.longitude}'); Log.print( '✅ _onConfirmTap confirmed coordinates: ${currentCameraPosition.latitude}, ${currentCameraPosition.longitude}'); if (controller.isPickingWaypoint && controller.pickingWaypointIndex >= 0) { final int wpIndex = controller.pickingWaypointIndex; controller.setMenuWaypointFromMap(wpIndex, currentCameraPosition); mySnackbarSuccess('Waypoint has been set successfully'.tr); return; } controller.clearPolyline(); controller.data = []; if (controller.passengerStartLocationFromMap) { final LatLng start = currentCameraPosition; controller.newStartPointLocation = start; controller.passengerStartLocationFromMap = false; controller.isPickerShown = false; controller.currentLocationToFormPlaces = false; controller.placesDestination = []; controller.clearPlacesStart(); controller.clearPlacesDestination(); controller.isMainBottomMenuMap = true; controller.mainBottomMenuMapHeight = Get.height * .22; controller.update(); await controller.getDirectionMap( '${start.latitude},${start.longitude}', '${controller.myDestination.latitude},${controller.myDestination.longitude}', ); controller.showBottomSheet1(); return; } if (controller.startLocationFromMap) { final LatLng start = currentCameraPosition; controller.newMyLocation = start; controller.newStartPointLocation = start; controller.hintTextStartPoint = '${start.latitude.toStringAsFixed(4)} , ${start.longitude.toStringAsFixed(4)}'; controller.startLocationFromMap = false; controller.isPickerShown = false; controller.update(); return; } if (controller.workLocationFromMap) { final LatLng work = currentCameraPosition; box.write(BoxName.addWork, '${work.latitude.toStringAsFixed(4)} , ${work.longitude.toStringAsFixed(4)}'); controller.hintTextDestinationPoint = 'To Work'.tr; controller.workLocationFromMap = false; controller.isPickerShown = false; controller.update(); mySnackbarSuccess('Work Saved'.tr); return; } if (controller.homeLocationFromMap) { final LatLng home = currentCameraPosition; box.write(BoxName.addHome, '${home.latitude.toStringAsFixed(4)} , ${home.longitude.toStringAsFixed(4)}'); controller.hintTextDestinationPoint = 'To Home'.tr; controller.homeLocationFromMap = false; controller.isPickerShown = false; controller.update(); mySnackbarSuccess('Home Saved'.tr); return; } final LatLng confirmedDestination = currentCameraPosition; controller.myDestination = confirmedDestination; controller.hintTextDestinationPoint = '${confirmedDestination.latitude.toStringAsFixed(4)} , ${confirmedDestination.longitude.toStringAsFixed(4)}'; controller.placesDestination = []; controller.placeDestinationController.clear(); controller.passengerStartLocationFromMap = true; controller.isPickerShown = true; // ✅ Keep picker UI open for pickup selection controller.update(); try { if (controller.isAnotherOreder) { await controller.mapController?.animateCamera( CameraUpdate.newLatLng(LatLng( controller.newStartPointLocation.latitude, controller.newStartPointLocation.longitude, )), ); } else { await controller.mapController?.animateCamera( CameraUpdate.newLatLng(LatLng( controller.passengerLocation.latitude, controller.passengerLocation.longitude, )), ); } } catch (e) { Log.print("Error occurred: $e"); } Get.snackbar( 'Destination Set'.tr, controller.isAnotherOreder ? 'Now set the pickup point for the other person'.tr : 'Now move the map to your pickup point'.tr, backgroundColor: Colors.green.shade600, colorText: Colors.white, snackPosition: SnackPosition.TOP, duration: const Duration(seconds: 2), margin: const EdgeInsets.all(12), borderRadius: 12, ); } } // ───────────────────────────────────────────────────────────────────────────── // HELPER WIDGETS - Modern Redesign // ───────────────────────────────────────────────────────────────────────────── class _LocationRow extends StatelessWidget { final IconData icon; final Color iconColor; final String label; final bool isStart; const _LocationRow({ required this.icon, required this.iconColor, required this.label, this.isStart = false, }); @override Widget build(BuildContext context) { return AnimatedContainer( duration: _D.fast, padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), decoration: BoxDecoration( gradient: isStart ? LinearGradient( colors: [ AppColor.primaryColor.withOpacity(0.06), AppColor.primaryColor.withOpacity(0.02), ], ) : null, color: isStart ? null : Colors.transparent, borderRadius: BorderRadius.circular(_D.radiusInner), border: Border.all(color: Colors.grey.shade100, width: 1), ), child: Row( children: [ AnimatedContainer( duration: _D.fast, width: 32, height: 32, decoration: BoxDecoration( color: iconColor.withOpacity(0.12), borderRadius: BorderRadius.circular(10), border: Border.all( color: iconColor.withOpacity(0.2), width: 1, ), ), child: Icon(icon, color: iconColor, size: 16), ), const SizedBox(width: 12), Expanded( child: Text( label, style: AppStyle.subtitle.copyWith( fontSize: 13.5, fontWeight: FontWeight.w500, ), maxLines: 1, overflow: TextOverflow.ellipsis, ), ), ], ), ); } } class _TimelineRow extends StatelessWidget { final IconData icon; final Color iconColor; final Color bgColor; final String label; const _TimelineRow({ required this.icon, required this.iconColor, required this.bgColor, required this.label, }); @override Widget build(BuildContext context) { return AnimatedContainer( duration: _D.fast, padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 11), decoration: BoxDecoration( gradient: LinearGradient( colors: [ bgColor.withAlpha(15), bgColor.withAlpha(8), ], ), borderRadius: BorderRadius.circular(_D.radiusInner), border: Border.all( color: bgColor.withAlpha(35), width: 1, ), ), child: Row( children: [ AnimatedContainer( duration: _D.fast, width: 30, height: 30, decoration: BoxDecoration( color: bgColor.withAlpha(25), borderRadius: BorderRadius.circular(10), border: Border.all( color: bgColor.withAlpha(40), width: 1, ), ), child: Icon(icon, color: iconColor, size: 15), ), const SizedBox(width: 12), Expanded( child: Text( label, style: AppStyle.subtitle.copyWith( fontSize: 13, fontWeight: FontWeight.w500, ), maxLines: 1, overflow: TextOverflow.ellipsis, ), ), ], ), ); } } /// شريحة الأماكن الأخيرة - تصميم عصري class _RecentPlaceChip extends StatelessWidget { final MapPassengerController controller; final int index; const _RecentPlaceChip({required this.controller, required this.index}); @override Widget build(BuildContext context) { final place = controller.recentPlaces[index]; return Material( color: Colors.transparent, child: InkWell( onTap: () { MyDialog().getDialog( 'Are you want to go this site'.tr, ' ', () async { Get.back(); await controller.getLocation(); await controller.getDirectionMap( '${controller.passengerLocation.latitude},${controller.passengerLocation.longitude}', '${place['latitude']},${place['longitude']}', ); controller.showBottomSheet1(); }, ); }, onLongPress: () { MyDialog().getDialog( 'Are you sure to delete this location?'.tr, '', () { sql.deleteData(TableName.recentLocations, place['id']); controller.getFavioratePlaces(); controller.update(); Get.back(); mySnackbarSuccess('deleted'.tr); }, ); }, borderRadius: BorderRadius.circular(_D.radiusChip), child: AnimatedContainer( duration: _D.fast, padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 7), decoration: BoxDecoration( gradient: LinearGradient( colors: [ AppColor.primaryColor.withOpacity(0.08), AppColor.primaryColor.withOpacity(0.04), ], ), borderRadius: BorderRadius.circular(_D.radiusChip), border: Border.all( color: AppColor.primaryColor.withOpacity(0.18), width: 1, ), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon( Icons.history_rounded, size: 14, color: AppColor.primaryColor.withOpacity(0.7), ), const SizedBox(width: 7), Text( place['name'] ?? '', style: TextStyle( fontSize: 12.5, color: AppColor.primaryColor.withOpacity(0.9), fontWeight: FontWeight.w600, letterSpacing: -0.2, ), ), ], ), ), ), ); } } /// زر رابط الواتساب - تصميم بطاقات حديث class _WhatsAppLinkButton extends StatelessWidget { final MapPassengerController controller; const _WhatsAppLinkButton({required this.controller}); @override Widget build(BuildContext context) { return Material( color: Colors.transparent, child: InkWell( onTap: () { Get.dialog( AlertDialog( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(22)), title: Text('WhatsApp Location Extractor'.tr), content: Form( key: controller.sosFormKey, child: Column( mainAxisSize: MainAxisSize.min, children: [ MyTextForm( controller: controller.whatsAppLocationText, label: 'Location Link'.tr, hint: 'Paste location link here'.tr, type: TextInputType.url, ), const SizedBox(height: 16), MyElevatedButton( title: 'Go to this location'.tr, onPressed: () => controller.goToWhatappLocation(), ), ], ), ), ), ); }, borderRadius: BorderRadius.circular(_D.radiusInner), child: AnimatedContainer( duration: _D.fast, padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), decoration: BoxDecoration( gradient: LinearGradient( colors: [ Colors.green.shade50.withOpacity(0.9), Colors.green.shade50.withOpacity(0.6), ], ), borderRadius: BorderRadius.circular(_D.radiusInner), border: Border.all( color: Colors.green.shade100.withOpacity(0.9), width: 1, ), ), child: Row( children: [ AnimatedContainer( duration: _D.fast, width: 34, height: 34, decoration: BoxDecoration( color: Colors.green.shade100, borderRadius: BorderRadius.circular(11), border: Border.all( color: Colors.green.shade200, width: 1, ), ), child: Icon( Icons.link_rounded, color: Colors.green.shade700, size: 18, ), ), const SizedBox(width: 14), Expanded( child: Text( 'Paste WhatsApp location link'.tr, style: TextStyle( color: Colors.green.shade800, fontSize: 13.5, fontWeight: FontWeight.w600, ), ), ), Icon( Icons.arrow_forward_ios_rounded, size: 13, color: Colors.green.shade400, ), ], ), ), ), ); } } /// زر نوع الطلب - تصميم تفاعلي حديث class _OrderTypeButton extends StatelessWidget { final MapPassengerController controller; const _OrderTypeButton({required this.controller}); @override Widget build(BuildContext context) { final bool isOther = controller.isAnotherOreder; final Color accent = isOther ? Colors.indigo.shade500 : AppColor.primaryColor; return Material( color: Colors.transparent, child: InkWell( onTap: () { showCupertinoModalPopup( context: context, builder: (ctx) => CupertinoActionSheet( title: Text('Select Order Type'.tr), message: Text('Choose who this order is for'.tr), actions: [ CupertinoActionSheetAction( child: Text('I want to order for myself'.tr), onPressed: () { controller.changeisAnotherOreder(false); Navigator.pop(ctx); }, ), CupertinoActionSheetAction( child: Text('I want to order for someone else'.tr), onPressed: () { controller.changeisAnotherOreder(true); Navigator.pop(ctx); }, ), ], cancelButton: CupertinoActionSheetAction( isDefaultAction: true, onPressed: () => Navigator.pop(ctx), child: Text('Cancel'.tr), ), ), ); }, borderRadius: BorderRadius.circular(_D.radiusInner), child: AnimatedContainer( duration: _D.fast, padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), decoration: BoxDecoration( gradient: LinearGradient( colors: [ accent.withOpacity(0.08), accent.withOpacity(0.04), ], ), borderRadius: BorderRadius.circular(_D.radiusInner), border: Border.all( color: accent.withOpacity(0.22), width: 1, ), ), child: Row( children: [ AnimatedContainer( duration: _D.fast, width: 34, height: 34, decoration: BoxDecoration( color: accent.withOpacity(0.14), borderRadius: BorderRadius.circular(11), border: Border.all( color: accent.withOpacity(0.25), width: 1, ), ), child: Icon( isOther ? Icons.person_rounded : Icons.group_rounded, color: accent, size: 17, ), ), const SizedBox(width: 14), Expanded( child: Text( isOther ? 'Order for myself'.tr : 'Order for someone else'.tr, style: TextStyle( color: accent, fontSize: 13.5, fontWeight: FontWeight.w600, letterSpacing: -0.2, ), ), ), AnimatedRotation( duration: _D.fast, turns: isOther ? 0.5 : 0, child: Icon( Icons.unfold_more_rounded, color: accent.withOpacity(0.55), size: 19, ), ), ], ), ), ), ); } } // ───────────────────────────────────────────────────────────────────────────── // FAVOURITE PLACES DIALOG - Modern Modal Design // ───────────────────────────────────────────────────────────────────────────── class FaviouratePlacesDialog extends StatelessWidget { const FaviouratePlacesDialog({super.key}); @override Widget build(BuildContext context) { Get.put(MapPassengerController()); return GetBuilder( builder: (controller) => Center( child: InkWell( borderRadius: BorderRadius.circular(14), onTap: () async { final List favoritePlaces = await sql.getAllData(TableName.placesFavorite); Get.defaultDialog( title: 'Favorite Places'.tr, titleStyle: AppStyle.title, content: SizedBox( width: Get.width * .85, height: 300, child: favoritePlaces.isEmpty ? Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ AnimatedContainer( duration: _D.medium, width: 76, height: 76, decoration: BoxDecoration( gradient: LinearGradient( colors: [ AppColor.accentColor.withOpacity(0.15), AppColor.accentColor.withOpacity(0.05), ], ), shape: BoxShape.circle, border: Border.all( color: AppColor.accentColor.withOpacity(0.2), width: 1, ), ), child: const Icon( Icons.star_border_rounded, size: 38, color: AppColor.accentColor, ), ), const SizedBox(height: 16), Text( 'No favorite places yet!'.tr, style: AppStyle.title.copyWith( fontWeight: FontWeight.w600, fontSize: 15, ), ), ], ), ) : ListView.separated( itemCount: favoritePlaces.length, separatorBuilder: (_, __) => Divider(height: 1, color: Colors.grey.shade100), itemBuilder: (context, index) => ListTile( contentPadding: const EdgeInsets.symmetric( horizontal: 8, vertical: 4), leading: AnimatedContainer( duration: _D.fast, width: 38, height: 38, decoration: BoxDecoration( gradient: LinearGradient( colors: [ Colors.amber.shade50, Colors.amber.shade100.withOpacity(0.5), ], ), borderRadius: BorderRadius.circular(12), border: Border.all( color: Colors.amber.shade100, width: 1, ), ), child: const Icon( Icons.star, color: Colors.amber, size: 19, ), ), title: Text( favoritePlaces[index]['name'], style: AppStyle.title.copyWith( fontSize: 14, fontWeight: FontWeight.w600, ), ), trailing: IconButton( icon: const Icon( Icons.delete_outline, color: Colors.redAccent, ), onPressed: () async { await sql.deleteData(TableName.placesFavorite, favoritePlaces[index]['id']); Get.back(); Toast.show( context, '${'Deleted'.tr} ${favoritePlaces[index]['name']}', AppColor.redColor, ); }, ), onTap: () async { Get.back(); await controller.getLocation(); await controller.getDirectionMap( '${controller.passengerLocation.latitude},${controller.passengerLocation.longitude}', '${favoritePlaces[index]['latitude']},${favoritePlaces[index]['longitude']}', ); controller.showBottomSheet1(); }, ), ), ), confirm: MyElevatedButton( title: 'Back'.tr, onPressed: () => Get.back()), ); }, child: Padding( padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10), child: Row( mainAxisSize: MainAxisSize.min, children: [ AnimatedContainer( duration: _D.fast, padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: AppColor.accentColor.withOpacity(0.1), borderRadius: BorderRadius.circular(10), ), child: const Icon( Icons.star_border_rounded, color: AppColor.accentColor, size: 21, ), ), const SizedBox(width: 10), Text( 'Favorite Places'.tr, style: AppStyle.title.copyWith( fontWeight: FontWeight.w600, fontSize: 14, ), ), ], ), ), ), ), ); } }