import 'dart:io'; import 'package:bubble_head/bubble.dart'; import 'package:intaleq_maps/intaleq_maps.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; import 'package:flutter_font_icons/flutter_font_icons.dart'; import 'package:sefer_driver/views/home/Captin/home_captain/drawer_captain.dart'; import 'package:sefer_driver/views/widgets/mycircular.dart'; import '../../../../constant/box_name.dart'; import '../../../../constant/colors.dart'; import '../../../../constant/info.dart'; import '../../../../controller/functions/location_controller.dart'; import '../../../../controller/functions/overlay_permisssion.dart'; import '../../../../controller/functions/package_info.dart'; import '../../../../controller/home/captin/home_captain_controller.dart'; import '../../../../controller/home/captin/map_driver_controller.dart'; import '../../../../controller/home/navigation/navigation_view.dart'; import '../../../../controller/profile/setting_controller.dart'; import '../../../../env/env.dart'; import '../../../../main.dart'; import '../../../notification/available_rides_page.dart'; import '../driver_map_page.dart'; import 'widget/connect.dart'; import 'widget/left_menu_map_captain.dart'; // ───────────────────────────────────────────── // Design Tokens (Responsive to Theme) // ───────────────────────────────────────────── class _Token { static Color surface(BuildContext context) => Theme.of(context).brightness == Brightness.dark ? const Color(0xFF1A1A2E) : Colors.white; static Color surfaceCard(BuildContext context) => Theme.of(context).brightness == Brightness.dark ? const Color(0xFF16213E) : const Color(0xFFF8F9FA); static const Color accent = Color(0xFFF0A500); static Color accentSoft(BuildContext context) => const Color(0xFFF0A500).withOpacity(0.12); static const Color danger = Color(0xFFE53935); static const Color success = Color(0xFF2ECC71); static const Color info = Color(0xFF3498DB); static Color border(BuildContext context) => Theme.of(context).brightness == Brightness.dark ? const Color(0xFF2A2A4A) : Colors.grey.withOpacity(0.2); static Color text(BuildContext context) => Theme.of(context).brightness == Brightness.dark ? Colors.white : const Color(0xFF2D3436); static Color textDim(BuildContext context) => Theme.of(context).brightness == Brightness.dark ? Colors.white38 : Colors.black45; static const double radius = 16.0; static const double radiusSm = 10.0; } // ───────────────────────────────────────────── // Root Widget // ───────────────────────────────────────────── class HomeCaptain extends StatelessWidget { HomeCaptain({super.key}); final LocationController locationController = Get.put(LocationController(), permanent: true); final HomeCaptainController homeCaptainController = Get.put(HomeCaptainController(), permanent: true); @override Widget build(BuildContext context) { WidgetsBinding.instance.addPostFrameCallback((_) async { await closeOverlayIfFound(); if (!context.mounted) return; await checkForUpdate(context); if (!context.mounted) return; await getPermissionOverlay(); if (!context.mounted) return; await showDriverGiftClaim(context); if (!context.mounted) return; await checkForAppliedRide(context); }); return Scaffold( extendBodyBehindAppBar: true, backgroundColor: _Token.surface(context), appBar: const _HomeAppBar(), drawer: AppDrawer(), body: SafeArea( top: false, child: Stack( children: [ const _MapView(), leftMainMenuCaptainIcons(), const _BottomStatusBar(), const _FloatingControls(), ], ), ), ); } } // ───────────────────────────────────────────── // AppBar — no blur, solid gradient // ───────────────────────────────────────────── class _HomeAppBar extends StatelessWidget implements PreferredSizeWidget { const _HomeAppBar(); @override Size get preferredSize => const Size.fromHeight(kToolbarHeight); @override Widget build(BuildContext context) { final ctrl = Get.find(); return AppBar( backgroundColor: _Token.surface(context), elevation: 0, systemOverlayStyle: SystemUiOverlayStyle.light, titleSpacing: 0, // ── Logo + App Name ────────────────────── title: Padding( padding: const EdgeInsets.only(left: 4), child: Row( children: [ _LogoBadge(), const SizedBox(width: 10), Text( AppInformation.appName.split(' ')[0].tr, style: const TextStyle( color: _Token.accent, fontSize: 20, fontWeight: FontWeight.w800, letterSpacing: 0.8, ), ), ], ), ), actions: [ // ── Refuse Counter ─────────────────── GetBuilder( builder: (c) => _PillBadge( icon: Icons.block_rounded, label: c.countRefuse.toString(), color: _Token.danger, ), ), const SizedBox(width: 6), // ── Map Controls Row ───────────────── _AppBarControls(ctrl: ctrl), const SizedBox(width: 8), ], ); } } class _LogoBadge extends StatelessWidget { @override Widget build(BuildContext context) => Container( width: 36, height: 36, decoration: BoxDecoration( color: _Token.surfaceCard(context), shape: BoxShape.circle, border: Border.all(color: _Token.accent, width: 1.5), ), child: ClipOval( child: Image.asset('assets/images/logo.gif', fit: BoxFit.cover), ), ); } class _PillBadge extends StatelessWidget { final IconData icon; final String label; final Color color; const _PillBadge( {required this.icon, required this.label, required this.color}); @override Widget build(BuildContext context) => Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: color.withOpacity(0.12), borderRadius: BorderRadius.circular(20), border: Border.all(color: color.withOpacity(0.35)), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon(icon, color: color, size: 13), const SizedBox(width: 4), Text( label, style: TextStyle( color: color, fontWeight: FontWeight.bold, fontSize: 13), ), ], ), ); } class _AppBarControls extends StatelessWidget { final HomeCaptainController ctrl; const _AppBarControls({required this.ctrl}); @override Widget build(BuildContext context) => Container( padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 4), decoration: BoxDecoration( color: _Token.surfaceCard(context), borderRadius: BorderRadius.circular(_Token.radiusSm), border: Border.all(color: _Token.border(context)), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ // Navigation _IconBtn( icon: Icons.map_rounded, color: _Token.success, tooltip: 'Navigation'.tr, onTap: () => Get.to(() => const NavigationView()), ), // Heatmap GetBuilder( builder: (c) => _IconBtn( icon: Icons.local_fire_department_rounded, color: c.isHeatmapVisible ? Colors.orange : Colors.grey.shade600, tooltip: 'Heatmap'.tr, onTap: c.toggleHeatmap, ), ), // Center on me _IconBtn( icon: Icons.my_location_rounded, color: _Token.accent, tooltip: 'My Location'.tr, onTap: () { ctrl.mapHomeCaptainController?.animateCamera( CameraUpdate.newLatLngZoom( Get.find().myLocation, 17.5, ), ); }, ), ], ), ); } class _IconBtn extends StatelessWidget { final IconData icon; final Color color; final String tooltip; final VoidCallback onTap; const _IconBtn( {required this.icon, required this.color, required this.tooltip, required this.onTap}); @override Widget build(BuildContext context) => Tooltip( message: tooltip, child: InkWell( onTap: onTap, borderRadius: BorderRadius.circular(8), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 9, vertical: 6), child: Icon(icon, color: color, size: 20), ), ), ); } // ───────────────────────────────────────────── // Map View // ───────────────────────────────────────────── class _MapView extends StatelessWidget { const _MapView(); @override Widget build(BuildContext context) { return GetBuilder( builder: (ctrl) { if (ctrl.isLoading) return const MyCircularProgressIndicator(); return GetBuilder( builder: (s) => GetBuilder( builder: (loc) => IntaleqMap( apiKey: Env.mapSaasKey, onMapCreated: ctrl.onMapCreated, minMaxZoomPreference: const MinMaxZoomPreference(6, 18), initialCameraPosition: CameraPosition( target: (loc.myLocation.latitude == 0 || loc.myLocation.latitude.isNaN) ? ctrl.myLocation : loc.myLocation, zoom: 15, ), mapType: s.isMapDarkMode ? IntaleqMapType.normal : IntaleqMapType.light, polygons: ctrl.heatmapPolygons, markers: { Marker( markerId: MarkerId('MyLocation'.tr), position: loc.myLocation, rotation: loc.heading, flat: true, anchor: const Offset(0.5, 0.5), icon: ctrl.carIcon, ) }, myLocationButtonEnabled: false, myLocationEnabled: false, compassEnabled: false, zoomControlsEnabled: false, ), ), ); }, ); } } // ───────────────────────────────────────────── // Bottom Status Bar — no blur, solid card // ───────────────────────────────────────────── class _BottomStatusBar extends StatelessWidget { const _BottomStatusBar(); @override Widget build(BuildContext context) { return Positioned( bottom: 12, left: 12, right: 12, child: GestureDetector( onTap: () => _showDetailsSheet(context), child: Container( padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10), decoration: BoxDecoration( color: _Token.surfaceCard(context), borderRadius: BorderRadius.circular(_Token.radius), border: Border.all(color: _Token.border(context)), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.35), blurRadius: 16, offset: const Offset(0, 4), ) ], ), child: Row( children: [ // Online toggle const ConnectWidget(), const Spacer(), // Ride count GetBuilder( builder: (c) => _StatChip( icon: Icons.directions_car_rounded, value: c.countRideToday, label: 'Rides'.tr, color: _Token.info, ), ), const SizedBox(width: 14), // Today earnings GetBuilder( builder: (c) => _StatChip( icon: Entypo.wallet, value: c.totalMoneyToday.toString(), label: 'Today'.tr, color: _Token.success, ), ), // Chevron hint const SizedBox(width: 8), const Icon(Icons.keyboard_arrow_up_rounded, color: Colors.grey, size: 18), ], ), ), ), ); } void _showDetailsSheet(BuildContext context) { final ctrl = Get.find(); showModalBottomSheet( context: context, backgroundColor: Colors.transparent, builder: (_) => _DetailsSheet(ctrl), ); } } class _StatChip extends StatelessWidget { final IconData icon; final String value; final String label; final Color color; const _StatChip( {required this.icon, required this.value, required this.label, required this.color}); @override Widget build(BuildContext context) => Column( mainAxisSize: MainAxisSize.min, children: [ Row( children: [ Icon(icon, color: color, size: 16), const SizedBox(width: 4), Text( value, style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 15), ), ], ), Text(label, style: const TextStyle(color: Colors.white38, fontSize: 11)), ], ); } // ───────────────────────────────────────────── // Details Bottom Sheet — replaces AlertDialog // ───────────────────────────────────────────── class _DetailsSheet extends StatelessWidget { final HomeCaptainController ctrl; const _DetailsSheet(this.ctrl); @override Widget build(BuildContext context) { return Container( decoration: BoxDecoration( color: _Token.surfaceCard(context), borderRadius: BorderRadius.circular(24), ), padding: const EdgeInsets.fromLTRB(20, 12, 20, 28), child: Column( mainAxisSize: MainAxisSize.min, children: [ // Drag handle Container( width: 36, height: 4, decoration: BoxDecoration( color: _Token.border(context), borderRadius: BorderRadius.circular(2)), ), const SizedBox(height: 16), Text( 'Your Activity'.tr, style: TextStyle( color: _Token.text(context), fontSize: 18, fontWeight: FontWeight.bold), ), const SizedBox(height: 16), Divider(color: _Token.border(context), height: 1), const SizedBox(height: 16), _SheetRow( icon: Entypo.wallet, color: _Token.success, label: 'Today'.tr, value: ctrl.totalMoneyToday.toString(), ), const SizedBox(height: 12), _SheetRow( icon: Entypo.wallet, color: _Token.accent, label: AppInformation.appName, value: ctrl.totalMoneyInSEFER.toString(), ), const SizedBox(height: 12), Divider(color: _Token.border(context), height: 1), const SizedBox(height: 12), _SheetRow( icon: Icons.timer_outlined, color: _Token.success, label: 'Active Duration'.tr, value: ctrl.stringActiveDuration, ), const SizedBox(height: 12), _SheetRow( icon: Icons.access_time_rounded, color: _Token.info, label: 'Total Connection'.tr, value: ctrl.totalDurationToday, ), const SizedBox(height: 12), Divider(color: _Token.border(context), height: 1), const SizedBox(height: 12), _SheetRow( icon: Icons.star_rounded, color: _Token.accent, label: 'Total Points'.tr, value: ctrl.totalPoints.toString(), ), const SizedBox(height: 20), SizedBox( width: double.infinity, child: TextButton( onPressed: () => Get.back(), style: TextButton.styleFrom( backgroundColor: _Token.accentSoft(context), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(_Token.radiusSm)), padding: const EdgeInsets.symmetric(vertical: 12), ), child: Text('Close'.tr, style: const TextStyle( color: _Token.accent, fontWeight: FontWeight.bold)), ), ), ], ), ); } } class _SheetRow extends StatelessWidget { final IconData icon; final Color color; final String label; final String value; const _SheetRow( {required this.icon, required this.color, required this.label, required this.value}); @override Widget build(BuildContext context) => Row( children: [ Icon(icon, color: color, size: 20), const SizedBox(width: 12), Text(label, style: TextStyle(color: _Token.textDim(context), fontSize: 14)), const Spacer(), Text(value, style: TextStyle( color: color, fontSize: 16, fontWeight: FontWeight.bold)), ], ); } // ───────────────────────────────────────────── // Floating Action Buttons (right side) // ───────────────────────────────────────────── class _FloatingControls extends StatelessWidget { const _FloatingControls({super.key}); @override Widget build(BuildContext context) { return Positioned( bottom: 88, right: 12, child: GetBuilder( builder: (ctrl) => Column( children: [ // Bubble/overlay mode (Android only) if (Platform.isAndroid) ...[ _Fab( onTap: () => Bubble().startBubbleHead(sendAppToBackground: true), tooltip: 'Overlay'.tr, child: Image.asset('assets/images/logo1.png', width: 26, height: 26), ), const SizedBox(height: 10), ], // Available rides _Fab( onTap: () => Get.to(() => const AvailableRidesPage()), icon: Icons.list_alt_rounded, color: AppColor.primaryColor, tooltip: 'Available Rides'.tr, ), // Continue active ride if (box.read(BoxName.rideStatus) == 'Applied' || box.read(BoxName.rideStatus) == 'Begin') ...[ const SizedBox(height: 10), _Fab( onTap: () { if (box.read(BoxName.rideStatus) == 'Applied') { Get.to(() => PassengerLocationMapPage(), arguments: box.read(BoxName.rideArguments)); Get.put(MapDriverController()) .changeRideToBeginToPassenger(); } else { Get.to(() => PassengerLocationMapPage(), arguments: box.read(BoxName.rideArguments)); Get.put(MapDriverController()).startRideFromStartApp(); } }, icon: Icons.navigation_rounded, color: _Token.info, tooltip: 'Continue Ride'.tr, ), ], ], ), ), ); } } class _Fab extends StatelessWidget { final VoidCallback onTap; final IconData? icon; final Widget? child; final Color? color; final String? tooltip; const _Fab( {required this.onTap, this.icon, this.child, this.color, this.tooltip}); @override Widget build(BuildContext context) => Tooltip( message: tooltip ?? '', child: Material( color: color ?? _Token.surfaceCard(context), shape: const CircleBorder(), elevation: 6, shadowColor: (color ?? Colors.black).withOpacity(0.4), child: InkWell( onTap: onTap, customBorder: const CircleBorder(), child: SizedBox( width: 52, height: 52, child: Center( child: child ?? Icon(icon, color: color != null ? Colors.white : _Token.accent, size: 24), ), ), ), ), ); } // ───────────────────────────────────────────── // Helper // ───────────────────────────────────────────── Future checkForAppliedRide(BuildContext context) async { checkForPendingOrderFromServer(); }