Initial commit for Intaleq Driver

This commit is contained in:
Hamza-Ayed
2025-09-01 19:04:50 +03:00
parent 889c67a691
commit 8c7f3e3a75
46 changed files with 4300 additions and 6192 deletions

View File

@@ -1,4 +1,5 @@
import 'dart:io';
import 'dart:ui';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:sefer_driver/constant/box_name.dart';
@@ -26,18 +27,19 @@ import 'widget/connect.dart';
import 'widget/left_menu_map_captain.dart';
import '../../../../main.dart';
// الويدجت الرئيسية للصفحة بعد تنظيمها
// ==================================================================
// Redesigned Main Widget (V3)
// ==================================================================
class HomeCaptain extends StatelessWidget {
HomeCaptain({super.key});
// تم الإبقاء على تعريف الـ Controllers كما هو في الكود الأصلي
final LocationController locationController = Get.put(LocationController());
final HomeCaptainController homeCaptainController =
Get.put(HomeCaptainController());
@override
Widget build(BuildContext context) {
// لم يتم تغيير أي شيء في هذه الأوامر
// Initial calls remain the same.
Get.put(HomeCaptainController());
WidgetsBinding.instance.addPostFrameCallback((_) async {
closeOverlayIfFound();
@@ -46,19 +48,20 @@ class HomeCaptain extends StatelessWidget {
showDriverGiftClaim(context);
});
// التصميم الجديد: أصبح الـ build الرئيسي نظيفاً وواضحاً جداً
// The stack is now even simpler.
return Scaffold(
appBar: const _HomeAppBar(), // 1. تم فصل الـ AppBar في ويدجت خاصة
appBar: const _HomeAppBar(),
drawer: AppDrawer(),
body: Stack(
children: [
// كل جزء من الواجهة أصبح ويدجت منفصلة
const _MapView(), // 2. تم فصل الخريطة
const _DriverStatsOverlay(), // 3. تم فصل كارت الإحصائيات العلوي
const _DriverDurationOverlay(), // 4. تم فصل كارت مدة العمل
const _FloatingActionButtons(), // 5. تم فصل الأزرار الجانبية العائمة
const _ConnectButtonOverlay(), // 6. تم فصل زر الاتصال السفلي
leftMainMenuCaptainIcons(), // هذه بقيت كما هي
// 1. The Map View is the base layer.
const _MapView(),
// 2. The new floating "Status Pod" at the bottom.
const _StatusPodOverlay(),
// This widget from the original code remains.
leftMainMenuCaptainIcons(),
],
),
);
@@ -66,64 +69,51 @@ class HomeCaptain extends StatelessWidget {
}
// ==================================================================
// الأجزاء الصغيرة التي تم فصلها (Helper Widgets)
// هذه الويدجتس تحتوي على نفس كود التصميم الأصلي الخاص بك تماماً، ولكنها منظمة بشكل أفضل
// Redesigned Helper Widgets (V3)
// ==================================================================
/// 1. ويدجت الـ AppBar
/// 1. The AppBar now contains the map actions in a PopupMenuButton.
class _HomeAppBar extends StatelessWidget implements PreferredSizeWidget {
const _HomeAppBar();
@override
Widget build(BuildContext context) {
// نفس الكود الأصلي للـ AppBar
final homeCaptainController = Get.find<HomeCaptainController>();
return AppBar(
elevation: 2,
flexibleSpace: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.white, Colors.grey.shade50],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.1),
spreadRadius: 1,
blurRadius: 4,
),
],
),
),
backgroundColor: Colors.white,
elevation: 1,
shadowColor: Colors.black.withOpacity(0.1),
title: Row(
children: [
Image.asset(
'assets/images/logo.gif',
height: 32,
width: 35,
height: 35,
),
const SizedBox(width: 8),
const SizedBox(width: 10),
Text(
AppInformation.appName.split(' ')[0].toString().tr,
style: AppStyle.title.copyWith(
fontSize: 22,
fontWeight: FontWeight.w600,
fontSize: 24,
fontWeight: FontWeight.bold,
color: AppColor.blueColor,
),
),
],
),
actions: [
// Refuse count indicator
Padding(
padding: const EdgeInsets.symmetric(horizontal: 4),
child: MyCircleContainer(
child: Text(
homeCaptainController.countRefuse.toString(),
style: AppStyle.title,
padding: const EdgeInsets.only(right: 8.0),
child: Center(
child: MyCircleContainer(
child: Text(
homeCaptainController.countRefuse.toString(),
style: AppStyle.title.copyWith(fontWeight: FontWeight.bold),
),
),
),
),
// The new PopupMenuButton for all map and ride actions.
Container(
margin: const EdgeInsets.symmetric(horizontal: 4),
decoration: BoxDecoration(
@@ -165,28 +155,45 @@ class _HomeAppBar extends StatelessWidget implements PreferredSizeWidget {
],
),
),
const SizedBox(width: 8),
],
);
}
PopupMenuItem<String> _buildPopupMenuItem({
required String value,
IconData? icon,
Widget? iconWidget,
required String text,
Color? iconColor,
}) {
return PopupMenuItem<String>(
value: value,
child: Row(
children: [
iconWidget ?? Icon(icon, color: iconColor ?? Colors.grey.shade600),
const SizedBox(width: 16),
Text(text),
],
),
);
}
@override
Size get preferredSize => const Size.fromHeight(kToolbarHeight);
}
/// 2. ويدجت الخريطة
/// 2. The Map View is unchanged functionally.
class _MapView extends StatelessWidget {
const _MapView();
@override
Widget build(BuildContext context) {
final locationController = Get.find<LocationController>();
// نفس الكود الأصلي للخريطة
return GetBuilder<HomeCaptainController>(builder: (controller) {
return controller.isLoading
? const MyCircularProgressIndicator()
: GoogleMap(
padding: EdgeInsets.only(bottom: 50, top: 300),
padding: const EdgeInsets.only(bottom: 110, top: 300),
fortyFiveDegreeImageryEnabled: true,
onMapCreated: controller.onMapCreated,
minMaxZoomPreference: const MinMaxZoomPreference(6, 18),
@@ -217,7 +224,7 @@ class _MapView extends StatelessWidget {
myLocationEnabled: false,
trafficEnabled: controller.mapTrafficON,
buildingsEnabled: true,
mapToolbarEnabled: true,
mapToolbarEnabled: false,
compassEnabled: true,
zoomControlsEnabled: false,
);
@@ -225,353 +232,213 @@ class _MapView extends StatelessWidget {
}
}
/// 3. ويدجت كارت الإحصائيات العلوي
class _DriverStatsOverlay extends StatelessWidget {
const _DriverStatsOverlay();
/// 3. The floating "Status Pod" at the bottom of the screen.
class _StatusPodOverlay extends StatelessWidget {
const _StatusPodOverlay();
@override
Widget build(BuildContext context) {
// نفس الكود الأصلي لكارت الإحصائيات
return Positioned(
top: 5,
right: Get.width * .05,
left: Get.width * .05,
child: GetBuilder<HomeCaptainController>(
builder: (homeCaptainController) {
return Container(
decoration: BoxDecoration(
gradient: const LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [Colors.white, Colors.white70],
),
borderRadius: BorderRadius.circular(15),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.2),
spreadRadius: 2,
blurRadius: 8,
offset: const Offset(0, 2),
),
],
),
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
width: Get.width * .8,
height: 120,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: AppColor.greenColor.withOpacity(0.1),
borderRadius: BorderRadius.circular(10),
),
child: Row(
children: [
const Icon(
Entypo.wallet,
color: AppColor.greenColor,
size: 20,
),
const SizedBox(width: 8),
Text(
'${"Today".tr}: ${(homeCaptainController.totalMoneyToday)}',
style: AppStyle.title.copyWith(
color: AppColor.greenColor,
fontWeight: FontWeight.bold,
),
),
],
),
),
Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: AppColor.yellowColor.withOpacity(0.1),
borderRadius: BorderRadius.circular(10),
),
child: Row(
children: [
const Icon(
Entypo.wallet,
color: AppColor.yellowColor,
size: 20,
),
const SizedBox(width: 8),
Text(
'${AppInformation.appName}: ${(homeCaptainController.totalMoneyInSEFER)}',
style: AppStyle.title.copyWith(
color: AppColor.yellowColor,
fontWeight: FontWeight.bold,
),
),
],
),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'${'Total Points is'.tr}: ${(homeCaptainController.totalPoints)}',
style: AppStyle.title.copyWith(
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
Container(
padding: const EdgeInsets.symmetric(
horizontal: 12, vertical: 6),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: int.parse(
(homeCaptainController.countRideToday)) <
5
? AppColor.accentColor
: int.parse((homeCaptainController
.countRideToday)) >
5 &&
int.parse((homeCaptainController
.countRideToday)) <
10
? AppColor.yellowColor
: AppColor.greenColor,
),
child: Row(
children: [
const Icon(
Icons.directions_car_rounded,
color: Colors.white,
size: 18,
),
const SizedBox(width: 4),
Text(
'${"Ride Today : ".tr}: ${(homeCaptainController.countRideToday)}',
style: AppStyle.title.copyWith(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
],
),
),
],
),
]),
);
},
),
void _showDetailsDialog(BuildContext context) {
Get.dialog(
const _DriverDetailsDialog(),
barrierColor: Colors.black.withOpacity(0.3),
);
}
}
/// 4. ويدجت كارت مدة العمل
class _DriverDurationOverlay extends StatelessWidget {
const _DriverDurationOverlay();
@override
Widget build(BuildContext context) {
// نفس الكود الأصلي لكارت المدة
final homeCaptainController = Get.find<HomeCaptainController>();
return Positioned(
bottom: 65,
right: Get.width * .1,
left: Get.width * .1,
child: GetBuilder<HomeCaptainController>(
builder: (homeCaptainController) => Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.2),
spreadRadius: 2,
blurRadius: 8,
offset: const Offset(0, 2),
),
],
),
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.timer_outlined, color: AppColor.greenColor),
const SizedBox(width: 8),
Text(
'Active Duration:'.tr,
style: AppStyle.title,
),
const SizedBox(width: 4),
Text(
(homeCaptainController.stringActiveDuration),
style: AppStyle.title.copyWith(
fontWeight: FontWeight.bold,
color: AppColor.greenColor,
),
),
bottom: 16,
left: 16,
right: 16,
child: GestureDetector(
onTap: () => _showDetailsDialog(context),
child: ClipRRect(
borderRadius: BorderRadius.circular(24),
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10),
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.85),
borderRadius: BorderRadius.circular(24),
border: Border.all(color: Colors.white.withOpacity(0.5)),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
blurRadius: 20,
spreadRadius: -5,
)
],
),
const SizedBox(height: 8),
Row(
mainAxisAlignment: MainAxisAlignment.center,
child: Row(
children: [
const Icon(Icons.access_time, color: AppColor.accentColor),
const ConnectWidget(),
const Spacer(),
_buildQuickStat(
icon: Icons.directions_car_rounded,
value: homeCaptainController.countRideToday,
label: 'Rides'.tr,
color: AppColor.blueColor,
),
const SizedBox(width: 16),
_buildQuickStat(
icon: Entypo.wallet,
value: homeCaptainController.totalMoneyToday.toString(),
label: 'Today'.tr,
color: AppColor.greenColor,
),
const SizedBox(width: 8),
Text(
'Total Connection Duration:'.tr,
style: AppStyle.title,
),
const SizedBox(width: 4),
Text(
(homeCaptainController.totalDurationToday),
style: AppStyle.title.copyWith(
fontWeight: FontWeight.bold,
color: AppColor.accentColor,
),
),
],
),
],
),
),
),
),
);
}
}
/// 5. ويدجت الأزرار الجانبية العائمة
class _FloatingActionButtons extends StatelessWidget {
const _FloatingActionButtons();
@override
Widget build(BuildContext context) {
// نفس الكود الأصلي للأزرار
return Positioned(
bottom: Get.height * .2,
right: 6,
child:
GetBuilder<HomeCaptainController>(builder: (homeCaptainController) {
return Column(
Widget _buildQuickStat(
{required IconData icon,
required String value,
required String label,
required Color color}) {
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Row(
children: [
Platform.isAndroid
? AnimatedContainer(
duration: const Duration(microseconds: 200),
width: homeCaptainController.widthMapTypeAndTraffic,
decoration: BoxDecoration(
border: Border.all(color: AppColor.blueColor),
color: AppColor.secondaryColor,
borderRadius: BorderRadius.circular(15)),
child: IconButton(
onPressed: () async {
Bubble().startBubbleHead(sendAppToBackground: true);
},
icon: Image.asset(
'assets/images/logo1.png',
fit: BoxFit.cover,
width: 35,
height: 35,
),
),
)
: const SizedBox(),
const SizedBox(
height: 5,
),
AnimatedContainer(
duration: const Duration(microseconds: 200),
width: homeCaptainController.widthMapTypeAndTraffic,
decoration: BoxDecoration(
border: Border.all(color: AppColor.blueColor),
color: AppColor.secondaryColor,
borderRadius: BorderRadius.circular(15)),
child: IconButton(
onPressed: () {
Get.to(() => const AvailableRidesPage());
},
icon: const Icon(
Icons.train_sharp,
size: 29,
color: AppColor.blueColor,
),
),
),
const SizedBox(
height: 5,
),
box.read(BoxName.rideStatus) == 'Applied' ||
box.read(BoxName.rideStatus) == 'Begin'
? Positioned(
bottom: Get.height * .2,
right: 6,
child: AnimatedContainer(
duration: const Duration(microseconds: 200),
width: homeCaptainController.widthMapTypeAndTraffic,
decoration: BoxDecoration(
border: Border.all(color: AppColor.blueColor),
color: AppColor.secondaryColor,
borderRadius: BorderRadius.circular(15)),
child: GestureDetector(
onLongPress: () {
box.write(BoxName.rideStatus, 'delete');
homeCaptainController.update();
},
child: IconButton(
onPressed: () {
box.read(BoxName.rideStatus) == 'Applied'
? {
Get.to(() => PassengerLocationMapPage(),
arguments:
box.read(BoxName.rideArguments)),
Get.put(MapDriverController())
.changeRideToBeginToPassenger()
}
: {
Get.to(() => PassengerLocationMapPage(),
arguments:
box.read(BoxName.rideArguments)),
Get.put(MapDriverController())
.startRideFromStartApp()
};
},
icon: const Icon(
Icons.directions_rounded,
size: 29,
color: AppColor.blueColor,
),
),
),
),
)
: const SizedBox()
Icon(icon, color: color, size: 20),
const SizedBox(width: 4),
Text(value,
style: AppStyle.title
.copyWith(fontSize: 16, fontWeight: FontWeight.bold)),
],
);
}),
),
Text(label,
style: AppStyle.title
.copyWith(fontSize: 12, color: Colors.grey.shade700)),
],
);
}
}
/// 6. ويدجت زر الاتصال السفلي
class _ConnectButtonOverlay extends StatelessWidget {
const _ConnectButtonOverlay();
/// 4. The Dialog that shows detailed driver stats.
class _DriverDetailsDialog extends StatelessWidget {
const _DriverDetailsDialog();
@override
Widget build(BuildContext context) {
// نفس الكود الأصلي لزر الاتصال
return Positioned(
bottom: 10,
right: Get.width * .1,
left: Get.width * .1,
child: const ConnectWidget());
final homeCaptainController = Get.find<HomeCaptainController>();
return BackdropFilter(
filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5),
child: AlertDialog(
backgroundColor: Colors.white.withOpacity(0.95),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
titlePadding: const EdgeInsets.only(top: 20),
title: Center(
child: Text(
'Your Activity'.tr,
style: AppStyle.title
.copyWith(fontSize: 20, fontWeight: FontWeight.bold),
),
),
content: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Divider(height: 20),
_buildStatRow(
icon: Entypo.wallet,
color: AppColor.greenColor,
label: 'Today'.tr,
value: homeCaptainController.totalMoneyToday.toString(),
),
const SizedBox(height: 12),
_buildStatRow(
icon: Entypo.wallet,
color: AppColor.yellowColor,
label: AppInformation.appName,
value: homeCaptainController.totalMoneyInSEFER.toString(),
),
const Divider(height: 24),
_buildDurationRow(
icon: Icons.timer_outlined,
label: 'Active Duration:'.tr,
value: homeCaptainController.stringActiveDuration,
color: AppColor.greenColor,
),
const SizedBox(height: 12),
_buildDurationRow(
icon: Icons.access_time,
label: 'Total Connection Duration:'.tr,
value: homeCaptainController.totalDurationToday,
color: AppColor.accentColor,
),
const Divider(height: 24),
_buildStatRow(
icon: Icons.star_border_rounded,
color: AppColor.blueColor,
label: 'Total Points'.tr,
value: homeCaptainController.totalPoints.toString(),
),
],
),
),
actions: [
TextButton(
onPressed: () => Get.back(),
child: Text('Close'.tr,
style: AppStyle.title.copyWith(
color: AppColor.blueColor, fontWeight: FontWeight.bold)),
)
],
),
);
}
Widget _buildStatRow(
{required IconData icon,
required Color color,
required String label,
required String value}) {
return Row(
children: [
Icon(icon, color: color, size: 22),
const SizedBox(width: 12),
Text('$label:', style: AppStyle.title),
const Spacer(),
Text(
value,
style: AppStyle.title.copyWith(
color: color, fontWeight: FontWeight.bold, fontSize: 18),
),
],
);
}
Widget _buildDurationRow(
{required IconData icon,
required String label,
required String value,
required Color color}) {
return Row(
children: [
Icon(icon, color: color, size: 20),
const SizedBox(width: 12),
Text(label, style: AppStyle.title),
const Spacer(),
Text(
value,
style: AppStyle.title.copyWith(
fontWeight: FontWeight.bold, color: color, fontSize: 16),
),
],
);
}
}
// هذه الويدجت المساعدة بقيت كما هي
class _MapControlButton extends StatelessWidget {
final IconData icon;
final VoidCallback onPressed;
@@ -606,7 +473,44 @@ class _MapControlButton extends StatelessWidget {
}
}
// الدوال المساعدة الأخرى تبقى كما هي في ملفك...
// showFirstTimeOfferNotification(BuildContext context) async { ... }
// bool _checkIfFirstTime() { ... }
// void _markAsNotFirstTime() { ... }
/// NOTE: The _FloatingActionButtons and _MapControlButton widgets have been removed
/// as their functionality is now integrated into the _HomeAppBar.
///
/// You will still need to modify your existing `ConnectWidget`
/// to accept an `isCompact` boolean flag as mentioned in the previous design.
/*
class ConnectWidget extends StatelessWidget {
final bool isCompact;
const ConnectWidget({super.key, this.isCompact = false});
@override
Widget build(BuildContext context) {
// ... your existing controller logic
if (isCompact) {
// Return a smaller version for the pod
return Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
decoration: BoxDecoration(
color: controller.isConnect ? AppColor.greenColor : AppColor.accentColor,
borderRadius: BorderRadius.circular(16),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(controller.isConnect ? Icons.wifi_tethering_rounded : Icons.wifi_tethering_off_rounded, color: Colors.white, size: 20),
const SizedBox(width: 8),
Text(
controller.isConnect ? 'Online'.tr : 'Offline'.tr,
style: AppStyle.title.copyWith(color: Colors.white, fontSize: 14),
),
],
),
);
}
// Return the original, larger button
return ElevatedButton.icon(...)
}
}
*/