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 '../../widgets/error_snakbar.dart'; import '../../widgets/mydialoug.dart'; import 'form_search_start.dart'; // ─── Design Tokens (Modern & Dynamic) ──────────────────────────────────────── class _D { 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; 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 const Duration fast = Duration(milliseconds: 180); static const Duration medium = Duration(milliseconds: 420); static const Duration slow = Duration(milliseconds: 600); 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), ], ); } // ───────────────────────────────────────────────────────────────────────────── // MAIN BOTTOM MENU MAP - Scrollable 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, // تم استبدال الارتفاع الثابت بـ BoxConstraints للسماح بالتمدد الديناميكي constraints: BoxConstraints( maxHeight: controller.isMainBottomMenuMap ? Get.height * 0.4 : Get.height * 0.75, // الحد الأقصى للشاشة المفتوحة ), 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: ClipRRect( borderRadius: BorderRadius.circular(_D.radiusCard), // تفعيل السحب والنزول child: SingleChildScrollView( physics: const BouncingScrollPhysics(), child: controller.isMainBottomMenuMap ? _CollapsedView(controller: controller) : _ExpandedView(controller: controller, context: context), ), ), ), ); }, ); } } // ───────────────────────────────────────────────────────────────────────────── // COLLAPSED VIEW // ───────────────────────────────────────────────────────────────────────────── 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: [ 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), Semantics( button: true, label: 'Open destination search'.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: [ 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), 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) Text( 'Tap to search your destination'.tr, style: AppStyle.subtitle.copyWith( fontSize: 12, color: Colors.grey.shade500, fontWeight: FontWeight.w400, ), ), ], ), ), ], ), ), ), ), ), 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 - Grouped Layout // ───────────────────────────────────────────────────────────────────────────── 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: [ 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), ), ), ), // ── Header ── Container( padding: const EdgeInsets.fromLTRB(20, 18, 16, 14), child: Row( children: [ Text( 'Plan Your Route'.tr, style: AppStyle.title.copyWith( fontWeight: FontWeight.w800, fontSize: 18, letterSpacing: -0.5, ), ), const Spacer(), Semantics( button: true, label: 'Close panel'.tr, child: Material( color: Colors.transparent, child: InkWell( onTap: controller.changeMainBottomMenuMap, borderRadius: BorderRadius.circular(_D.radiusPill), child: Container( width: 38, height: 38, decoration: BoxDecoration( color: Colors.grey.shade100, shape: BoxShape.circle, ), child: Icon(Icons.keyboard_arrow_down_rounded, size: 24, color: Colors.grey.shade600), ), ), ), ), ], ), ), // ── Group 1: Core Routing ── _buildSectionTitle('Route'.tr), _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(), ), ), ...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), ), child: Row( children: [ Container( width: 26, height: 26, decoration: BoxDecoration(color: accent, shape: BoxShape.circle), child: Center( child: Text('${index + 1}', style: const TextStyle( color: Colors.white, fontSize: 11, fontWeight: FontWeight.w800))), ), const SizedBox(width: 12), Expanded( 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, ), maxLines: 1, overflow: TextOverflow.ellipsis, ), )), GestureDetector( onTap: () => controller.removeMenuWaypoint(index), child: Container( width: 28, height: 28, decoration: BoxDecoration( color: Colors.red.shade50, shape: BoxShape.circle), child: Icon(Icons.close_rounded, color: Colors.red.shade400, size: 15), ), ), ], ), ), ); }), if (controller.activeMenuWaypointCount < 2) _buildTimelineItem( dotColor: Colors.orange.shade300, isDotDashed: true, showTopLine: true, showBottomLine: true, child: InkWell( onTap: () => controller.addMenuWaypoint(), borderRadius: BorderRadius.circular(_D.radiusInner), child: Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), decoration: BoxDecoration( borderRadius: BorderRadius.circular(_D.radiusInner), border: Border.all(color: Colors.orange.shade200, width: 1.5), color: Colors.orange.shade50.withOpacity(0.6), ), 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)), ], ), ), ), ), _buildTimelineItem( dotColor: Colors.red.shade500, showTopLine: true, showBottomLine: false, isEnd: true, child: Padding( padding: const EdgeInsets.only(right: 16), child: formSearchPlacesDestenation(), ), ), const SizedBox(height: 16), // ── Group 2: Quick Access ── _buildSectionDivider(), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ _buildSectionTitle('Quick Access'.tr), const FaviouratePlacesDialog(), // تم نقلها هنا لتكون جزء من الوصول السريع ], ), if (controller.recentPlaces.isNotEmpty) Container( height: 40, margin: const EdgeInsets.only(bottom: 16), child: ListView.separated( padding: const EdgeInsets.symmetric(horizontal: 20), scrollDirection: Axis.horizontal, itemCount: controller.recentPlaces.length, separatorBuilder: (_, __) => const SizedBox(width: 10), itemBuilder: (context, index) => _RecentPlaceChip(controller: controller, index: index), ), ), // ── Group 3: Advanced Tools ── _buildSectionDivider(), _buildSectionTitle('Advanced Tools'.tr), Padding( padding: const EdgeInsets.symmetric(horizontal: 18), child: _WhatsAppLinkButton(controller: controller), ), const SizedBox(height: 12), Padding( padding: const EdgeInsets.symmetric(horizontal: 18), child: _OrderTypeButton(controller: controller), ), const SizedBox(height: 24), // مساحة سفلية لضمان راحة السحب ], ); } Widget _buildSectionTitle(String title) { return Padding( padding: const EdgeInsets.only(left: 20, right: 20, bottom: 12), child: Text( title, style: TextStyle( fontSize: 14, fontWeight: FontWeight.bold, color: Colors.grey.shade400, letterSpacing: 0.5, ), ), ); } Widget _buildSectionDivider() { return Container( height: 1, margin: const EdgeInsets.symmetric(horizontal: 20, vertical: 16), color: Colors.grey.shade200, ); } 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) Container( width: 2.5, height: 12, color: Colors.grey.shade300), Container( width: 15, height: 15, decoration: BoxDecoration( color: isDotDashed ? Colors.transparent : dotColor, shape: BoxShape.circle, border: Border.all(color: dotColor, width: isDotDashed ? 2 : 3), ), ), if (showBottomLine) Container( width: 2.5, height: 12, color: Colors.grey.shade300), ], ), ), const SizedBox(width: 14), Expanded(child: child), ], ), ); } } // ───────────────────────────────────────────────────────────────────────────── // MAP PICKER OVERLAY // ───────────────────────────────────────────────────────────────────────────── 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; if (controller.startLocationFromMap) return 'Move map to set start location'.tr; if (controller.workLocationFromMap) return 'Move map to your work location'.tr; 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: [ Container( padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 14), decoration: BoxDecoration( color: modeColor, borderRadius: BorderRadius.circular(_D.radiusCard), ), child: Row( children: [ 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), ), ), ], ), ), const SizedBox(height: 12), Container( decoration: BoxDecoration( color: AppColor.secondaryColor, borderRadius: BorderRadius.circular(_D.radiusCard), boxShadow: _D.cardShadow, ), child: Column( mainAxisSize: MainAxisSize.min, children: [ Padding( padding: const EdgeInsets.fromLTRB(20, 18, 20, 2), child: Row( children: [ Icon(Icons.gps_fixed_rounded, color: modeColor, size: 16), const SizedBox(width: 14), Expanded( child: Text( '${controller.newMyLocation.latitude.toStringAsFixed(5)}, ${controller.newMyLocation.longitude.toStringAsFixed(5)}', style: TextStyle( fontSize: 12, color: Colors.grey.shade700, fontWeight: FontWeight.w500), ), ), ], ), ), const SizedBox(height: 16), Padding( padding: const EdgeInsets.fromLTRB(16, 14, 16, 18), child: Row( children: [ Expanded( flex: 2, child: OutlinedButton( 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(); }, child: Text('Cancel'.tr), ), ), const SizedBox(width: 12), Expanded( flex: 3, child: ElevatedButton( onPressed: () => _onConfirmTap(controller, context), style: ElevatedButton.styleFrom( backgroundColor: modeColor), child: Text(_getConfirmLabel(context), style: const TextStyle(color: Colors.white)), ), ), ], ), ), ], ), ), ], ), ); } Future _onConfirmTap( MapPassengerController controller, BuildContext context) async { await Future.delayed(const Duration(milliseconds: 280)); final LatLng currentCameraPosition = LatLng( controller.newMyLocation.latitude, controller.newMyLocation.longitude); if (controller.isPickingWaypoint && controller.pickingWaypointIndex >= 0) { controller.setMenuWaypointFromMap( controller.pickingWaypointIndex, 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) { box.write(BoxName.addWork, '${currentCameraPosition.latitude.toStringAsFixed(4)} , ${currentCameraPosition.longitude.toStringAsFixed(4)}'); controller.hintTextDestinationPoint = 'To Work'.tr; controller.workLocationFromMap = false; controller.isPickerShown = false; controller.update(); mySnackbarSuccess('Work Saved'.tr); return; } if (controller.homeLocationFromMap) { box.write(BoxName.addHome, '${currentCameraPosition.latitude.toStringAsFixed(4)} , ${currentCameraPosition.longitude.toStringAsFixed(4)}'); controller.hintTextDestinationPoint = 'To Home'.tr; controller.homeLocationFromMap = false; controller.isPickerShown = false; controller.update(); mySnackbarSuccess('Home Saved'.tr); return; } controller.myDestination = currentCameraPosition; controller.hintTextDestinationPoint = '${currentCameraPosition.latitude.toStringAsFixed(4)} , ${currentCameraPosition.longitude.toStringAsFixed(4)}'; controller.placesDestination = []; controller.placeDestinationController.clear(); controller.passengerStartLocationFromMap = true; controller.isPickerShown = true; 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"); } } } // ───────────────────────────────────────────────────────────────────────────── // HELPER WIDGETS // ───────────────────────────────────────────────────────────────────────────── 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 Container( padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 11), decoration: BoxDecoration( color: bgColor.withAlpha(15), borderRadius: BorderRadius.circular(_D.radiusInner)), child: Row( children: [ 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(); }, ); }, borderRadius: BorderRadius.circular(_D.radiusChip), child: Container( padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 7), decoration: BoxDecoration( color: AppColor.primaryColor.withOpacity(0.08), borderRadius: BorderRadius.circular(_D.radiusChip), ), 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)), ], ), ), ), ); } } 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, type: TextInputType.url, hint: 'https://maps.app.goo.gl/...'), const SizedBox(height: 16), MyElevatedButton( title: 'Go to this location'.tr, onPressed: () => controller.goToWhatappLocation()), ], ), ), ), ); }, borderRadius: BorderRadius.circular(_D.radiusInner), child: Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), decoration: BoxDecoration( color: Colors.green.shade50, borderRadius: BorderRadius.circular(_D.radiusInner)), child: Row( children: [ 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))), ], ), ), ), ); } } 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), 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: Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), decoration: BoxDecoration( color: accent.withOpacity(0.08), borderRadius: BorderRadius.circular(_D.radiusInner)), child: Row( children: [ 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))), ], ), ), ), ); } } class FaviouratePlacesDialog extends StatelessWidget { const FaviouratePlacesDialog({super.key}); @override Widget build(BuildContext context) { Get.put(MapPassengerController()); return GetBuilder( builder: (controller) => InkWell( borderRadius: BorderRadius.circular(14), onTap: () async { final List favoritePlaces = await sql.getAllData(TableName.placesFavorite); Get.defaultDialog( title: 'Favorite Places'.tr, content: SizedBox( width: Get.width * .85, height: 300, child: favoritePlaces.isEmpty ? Center(child: Text('No favorite places yet!'.tr)) : ListView.separated( itemCount: favoritePlaces.length, separatorBuilder: (_, __) => Divider(height: 1, color: Colors.grey.shade100), itemBuilder: (context, index) => ListTile( leading: const Icon(Icons.star, color: Colors.amber, size: 19), title: Text(favoritePlaces[index]['name']), trailing: IconButton( icon: const Icon(Icons.delete_outline, color: Colors.redAccent), onPressed: () async { await sql.deleteData(TableName.placesFavorite, favoritePlaces[index]['id']); Get.back(); }, ), 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: [ 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)), ], ), ), ), ); } }