Update codebase

This commit is contained in:
Hamza-Ayed
2026-08-09 16:56:13 +03:00
parent 95e2e4f35d
commit b64debaa88
1058 changed files with 164327 additions and 113928 deletions
@@ -1,38 +1,37 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:flutter_staggered_animations/flutter_staggered_animations.dart';
import 'package:tripz_driver/constant/box_name.dart';
import 'package:tripz_driver/constant/links.dart';
import 'package:tripz_driver/controller/functions/upload_image.dart';
import 'package:tripz_driver/controller/home/captin/home_captain_controller.dart';
import 'package:tripz_driver/device_compatibility_page.dart';
import 'package:tripz_driver/main.dart';
import 'package:siro_driver/constant/box_name.dart';
import 'package:siro_driver/constant/links.dart';
import 'package:siro_driver/controller/functions/upload_image.dart';
import 'package:siro_driver/controller/home/captin/home_captain_controller.dart';
import 'package:siro_driver/device_compatibility_page.dart';
import 'package:siro_driver/main.dart';
// استيراد الصفحات الأخرى... تأكد من صحة المسارات
import 'package:tripz_driver/views/Rate/rate_app_page.dart';
import 'package:tripz_driver/views/auth/captin/contact_us_page.dart';
import 'package:tripz_driver/views/auth/captin/invite_driver_screen.dart';
import 'package:tripz_driver/views/home/statistics/statistics_dashboard.dart';
import 'package:tripz_driver/views/gamification/challenges_page.dart';
import 'package:tripz_driver/views/gamification/leaderboard_page.dart';
import 'package:tripz_driver/views/gamification/referral_center_page.dart';
import 'package:tripz_driver/views/home/journal/schedule_page.dart';
import 'package:tripz_driver/views/notification/available_rides_page.dart';
import 'package:tripz_driver/views/auth/captin/logout_captain.dart';
import 'package:tripz_driver/views/home/Captin/history/history_captain.dart';
import 'package:tripz_driver/views/home/Captin/home_captain/help_captain.dart';
import 'package:tripz_driver/views/home/Captin/About Us/settings_captain.dart';
import 'package:tripz_driver/views/home/my_wallet/walet_captain.dart';
import 'package:tripz_driver/views/home/profile/profile_captain.dart';
import 'package:tripz_driver/views/notification/notification_captain.dart';
import 'package:siro_driver/views/Rate/rate_app_page.dart';
import 'package:siro_driver/views/auth/captin/contact_us_page.dart';
import 'package:siro_driver/views/auth/captin/invite_driver_screen.dart';
import 'package:siro_driver/views/home/statistics/earnings_page.dart';
import 'package:siro_driver/views/gamification/challenges_page.dart';
import 'package:siro_driver/views/gamification/leaderboard_page.dart';
import 'package:siro_driver/views/home/journal/schedule_page.dart';
import 'package:siro_driver/views/notification/available_rides_page.dart';
import 'package:siro_driver/views/auth/captin/logout_captain.dart';
import 'package:siro_driver/views/home/Captin/history/history_captain.dart';
import 'package:siro_driver/views/home/Captin/home_captain/help_captain.dart';
import 'package:siro_driver/views/home/Captin/About Us/settings_captain.dart';
import 'package:siro_driver/views/home/my_wallet/walet_captain.dart';
import 'package:siro_driver/views/home/profile/profile_captain.dart';
import 'package:siro_driver/views/notification/notification_captain.dart';
import 'package:url_launcher/url_launcher.dart';
import '../../../../constant/colors.dart';
import '../About Us/video_page.dart';
import '../assurance_health_page.dart';
import '../maintain_center_page.dart';
import '../../../widgets/ui/siro_ui.dart';
import '../../../transit/transit_driver_home_page.dart';
import '../About Us/video_page.dart';
import '../../../food_delivery/food_delivery_home_page.dart';
import '../../journal/driver_scheduled_rides_page.dart';
import '../../journal/driver_insurance_page.dart';
// 1. إنشاء Class لتعريف بيانات كل عنصر في القائمة
class DrawerItem {
@@ -48,173 +47,224 @@ class DrawerItem {
required this.onTap});
}
/// مجموعة عناصر تحت عنوان واحد. القائمة كانت ٢٢ عنصراً مسطّحاً بـ ٢٢ لوناً
/// مختلفاً، فيصعب العثور على أي بند. التجميع يقصّر زمن البحث بلا تغيير أي وجهة.
class DrawerSection {
final String title;
final List<DrawerItem> items;
DrawerSection({required this.title, required this.items});
}
// --- الويدجت الرئيسية للقائمة الجانبية ---
class AppDrawer extends StatelessWidget {
AppDrawer({super.key});
final ImageController imageController = Get.put(ImageController());
// 2. تعريف بيانات القائمة بشكل مركزي ومنظم
final List<DrawerItem> drawerItems = [
// DrawerItem(
// title: 'Mawasalati'.tr,
// icon: Icons.directions_bus_filled_rounded,
// color: Colors.teal,
// onTap: () => Get.to(() => const TransitDriverHomePage())),
DrawerItem(
title: 'Balance'.tr,
icon: Icons.account_balance_wallet,
color: Colors.green,
onTap: () => Get.to(() => WalletCaptainRefactored())),
DrawerItem(
title: 'Statistics'.tr,
icon: Icons.bar_chart_rounded,
color: Colors.deepPurple,
onTap: () => Get.to(() => StatisticsDashboard())),
DrawerItem(
title: 'Challenges'.tr,
icon: Icons.bolt_rounded,
color: Colors.amber,
onTap: () => Get.to(() => ChallengesPage())),
DrawerItem(
title: 'My Schedule'.tr,
icon: Icons.calendar_today_rounded,
color: Colors.teal,
onTap: () => Get.to(() => SchedulePage())),
DrawerItem(
title: 'Leaderboard'.tr,
icon: Icons.leaderboard_rounded,
color: Colors.red,
onTap: () => Get.to(() => LeaderboardPage())),
DrawerItem(
title: 'Profile'.tr,
icon: Icons.person,
color: Colors.blue,
onTap: () => Get.to(() => ProfileCaptain())),
DrawerItem(
title: 'History of Trip'.tr,
icon: Icons.history,
color: Colors.orange,
onTap: () => Get.to(() => const HistoryCaptain())),
DrawerItem(
title: 'Available for rides'.tr,
icon: Icons.drive_eta,
color: Colors.teal,
onTap: () => Get.to(() => const AvailableRidesPage())),
DrawerItem(
title: 'Notifications'.tr,
icon: Icons.notifications,
color: Colors.purple,
onTap: () => Get.to(() => const NotificationCaptain())),
DrawerItem(
title: 'Helping Center'.tr,
icon: Icons.help_center,
color: Colors.cyan,
onTap: () => Get.to(() => HelpCaptain())),
DrawerItem(
title: 'Invite Driver'.tr,
icon: Icons.person_add_rounded,
color: Colors.indigo,
onTap: () => Get.to(() => InviteScreen())),
// DrawerItem(
// title: 'Maintenance Center'.tr,
// icon: Icons.build,
// color: Colors.brown,
// onTap: () => Get.to(() => MaintainCenterPage())),
// DrawerItem(
// title: 'Health Insurance'.tr,
// icon: Icons.favorite,
// color: Colors.pink,
// onTap: () => Get.to(() => AssuranceHealthPage())),
DrawerItem(
title: 'Contact Us'.tr,
icon: Icons.email,
color: Colors.blueGrey,
onTap: () => Get.to(() => ContactUsPage())),
DrawerItem(
title: 'Videos Tutorials'.tr,
icon: Icons.video_library,
color: Colors.redAccent,
onTap: () => Get.to(() => VideoListPage())),
DrawerItem(
title: 'Rate Our App'.tr,
icon: Icons.star,
color: Colors.amber,
onTap: () => Get.to(() => RatingScreen())),
DrawerItem(
title: 'Is device compatible'.tr,
icon: Icons.memory,
color: Colors.greenAccent,
onTap: () => Get.to(() => DeviceCompatibilityPage())),
DrawerItem(
title: 'Privacy Policy'.tr,
icon: Icons.memory,
color: Colors.greenAccent,
onTap: () =>
launchUrl(Uri.parse('${AppLink.server}/privacy_policy.php'))),
DrawerItem(
title: 'Settings'.tr,
icon: Icons.settings,
color: Colors.grey.shade600,
onTap: () => Get.to(() => const SettingsCaptain())),
// 2. تعريف بيانات القائمة مجمَّعة حسب الغرض.
// الوجهات لم تتغيّر — التغيير في الترتيب واللون فقط.
// اللون صار دلالياً: أخضر = مال، كهرماني = مكافآت، أحمر = خروج،
// وما عداه لون العلامة. الطيف العشوائي السابق كان يشتّت لا يوجّه.
final List<DrawerSection> sections = [
DrawerSection(title: 'Services'.tr, items: [
DrawerItem(
title: 'Available for rides'.tr,
icon: Icons.drive_eta_rounded,
color: AppColor.primaryColor,
onTap: () => Get.to(() => const AvailableRidesPage())),
DrawerItem(
title: 'Mawasalati'.tr,
icon: Icons.directions_bus_filled_rounded,
color: AppColor.primaryColor,
onTap: () => Get.to(() => const TransitDriverHomePage())),
DrawerItem(
title: 'Delivery'.tr,
icon: Icons.delivery_dining_rounded,
color: AppColor.primaryColor,
onTap: () => Get.to(() => const FoodDeliveryHomePage())),
]),
DrawerSection(title: 'Wallet & Earnings'.tr, items: [
DrawerItem(
title: 'Balance'.tr,
icon: Icons.account_balance_wallet_rounded,
color: AppColor.greenColor,
onTap: () => Get.to(() => const WalletCaptainRefactored())),
DrawerItem(
title: 'My Earnings'.tr,
icon: Icons.payments_rounded,
color: AppColor.greenColor,
onTap: () => Get.to(() => EarningsPage())),
DrawerItem(
title: 'Insurance'.tr,
icon: Icons.health_and_safety_rounded,
color: AppColor.greenColor,
onTap: () => Get.to(() => const DriverInsurancePage())),
]),
DrawerSection(title: 'My Trips'.tr, items: [
DrawerItem(
title: 'My Schedule'.tr,
icon: Icons.calendar_today_rounded,
color: AppColor.primaryColor,
onTap: () => Get.to(() => SchedulePage())),
DrawerItem(
title: 'Upcoming Scheduled Rides'.tr,
icon: Icons.edit_calendar_rounded,
color: AppColor.primaryColor,
onTap: () => Get.to(() => const DriverScheduledRidesPage())),
DrawerItem(
title: 'History of Trip'.tr,
icon: Icons.history_rounded,
color: AppColor.primaryColor,
onTap: () => Get.to(() => const HistoryCaptain())),
]),
DrawerSection(title: 'Rewards'.tr, items: [
DrawerItem(
title: 'Challenges'.tr,
icon: Icons.bolt_rounded,
color: AppColor.yellowColor,
onTap: () => Get.to(() => ChallengesPage())),
DrawerItem(
title: 'Leaderboard'.tr,
icon: Icons.leaderboard_rounded,
color: AppColor.yellowColor,
onTap: () => Get.to(() => LeaderboardPage())),
DrawerItem(
title: 'Invite Driver'.tr,
icon: Icons.person_add_alt_1_rounded,
color: AppColor.yellowColor,
onTap: () => Get.to(() => InviteScreen())),
]),
DrawerSection(title: 'My Account'.tr, items: [
DrawerItem(
title: 'Profile'.tr,
icon: Icons.person_rounded,
color: AppColor.primaryColor,
onTap: () => Get.to(() => ProfileCaptain())),
DrawerItem(
title: 'Notifications'.tr,
icon: Icons.notifications_rounded,
color: AppColor.primaryColor,
onTap: () => Get.to(() => const NotificationCaptain())),
DrawerItem(
title: 'Settings'.tr,
icon: Icons.settings_rounded,
color: AppColor.primaryColor,
onTap: () => Get.to(() => const SettingsCaptain())),
]),
DrawerSection(title: 'Support'.tr, items: [
DrawerItem(
title: 'Helping Center'.tr,
icon: Icons.help_center_rounded,
color: AppColor.primaryColor,
onTap: () => Get.to(() => HelpCaptain())),
DrawerItem(
title: 'Contact Us'.tr,
icon: Icons.email_rounded,
color: AppColor.primaryColor,
onTap: () => Get.to(() => ContactUsPage())),
DrawerItem(
title: 'Videos Tutorials'.tr,
icon: Icons.play_circle_fill_rounded,
color: AppColor.primaryColor,
onTap: () => Get.to(() => VideoListPage())),
DrawerItem(
title: 'Rate Our App'.tr,
icon: Icons.star_rounded,
color: AppColor.primaryColor,
onTap: () => Get.to(() => RatingScreen())),
DrawerItem(
title: 'Is device compatible'.tr,
icon: Icons.memory_rounded,
color: AppColor.primaryColor,
onTap: () => Get.to(() => DeviceCompatibilityPage())),
DrawerItem(
title: 'Privacy Policy'.tr,
icon: Icons.privacy_tip_rounded,
color: AppColor.primaryColor,
onTap: () =>
launchUrl(Uri.parse('${AppLink.server}/privacy_policy.php'))),
]),
];
@override
Widget build(BuildContext context) {
// نبني قائمة مسطّحة من العناوين والعناصر لتبقى الحركة المتدرّجة تعمل.
final rows = <Widget>[];
for (final section in sections) {
rows.add(_DrawerSectionTitle(section.title));
rows.addAll(section.items.map((e) => _DrawerItemTile(item: e)));
}
return Drawer(
child: Container(
color: Theme.of(context).scaffoldBackgroundColor,
child: Column(
children: [
// --- الجزء العلوي من القائمة (بيانات المستخدم) ---
UserHeader(), // استخدمنا الويدجت المحسنة بالأسفل
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
child: Column(
children: [
// --- الجزء العلوي من القائمة (بيانات المستخدم) ---
UserHeader(),
// --- قائمة العناصر المتحركة ---
Expanded(
child: AnimationLimiter(
child: ListView.builder(
padding: const EdgeInsets.all(8.0),
itemCount: drawerItems.length + 1, // +1 لزر تسجيل الخروج
itemBuilder: (BuildContext context, int index) {
// --- زر تسجيل الخروج في النهاية ---
if (index == drawerItems.length) {
return AnimationConfiguration.staggeredList(
position: index,
duration: const Duration(milliseconds: 375),
child: SlideAnimation(
verticalOffset: 50.0,
child: FadeInAnimation(
child: _DrawerItemTile(
item: DrawerItem(
title: 'Sign Out'.tr,
icon: Icons.logout,
color: Colors.red,
onTap: () =>
Get.to(() => const LogoutCaptain())),
),
),
),
);
}
// --- بقية العناصر ---
final item = drawerItems[index];
return AnimationConfiguration.staggeredList(
position: index,
duration: const Duration(milliseconds: 375),
child: SlideAnimation(
verticalOffset: 50.0,
child: FadeInAnimation(
child: _DrawerItemTile(item: item),
),
),
);
},
),
// --- قائمة العناصر المتحركة ---
Expanded(
child: AnimationLimiter(
child: ListView.builder(
padding: const EdgeInsets.fromLTRB(10, 8, 10, 8),
itemCount: rows.length,
itemBuilder: (BuildContext context, int index) {
return AnimationConfiguration.staggeredList(
position: index,
duration: const Duration(milliseconds: 300),
child: SlideAnimation(
verticalOffset: 40.0,
child: FadeInAnimation(child: rows[index]),
),
);
},
),
),
],
),
),
// --- تسجيل الخروج مثبَّت أسفل القائمة ---
// كان آخر عنصر في قائمة من ٢٢ بنداً، فيتطلّب تمريراً كاملاً للوصول إليه.
SafeArea(
top: false,
child: Container(
width: double.infinity,
decoration: BoxDecoration(
border: Border(
top: BorderSide(color: Theme.of(context).dividerColor)),
),
padding: const EdgeInsets.fromLTRB(10, 6, 10, 6),
child: _DrawerItemTile(
item: DrawerItem(
title: 'Sign Out'.tr,
icon: Icons.logout_rounded,
color: AppColor.redColor,
onTap: () => Get.to(() => const LogoutCaptain())),
),
),
),
],
),
);
}
}
// --- عنوان مجموعة داخل القائمة ---
class _DrawerSectionTitle extends StatelessWidget {
final String title;
const _DrawerSectionTitle(this.title);
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsetsDirectional.fromSTEB(14, 16, 14, 6),
child: Text(
title.toUpperCase(),
style: Theme.of(context).textTheme.bodySmall?.copyWith(
fontSize: 11,
fontWeight: FontWeight.bold,
letterSpacing: 0.8,
),
),
);
}
@@ -227,22 +277,26 @@ class _DrawerItemTile extends StatelessWidget {
@override
Widget build(BuildContext context) {
// النيفي الداكن لا يُقرأ على خلفية ليلية، فنستبدله بلون العلامة الفاتح.
final isDark = Theme.of(context).brightness == Brightness.dark;
final color = item.color == AppColor.primaryColor && isDark
? AppColor.secondaryColorStatic
: item.color;
return Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0),
padding: const EdgeInsets.symmetric(vertical: 2.0),
child: ListTile(
leading: Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: item.color.withValues(alpha: 0.1),
shape: BoxShape.circle,
),
child: Icon(item.icon, color: item.color, size: 24),
),
dense: true,
visualDensity: const VisualDensity(vertical: -1),
horizontalTitleGap: 12,
contentPadding: const EdgeInsets.symmetric(horizontal: 12),
leading: SiroIconBadge(item.icon, color: color, size: 20),
title: Text(
item.title,
overflow: TextOverflow.ellipsis,
style: Theme.of(context)
.textTheme
.titleMedium
.bodyMedium
?.copyWith(fontWeight: FontWeight.w500),
),
onTap: () {
@@ -252,7 +306,7 @@ class _DrawerItemTile extends StatelessWidget {
});
},
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
splashColor: item.color.withValues(alpha: 0.2),
splashColor: color.withValues(alpha: 0.15),
),
);
}
@@ -320,10 +374,9 @@ class UserHeader extends StatelessWidget {
fontSize: 18,
shadows: [Shadow(blurRadius: 2, color: Colors.black26)]),
),
accountEmail:
box.read(BoxName.emailDriver).toString().contains('tripzapp')
? Text('Your email not updated yet'.tr)
: Text(box.read(BoxName.emailDriver)),
accountEmail: box.read(BoxName.emailDriver).toString().contains('siroapp')
? Text('Your email not updated yet'.tr)
: Text(box.read(BoxName.emailDriver)),
currentAccountPicture: GetBuilder<ImageController>(
builder: (controller) => Stack(
clipBehavior: Clip.none,
@@ -333,34 +386,37 @@ class UserHeader extends StatelessWidget {
shape: BoxShape.circle,
border: Border.all(color: Colors.white, width: 2),
boxShadow: [
BoxShadow(color: Colors.black.withValues(alpha: 0.3), blurRadius: 5)
BoxShadow(
color: Colors.black.withValues(alpha: 0.3), blurRadius: 5)
],
),
child: controller.isloading
? const CircularProgressIndicator(color: Colors.white)
: CircleAvatar(
backgroundImage: (box
.read(BoxName.driverPhotoUrl)
?.toString()
.isNotEmpty ==
true)
? NetworkImage(box.read(BoxName.driverPhotoUrl))
: null,
: Builder(builder: (context) {
final photoUrl =
box.read(BoxName.driverPhotoUrl)?.toString() ?? '';
final avatarImage =
photoUrl.isNotEmpty ? NetworkImage(photoUrl) : null;
// [تعديل هام]: في حال فشل تحميل الصورة (غير موجودة)
onBackgroundImageError: (exception, stackTrace) {
// طباعة الخطأ في الكونسول للتوضيح
debugPrint(
"Profile image not found or error loading: $exception");
// استدعاء نافذة التنبيه
_showUploadPhotoDialog(context, controller);
},
return CircleAvatar(
backgroundImage: avatarImage,
// أيقونة بديلة تظهر في الخلفية إذا لم تكن الصورة موجودة
backgroundColor: Colors.grey.shade300,
child: const Icon(Icons.person,
size: 40, color: Colors.white),
),
// Flutter يمنع onBackgroundImageError بلا صورة
// (assertion)، فنمرّره فقط عند وجود صورة فعلية.
onBackgroundImageError: avatarImage == null
? null
: (exception, stackTrace) {
debugPrint(
"Profile image not found or error loading: $exception");
_showUploadPhotoDialog(context, controller);
},
// أيقونة بديلة تظهر في الخلفية إذا لم تكن الصورة موجودة
backgroundColor: Colors.grey.shade300,
child: const Icon(Icons.person,
size: 40, color: Colors.white),
);
}),
),
Positioned(
bottom: -5,
@@ -383,31 +439,31 @@ class UserHeader extends StatelessWidget {
),
),
otherAccountsPictures: [
SizedBox(
width: 60,
Container(
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 4),
decoration: BoxDecoration(
color: Colors.white.withValues(alpha: 0.15),
borderRadius: BorderRadius.circular(999),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
mainAxisSize: MainAxisSize.min,
children: [
const Icon(Icons.star_rounded, color: AppColor.gold, size: 15),
const SizedBox(width: 3),
Text(
homeCaptainController.rating.toString(),
style: const TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 14),
fontSize: 13),
),
const SizedBox(width: 2),
const Icon(Icons.star, color: Colors.amber, size: 16),
],
),
),
],
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Theme.of(context).primaryColor, Colors.blue.shade700],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
),
// تدرّج العلامة نفسه المستعمل في رؤوس الصفحات الداخلية
// (كان `Colors.blue.shade700` وهو أزرق لا علاقة له بهوية سيرو).
decoration: BoxDecoration(gradient: SiroUi.brandGradient(context)),
);
}
}
@@ -1,52 +1,43 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:tripz_driver/controller/home/captin/help/help_controller.dart';
import 'package:tripz_driver/views/home/Captin/home_captain/help_details_replay_page.dart';
import 'package:siro_driver/controller/home/captin/help/help_controller.dart';
import 'package:siro_driver/views/home/Captin/home_captain/help_details_replay_page.dart';
import 'package:flutter/cupertino.dart';
import '../../../../constant/colors.dart';
import '../../../../controller/functions/encrypt_decrypt.dart';
import '../../../widgets/my_scafold.dart';
import '../../../widgets/ui/siro_ui.dart';
class HelpCaptain extends StatelessWidget {
HelpCaptain({super.key});
const HelpCaptain({super.key});
@override
Widget build(BuildContext context) {
Get.put(HelpController());
final theme = Theme.of(context);
return MyScafolld(
return SiroPage(
title: 'Helping Page'.tr,
isleading: true,
body: [
SingleChildScrollView(
padding: const EdgeInsets.all(20.0),
padding: SiroUi.pageInsets,
body: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
padding: const EdgeInsets.all(18.0),
decoration: BoxDecoration(
color: theme.colorScheme.surfaceVariant.withOpacity(0.5),
borderRadius: BorderRadius.circular(15.0),
border: Border.all(color: theme.dividerColor),
),
child: Text(
'If you need any help or have questions, this is the right place to do that. You are welcome!'
.tr,
style: theme.textTheme.bodyLarge,
textAlign: TextAlign.center,
SiroCard(
child: Row(
children: [
SiroIconBadge(Icons.support_agent_rounded,
color: SiroUi.interactive(context)),
const SizedBox(width: 12),
Expanded(
child: Text(
'If you need any help or have questions, this is the right place to do that. You are welcome!'
.tr,
style: theme.textTheme.bodyMedium,
),
),
],
),
),
const SizedBox(height: 24),
Text(
'Submit Your Question'.tr,
style: theme.textTheme.titleMedium
?.copyWith(fontWeight: FontWeight.bold),
),
const SizedBox(height: 12),
SiroSectionTitle('Submit Your Question'.tr),
GetBuilder<HelpController>(
builder: (helpController) => Form(
key: helpController.formKey,
@@ -58,8 +49,6 @@ class HelpCaptain extends StatelessWidget {
hintText: 'Enter your Question here'.tr,
prefixIcon:
const Icon(Icons.question_answer_outlined),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12)),
),
maxLines: 3,
validator: (value) {
@@ -71,10 +60,10 @@ class HelpCaptain extends StatelessWidget {
),
const SizedBox(height: 16),
helpController.isLoading
? const Center(child: CircularProgressIndicator())
? const SiroLoading()
: SizedBox(
width: double.infinity,
child: ElevatedButton(
child: ElevatedButton.icon(
onPressed: () {
if (helpController.formKey.currentState!
.validate()) {
@@ -83,53 +72,36 @@ class HelpCaptain extends StatelessWidget {
.clear();
}
},
style: ElevatedButton.styleFrom(
backgroundColor: AppColor.primaryColor,
foregroundColor: Colors.white,
padding:
const EdgeInsets.symmetric(vertical: 14),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12)),
),
child: Text('Submit Question'.tr),
icon: const Icon(Icons.send_rounded, size: 18),
label: Text('Submit Question'.tr),
),
),
],
),
),
),
const SizedBox(height: 32),
Text(
'Your Questions'.tr,
style: theme.textTheme.titleMedium
?.copyWith(fontWeight: FontWeight.bold),
),
const SizedBox(height: 12),
SiroSectionTitle('Your Questions'.tr),
GetBuilder<HelpController>(
builder: (helpController) {
final questions = helpController.helpQuestionDate['message'];
if (questions == null || questions.isEmpty) {
return Center(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Text('No questions asked yet.'.tr),
return Padding(
padding: const EdgeInsets.symmetric(vertical: 24),
child: SiroEmptyState(
icon: Icons.forum_outlined,
title: 'No questions asked yet.'.tr,
),
);
}
return ListView.separated(
return ListView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: questions.length,
separatorBuilder: (context, index) =>
const SizedBox(height: 12),
itemBuilder: (context, index) {
var list = questions[index];
return Card(
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
side: BorderSide(color: theme.dividerColor),
),
return SiroCard(
padding: EdgeInsets.zero,
child: ListTile(
title: Text(
EncryptionHelper.instance
@@ -142,8 +114,8 @@ class HelpCaptain extends StatelessWidget {
list['datecreated'],
style: theme.textTheme.bodySmall,
),
trailing:
const Icon(Icons.arrow_forward_ios, size: 16),
trailing: Icon(Icons.arrow_forward_ios,
size: 14, color: SiroUi.subtle(context)),
onTap: () {
helpController.getIndex(
int.parse(EncryptionHelper.instance
@@ -159,173 +131,10 @@ class HelpCaptain extends StatelessWidget {
);
},
),
const SizedBox(height: 16),
],
),
),
],
);
}
}
// class HelpCaptain extends StatelessWidget {
// HelpCaptain({super.key});
// @override
// Widget build(BuildContext context) {
// Get.put(HelpController());
// return CupertinoPageScaffold(
// navigationBar: CupertinoNavigationBar(
// middle: Text('Helping Page'.tr),
// leading: CupertinoButton(
// padding: EdgeInsets.zero,
// child: Icon(CupertinoIcons.back),
// onPressed: () => Navigator.pop(context),
// ),
// ),
// child: SafeArea(
// child: Padding(
// padding: const EdgeInsets.all(16.0),
// child: Column(
// children: [
// Padding(
// padding: const EdgeInsets.symmetric(vertical: 12.0),
// child: Container(
// padding: const EdgeInsets.all(16.0),
// decoration: BoxDecoration(
// borderRadius: BorderRadius.circular(12.0),
// border: Border.all(
// color: CupertinoColors.systemGrey2,
// ),
// ),
// child: Text(
// 'If you need any help or have questions, this is the right place to do that. You are welcome!'
// .tr,
// style: CupertinoTheme.of(context).textTheme.textStyle,
// textAlign: TextAlign.center,
// ),
// ),
// ),
// Card(
// elevation: 3,
// color: CupertinoColors.systemGrey6,
// shape: RoundedRectangleBorder(
// borderRadius: BorderRadius.circular(12.0),
// ),
// child: Padding(
// padding: const EdgeInsets.all(16.0),
// child: GetBuilder<HelpController>(
// builder: (helpController) => Form(
// key: helpController.formKey,
// child: Column(
// children: [
// CupertinoTextField(
// controller: helpController.helpQuestionController,
// placeholder: 'Enter your Question here'.tr,
// decoration: BoxDecoration(
// borderRadius: BorderRadius.circular(12),
// border: Border.all(
// color: CupertinoColors.systemGrey,
// ),
// ),
// padding: const EdgeInsets.all(16),
// clearButtonMode: OverlayVisibilityMode.editing,
// ),
// const SizedBox(height: 20),
// helpController.isLoading
// ? const CupertinoActivityIndicator()
// : CupertinoButton.filled(
// onPressed: () {
// if (helpController.formKey.currentState!
// .validate()) {
// helpController.addHelpQuestion();
// // Clear the feedback form
// helpController.formKey.currentState!
// .reset();
// }
// },
// child: Text('Submit Question'.tr),
// ),
// ],
// ),
// ),
// ),
// ),
// ),
// const SizedBox(height: 20),
// Expanded(
// child: GetBuilder<HelpController>(
// builder: (helpController) => Padding(
// padding: const EdgeInsets.all(10),
// child: Container(
// decoration: BoxDecoration(
// border: Border.all(
// color: CupertinoColors.systemGrey2,
// ),
// borderRadius: BorderRadius.circular(12.0),
// ),
// child: ListView.builder(
// itemCount: helpController.helpQuestionDate['message'] !=
// null
// ? helpController.helpQuestionDate['message'].length
// : 0,
// itemBuilder: (BuildContext context, int index) {
// var list =
// helpController.helpQuestionDate['message'][index];
// return Padding(
// padding: const EdgeInsets.all(3),
// child: Container(
// padding: const EdgeInsets.symmetric(
// vertical: 12, horizontal: 16),
// decoration: BoxDecoration(
// border: Border.all(
// color: CupertinoColors.activeGreen,
// width: 2,
// ),
// borderRadius: BorderRadius.circular(12),
// ),
// child: GestureDetector(
// onTap: () {
// helpController.getIndex(
// list['id'], list['helpQuestion']);
// helpController
// .getHelpRepley(list['id'].toString());
// Get.to(() => const HelpDetailsReplayPage());
// },
// child: Row(
// mainAxisAlignment:
// MainAxisAlignment.spaceBetween,
// children: [
// Expanded(
// child: Text(
// list['helpQuestion'],
// style: CupertinoTheme.of(context)
// .textTheme
// .textStyle,
// overflow: TextOverflow.ellipsis,
// ),
// ),
// Text(
// list['datecreated'],
// style: CupertinoTheme.of(context)
// .textTheme
// .tabLabelTextStyle,
// ),
// ],
// ),
// ),
// ),
// );
// },
// ),
// ),
// ),
// ),
// ),
// ],
// ),
// ),
// ),
// );
// }
// }
@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:tripz_driver/constant/style.dart';
import 'package:tripz_driver/views/widgets/mycircular.dart';
import 'package:siro_driver/constant/style.dart';
import 'package:siro_driver/views/widgets/mycircular.dart';
import '../../../../controller/functions/encrypt_decrypt.dart';
import '../../../../controller/home/captin/help/help_controller.dart';
@@ -88,6 +88,13 @@ class HelpDetailsReplayPage extends StatelessWidget {
replayData == null ||
EncryptionHelper.instance.decryptData(replayData['replay']).toString() == 'not yet';
if (isNoReply && helpController.aiReplies.containsKey(helpController.indexQuestion)) {
return Text(
helpController.aiReplies[helpController.indexQuestion]!,
style: Theme.of(context).textTheme.bodyLarge,
);
}
return Text(
isNoReply
? 'No Response yet.'.tr
@@ -6,8 +6,8 @@ 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:tripz_driver/views/home/Captin/home_captain/drawer_captain.dart';
import 'package:tripz_driver/views/widgets/mycircular.dart';
import 'package:siro_driver/views/home/Captin/home_captain/drawer_captain.dart';
import 'package:siro_driver/views/widgets/mycircular.dart';
import '../../../../constant/box_name.dart';
import '../../../../constant/colors.dart';
@@ -222,23 +222,34 @@ class _HomeAppBar extends StatelessWidget implements PreferredSizeWidget {
// ── Logo + App Name ──────────────────────
title: Padding(
padding: const EdgeInsets.only(left: 4),
child: Row(
children: [
_LogoBadge(),
const SizedBox(width: 10),
Expanded(
child: Text(
AppInformation.appName.split(' ')[0].tr,
style: const TextStyle(
color: _Token.accent,
fontSize: 20,
fontWeight: FontWeight.w800,
letterSpacing: 0.8,
),
overflow: TextOverflow.ellipsis,
),
),
],
// ‏شارات الـ actions تلتهم عرض الـ AppBar فلا يبقى للعنوان أحياناً
// ‏سوى ~26px، بينما الشعار وحده 36px — ومن هنا كان الفيض.
// ‏نُسقط الاسم عند ضيق المساحة ونُبقي الشعار: هو الهوية الأهم.
child: LayoutBuilder(
builder: (context, constraints) {
final showName = constraints.maxWidth >= 96;
return Row(
mainAxisSize: MainAxisSize.min,
children: [
_LogoBadge(),
if (showName) ...[
const SizedBox(width: 6),
Flexible(
child: Text(
AppInformation.appName.split(' ')[0].tr,
style: const TextStyle(
color: _Token.accent,
fontSize: 18,
fontWeight: FontWeight.w800,
letterSpacing: 0.5,
),
overflow: TextOverflow.ellipsis,
),
),
],
],
);
},
),
),
actions: [
@@ -734,7 +745,7 @@ class _FloatingControls extends StatelessWidget {
onTap: () =>
Bubble().startBubbleHead(sendAppToBackground: true),
tooltip: 'Overlay'.tr,
child: Image.asset('assets/images/logo1.png',
child: Image.asset('assets/images/logo.png',
width: 26, height: 26),
),
const SizedBox(height: 10),
@@ -24,8 +24,7 @@ class OsmMapView extends StatelessWidget {
final double currentHeading = locationController.heading;
final cityPolygon = CountryLogic.getCurrentCityPolygon();
final bool inServiceArea =
CountryLogic.isPointInPolygon(currentLocation, cityPolygon);
final bool inServiceArea = CountryLogic.isPointInPolygon(currentLocation, cityPolygon);
return Stack(
children: [
@@ -66,16 +65,12 @@ class OsmMapView extends StatelessWidget {
left: 20,
right: 20,
child: Container(
padding:
const EdgeInsets.symmetric(vertical: 12, horizontal: 16),
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16),
decoration: BoxDecoration(
color: Colors.redAccent.withOpacity(0.9),
borderRadius: BorderRadius.circular(12),
boxShadow: const [
BoxShadow(
color: Colors.black26,
blurRadius: 4,
offset: Offset(0, 2))
BoxShadow(color: Colors.black26, blurRadius: 4, offset: Offset(0, 2))
],
),
child: const Row(
@@ -1,8 +1,8 @@
import 'package:tripz_driver/controller/functions/tts.dart';
import 'package:siro_driver/controller/functions/tts.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:tripz_driver/controller/home/payment/captain_wallet_controller.dart';
import 'package:siro_driver/controller/home/payment/captain_wallet_controller.dart';
import '../../../../../constant/style.dart';
import '../../../../widgets/elevated_btn.dart';
@@ -1,9 +1,9 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:intaleq_maps/intaleq_maps.dart';
import 'package:tripz_driver/constant/colors.dart';
import 'package:tripz_driver/controller/home/captin/destination_controller.dart';
import 'package:tripz_driver/controller/functions/tts.dart';
import 'package:siro_driver/constant/colors.dart';
import 'package:siro_driver/controller/home/captin/destination_controller.dart';
import 'package:siro_driver/controller/functions/tts.dart';
class DestinationBottomSheet extends StatelessWidget {
const DestinationBottomSheet({super.key});
@@ -67,9 +67,7 @@ class DestinationBottomSheet extends StatelessWidget {
init: Get.find<TextToSpeechController>(),
builder: (tts) => IconButton(
icon: Icon(
tts.isSpeaking
? Icons.volume_up_rounded
: Icons.volume_mute_rounded,
tts.isSpeaking ? Icons.volume_up_rounded : Icons.volume_mute_rounded,
color: AppColor.primaryColor,
size: 26,
),
@@ -111,12 +109,10 @@ class DestinationBottomSheet extends StatelessWidget {
side: BorderSide(color: Colors.green.withOpacity(0.3)),
),
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 14, vertical: 12),
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 12),
child: Row(
children: [
const Icon(Icons.check_circle_rounded,
color: Colors.green, size: 22),
const Icon(Icons.check_circle_rounded, color: Colors.green, size: 22),
const SizedBox(width: 10),
Expanded(
child: Column(
@@ -167,8 +163,7 @@ class DestinationBottomSheet extends StatelessWidget {
fillColor: Theme.of(context).brightness == Brightness.dark
? const Color(0xFF202B4B)
: Colors.grey.withOpacity(0.1),
contentPadding: const EdgeInsets.symmetric(
vertical: 14, horizontal: 16),
contentPadding: const EdgeInsets.symmetric(vertical: 14, horizontal: 16),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(14),
borderSide: BorderSide.none,
@@ -195,28 +190,21 @@ class DestinationBottomSheet extends StatelessWidget {
itemBuilder: (context, index) {
final place = c.placesSuggestions[index];
return ListTile(
leading: const Icon(Icons.place_rounded,
color: Colors.grey),
leading: const Icon(Icons.place_rounded, color: Colors.grey),
title: Text(
place['name'] ?? "",
style: const TextStyle(fontSize: 13),
),
subtitle: Text(
place['description'] ?? "",
style: const TextStyle(
fontSize: 11, color: Colors.grey),
style: const TextStyle(fontSize: 11, color: Colors.grey),
),
onTap: () {
FocusScope.of(context).unfocus();
Get.back(); // Close sheet
final lat = double.tryParse(
place['latitude']?.toString() ?? '0') ??
0.0;
final lng = double.tryParse(
place['longitude']?.toString() ?? '0') ??
0.0;
c.saveDestination(LatLng(lat, lng),
place['name'] ?? 'Destination');
final lat = double.tryParse(place['latitude']?.toString() ?? '0') ?? 0.0;
final lng = double.tryParse(place['longitude']?.toString() ?? '0') ?? 0.0;
c.saveDestination(LatLng(lat, lng), place['name'] ?? 'Destination');
},
);
},
@@ -1,14 +1,14 @@
import 'package:tripz_driver/constant/box_name.dart';
import 'package:tripz_driver/controller/firebase/local_notification.dart';
import 'package:tripz_driver/main.dart';
import 'package:tripz_driver/views/home/Captin/driver_map_page.dart';
import 'package:tripz_driver/views/home/Captin/orderCaptin/vip_order_page.dart';
import 'package:tripz_driver/views/auth/syria/registration_view.dart';
import 'package:siro_driver/constant/box_name.dart';
import 'package:siro_driver/controller/firebase/local_notification.dart';
import 'package:siro_driver/main.dart';
import 'package:siro_driver/views/home/Captin/driver_map_page.dart';
import 'package:siro_driver/views/home/Captin/orderCaptin/vip_order_page.dart';
import 'package:siro_driver/views/auth/syria/registration_view.dart';
import 'package:flutter/material.dart';
import 'package:flutter_font_icons/flutter_font_icons.dart';
import 'package:get/get.dart';
import 'package:tripz_driver/controller/home/captin/home_captain_controller.dart';
import 'package:tripz_driver/views/widgets/mydialoug.dart';
import 'package:siro_driver/controller/home/captin/home_captain_controller.dart';
import 'package:siro_driver/views/widgets/mydialoug.dart';
import '../../../../../constant/links.dart';
import '../../../../../controller/firebase/notification_service.dart';
@@ -16,7 +16,7 @@ import '../../../../../controller/functions/crud.dart';
import '../../../../../controller/home/captin/order_request_controller.dart';
import '../../../../../print.dart';
import '../../../../Rate/ride_calculate_driver.dart';
import 'package:tripz_driver/views/home/statistics/statistics_dashboard.dart';
import 'package:siro_driver/views/home/statistics/earnings_page.dart';
// ─────────────────────────────────────────────
// Design Tokens (Responsive)
@@ -103,7 +103,7 @@ GetBuilder<HomeCaptainController> leftMainMenuCaptainIcons() {
color: _T.blue,
tooltip: 'Statistics'.tr,
onTap: () {
Get.to(() => StatisticsDashboard());
Get.to(() => EarningsPage());
},
onLongPress: () =>
box.write(BoxName.statusDriverLocation, 'off'),