From 8f555691b97fbf3fe44317f2b868af884b38525b Mon Sep 17 00:00:00 2001 From: Hamza-Ayed Date: Fri, 8 May 2026 22:44:55 +0300 Subject: [PATCH] add new featurs like new stat page --- lib/constant/finance_design_system.dart | 30 +- .../auth/captin/invit_controller.dart | 4 +- .../gamification/challenges_controller.dart | 24 +- .../statistics/statistics_controller.dart | 39 +- lib/controller/local/translations.dart | 102 +++++- .../profile/setting_controller.dart | 5 +- lib/translations_ar.json | 52 ++- lib/views/gamification/challenges_page.dart | 45 +-- lib/views/gamification/leaderboard_page.dart | 274 ++++++++++---- .../gamification/referral_center_page.dart | 38 +- .../home/Captin/history/history_captain.dart | 26 +- .../Captin/home_captain/drawer_captain.dart | 43 +-- .../home/Captin/home_captain/home_captin.dart | 59 +-- lib/views/home/journal/schedule_page.dart | 16 +- .../payment_history_driver_page.dart | 6 +- lib/views/home/my_wallet/points_captain.dart | 32 +- lib/views/home/my_wallet/walet_captain.dart | 17 +- .../home/my_wallet/weekly_payment_page.dart | 84 +++-- .../widgets/financial_summary_card.dart | 10 +- .../widgets/promo_gamification_card.dart | 2 +- .../home/my_wallet/widgets/quick_actions.dart | 2 +- .../widgets/transaction_preview_item.dart | 2 +- lib/views/home/profile/behavior_page.dart | 80 +++-- .../home/statistics/statistics_dashboard.dart | 339 ++++++++++-------- .../statistics/widgets/daily_goal_widget.dart | 39 +- .../widgets/level_progress_widget.dart | 116 ++++-- .../widgets/monthly_chart_widget.dart | 120 +++++-- .../statistics/widgets/stat_summary_card.dart | 4 +- .../widgets/today_chart_widget.dart | 50 ++- .../widgets/weekly_chart_widget.dart | 114 ++++-- lib/views/lang/languages.dart | 2 +- pubspec.lock | 2 +- pubspec.yaml | 1 + 33 files changed, 1194 insertions(+), 585 deletions(-) diff --git a/lib/constant/finance_design_system.dart b/lib/constant/finance_design_system.dart index 16e9f59..510897a 100644 --- a/lib/constant/finance_design_system.dart +++ b/lib/constant/finance_design_system.dart @@ -1,19 +1,23 @@ import 'package:flutter/material.dart'; +import 'package:get/get.dart'; class FinanceDesignSystem { // --- Colors --- - static const Color primaryDark = Color(0xFF0A0E21); - static const Color accentBlue = Color(0xFF3D5AFE); - static const Color successGreen = Color(0xFF00C853); - static const Color dangerRed = Color(0xFFD50000); - static const Color backgroundColor = Color(0xFFF6F8FA); - static const Color cardColor = Color(0xFFFFFFFF); - static const Color textSecondary = Color(0xFF757575); - static const Color textMuted = Color(0xFFBDBDBD); + static Color get primaryDark => Get.isDarkMode ? const Color(0xFFE0E0E0) : const Color(0xFF0A0E21); + static Color get accentBlue => const Color(0xFF3D5AFE); + static Color get successGreen => const Color(0xFF00C853); + static Color get dangerRed => const Color(0xFFD50000); + static Color get backgroundColor => Get.isDarkMode ? const Color(0xFF0A0E21) : const Color(0xFFF6F8FA); + static Color get cardColor => Get.isDarkMode ? const Color(0xFF1E1E2E) : const Color(0xFFFFFFFF); + static Color get textSecondary => Get.isDarkMode ? Colors.white70 : const Color(0xFF757575); + static Color get textMuted => Get.isDarkMode ? Colors.white38 : const Color(0xFFBDBDBD); + static Color get borderColor => Get.isDarkMode ? Colors.white10 : Colors.grey.withOpacity(0.1); // --- Gradients --- - static const LinearGradient balanceGradient = LinearGradient( - colors: [Color(0xFF0A0E21), Color(0xFF1A237E)], + static LinearGradient get balanceGradient => LinearGradient( + colors: Get.isDarkMode + ? [const Color(0xFF1E1E2E), const Color(0xFF2A2A3E)] + : [const Color(0xFF0A0E21), const Color(0xFF1A237E)], begin: Alignment.topLeft, end: Alignment.bottomRight, ); @@ -34,19 +38,19 @@ class FinanceDesignSystem { static const double verticalSectionPadding = 24.0; // --- Text Styles --- - static const TextStyle balanceStyle = TextStyle( + static TextStyle get balanceStyle => const TextStyle( fontSize: 32, fontWeight: FontWeight.bold, color: Colors.white, ); - static const TextStyle headingStyle = TextStyle( + static TextStyle get headingStyle => TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: primaryDark, ); - static const TextStyle subHeadingStyle = TextStyle( + static TextStyle get subHeadingStyle => TextStyle( fontSize: 14, color: textSecondary, ); diff --git a/lib/controller/auth/captin/invit_controller.dart b/lib/controller/auth/captin/invit_controller.dart index 9e12ffc..4fcf53d 100755 --- a/lib/controller/auth/captin/invit_controller.dart +++ b/lib/controller/auth/captin/invit_controller.dart @@ -532,7 +532,7 @@ Download the Intaleq app now and enjoy your ride! String message = '${'*Intaleq DRIVER CODE*'.tr}\n\n' '${"Use this code in registration".tr}\n' '${"To get a gift for both".tr}\n\n' - '${"The period of this code is 1 hour".tr}\n\n' + '${"The period of this code is 24 hours".tr}\n\n' '${'before'.tr} *${d['message']['expirationTime'].toString()}*\n\n' '_*${d['message']['inviteCode'].toString()}*_\n\n' '${"Install our app:".tr}\n' @@ -581,7 +581,7 @@ Download the Intaleq app now and enjoy your ride! String message = '${'*Intaleq APP CODE*'.tr}\n\n' '${"Use this code in registration".tr}\n\n' '${"To get a gift for both".tr}\n\n' - '${"The period of this code is 1 hour".tr}\n\n' + '${"The period of this code is 24 hours".tr}\n\n' '${'before'.tr} *${d['message']['expirationTime'].toString()}*\n\n' '_*${d['message']['inviteCode'].toString()}*_\n\n' '${"Install our app:".tr}\n' diff --git a/lib/controller/gamification/challenges_controller.dart b/lib/controller/gamification/challenges_controller.dart index edb0fe9..010ae33 100644 --- a/lib/controller/gamification/challenges_controller.dart +++ b/lib/controller/gamification/challenges_controller.dart @@ -218,22 +218,34 @@ class ChallengesController extends GetxController { } } - // Fetch weekly aggregate for weekly challenges - var weeklyRes = await CRUD().get( + // 2. Fetch weekly earnings from PAYMENT server + var weeklyEarningsRes = await CRUD().getWallet( + link: AppLink.getDriverWeekPaymentMove, + payload: {'driverID': box.read(BoxName.driverID).toString()}, + ); + + double weeklyEarnings = 0; + if (weeklyEarningsRes != null && weeklyEarningsRes != 'failure') { + var data = jsonDecode(weeklyEarningsRes); + if (data['message'] is List && data['message'].isNotEmpty) { + weeklyEarnings = double.tryParse(data['message'][0]['totalAmount']?.toString() ?? '0') ?? 0; + } + } + + // 3. Fetch weekly trips and hours from RIDES server (avoiding earnings join) + var weeklyAggregateRes = await CRUD().get( link: AppLink.getWeeklyAggregate, payload: {'driver_id': box.read(BoxName.driverID).toString()}, ); int weeklyTrips = 0; - double weeklyEarnings = 0; double weeklyHours = 0; - if (weeklyRes != null && weeklyRes != 'failure') { - var data = jsonDecode(weeklyRes); + if (weeklyAggregateRes != null && weeklyAggregateRes != 'failure') { + var data = jsonDecode(weeklyAggregateRes); if (data['message'] is List) { for (var day in data['message']) { weeklyTrips += int.tryParse(day['trips']?.toString() ?? '0') ?? 0; - weeklyEarnings += double.tryParse(day['earnings']?.toString() ?? '0') ?? 0; weeklyHours += double.tryParse(day['hours']?.toString() ?? '0') ?? 0; } } diff --git a/lib/controller/home/statistics/statistics_controller.dart b/lib/controller/home/statistics/statistics_controller.dart index 3e63f5d..6aeb2ce 100644 --- a/lib/controller/home/statistics/statistics_controller.dart +++ b/lib/controller/home/statistics/statistics_controller.dart @@ -32,8 +32,7 @@ class StatisticsController extends GetxController { @override void onInit() { super.onInit(); - fetchWeeklyData(); - fetchMonthlyData(); + reloadData(); } void changeTab(int tab) { @@ -89,12 +88,13 @@ class StatisticsController extends GetxController { monthlyEarnings = (data['message'] as List) .map((e) => MonthlyPriceDriverModel.fromJson(e)) .toList(); - monthlyTotalEarnings = monthlyEarnings.fold(0, (s, d) => s + d.pricePerDay); + monthlyTotalEarnings = + monthlyEarnings.fold(0, (s, d) => s + d.pricePerDay); // أفضل يوم if (monthlyEarnings.isNotEmpty) { - var best = monthlyEarnings.reduce((a, b) => - a.pricePerDay > b.pricePerDay ? a : b); + var best = monthlyEarnings + .reduce((a, b) => a.pricePerDay > b.pricePerDay ? a : b); bestDay = best.day.toString(); bestDayEarnings = best.pricePerDay; } @@ -127,7 +127,8 @@ class StatisticsController extends GetxController { monthlyDuration = (data['message'] as List) .map((e) => MonthlyDataModel.fromJson(e)) .toList(); - monthlyTotalHours = monthlyDuration.fold(0, (s, d) => s + d.totalDuration.toDouble()); + monthlyTotalHours = + monthlyDuration.fold(0, (s, d) => s + d.totalDuration.toDouble()); } } } catch (e) { @@ -157,9 +158,26 @@ class StatisticsController extends GetxController { return days[weekday - 1]; } - Future refresh() async { - await fetchWeeklyData(); - await fetchMonthlyData(); + bool _isFetching = false; + + Future reloadData() async { + if (_isFetching) return; + _isFetching = true; + isLoading = true; + update(); + + try { + debugPrint('📊 [Statistics] Reloading data...'); + await fetchWeeklyData(); + await fetchMonthlyData(); + debugPrint('📊 [Statistics] Data reload complete.'); + } catch (e) { + debugPrint('❌ [Statistics] Error reloading data: $e'); + } finally { + _isFetching = false; + isLoading = false; + update(); + } } } @@ -180,7 +198,8 @@ class DayStat { }); factory DayStat.fromJson(Map json) { - final date = DateTime.tryParse(json['day']?.toString() ?? '') ?? DateTime.now(); + final date = + DateTime.tryParse(json['day']?.toString() ?? '') ?? DateTime.now(); const dayNames = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']; return DayStat( date: date, diff --git a/lib/controller/local/translations.dart b/lib/controller/local/translations.dart index 5ee8184..3610fa5 100755 --- a/lib/controller/local/translations.dart +++ b/lib/controller/local/translations.dart @@ -201,7 +201,79 @@ class MyTranslation extends Translations { "Average of Hours of": "متوسط ساعات", "Awaiting response...": "عم نستنى الرد...", "Awfar Car": "سيارة أوفر", - "Back": "رجوع", + "Mon": "الاثنين", + "Tue": "الثلاثاء", + "Wed": "الأربعاء", + "Thu": "الخميس", + "Fri": "الجمعة", + "Sat": "السبت", + "Sun": "الأحد", + "The price must be over than": "السعر لازم يكون أكثر من", + "Driver Level": "مستوى السائق", + "Next Level:": "المستوى التالي:", + "Points": "نقطة", + "Maximum Level Reached!": "وصلت لأعلى مستوى!", + "Basic features": "ميزات أساسية", + "Standard support": "دعم قياسي", + "Priority medium": "أولوية متوسطة", + "Silver badge": "وسام فضي", + "-1% commission": "خصم 1% من العمولة", + "High priority": "أولوية عالية", + "Gold badge": "وسام ذهبي", + "-2% commission": "خصم 2% من العمولة", + "VIP first": "أولوية VIP", + "Diamond badge": "وسام ألماسي", + "-5% commission": "خصم 5% من العمولة", + "Priority support": "دعم فني ذو أولوية", + "Daily Goal": "الهدف اليومي", + "Edit": "تعديل", + "Set Goal": "تحديد هدف", + "Goal Achieved!": "تم تحقيق الهدف!", + "Remaining:": "المتبقي:", + "Set Daily Goal": "تحديد الهدف اليومي", + "How much do you want to earn today?": "كم تريد أن تربح اليوم؟", + "Save": "حفظ", + "Cancel": "إلغاء", + "Today Overview": "نظرة عامة على اليوم", + "Online Duration": "مدة التواجد", + "Refused": "المرفوضة", + "Score": "التقييم", + "Max Speed": "أعلى سرعة", + "Hard Brakes": "الفرامل المفاجئة", + "Driving Behavior": "سلوك القيادة", + "Excellent": "ممتاز", + "Good": "جيد", + "Needs Improvement": "يحتاج تحسين", + "Achievements": "الإنجازات", + "Day Streak": "سلسلة الأيام", + "Rating": "التقييم", + "Referrals": "الإحالات", + "First Trip": "أول رحلة", + "Complete your first trip": "أكمل أول رحلة لك", + "Road Warrior": "محارب الطريق", + "Complete 50 trips": "أكمل 50 رحلة", + "Century Rider": "سائق المئة", + "Complete 100 trips": "أكمل 100 رحلة", + "Road Legend": "أسطورة الطريق", + "Complete 500 trips": "أكمل 500 رحلة", + "Five Star Driver": "سائق 5 نجوم", + "Maintain 5.0 rating": "حافظ على تقييم 5.0", + "Weekly Streak": "سلسلة أسبوعية", + "Work 7 consecutive days": "اعمل 7 أيام متتالية", + "Monthly Streak": "سلسلة شهرية", + "Work 30 consecutive days": "اعمل 30 يوم متتالي", + "Social Butterfly": "الفراشة الاجتماعية", + "Refer 5 drivers": "ادعُ 5 سائقين", + "Weekly Earnings": "الأرباح الأسبوعية", + "Monthly Report": "التقرير الشهري", + "Best Day": "أفضل يوم", + "No data yet": "لا توجد بيانات بعد", + "h": "ساعة", + "Trip": "رحلة", + "Rides": "رحلات", + "Hours": "ساعات", + "Total Trips": "إجمالي الرحلات", + "Total Earnings": "إجمالي الأرباح", "Back to other sign-in options": "الرجوع لخيارات تسجيل الدخول التانية", "Bahrain": "البحرين", @@ -1511,7 +1583,24 @@ class MyTranslation extends Translations { "The payment was approved.": "تمت الموافقة على الدفع.", "The payment was not approved. Please try again.": "ما انقبل الدفع. تفضل جرّب مرة تانية.", - "The period of this code is 1 hour": "مدة هالكود ساعة وحدة", + "The period of this code is 24 hours": "صلاحية هذا الكود هي 24 ساعة", + "Trips": "الرحلات", + "Challenges": "التحديات", + "My Schedule": "جدولي", + "Leaderboard": "لوحة المتصدرين", + "Daily Challenges": "التحديات اليومية", + "Weekly Challenges": "التحديات الأسبوعية", + "Claim Reward": "استلام المكافأة", + "Claimed": "تم الاستلام", + "Earnings": "الأرباح", + "You": "أنت", + "Weekly Plan": "الخطة الأسبوعية", + "Work Days": "أيام العمل", + "Day Off": "يوم عطلة", + "Helping Center": "مركز المساعدة", + "Invite Driver": "دعوة سائق", + "Available for rides": "متاح للرحلات", + "History of Trip": "سجل الرحلات", "The price may increase if the route changes.": "السعر ممكن يزيد إذا تغيّر الطريق.", "The price must be over than": "السعر لازم يكون أكثر من", @@ -2477,7 +2566,8 @@ class MyTranslation extends Translations { "Go Now": "اذهب الآن", "Selected Location": "الموقع المحدد", "Add Balance": "إضافة رصيد", - "Select how you want to charge your account": "اختر كيف تريد شحن حسابك", + "Select how you want to charge your account": + "اختر كيف تريد شحن حسابك", "Recharge Balance Packages": "باقات شحن الرصيد", "Select Payment Method": "اختر طريقة الدفع", "Amount to charge:": "المبلغ المطلوب شحنه:", @@ -2495,7 +2585,8 @@ class MyTranslation extends Translations { "for": "بـ", "Points": "نقاط", "Pay from my budget": "الدفع من الرصيد المتاح", - "Use Touch ID or Face ID to confirm payment": "استخدم بصمة الإصبع أو الوجه لتأكيد الدفع", + "Use Touch ID or Face ID to confirm payment": + "استخدم بصمة الإصبع أو الوجه لتأكيد الدفع", "Your Budget less than needed": "رصيدك أقل من المطلوب", "Available Balance": "الرصيد المتاح", "Total Rides": "إجمالي الرحلات", @@ -2512,7 +2603,8 @@ class MyTranslation extends Translations { "Driver Balance": "رصيد السائق", "Pay from my budget": "الدفع من الرصيد المتاح", "You have in account": "لديك في الحساب", - "Select how you want to charge your account": "اختر كيف تريد شحن حسابك", + "Select how you want to charge your account": + "اختر كيف تريد شحن حسابك", "Add Balance": "إضافة رصيد", "SYP": "ل.س", "Your completed trips will appear here": "ستظهر رحلاتك المكتملة هنا", diff --git a/lib/controller/profile/setting_controller.dart b/lib/controller/profile/setting_controller.dart index e7a5f09..bd77e7b 100755 --- a/lib/controller/profile/setting_controller.dart +++ b/lib/controller/profile/setting_controller.dart @@ -25,7 +25,10 @@ class SettingController extends GetxController { isDarkMode = !isDarkMode; box.write('isDarkMode', isDarkMode); - // Update the theme using the LocaleController to ensure correct fonts are used + // Switch theme instantly across the app + Get.changeThemeMode(isDarkMode ? ThemeMode.dark : ThemeMode.light); + + // Update the theme using the LocaleController to ensure correct fonts/colors are refreshed if (Get.isRegistered()) { Get.find().refreshTheme(); } diff --git a/lib/translations_ar.json b/lib/translations_ar.json index 9101d74..f36d09d 100644 --- a/lib/translations_ar.json +++ b/lib/translations_ar.json @@ -56,10 +56,54 @@ "What are the order details we provide to you?": "", "Toggle Traffic": "", "General Authority For Supply Commodities": "", - "Error fetching rides. Please try again.": "", - "Please enter Your Email.": "", - "Health Insurance": "", - "Please enter your first name.": "", + "Please enter your first name.": "الرجاء إدخال اسمك الأول", + "Health Insurance": "التأمين الصحي", + "Invite Driver": "دعوة سائق", + "Leaderboard": "قائمة المتصدرين", + "Challenges": "التحديات", + "My Schedule": "جدولي", + "Statistics": "الإحصائيات", + "Balance": "الرصيد", + "History of Trip": "سجل الرحلات", + "Available for rides": "متاح للرحلات", + "Notifications": "التنبيهات", + "Helping Center": "مركز المساعدة", + "Is device compatible": "هل الجهاز متوافق؟", + "Privacy Policy": "سياسة الخصوصية", + "Daily Challenges": "تحديات يومية", + "Weekly Challenges": "تحديات أسبوعية", + "Invite Rider": "دعوة راكب", + "Referral Code": "كود الإحالة", + "Referral Center": "مركز الإحالة", + "Share": "مشاركة", + "WhatsApp": "واتساب", + "Share via": "مشاركة عبر", + "How It Works": "كيف يعمل", + "Share your code": "شارك كودك", + "Friend signs up": "تسجيل الصديق", + "Both earn rewards": "كلاكما يربح", + "Bonus at 10 trips": "مكافأة عند 10 رحلات", + "Send your referral code to friends": "أرسل كود الإحالة لأصدقائك", + "They register using your code": "يسجلون باستخدام كودك", + "You get 100 pts, they get 50 pts": "تحصل على 100 نقطة، وهم يحصلون على 50", + "Extra 200 pts when they complete 10 trips": "200 نقطة إضافية عند إكمالهم 10 رحلات", + "Driver Invitations": "دعوات السائقين", + "Passenger Invitations": "دعوات الركاب", + "Code copied!": "تم نسخ الكود!", + "Your Referral Code": "كود الإحالة الخاص بك", + "Share this code to earn rewards": "شارك هذا الكود لربح المكافآت", + "Profile": "الملف الشخصي", + "Settings": "الإعدادات", + "Contact Us": "اتصل بنا", + "Videos Tutorials": "الفيديوهات التعليمية", + "Rate Our App": "قيم تطبيقنا", + "About Us": "من نحن", + "Sign Out": "تسجيل الخروج", + "Claimed": "تم الاستلام", + "Claim Reward": "احصل على المكافأة", + "Active": "نشط", + "Rewards": "المكافآت", + "Total Invites": "إجمالي الدعوات", "Payment Method": "", "wallet_credited_message": "", "similar": "", diff --git a/lib/views/gamification/challenges_page.dart b/lib/views/gamification/challenges_page.dart index 64e1dfb..aa413b4 100644 --- a/lib/views/gamification/challenges_page.dart +++ b/lib/views/gamification/challenges_page.dart @@ -12,17 +12,18 @@ class ChallengesPage extends StatelessWidget { return Scaffold( backgroundColor: FinanceDesignSystem.backgroundColor, body: GetBuilder(builder: (cc) { - if (cc.isLoading) - return const Center( + if (cc.isLoading) { + return Center( child: CircularProgressIndicator( color: FinanceDesignSystem.primaryDark)); + } return CustomScrollView( physics: const BouncingScrollPhysics(), slivers: [ SliverAppBar( expandedHeight: 160, pinned: true, - backgroundColor: const Color(0xFF1A237E), + backgroundColor: Get.isDarkMode ? FinanceDesignSystem.primaryDark : const Color(0xFF1A237E), leading: IconButton( icon: const Icon(Icons.arrow_back_ios_new_rounded, color: Colors.white, size: 20), @@ -36,22 +37,22 @@ class ChallengesPage extends StatelessWidget { flexibleSpace: FlexibleSpaceBar( centerTitle: true, title: Text('Challenges'.tr, - style: const TextStyle( + style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 18)), background: Stack(fit: StackFit.expand, children: [ Container( - decoration: const BoxDecoration( - gradient: LinearGradient(colors: [ - Color(0xFF0A0E21), - Color(0xFF1A237E) - ]))), + decoration: BoxDecoration( + gradient: LinearGradient(colors: Get.isDarkMode + ? [FinanceDesignSystem.primaryDark, const Color(0xFF1E1E2E)] + : [const Color(0xFF0A0E21), const Color(0xFF1A237E)] + ))), Positioned( right: -30, top: -10, child: Icon(Icons.bolt_rounded, - size: 160, color: Colors.white.withOpacity(0.04))), + size: 160, color: Colors.white.withValues(alpha: 0.04))), ]), ), ), @@ -92,10 +93,10 @@ class ChallengesPage extends StatelessWidget { Container( padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4), decoration: BoxDecoration( - color: FinanceDesignSystem.accentBlue.withOpacity(0.1), + color: FinanceDesignSystem.accentBlue.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(20)), child: Text('$done/$total', - style: const TextStyle( + style: TextStyle( fontSize: 12, fontWeight: FontWeight.bold, color: FinanceDesignSystem.accentBlue)), @@ -112,11 +113,11 @@ class ChallengesPage extends StatelessWidget { color: Colors.white, borderRadius: BorderRadius.circular(FinanceDesignSystem.cardRadius), border: c.isCompleted - ? Border.all(color: c.color.withOpacity(0.3), width: 1.5) + ? Border.all(color: c.color.withValues(alpha: 0.3), width: 1.5) : null, boxShadow: [ BoxShadow( - color: Colors.black.withOpacity(0.03), + color: Colors.black.withValues(alpha: 0.03), blurRadius: 10, offset: const Offset(0, 4)) ], @@ -127,7 +128,7 @@ class ChallengesPage extends StatelessWidget { width: 44, height: 44, decoration: BoxDecoration( - color: c.color.withOpacity(0.12), + color: c.color.withValues(alpha: 0.12), borderRadius: BorderRadius.circular(12)), child: Icon(c.icon, color: c.color, size: 22), ), @@ -143,12 +144,12 @@ class ChallengesPage extends StatelessWidget { color: FinanceDesignSystem.primaryDark)), Text(isAr ? c.descriptionAr : c.descriptionEn, style: - TextStyle(fontSize: 11, color: Colors.grey.shade500)), + TextStyle(fontSize: 11, color: FinanceDesignSystem.textSecondary)), ])), Container( padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5), decoration: BoxDecoration( - color: const Color(0xFFFFD700).withOpacity(0.15), + color: const Color(0xFFFFD700).withValues(alpha: 0.15), borderRadius: BorderRadius.circular(12)), child: Text('+${c.reward}', style: const TextStyle( @@ -164,7 +165,7 @@ class ChallengesPage extends StatelessWidget { style: TextStyle( fontSize: 11, fontWeight: FontWeight.w600, - color: Colors.grey.shade600)), + color: FinanceDesignSystem.textSecondary)), Text('${(c.progress * 100).toStringAsFixed(0)}%', style: TextStyle( fontSize: 11, fontWeight: FontWeight.bold, color: c.color)), @@ -174,7 +175,7 @@ class ChallengesPage extends StatelessWidget { Container( height: 8, decoration: BoxDecoration( - color: Colors.grey.shade100, + color: FinanceDesignSystem.backgroundColor, borderRadius: BorderRadius.circular(4))), LayoutBuilder( builder: (ctx, cons) => AnimatedContainer( @@ -184,7 +185,7 @@ class ChallengesPage extends StatelessWidget { width: cons.maxWidth * c.progress, decoration: BoxDecoration( gradient: LinearGradient( - colors: [c.color, c.color.withOpacity(0.6)]), + colors: [c.color, c.color.withValues(alpha: 0.6)]), borderRadius: BorderRadius.circular(4), ), )), @@ -212,11 +213,11 @@ class ChallengesPage extends StatelessWidget { const SizedBox(height: 8), Center( child: Row(mainAxisSize: MainAxisSize.min, children: [ - const Icon(Icons.check_circle_rounded, + Icon(Icons.check_circle_rounded, color: FinanceDesignSystem.successGreen, size: 16), const SizedBox(width: 4), Text('Claimed'.tr, - style: const TextStyle( + style: TextStyle( fontSize: 12, fontWeight: FontWeight.bold, color: FinanceDesignSystem.successGreen)), diff --git a/lib/views/gamification/leaderboard_page.dart b/lib/views/gamification/leaderboard_page.dart index cc65dd3..e73941b 100644 --- a/lib/views/gamification/leaderboard_page.dart +++ b/lib/views/gamification/leaderboard_page.dart @@ -12,121 +12,251 @@ class LeaderboardPage extends StatelessWidget { return Scaffold( backgroundColor: FinanceDesignSystem.backgroundColor, body: GetBuilder(builder: (lc) { - if (lc.isLoading) return const Center(child: CircularProgressIndicator(color: FinanceDesignSystem.primaryDark)); - return CustomScrollView(physics: const BouncingScrollPhysics(), slivers: [ - SliverAppBar( - expandedHeight: 200, pinned: true, - backgroundColor: const Color(0xFF0A0E21), - leading: IconButton(icon: const Icon(Icons.arrow_back_ios_new_rounded, color: Colors.white, size: 20), onPressed: () => Get.back()), - flexibleSpace: FlexibleSpaceBar( - centerTitle: true, - title: Text('Leaderboard'.tr, style: const TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 18)), - background: Stack(fit: StackFit.expand, children: [ - Container(decoration: const BoxDecoration(gradient: LinearGradient(colors: [Color(0xFF0A0E21), Color(0xFFB71C1C)]))), - Positioned(right: -40, top: -20, child: Icon(Icons.leaderboard_rounded, size: 180, color: Colors.white.withOpacity(0.04))), - // Top 3 podium - if (lc.currentLeaderboard.length >= 3) Positioned(bottom: 50, left: 0, right: 0, child: _buildPodium(lc)), - ]), - ), - ), - // Tab bar - SliverToBoxAdapter(child: Container( - margin: const EdgeInsets.fromLTRB(16, 16, 16, 0), - padding: const EdgeInsets.all(4), - decoration: BoxDecoration(color: Colors.grey.shade100, borderRadius: BorderRadius.circular(14)), - child: Row(children: [ - _tab('Trips'.tr, Icons.local_taxi_rounded, 0, lc), - _tab('Earnings'.tr, Icons.monetization_on_rounded, 1, lc), - ]), - )), - // List - SliverPadding(padding: const EdgeInsets.fromLTRB(16, 16, 16, 40), sliver: SliverList( - delegate: SliverChildBuilderDelegate( - (ctx, i) { - if (i >= lc.currentLeaderboard.length) return null; - return _buildRow(lc.currentLeaderboard[i], lc.selectedTab == 1); - }, - childCount: lc.currentLeaderboard.length, - ), - )), - ]); + if (lc.isLoading) { + return Center( + child: CircularProgressIndicator( + color: FinanceDesignSystem.primaryDark)); + } + return CustomScrollView( + physics: const BouncingScrollPhysics(), + slivers: [ + SliverAppBar( + expandedHeight: 200, + pinned: true, + backgroundColor: Get.isDarkMode + ? FinanceDesignSystem.primaryDark + : const Color(0xFF0A0E21), + leading: IconButton( + icon: const Icon(Icons.arrow_back_ios_new_rounded, + color: Colors.white, size: 20), + onPressed: () => Get.back()), + flexibleSpace: FlexibleSpaceBar( + centerTitle: true, + title: Text('Leaderboard'.tr, + style: const TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 18)), + background: Stack(fit: StackFit.expand, children: [ + Container( + decoration: const BoxDecoration( + gradient: LinearGradient(colors: [ + Color(0xFF0A0E21), + Color(0xFFB71C1C) + ]))), + Positioned( + right: -40, + top: -20, + child: Icon(Icons.leaderboard_rounded, + size: 180, color: Colors.white.withValues(alpha: 0.04))), + // Top 3 podium + if (lc.currentLeaderboard.length >= 3) + Positioned( + bottom: 50, + left: 0, + right: 0, + child: _buildPodium(lc)), + ]), + ), + ), + // Tab bar + SliverToBoxAdapter( + child: Container( + margin: const EdgeInsets.fromLTRB(16, 16, 16, 0), + padding: const EdgeInsets.all(4), + decoration: BoxDecoration( + color: FinanceDesignSystem.backgroundColor.withValues(alpha: 0.5), + borderRadius: BorderRadius.circular(14)), + child: Row(children: [ + _tab('Trips'.tr, Icons.local_taxi_rounded, 0, lc), + _tab('Earnings'.tr, Icons.monetization_on_rounded, 1, lc), + ]), + )), + // List + SliverPadding( + padding: const EdgeInsets.fromLTRB(16, 16, 16, 40), + sliver: SliverList( + delegate: SliverChildBuilderDelegate( + (ctx, i) { + if (i >= lc.currentLeaderboard.length) return null; + return _buildRow( + lc.currentLeaderboard[i], lc.selectedTab == 1); + }, + childCount: lc.currentLeaderboard.length, + ), + )), + ]); }), ); } Widget _buildPodium(LeaderboardController lc) { final top3 = lc.currentLeaderboard.take(3).toList(); - return Row(mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.end, children: [ - if (top3.length > 1) _podiumItem(top3[1], 2, 50, const Color(0xFFC0C0C0)), - if (top3.isNotEmpty) _podiumItem(top3[0], 1, 70, const Color(0xFFFFD700)), - if (top3.length > 2) _podiumItem(top3[2], 3, 35, const Color(0xFFCD7F32)), - ]); + return Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + if (top3.length > 1) + _podiumItem(top3[1], 2, 50, const Color(0xFFC0C0C0)), + if (top3.isNotEmpty) + _podiumItem(top3[0], 1, 70, const Color(0xFFFFD700)), + if (top3.length > 2) + _podiumItem(top3[2], 3, 35, const Color(0xFFCD7F32)), + ]); } Widget _podiumItem(LeaderboardEntry e, int rank, double height, Color color) { - return Padding(padding: const EdgeInsets.symmetric(horizontal: 8), child: Column(mainAxisSize: MainAxisSize.min, children: [ - CircleAvatar(radius: rank == 1 ? 22 : 18, backgroundColor: color.withOpacity(0.3), - child: Text(_getRankEmoji(rank), style: TextStyle(fontSize: rank == 1 ? 22 : 16))), - const SizedBox(height: 4), - Text(e.name.length > 8 ? '${e.name.substring(0, 8)}...' : e.name, - style: TextStyle(color: Colors.white, fontSize: 10, fontWeight: e.isCurrentUser ? FontWeight.bold : FontWeight.normal)), - ])); + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 8), + child: Column(mainAxisSize: MainAxisSize.min, children: [ + CircleAvatar( + radius: rank == 1 ? 22 : 18, + backgroundColor: color.withValues(alpha: 0.3), + child: Text(_getRankEmoji(rank), + style: TextStyle(fontSize: rank == 1 ? 22 : 16))), + const SizedBox(height: 4), + Text(e.name.length > 8 ? '${e.name.substring(0, 8)}...' : e.name, + style: TextStyle( + color: Colors.white, + fontSize: 10, + fontWeight: + e.isCurrentUser ? FontWeight.bold : FontWeight.normal)), + ])); } Widget _tab(String label, IconData icon, int idx, LeaderboardController lc) { final selected = lc.selectedTab == idx; - return Expanded(child: GestureDetector( + return Expanded( + child: GestureDetector( onTap: () => lc.changeTab(idx), child: AnimatedContainer( duration: const Duration(milliseconds: 200), padding: const EdgeInsets.symmetric(vertical: 10), - decoration: BoxDecoration(color: selected ? Colors.white : Colors.transparent, borderRadius: BorderRadius.circular(10), - boxShadow: selected ? [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 5)] : null), + decoration: BoxDecoration( + color: + selected ? FinanceDesignSystem.cardColor : Colors.transparent, + borderRadius: BorderRadius.circular(10), + boxShadow: selected + ? [ + BoxShadow( + color: Colors.black.withValues(alpha: 0.05), blurRadius: 5) + ] + : null), child: Row(mainAxisAlignment: MainAxisAlignment.center, children: [ - Icon(icon, size: 16, color: selected ? FinanceDesignSystem.primaryDark : Colors.grey), + Icon(icon, + size: 16, + color: selected ? FinanceDesignSystem.primaryDark : Colors.grey), const SizedBox(width: 6), - Text(label, style: TextStyle(fontSize: 13, fontWeight: FontWeight.w600, color: selected ? FinanceDesignSystem.primaryDark : Colors.grey)), + Text(label, + style: TextStyle( + fontSize: 13, + fontWeight: FontWeight.w600, + color: selected + ? FinanceDesignSystem.primaryDark + : Colors.grey)), ]), ), )); } Widget _buildRow(LeaderboardEntry e, bool isEarnings) { - final rankColor = e.rank == 1 ? const Color(0xFFFFD700) : e.rank == 2 ? const Color(0xFFC0C0C0) : e.rank == 3 ? const Color(0xFFCD7F32) : Colors.grey.shade400; + final rankColor = e.rank == 1 + ? const Color(0xFFFFD700) + : e.rank == 2 + ? const Color(0xFFC0C0C0) + : e.rank == 3 + ? const Color(0xFFCD7F32) + : Colors.grey.shade400; return Container( margin: const EdgeInsets.only(bottom: 8), padding: const EdgeInsets.all(14), decoration: BoxDecoration( - color: e.isCurrentUser ? FinanceDesignSystem.accentBlue.withOpacity(0.08) : Colors.white, + color: e.isCurrentUser + ? FinanceDesignSystem.accentBlue.withValues(alpha: 0.08) + : FinanceDesignSystem.cardColor, borderRadius: BorderRadius.circular(14), - border: e.isCurrentUser ? Border.all(color: FinanceDesignSystem.accentBlue.withOpacity(0.3), width: 1.5) : null, - boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.02), blurRadius: 8, offset: const Offset(0, 3))], + border: e.isCurrentUser + ? Border.all( + color: FinanceDesignSystem.accentBlue.withValues(alpha: 0.3), + width: 1.5) + : null, + boxShadow: [ + BoxShadow( + color: Colors.black.withValues(alpha: 0.02), + blurRadius: 8, + offset: const Offset(0, 3)) + ], ), child: Row(children: [ // Rank - Container(width: 32, height: 32, decoration: BoxDecoration(color: rankColor.withOpacity(0.15), borderRadius: BorderRadius.circular(8)), - child: Center(child: e.rank <= 3 - ? Text(_getRankEmoji(e.rank), style: const TextStyle(fontSize: 16)) - : Text('${e.rank}', style: TextStyle(fontSize: 12, fontWeight: FontWeight.bold, color: rankColor)))), + Container( + width: 32, + height: 32, + decoration: BoxDecoration( + color: rankColor.withValues(alpha: 0.15), + borderRadius: BorderRadius.circular(8)), + child: Center( + child: e.rank <= 3 + ? Text(_getRankEmoji(e.rank), + style: const TextStyle(fontSize: 16)) + : Text('${e.rank}', + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.bold, + color: rankColor)))), const SizedBox(width: 12), // Avatar - CircleAvatar(radius: 18, backgroundColor: Colors.grey.shade200, child: Text(e.name.isNotEmpty ? e.name[0] : '?', style: TextStyle(fontWeight: FontWeight.bold, color: Colors.grey.shade600))), + CircleAvatar( + radius: 18, + backgroundColor: FinanceDesignSystem.backgroundColor, + child: Text(e.name.isNotEmpty ? e.name[0] : '?', + style: TextStyle( + fontWeight: FontWeight.bold, + color: FinanceDesignSystem.textSecondary))), const SizedBox(width: 12), // Name - Expanded(child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + Expanded( + child: + Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ Row(children: [ - Text(e.name, style: TextStyle(fontSize: 13, fontWeight: e.isCurrentUser ? FontWeight.bold : FontWeight.w500, color: FinanceDesignSystem.primaryDark)), - if (e.isCurrentUser) ...[const SizedBox(width: 6), - Container(padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), decoration: BoxDecoration(color: FinanceDesignSystem.accentBlue, borderRadius: BorderRadius.circular(6)), - child: Text('You'.tr, style: const TextStyle(fontSize: 8, fontWeight: FontWeight.bold, color: Colors.white)))], + Text(e.name, + style: TextStyle( + fontSize: 13, + fontWeight: + e.isCurrentUser ? FontWeight.bold : FontWeight.w500, + color: FinanceDesignSystem.primaryDark)), + if (e.isCurrentUser) ...[ + const SizedBox(width: 6), + Container( + padding: + const EdgeInsets.symmetric(horizontal: 6, vertical: 2), + decoration: BoxDecoration( + color: FinanceDesignSystem.accentBlue, + borderRadius: BorderRadius.circular(6)), + child: Text('You'.tr, + style: const TextStyle( + fontSize: 8, + fontWeight: FontWeight.bold, + color: Colors.white))) + ], ]), ])), // Value - Text(isEarnings ? '${e.value.toStringAsFixed(0)} ${'SYP'.tr}' : '${e.value.toInt()} ${'Rides'.tr}', - style: TextStyle(fontSize: 13, fontWeight: FontWeight.w800, color: FinanceDesignSystem.primaryDark)), + Text( + isEarnings + ? '${e.value.toStringAsFixed(0)} ${'SYP'.tr}' + : '${e.value.toInt()} ${'Rides'.tr}', + style: TextStyle( + fontSize: 13, + fontWeight: FontWeight.w800, + color: FinanceDesignSystem.primaryDark)), ]), ); } - String _getRankEmoji(int rank) => rank == 1 ? '🥇' : rank == 2 ? '🥈' : '🥉'; + String _getRankEmoji(int rank) => rank == 1 + ? '🥇' + : rank == 2 + ? '🥈' + : '🥉'; } diff --git a/lib/views/gamification/referral_center_page.dart b/lib/views/gamification/referral_center_page.dart index 5319373..8e263b0 100644 --- a/lib/views/gamification/referral_center_page.dart +++ b/lib/views/gamification/referral_center_page.dart @@ -16,7 +16,11 @@ class ReferralCenterPage extends StatelessWidget { return Scaffold( backgroundColor: FinanceDesignSystem.backgroundColor, body: GetBuilder(builder: (rc) { - if (rc.isLoading) return const Center(child: CircularProgressIndicator(color: FinanceDesignSystem.primaryDark)); + if (rc.isLoading) { + return Center( + child: CircularProgressIndicator( + color: FinanceDesignSystem.primaryDark)); + } return CustomScrollView(physics: const BouncingScrollPhysics(), slivers: [ // ═══ Header ═══ SliverAppBar( @@ -28,7 +32,7 @@ class ReferralCenterPage extends StatelessWidget { title: Text('Referral Center'.tr, style: const TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 18)), background: Stack(fit: StackFit.expand, children: [ Container(decoration: const BoxDecoration(gradient: LinearGradient(colors: [Color(0xFF0A0E21), Color(0xFF311B92)]))), - Positioned(right: -50, bottom: -30, child: Icon(Icons.share_rounded, size: 200, color: Colors.white.withOpacity(0.03))), + Positioned(right: -50, bottom: -30, child: Icon(Icons.share_rounded, size: 200, color: Colors.white.withValues(alpha: 0.03))), // Stats in header Positioned(bottom: 60, left: 24, right: 24, child: Row(children: [ _headerStat('${rc.totalReferrals}', 'Total Invites'.tr), @@ -72,7 +76,7 @@ class ReferralCenterPage extends StatelessWidget { Widget _headerStat(String value, String label) { return Expanded(child: Column(children: [ Text(value, style: const TextStyle(fontSize: 22, fontWeight: FontWeight.w900, color: Colors.white)), - Text(label, style: TextStyle(fontSize: 10, color: Colors.white.withOpacity(0.6))), + Text(label, style: TextStyle(fontSize: 10, color: Colors.white.withValues(alpha: 0.6))), ])); } @@ -82,14 +86,14 @@ class ReferralCenterPage extends StatelessWidget { decoration: BoxDecoration( gradient: const LinearGradient(colors: [Color(0xFF1A237E), Color(0xFF311B92)]), borderRadius: BorderRadius.circular(FinanceDesignSystem.cardRadius), - boxShadow: [BoxShadow(color: const Color(0xFF311B92).withOpacity(0.3), blurRadius: 15, offset: const Offset(0, 8))], + boxShadow: [BoxShadow(color: const Color(0xFF311B92).withValues(alpha: 0.3), blurRadius: 15, offset: const Offset(0, 8))], ), child: Column(children: [ - Text('Your Referral Code'.tr, style: TextStyle(color: Colors.white.withOpacity(0.7), fontSize: 14)), + Text('Your Referral Code'.tr, style: TextStyle(color: Colors.white.withValues(alpha: 0.7), fontSize: 14)), const SizedBox(height: 12), Container( padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), - decoration: BoxDecoration(color: Colors.white.withOpacity(0.15), borderRadius: BorderRadius.circular(12), border: Border.all(color: Colors.white.withOpacity(0.2))), + decoration: BoxDecoration(color: Colors.white.withValues(alpha: 0.15), borderRadius: BorderRadius.circular(12), border: Border.all(color: Colors.white.withValues(alpha: 0.2))), child: Row(mainAxisSize: MainAxisSize.min, children: [ Text(rc.referralCode, style: const TextStyle(fontSize: 24, fontWeight: FontWeight.w900, color: Colors.white, letterSpacing: 3)), const SizedBox(width: 12), @@ -97,14 +101,14 @@ class ReferralCenterPage extends StatelessWidget { onTap: () { rc.copyCode(); mySnackbarSuccess('Code copied!'.tr); }, child: Container( padding: const EdgeInsets.all(6), - decoration: BoxDecoration(color: Colors.white.withOpacity(0.2), borderRadius: BorderRadius.circular(8)), + decoration: BoxDecoration(color: Colors.white.withValues(alpha: 0.2), borderRadius: BorderRadius.circular(8)), child: const Icon(Icons.copy_rounded, color: Colors.white, size: 18), ), ), ]), ), const SizedBox(height: 12), - Text('Share this code to earn rewards'.tr, style: TextStyle(color: Colors.white.withOpacity(0.5), fontSize: 12)), + Text('Share this code to earn rewards'.tr, style: TextStyle(color: Colors.white.withValues(alpha: 0.5), fontSize: 12)), ]), ); } @@ -130,7 +134,7 @@ class ReferralCenterPage extends StatelessWidget { onTap: onTap, child: Container( padding: const EdgeInsets.symmetric(vertical: 14), - decoration: BoxDecoration(color: color.withOpacity(0.1), borderRadius: BorderRadius.circular(14)), + decoration: BoxDecoration(color: color.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(14)), child: Column(children: [ Icon(icon, color: color, size: 24), const SizedBox(height: 6), @@ -144,9 +148,9 @@ class ReferralCenterPage extends StatelessWidget { return Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(FinanceDesignSystem.cardRadius), - boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 10, offset: const Offset(0, 4))]), + boxShadow: [BoxShadow(color: Colors.black.withValues(alpha: 0.03), blurRadius: 10, offset: const Offset(0, 4))]), child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text('How It Works'.tr, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: FinanceDesignSystem.primaryDark)), + Text('How It Works'.tr, style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: FinanceDesignSystem.primaryDark)), const SizedBox(height: 16), _step('1', 'Share your code'.tr, 'Send your referral code to friends'.tr, const Color(0xFF2196F3)), _step('2', 'Friend signs up'.tr, 'They register using your code'.tr, const Color(0xFFFF9800)), @@ -158,12 +162,12 @@ class ReferralCenterPage extends StatelessWidget { Widget _step(String num, String title, String desc, Color color) { return Padding(padding: const EdgeInsets.only(bottom: 12), child: Row(children: [ - Container(width: 32, height: 32, decoration: BoxDecoration(color: color.withOpacity(0.15), borderRadius: BorderRadius.circular(8)), + Container(width: 32, height: 32, decoration: BoxDecoration(color: color.withValues(alpha: 0.15), borderRadius: BorderRadius.circular(8)), child: Center(child: Text(num, style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold, color: color))), ), const SizedBox(width: 12), Expanded(child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text(title, style: const TextStyle(fontSize: 13, fontWeight: FontWeight.w600, color: FinanceDesignSystem.primaryDark)), + Text(title, style: TextStyle(fontSize: 13, fontWeight: FontWeight.w600, color: FinanceDesignSystem.primaryDark)), Text(desc, style: TextStyle(fontSize: 11, color: Colors.grey.shade500)), ])), ])); @@ -174,9 +178,9 @@ class ReferralCenterPage extends StatelessWidget { margin: const EdgeInsets.only(bottom: 10), padding: const EdgeInsets.all(14), decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(14), - boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.02), blurRadius: 8, offset: const Offset(0, 3))]), + boxShadow: [BoxShadow(color: Colors.black.withValues(alpha: 0.02), blurRadius: 8, offset: const Offset(0, 3))]), child: Row(children: [ - Container(width: 40, height: 40, decoration: BoxDecoration(color: color.withOpacity(0.1), borderRadius: BorderRadius.circular(10)), + Container(width: 40, height: 40, decoration: BoxDecoration(color: color.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(10)), child: Icon(r.type == 'driver' ? Icons.local_taxi_rounded : Icons.person_rounded, color: color, size: 20)), const SizedBox(width: 12), Expanded(child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -186,8 +190,8 @@ class ReferralCenterPage extends StatelessWidget { Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( - color: r.status == 'active' ? FinanceDesignSystem.successGreen.withOpacity(0.1) - : r.status == 'registered' ? FinanceDesignSystem.accentBlue.withOpacity(0.1) : Colors.grey.shade100, + color: r.status == 'active' ? FinanceDesignSystem.successGreen.withValues(alpha: 0.1) + : r.status == 'registered' ? FinanceDesignSystem.accentBlue.withValues(alpha: 0.1) : Colors.grey.shade100, borderRadius: BorderRadius.circular(8)), child: Text(r.status.tr, style: TextStyle(fontSize: 10, fontWeight: FontWeight.w600, color: r.status == 'active' ? FinanceDesignSystem.successGreen diff --git a/lib/views/home/Captin/history/history_captain.dart b/lib/views/home/Captin/history/history_captain.dart index e8b3a8e..b09e354 100755 --- a/lib/views/home/Captin/history/history_captain.dart +++ b/lib/views/home/Captin/history/history_captain.dart @@ -18,7 +18,7 @@ class HistoryCaptain extends StatelessWidget { body: GetBuilder( builder: (controller) { if (controller.isloading) { - return const Center( + return Center( child: CircularProgressIndicator( color: FinanceDesignSystem.primaryDark), ); @@ -49,7 +49,7 @@ class HistoryCaptain extends StatelessWidget { fit: StackFit.expand, children: [ Container( - decoration: const BoxDecoration( + decoration: BoxDecoration( gradient: FinanceDesignSystem.balanceGradient, ), ), @@ -59,7 +59,7 @@ class HistoryCaptain extends StatelessWidget { child: Icon( Icons.history_rounded, size: 200, - color: Colors.white.withOpacity(0.05), + color: Colors.white.withValues(alpha: 0.05), ), ), Column( @@ -77,7 +77,7 @@ class HistoryCaptain extends StatelessWidget { Text( 'Total Rides'.tr, style: TextStyle( - color: Colors.white.withOpacity(0.7), + color: Colors.white.withValues(alpha: 0.7), fontSize: 14, fontWeight: FontWeight.w500, ), @@ -203,7 +203,7 @@ class _TripHistoryCard extends StatelessWidget { borderRadius: BorderRadius.circular(FinanceDesignSystem.cardRadius), boxShadow: [ BoxShadow( - color: Colors.black.withOpacity(0.04), + color: Colors.black.withValues(alpha: 0.04), blurRadius: 15, offset: const Offset(0, 8), ), @@ -227,10 +227,10 @@ class _TripHistoryCard extends StatelessWidget { padding: const EdgeInsets.all(10), decoration: BoxDecoration( color: FinanceDesignSystem.primaryDark - .withOpacity(0.05), + .withValues(alpha: 0.05), borderRadius: BorderRadius.circular(12), ), - child: const Icon( + child: Icon( Icons.receipt_long_rounded, color: FinanceDesignSystem.primaryDark, size: 20, @@ -242,7 +242,7 @@ class _TripHistoryCard extends StatelessWidget { children: [ Text( '${'OrderId'.tr} #${trip['order_id']}', - style: const TextStyle( + style: TextStyle( fontWeight: FontWeight.bold, fontSize: 15, color: FinanceDesignSystem.primaryDark, @@ -269,14 +269,14 @@ class _TripHistoryCard extends StatelessWidget { children: [ Column( children: [ - const Icon(Icons.circle, + Icon(Icons.circle, size: 12, color: FinanceDesignSystem.accentBlue), Container( width: 2, height: 20, color: Colors.grey.shade200, ), - const Icon(Icons.location_on_rounded, + Icon(Icons.location_on_rounded, size: 14, color: FinanceDesignSystem.dangerRed), ], ), @@ -315,7 +315,7 @@ class _TripHistoryCard extends StatelessWidget { children: [ Text( '${trip['price']} ${'SYP'.tr}', - style: const TextStyle( + style: TextStyle( fontWeight: FontWeight.w900, fontSize: 16, color: FinanceDesignSystem.primaryDark, @@ -381,10 +381,10 @@ class _TripHistoryCard extends StatelessWidget { end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(20), - border: Border.all(color: color.withOpacity(0.3), width: 1), + border: Border.all(color: color.withValues(alpha: 0.3), width: 1), boxShadow: [ BoxShadow( - color: color.withOpacity(0.1), + color: color.withValues(alpha: 0.1), blurRadius: 4, offset: const Offset(0, 2), ), diff --git a/lib/views/home/Captin/home_captain/drawer_captain.dart b/lib/views/home/Captin/home_captain/drawer_captain.dart index abe1ab2..4448cc7 100755 --- a/lib/views/home/Captin/home_captain/drawer_captain.dart +++ b/lib/views/home/Captin/home_captain/drawer_captain.dart @@ -106,10 +106,10 @@ class AppDrawer extends StatelessWidget { color: Colors.cyan, onTap: () => Get.to(() => HelpCaptain())), DrawerItem( - title: 'Referral Center'.tr, - icon: Icons.card_giftcard_rounded, + title: 'Invite Driver'.tr, + icon: Icons.person_add_rounded, color: Colors.indigo, - onTap: () => Get.to(() => ReferralCenterPage())), + onTap: () => Get.to(() => InviteScreen())), // DrawerItem( // title: 'Maintenance Center'.tr, // icon: Icons.build, @@ -227,7 +227,7 @@ class _DrawerItemTile extends StatelessWidget { leading: Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( - color: item.color.withOpacity(0.1), + color: item.color.withValues(alpha: 0.1), shape: BoxShape.circle, ), child: Icon(item.icon, color: item.color, size: 24), @@ -240,13 +240,13 @@ class _DrawerItemTile extends StatelessWidget { ?.copyWith(fontWeight: FontWeight.w500), ), onTap: () { - Get.back(); // لإغلاق القائمة عند الضغط + Navigator.pop(context); // لإغلاق القائمة عند الضغط بشكل آمن Future.delayed(const Duration(milliseconds: 250), () { item.onTap(); // الانتقال للصفحة بعد تأخير بسيط لإظهار الأنيميشن }); }, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), - splashColor: item.color.withOpacity(0.2), + splashColor: item.color.withValues(alpha: 0.2), ), ); } @@ -327,7 +327,7 @@ class UserHeader extends StatelessWidget { shape: BoxShape.circle, border: Border.all(color: Colors.white, width: 2), boxShadow: [ - BoxShadow(color: Colors.black.withOpacity(0.3), blurRadius: 5) + BoxShadow(color: Colors.black.withValues(alpha: 0.3), blurRadius: 5) ], ), child: controller.isloading @@ -377,19 +377,22 @@ class UserHeader extends StatelessWidget { ), ), otherAccountsPictures: [ - Row( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - homeCaptainController.rating.toString(), - style: const TextStyle( - color: Colors.white, - fontWeight: FontWeight.bold, - fontSize: 16), - ), - const SizedBox(width: 4), - const Icon(Icons.star, color: Colors.amber, size: 20), - ], + SizedBox( + width: 60, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text( + homeCaptainController.rating.toString(), + style: const TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 14), + ), + const SizedBox(width: 2), + const Icon(Icons.star, color: Colors.amber, size: 16), + ], + ), ), ], decoration: BoxDecoration( diff --git a/lib/views/home/Captin/home_captain/home_captin.dart b/lib/views/home/Captin/home_captain/home_captin.dart index d326fb8..a73dbe5 100755 --- a/lib/views/home/Captin/home_captain/home_captin.dart +++ b/lib/views/home/Captin/home_captain/home_captin.dart @@ -299,37 +299,38 @@ class _MapView extends StatelessWidget { return GetBuilder( builder: (ctrl) { if (ctrl.isLoading) return const MyCircularProgressIndicator(); - final s = Get.find(); - return 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, + 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, ), - 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, ), ); }, diff --git a/lib/views/home/journal/schedule_page.dart b/lib/views/home/journal/schedule_page.dart index d8f9969..c6a766e 100644 --- a/lib/views/home/journal/schedule_page.dart +++ b/lib/views/home/journal/schedule_page.dart @@ -12,9 +12,9 @@ class SchedulePage extends StatelessWidget { return Scaffold( backgroundColor: FinanceDesignSystem.backgroundColor, appBar: AppBar( - title: Text('My Schedule'.tr, style: const TextStyle(fontWeight: FontWeight.bold, color: FinanceDesignSystem.primaryDark)), + title: Text('My Schedule'.tr, style: TextStyle(fontWeight: FontWeight.bold, color: FinanceDesignSystem.primaryDark)), backgroundColor: Colors.transparent, elevation: 0, centerTitle: true, - leading: IconButton(icon: const Icon(Icons.arrow_back_ios_new_rounded, color: FinanceDesignSystem.primaryDark, size: 20), onPressed: () => Get.back()), + leading: IconButton(icon: Icon(Icons.arrow_back_ios_new_rounded, color: FinanceDesignSystem.primaryDark, size: 20), onPressed: () => Get.back()), ), body: GetBuilder(builder: (sc) { return SingleChildScrollView( @@ -29,14 +29,14 @@ class SchedulePage extends StatelessWidget { ), child: Row(children: [ Expanded(child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text('Weekly Plan'.tr, style: TextStyle(color: Colors.white.withOpacity(0.7), fontSize: 14)), + Text('Weekly Plan'.tr, style: TextStyle(color: Colors.white.withValues(alpha: 0.7), fontSize: 14)), const SizedBox(height: 8), Text('${sc.totalWeeklyHours.toStringAsFixed(1)}h', style: const TextStyle(fontSize: 32, fontWeight: FontWeight.w900, color: Colors.white)), - Text('${sc.activeDays} ${'Days'.tr}', style: TextStyle(color: Colors.white.withOpacity(0.6), fontSize: 13)), + Text('${sc.activeDays} ${'Days'.tr}', style: TextStyle(color: Colors.white.withValues(alpha: 0.6), fontSize: 13)), ])), Container( padding: const EdgeInsets.all(14), - decoration: BoxDecoration(color: Colors.white.withOpacity(0.15), borderRadius: BorderRadius.circular(14)), + decoration: BoxDecoration(color: Colors.white.withValues(alpha: 0.15), borderRadius: BorderRadius.circular(14)), child: const Icon(Icons.calendar_today_rounded, color: Colors.white, size: 28), ), ]), @@ -61,7 +61,7 @@ class SchedulePage extends StatelessWidget { decoration: BoxDecoration( color: slot.isActive ? Colors.white : Colors.grey.shade50, borderRadius: BorderRadius.circular(14), - boxShadow: slot.isActive ? [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 8, offset: const Offset(0, 3))] : null, + boxShadow: slot.isActive ? [BoxShadow(color: Colors.black.withValues(alpha: 0.03), blurRadius: 8, offset: const Offset(0, 3))] : null, ), child: Row(children: [ // Toggle @@ -71,7 +71,7 @@ class SchedulePage extends StatelessWidget { duration: const Duration(milliseconds: 200), width: 44, height: 44, decoration: BoxDecoration( - color: slot.isActive ? FinanceDesignSystem.accentBlue.withOpacity(0.1) : Colors.grey.shade200, + color: slot.isActive ? FinanceDesignSystem.accentBlue.withValues(alpha: 0.1) : Colors.grey.shade200, borderRadius: BorderRadius.circular(12), ), child: Center(child: Text( @@ -102,7 +102,7 @@ class SchedulePage extends StatelessWidget { Switch( value: slot.isActive, onChanged: (_) => sc.toggleDay(slot.dayOfWeek), - activeColor: FinanceDesignSystem.accentBlue, + activeThumbColor: FinanceDesignSystem.accentBlue, ), ]), ); diff --git a/lib/views/home/my_wallet/payment_history_driver_page.dart b/lib/views/home/my_wallet/payment_history_driver_page.dart index 632497a..a403d58 100755 --- a/lib/views/home/my_wallet/payment_history_driver_page.dart +++ b/lib/views/home/my_wallet/payment_history_driver_page.dart @@ -1,8 +1,6 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; -import 'package:sefer_driver/constant/colors.dart'; -import 'package:sefer_driver/constant/style.dart'; import 'package:sefer_driver/constant/finance_design_system.dart'; import 'package:sefer_driver/views/widgets/mycircular.dart'; import '../../../controller/payment/driver_payment_controller.dart'; @@ -19,12 +17,12 @@ class PaymentHistoryDriverPage extends StatelessWidget { backgroundColor: FinanceDesignSystem.backgroundColor, appBar: AppBar( title: Text('Payment History'.tr, - style: const TextStyle(fontWeight: FontWeight.bold, color: FinanceDesignSystem.primaryDark)), + style: TextStyle(fontWeight: FontWeight.bold, color: FinanceDesignSystem.primaryDark)), backgroundColor: Colors.transparent, elevation: 0, centerTitle: true, leading: IconButton( - icon: const Icon(Icons.arrow_back_ios_new_rounded, color: FinanceDesignSystem.primaryDark, size: 20), + icon: Icon(Icons.arrow_back_ios_new_rounded, color: FinanceDesignSystem.primaryDark, size: 20), onPressed: () => Get.back(), ), ), diff --git a/lib/views/home/my_wallet/points_captain.dart b/lib/views/home/my_wallet/points_captain.dart index f8ec2c1..2e481df 100755 --- a/lib/views/home/my_wallet/points_captain.dart +++ b/lib/views/home/my_wallet/points_captain.dart @@ -3,8 +3,6 @@ import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:local_auth/local_auth.dart'; -import 'package:sefer_driver/constant/colors.dart'; -import 'package:sefer_driver/constant/style.dart'; import 'package:sefer_driver/controller/home/payment/captain_wallet_controller.dart'; import 'package:sefer_driver/controller/payment/payment_controller.dart'; import 'package:sefer_driver/controller/payment/smsPaymnet/payment_services.dart'; @@ -45,7 +43,7 @@ class PointsCaptain extends StatelessWidget { color: Colors.white, borderRadius: BorderRadius.circular(20), elevation: 4, - shadowColor: kolor.withOpacity(0.3), + shadowColor: kolor.withValues(alpha: 0.3), child: InkWell( onTap: () => _showPaymentOptions(context), borderRadius: BorderRadius.circular(20), @@ -58,11 +56,12 @@ class PointsCaptain extends StatelessWidget { begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ - kolor.withOpacity(0.05), + kolor.withValues(alpha: 0.05), Colors.white, ], ), - border: Border.all(color: kolor.withOpacity(0.2), width: 1.5), + border: + Border.all(color: kolor.withValues(alpha: 0.2), width: 1.5), ), child: Column( mainAxisAlignment: MainAxisAlignment.center, @@ -70,7 +69,7 @@ class PointsCaptain extends StatelessWidget { Container( padding: const EdgeInsets.all(10), decoration: BoxDecoration( - color: kolor.withOpacity(0.1), + color: kolor.withValues(alpha: 0.1), shape: BoxShape.circle, ), child: Icon(Icons.account_balance_wallet_rounded, @@ -79,7 +78,7 @@ class PointsCaptain extends StatelessWidget { const SizedBox(height: 10), Text( '$countPoint ${'SYP'.tr}', - style: const TextStyle( + style: TextStyle( fontWeight: FontWeight.w900, fontSize: 15, color: FinanceDesignSystem.primaryDark, @@ -110,9 +109,9 @@ class PointsCaptain extends StatelessWidget { maxHeight: MediaQuery.of(context).size.height * 0.8, ), padding: const EdgeInsets.fromLTRB(24, 24, 24, 32), - decoration: const BoxDecoration( + decoration: BoxDecoration( color: Colors.white, - borderRadius: BorderRadius.vertical(top: Radius.circular(32)), + borderRadius: const BorderRadius.vertical(top: Radius.circular(32)), ), child: SingleChildScrollView( child: Column( @@ -131,8 +130,7 @@ class PointsCaptain extends StatelessWidget { ], ), const SizedBox(height: 8), - Text( - "${'Amount to charge:'.tr} $countPoint ${'SYP'.tr}", + Text("${'Amount to charge:'.tr} $countPoint ${'SYP'.tr}", style: FinanceDesignSystem.subHeadingStyle), const SizedBox(height: 24), _buildPaymentMethodTile( @@ -211,7 +209,7 @@ class PointsCaptain extends StatelessWidget { borderRadius: BorderRadius.circular(14), boxShadow: [ BoxShadow( - color: color.withOpacity(0.1), + color: color.withValues(alpha: 0.1), blurRadius: 10, offset: const Offset(0, 4), ), @@ -227,7 +225,7 @@ class PointsCaptain extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(title, - style: const TextStyle( + style: TextStyle( fontWeight: FontWeight.bold, fontSize: 16, color: FinanceDesignSystem.primaryDark)), @@ -285,8 +283,7 @@ class PaymentScreen extends StatefulWidget { final String countPrice; const PaymentScreen( - {required this.iframeUrl, Key? key, required this.countPrice}) - : super(key: key); + {required this.iframeUrl, super.key, required this.countPrice}); @override State createState() => _PaymentScreenState(); @@ -439,8 +436,7 @@ class PaymentScreenWallet extends StatefulWidget { final String countPrice; const PaymentScreenWallet( - {required this.iframeUrl, Key? key, required this.countPrice}) - : super(key: key); + {required this.iframeUrl, super.key, required this.countPrice}); @override State createState() => _PaymentScreenWalletState(); @@ -472,7 +468,7 @@ class _PaymentScreenWalletState extends State { } Future _fetchPaymentStatus() async { - final String userId = '+963' + box.read(BoxName.phoneWallet); + final String userId = '+963${box.read(BoxName.phoneWallet)}'; await Future.delayed(const Duration(seconds: 2)); try { diff --git a/lib/views/home/my_wallet/walet_captain.dart b/lib/views/home/my_wallet/walet_captain.dart index 25ffb6f..d063cd1 100755 --- a/lib/views/home/my_wallet/walet_captain.dart +++ b/lib/views/home/my_wallet/walet_captain.dart @@ -36,20 +36,20 @@ class WalletCaptainRefactored extends StatelessWidget { backgroundColor: FinanceDesignSystem.backgroundColor, appBar: AppBar( title: Text('Driver Balance'.tr, - style: const TextStyle( + style: TextStyle( fontWeight: FontWeight.bold, color: FinanceDesignSystem.primaryDark)), backgroundColor: Colors.transparent, elevation: 0, centerTitle: true, leading: IconButton( - icon: const Icon(Icons.arrow_back_ios_new_rounded, + icon: Icon(Icons.arrow_back_ios_new_rounded, color: FinanceDesignSystem.primaryDark, size: 20), onPressed: () => Get.back(), ), actions: [ IconButton( - icon: const Icon(Icons.refresh_rounded, + icon: Icon(Icons.refresh_rounded, color: FinanceDesignSystem.primaryDark), onPressed: () => controller.refreshCaptainWallet(), tooltip: 'Refresh'.tr, @@ -204,7 +204,7 @@ class WalletCaptainRefactored extends StatelessWidget { Get.to(() => const PaymentHistoryDriverPage()); }, child: Text('View All'.tr, - style: const TextStyle( + style: TextStyle( color: FinanceDesignSystem.accentBlue, fontWeight: FontWeight.bold)), ), @@ -255,9 +255,9 @@ class WalletCaptainRefactored extends StatelessWidget { Get.bottomSheet( Container( padding: const EdgeInsets.all(24), - decoration: const BoxDecoration( + decoration: BoxDecoration( color: Colors.white, - borderRadius: BorderRadius.vertical(top: Radius.circular(24)), + borderRadius: const BorderRadius.vertical(top: Radius.circular(24)), ), child: Column( mainAxisSize: MainAxisSize.min, @@ -272,9 +272,10 @@ class WalletCaptainRefactored extends StatelessWidget { leading: Container( padding: const EdgeInsets.all(10), decoration: BoxDecoration( - color: FinanceDesignSystem.accentBlue.withOpacity(0.1), + color: + FinanceDesignSystem.accentBlue.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(12)), - child: const Icon(Icons.account_balance_wallet_rounded, + child: Icon(Icons.account_balance_wallet_rounded, color: FinanceDesignSystem.accentBlue), ), title: Text("Pay from my budget".tr), diff --git a/lib/views/home/my_wallet/weekly_payment_page.dart b/lib/views/home/my_wallet/weekly_payment_page.dart index 822ec51..fc6213a 100755 --- a/lib/views/home/my_wallet/weekly_payment_page.dart +++ b/lib/views/home/my_wallet/weekly_payment_page.dart @@ -1,9 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:get/get.dart'; -import 'package:intl/intl.dart'; import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; -import 'package:sefer_driver/constant/colors.dart'; -import 'package:sefer_driver/constant/style.dart'; +import 'package:get/get.dart'; import 'package:sefer_driver/constant/finance_design_system.dart'; import 'package:sefer_driver/views/widgets/mycircular.dart'; import '../../../controller/payment/driver_payment_controller.dart'; @@ -20,12 +17,15 @@ class WeeklyPaymentPage extends StatelessWidget { backgroundColor: FinanceDesignSystem.backgroundColor, appBar: AppBar( title: Text('Weekly Summary'.tr, - style: const TextStyle(fontWeight: FontWeight.bold, color: FinanceDesignSystem.primaryDark)), + style: TextStyle( + fontWeight: FontWeight.bold, + color: FinanceDesignSystem.primaryDark)), backgroundColor: Colors.transparent, elevation: 0, centerTitle: true, leading: IconButton( - icon: const Icon(Icons.arrow_back_ios_new_rounded, color: FinanceDesignSystem.primaryDark, size: 20), + icon: Icon(Icons.arrow_back_ios_new_rounded, + color: FinanceDesignSystem.primaryDark, size: 20), onPressed: () => Get.back(), ), ), @@ -45,9 +45,11 @@ class WeeklyPaymentPage extends StatelessWidget { padding: const EdgeInsets.symmetric(horizontal: 20), child: Row( children: [ - Text('Transactions this week'.tr, style: FinanceDesignSystem.headingStyle), + Text('Transactions this week'.tr, + style: FinanceDesignSystem.headingStyle), const Spacer(), - Icon(Icons.list_rounded, color: Colors.grey.shade400, size: 20), + Icon(Icons.list_rounded, + color: Colors.grey.shade400, size: 20), ], ), ), @@ -61,7 +63,9 @@ class WeeklyPaymentPage extends StatelessWidget { itemCount: controller.weeklyList.length, itemBuilder: (BuildContext context, int index) { final tx = controller.weeklyList[index]; - final double amount = double.tryParse(tx['amount']?.toString() ?? '0') ?? 0; + final double amount = double.tryParse( + tx['amount']?.toString() ?? '0') ?? + 0; return AnimationConfiguration.staggeredList( position: index, duration: const Duration(milliseconds: 250), @@ -69,10 +73,12 @@ class WeeklyPaymentPage extends StatelessWidget { verticalOffset: 25, child: FadeInAnimation( child: TransactionPreviewItem( - title: amount >= 0 ? 'Credit'.tr : 'Debit'.tr, + title: + amount >= 0 ? 'Credit'.tr : 'Debit'.tr, subtitle: tx['dateUpdated'] ?? '', amount: amount.abs().toStringAsFixed(0), - date: tx['dateUpdated']?.split(' ')[0] ?? '', + date: + tx['dateUpdated']?.split(' ')[0] ?? '', type: amount >= 0 ? 'credit' : 'debit', method: tx['paymentMethod'], onTap: () {}, @@ -95,7 +101,7 @@ class WeeklyPaymentPage extends StatelessWidget { final totalAmount = controller.weeklyList.isEmpty ? '0.00' : controller.weeklyList[0]['totalAmount']?.toString() ?? '0.00'; - + final double earnings = double.tryParse(totalAmount) ?? 0; final int trips = controller.weeklyList.length; final double commission = earnings * 0.15; // Example 15% @@ -109,7 +115,7 @@ class WeeklyPaymentPage extends StatelessWidget { borderRadius: BorderRadius.circular(24), boxShadow: [ BoxShadow( - color: FinanceDesignSystem.primaryDark.withOpacity(0.3), + color: FinanceDesignSystem.primaryDark.withValues(alpha: 0.3), blurRadius: 20, offset: const Offset(0, 8), ), @@ -118,17 +124,24 @@ class WeeklyPaymentPage extends StatelessWidget { child: Column( children: [ Text('Total Weekly Earnings'.tr, - style: TextStyle(color: Colors.white.withOpacity(0.8), fontSize: 14)), + style: TextStyle( + color: Colors.white.withValues(alpha: 0.8), fontSize: 14)), const SizedBox(height: 8), Text('${earnings.toStringAsFixed(0)} SYP', - style: const TextStyle(color: Colors.white, fontSize: 36, fontWeight: FontWeight.bold)), + style: const TextStyle( + color: Colors.white, + fontSize: 36, + fontWeight: FontWeight.bold)), const SizedBox(height: 24), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - _buildStatItem('Total Trips'.tr, trips.toString(), Icons.directions_car_rounded), - _buildStatItem('Commission'.tr, '${commission.toStringAsFixed(0)}', Icons.percent_rounded), - _buildStatItem('Net Profit'.tr, '${netProfit.toStringAsFixed(0)}', Icons.account_balance_rounded), + _buildStatItem('Total Trips'.tr, trips.toString(), + Icons.directions_car_rounded), + _buildStatItem('Commission'.tr, commission.toStringAsFixed(0), + Icons.percent_rounded), + _buildStatItem('Net Profit'.tr, netProfit.toStringAsFixed(0), + Icons.account_balance_rounded), ], ), ], @@ -141,12 +154,20 @@ class WeeklyPaymentPage extends StatelessWidget { children: [ Container( padding: const EdgeInsets.all(8), - decoration: BoxDecoration(color: Colors.white.withOpacity(0.1), borderRadius: BorderRadius.circular(10)), + decoration: BoxDecoration( + color: Colors.white.withValues(alpha: 0.1), + borderRadius: BorderRadius.circular(10)), child: Icon(icon, color: Colors.white, size: 18), ), const SizedBox(height: 8), - Text(value, style: const TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 14)), - Text(label, style: TextStyle(color: Colors.white.withOpacity(0.6), fontSize: 10)), + Text(value, + style: const TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 14)), + Text(label, + style: TextStyle( + color: Colors.white.withValues(alpha: 0.6), fontSize: 10)), ], ); } @@ -159,18 +180,27 @@ class WeeklyPaymentPage extends StatelessWidget { decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), - boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.02), blurRadius: 10)], + boxShadow: [ + BoxShadow( + color: Colors.black.withValues(alpha: 0.02), blurRadius: 10) + ], ), child: Row( children: [ - IconButton(icon: const Icon(Icons.chevron_left_rounded), onPressed: () {}), + IconButton( + icon: const Icon(Icons.chevron_left_rounded), onPressed: () {}), Expanded( child: Center( child: Text('Dec 15 - Dec 21, 2024'.tr, - style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 14, color: FinanceDesignSystem.primaryDark)), + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 14, + color: FinanceDesignSystem.primaryDark)), ), ), - IconButton(icon: const Icon(Icons.chevron_right_rounded), onPressed: () {}), + IconButton( + icon: const Icon(Icons.chevron_right_rounded), + onPressed: () {}), ], ), ), @@ -184,7 +214,9 @@ class WeeklyPaymentPage extends StatelessWidget { children: [ Icon(Icons.bar_chart_rounded, size: 64, color: Colors.grey.shade300), const SizedBox(height: 16), - Text('No transactions this week'.tr, style: const TextStyle(fontWeight: FontWeight.bold, color: Colors.grey)), + Text('No transactions this week'.tr, + style: const TextStyle( + fontWeight: FontWeight.bold, color: Colors.grey)), ], ), ); diff --git a/lib/views/home/my_wallet/widgets/financial_summary_card.dart b/lib/views/home/my_wallet/widgets/financial_summary_card.dart index a6b2cd5..d371868 100644 --- a/lib/views/home/my_wallet/widgets/financial_summary_card.dart +++ b/lib/views/home/my_wallet/widgets/financial_summary_card.dart @@ -40,7 +40,7 @@ class FinancialSummaryCard extends StatelessWidget { borderRadius: BorderRadius.circular(FinanceDesignSystem.cardRadius), boxShadow: [ BoxShadow( - color: Colors.black.withOpacity(0.03), + color: Colors.black.withValues(alpha: 0.03), blurRadius: 10, offset: const Offset(0, 4), ), @@ -51,7 +51,7 @@ class FinancialSummaryCard extends StatelessWidget { physics: const NeverScrollableScrollPhysics(), itemCount: items.length, separatorBuilder: (context, index) => - Divider(color: Colors.grey.withOpacity(0.1), height: 24), + Divider(color: Colors.grey.withValues(alpha: 0.1), height: 24), itemBuilder: (context, index) { final item = items[index]; return Row( @@ -59,7 +59,7 @@ class FinancialSummaryCard extends StatelessWidget { Container( padding: const EdgeInsets.all(10), decoration: BoxDecoration( - color: item.color.withOpacity(0.1), + color: item.color.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(10), ), child: Icon(item.icon, color: item.color, size: 20), @@ -71,7 +71,7 @@ class FinancialSummaryCard extends StatelessWidget { children: [ Text( item.label, - style: const TextStyle( + style: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, color: FinanceDesignSystem.primaryDark, @@ -93,7 +93,7 @@ class FinancialSummaryCard extends StatelessWidget { children: [ Text( "${item.amount} ${'SYP'.tr}", - style: const TextStyle( + style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: FinanceDesignSystem.primaryDark, diff --git a/lib/views/home/my_wallet/widgets/promo_gamification_card.dart b/lib/views/home/my_wallet/widgets/promo_gamification_card.dart index 76e48e4..3223ce7 100644 --- a/lib/views/home/my_wallet/widgets/promo_gamification_card.dart +++ b/lib/views/home/my_wallet/widgets/promo_gamification_card.dart @@ -50,7 +50,7 @@ class PromoGamificationCard extends StatelessWidget { children: [ Text( title, - style: const TextStyle( + style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: FinanceDesignSystem.primaryDark, diff --git a/lib/views/home/my_wallet/widgets/quick_actions.dart b/lib/views/home/my_wallet/widgets/quick_actions.dart index d0ef713..8986fb6 100644 --- a/lib/views/home/my_wallet/widgets/quick_actions.dart +++ b/lib/views/home/my_wallet/widgets/quick_actions.dart @@ -96,7 +96,7 @@ class _ActionItem extends StatelessWidget { const SizedBox(height: 8), Text( label, - style: const TextStyle( + style: TextStyle( fontSize: 13, fontWeight: FontWeight.bold, color: FinanceDesignSystem.primaryDark, diff --git a/lib/views/home/my_wallet/widgets/transaction_preview_item.dart b/lib/views/home/my_wallet/widgets/transaction_preview_item.dart index 55aa6a5..6ccab13 100644 --- a/lib/views/home/my_wallet/widgets/transaction_preview_item.dart +++ b/lib/views/home/my_wallet/widgets/transaction_preview_item.dart @@ -59,7 +59,7 @@ class TransactionPreviewItem extends StatelessWidget { children: [ Text( title, - style: const TextStyle( + style: TextStyle( fontSize: 15, fontWeight: FontWeight.bold, color: FinanceDesignSystem.primaryDark, diff --git a/lib/views/home/profile/behavior_page.dart b/lib/views/home/profile/behavior_page.dart index 8d93dad..fbc7a8d 100644 --- a/lib/views/home/profile/behavior_page.dart +++ b/lib/views/home/profile/behavior_page.dart @@ -15,27 +15,36 @@ class BehaviorPage extends StatelessWidget { return Scaffold( backgroundColor: FinanceDesignSystem.backgroundColor, appBar: AppBar( - title: Text('Driver Behavior'.tr, style: const TextStyle(fontWeight: FontWeight.bold, color: FinanceDesignSystem.primaryDark)), + title: Text('Driver Behavior'.tr, + style: TextStyle( + fontWeight: FontWeight.bold, + color: FinanceDesignSystem.primaryDark)), centerTitle: true, backgroundColor: FinanceDesignSystem.cardColor, elevation: 0, - iconTheme: const IconThemeData(color: FinanceDesignSystem.primaryDark), + iconTheme: IconThemeData(color: FinanceDesignSystem.primaryDark), ), body: Obx(() { if (controller.isLoading.value) { - return const Center(child: CircularProgressIndicator(color: FinanceDesignSystem.accentBlue)); + return Center( + child: CircularProgressIndicator( + color: FinanceDesignSystem.accentBlue)); } double score = controller.overallScore.value; bool isExcellent = score >= 90; bool isGood = score >= 75 && score < 90; - Color statusColor = isExcellent ? Colors.green : (isGood ? Colors.orange : Colors.red); - String statusText = isExcellent ? 'Excellent'.tr : (isGood ? 'Good'.tr : 'Needs Improvement'.tr); + Color statusColor = + isExcellent ? Colors.green : (isGood ? Colors.orange : Colors.red); + String statusText = isExcellent + ? 'Excellent'.tr + : (isGood ? 'Good'.tr : 'Needs Improvement'.tr); return CustomScrollView( slivers: [ SliverPadding( - padding: const EdgeInsets.all(FinanceDesignSystem.horizontalPadding), + padding: + const EdgeInsets.all(FinanceDesignSystem.horizontalPadding), sliver: SliverList( delegate: SliverChildListDelegate([ // Overall Score Card @@ -44,11 +53,17 @@ class BehaviorPage extends StatelessWidget { decoration: BoxDecoration( color: FinanceDesignSystem.cardColor, borderRadius: BorderRadius.circular(24), - boxShadow: const [BoxShadow(color: Colors.black12, blurRadius: 10, offset: Offset(0, 4))], + boxShadow: const [ + BoxShadow( + color: Colors.black12, + blurRadius: 10, + offset: Offset(0, 4)) + ], ), child: Column( children: [ - Icon(Icons.shield_rounded, size: 48, color: statusColor), + Icon(Icons.shield_rounded, + size: 48, color: statusColor), const SizedBox(height: 16), Text( "Overall Behavior Score".tr, @@ -65,33 +80,41 @@ class BehaviorPage extends StatelessWidget { ), const SizedBox(height: 8), Container( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 6), + padding: const EdgeInsets.symmetric( + horizontal: 16, vertical: 6), decoration: BoxDecoration( color: statusColor.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(20), ), child: Text( statusText, - style: TextStyle(color: statusColor, fontWeight: FontWeight.bold), + style: TextStyle( + color: statusColor, + fontWeight: FontWeight.bold), ), ), ], ), ), const SizedBox(height: 30), - Text("Last 10 Trips".tr, style: FinanceDesignSystem.headingStyle), + Text("Last 10 Trips".tr, + style: FinanceDesignSystem.headingStyle), const SizedBox(height: 16), ]), ), ), SliverPadding( - padding: const EdgeInsets.symmetric(horizontal: FinanceDesignSystem.horizontalPadding), + padding: const EdgeInsets.symmetric( + horizontal: FinanceDesignSystem.horizontalPadding), sliver: SliverList( delegate: SliverChildBuilderDelegate( (context, index) { var trip = controller.lastTrips[index]; - double tripScore = double.tryParse(trip['behavior_score'].toString()) ?? 0; - Color tColor = tripScore >= 90 ? Colors.green : (tripScore >= 75 ? Colors.orange : Colors.red); + double tripScore = + double.tryParse(trip['behavior_score'].toString()) ?? 0; + Color tColor = tripScore >= 90 + ? Colors.green + : (tripScore >= 75 ? Colors.orange : Colors.red); return Container( margin: const EdgeInsets.only(bottom: 12), @@ -118,7 +141,8 @@ class BehaviorPage extends StatelessWidget { ), title: Text( "Trip ID: ${trip['trip_id']}", - style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16), + style: const TextStyle( + fontWeight: FontWeight.bold, fontSize: 16), ), subtitle: Padding( padding: const EdgeInsets.only(top: 8.0), @@ -126,9 +150,16 @@ class BehaviorPage extends StatelessWidget { spacing: 12, runSpacing: 8, children: [ - _buildBadge(Icons.speed, "${trip['max_speed']} km/h", Colors.blue), - _buildBadge(Icons.warning_amber_rounded, "${trip['hard_brakes']} ${'Hard Brakes'.tr}", Colors.orange), - _buildBadge(Icons.map_rounded, "${trip['total_distance']} km", Colors.purple), + _buildBadge(Icons.speed, + "${trip['max_speed']} km/h", Colors.blue), + _buildBadge( + Icons.warning_amber_rounded, + "${trip['hard_brakes']} ${'Hard Brakes'.tr}", + Colors.orange), + _buildBadge( + Icons.map_rounded, + "${trip['total_distance']} km", + Colors.purple), ], ), ), @@ -137,9 +168,14 @@ class BehaviorPage extends StatelessWidget { children: [ Text( "${tripScore.toStringAsFixed(0)}", - style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20, color: tColor), + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 20, + color: tColor), ), - Text('Score'.tr, style: const TextStyle(fontSize: 10, color: Colors.grey)), + Text('Score'.tr, + style: const TextStyle( + fontSize: 10, color: Colors.grey)), ], ), ), @@ -168,7 +204,9 @@ class BehaviorPage extends StatelessWidget { children: [ Icon(icon, size: 14, color: color), const SizedBox(width: 4), - Text(label, style: TextStyle(fontSize: 12, color: color, fontWeight: FontWeight.w600)), + Text(label, + style: TextStyle( + fontSize: 12, color: color, fontWeight: FontWeight.w600)), ], ), ); diff --git a/lib/views/home/statistics/statistics_dashboard.dart b/lib/views/home/statistics/statistics_dashboard.dart index 608042f..fd459e2 100644 --- a/lib/views/home/statistics/statistics_dashboard.dart +++ b/lib/views/home/statistics/statistics_dashboard.dart @@ -16,8 +16,7 @@ class StatisticsDashboard extends StatelessWidget { final GamificationController gamController = Get.put(GamificationController()); - final StatisticsController statsController = - Get.put(StatisticsController()); + final StatisticsController statsController = Get.put(StatisticsController()); @override Widget build(BuildContext context) { @@ -25,154 +24,160 @@ class StatisticsDashboard extends StatelessWidget { backgroundColor: FinanceDesignSystem.backgroundColor, body: GetBuilder( builder: (gc) { - if (gc.isLoading) { - return const Center( - child: CircularProgressIndicator( - color: FinanceDesignSystem.primaryDark), - ); - } + return GetBuilder( + builder: (sc) { + if (gc.isLoading || sc.isLoading) { + return Center( + child: CircularProgressIndicator( + color: FinanceDesignSystem.primaryDark), + ); + } - return CustomScrollView( - physics: const BouncingScrollPhysics(), - slivers: [ - // ═══════ App Bar ═══════ - SliverAppBar( - expandedHeight: 200, - pinned: true, - stretch: true, - backgroundColor: FinanceDesignSystem.primaryDark, - leading: IconButton( - icon: const Icon(Icons.arrow_back_ios_new_rounded, - color: Colors.white, size: 20), - onPressed: () => Get.back(), - ), - actions: [ - IconButton( - icon: const Icon(Icons.refresh_rounded, - color: Colors.white), - onPressed: () => gc.fetchGamificationData(), - ), - ], - flexibleSpace: FlexibleSpaceBar( - centerTitle: true, - title: Text( - 'Statistics'.tr, - style: const TextStyle( - color: Colors.white, - fontWeight: FontWeight.bold, - fontSize: 18, + return CustomScrollView( + physics: const BouncingScrollPhysics(), + slivers: [ + // ═══════ App Bar ═══════ + SliverAppBar( + expandedHeight: 200, + pinned: true, + stretch: true, + backgroundColor: Get.isDarkMode + ? FinanceDesignSystem.primaryDark + : const Color(0xFF0A0E21), + leading: IconButton( + icon: const Icon(Icons.arrow_back_ios_new_rounded, + color: Colors.white, size: 20), + onPressed: () => Get.back(), ), - ), - background: Stack( - fit: StackFit.expand, - children: [ - Container( - decoration: const BoxDecoration( - gradient: FinanceDesignSystem.balanceGradient, - ), - ), - // أيقونة زخرفية - Positioned( - right: -40, - top: -20, - child: Icon( - Icons.bar_chart_rounded, - size: 200, - color: Colors.white.withOpacity(0.04), - ), - ), - Positioned( - left: -30, - bottom: 20, - child: Icon( - Icons.emoji_events_rounded, - size: 120, - color: Colors.white.withOpacity(0.03), - ), - ), - // بطاقة المستوى في الهيدر - Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const SizedBox(height: 40), - Text( - gc.currentLevel.emoji, - style: const TextStyle(fontSize: 40), - ), - const SizedBox(height: 4), - Text( - Get.locale?.languageCode == 'ar' - ? gc.currentLevel.nameAr - : gc.currentLevel.nameEn, - style: TextStyle( - color: Colors.white.withOpacity(0.9), - fontSize: 16, - fontWeight: FontWeight.w600, - ), - ), - const SizedBox(height: 2), - Text( - '${gc.unlockedCount}/${gc.totalAchievements} ${'Achievements'.tr}', - style: TextStyle( - color: Colors.white.withOpacity(0.5), - fontSize: 12, - ), - ), - ], - ), + actions: [ + IconButton( + icon: const Icon(Icons.refresh_rounded, + color: Colors.white), + onPressed: () => gc.fetchGamificationData(), ), ], + flexibleSpace: FlexibleSpaceBar( + centerTitle: true, + title: Text( + 'Statistics'.tr, + style: const TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 18, + ), + ), + background: Stack( + fit: StackFit.expand, + children: [ + Container( + decoration: BoxDecoration( + gradient: FinanceDesignSystem.balanceGradient, + ), + ), + // أيقونة زخرفية + Positioned( + right: -40, + top: -20, + child: Icon( + Icons.bar_chart_rounded, + size: 200, + color: Colors.white.withOpacity(0.04), + ), + ), + Positioned( + left: -30, + bottom: 20, + child: Icon( + Icons.emoji_events_rounded, + size: 120, + color: Colors.white.withOpacity(0.03), + ), + ), + // بطاقة المستوى في الهيدر + Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const SizedBox(height: 40), + Text( + gc.currentLevel.emoji, + style: const TextStyle(fontSize: 40), + ), + const SizedBox(height: 4), + Text( + Get.locale?.languageCode == 'ar' + ? gc.currentLevel.nameAr + : gc.currentLevel.nameEn, + style: TextStyle( + color: Colors.white.withOpacity(0.9), + fontSize: 16, + fontWeight: FontWeight.w600, + ), + ), + const SizedBox(height: 2), + Text( + '${gc.unlockedCount}/${gc.totalAchievements} ${'Achievements'.tr}', + style: TextStyle( + color: Colors.white.withOpacity(0.5), + fontSize: 12, + ), + ), + ], + ), + ), + ], + ), + ), ), - ), - ), - // ═══════ المحتوى ═══════ - SliverPadding( - padding: const EdgeInsets.fromLTRB(16, 24, 16, 40), - sliver: SliverList( - delegate: SliverChildListDelegate([ - // 1. بطاقات الإحصائيات الأربعة - _buildSummaryCards(gc), - const SizedBox( - height: FinanceDesignSystem.verticalSectionPadding), + // ═══════ المحتوى ═══════ + SliverPadding( + padding: const EdgeInsets.fromLTRB(16, 24, 16, 40), + sliver: SliverList( + delegate: SliverChildListDelegate([ + // 1. بطاقات الإحصائيات الأربعة + _buildSummaryCards(gc), + const SizedBox( + height: FinanceDesignSystem.verticalSectionPadding), - // 2. الهدف اليومي - DailyGoalWidget(controller: gc), - const SizedBox( - height: FinanceDesignSystem.verticalSectionPadding), + // 2. الهدف اليومي + DailyGoalWidget(controller: gc), + const SizedBox( + height: FinanceDesignSystem.verticalSectionPadding), - // 3. تقدم المستوى - LevelProgressWidget(controller: gc), - const SizedBox( - height: FinanceDesignSystem.verticalSectionPadding), + // 3. تقدم المستوى + LevelProgressWidget(controller: gc), + const SizedBox( + height: FinanceDesignSystem.verticalSectionPadding), - // 4. إحصائيات اليوم - TodayChartWidget(), - const SizedBox( - height: FinanceDesignSystem.verticalSectionPadding), + // 4. إحصائيات اليوم + TodayChartWidget(), + const SizedBox( + height: FinanceDesignSystem.verticalSectionPadding), - // 5. الرسم البياني الأسبوعي - const WeeklyChartWidget(), - const SizedBox( - height: FinanceDesignSystem.verticalSectionPadding), + // 5. الرسم البياني الأسبوعي + const WeeklyChartWidget(), + const SizedBox( + height: FinanceDesignSystem.verticalSectionPadding), - // 6. التقرير الشهري - const MonthlyChartWidget(), - const SizedBox( - height: FinanceDesignSystem.verticalSectionPadding), + // 6. التقرير الشهري + const MonthlyChartWidget(), + const SizedBox( + height: FinanceDesignSystem.verticalSectionPadding), - // 7. تقييم سلوك القيادة - _buildBehaviorSection(gc), - const SizedBox( - height: FinanceDesignSystem.verticalSectionPadding), + // 7. تقييم سلوك القيادة + _buildBehaviorSection(gc), + const SizedBox( + height: FinanceDesignSystem.verticalSectionPadding), - // 8. الإنجازات - _buildAchievementsSection(gc), - ]), - ), - ), - ], + // 8. الإنجازات + _buildAchievementsSection(gc), + ]), + ), + ), + ], + ); + }, ); }, ), @@ -221,21 +226,27 @@ class StatisticsDashboard extends StatelessWidget { Widget _buildBehaviorSection(GamificationController gc) { bool isExcellent = gc.behaviorScore >= 90; bool isGood = gc.behaviorScore >= 75 && gc.behaviorScore < 90; - - Color statusColor = isExcellent - ? Colors.green - : isGood ? Colors.orange : Colors.red; - String statusText = isExcellent - ? 'Excellent'.tr - : isGood ? 'Good'.tr : 'Needs Improvement'.tr; + Color statusColor = isExcellent + ? Colors.green + : isGood + ? Colors.orange + : Colors.red; + + String statusText = isExcellent + ? 'Excellent'.tr + : isGood + ? 'Good'.tr + : 'Needs Improvement'.tr; return Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: FinanceDesignSystem.cardColor, borderRadius: BorderRadius.circular(24), - boxShadow: const [BoxShadow(color: Colors.black12, blurRadius: 10, offset: Offset(0, 4))], + boxShadow: const [ + BoxShadow(color: Colors.black12, blurRadius: 10, offset: Offset(0, 4)) + ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -245,13 +256,16 @@ class StatisticsDashboard extends StatelessWidget { children: [ Row( children: [ - const Icon(Icons.shield_rounded, color: FinanceDesignSystem.accentBlue), + Icon(Icons.shield_rounded, + color: FinanceDesignSystem.accentBlue), const SizedBox(width: 8), - Text('Driving Behavior'.tr, style: FinanceDesignSystem.headingStyle), + Text('Driving Behavior'.tr, + style: FinanceDesignSystem.headingStyle), ], ), Container( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4), + padding: + const EdgeInsets.symmetric(horizontal: 10, vertical: 4), decoration: BoxDecoration( color: statusColor.withOpacity(0.1), borderRadius: BorderRadius.circular(20), @@ -306,7 +320,11 @@ class StatisticsDashboard extends StatelessWidget { ); } - Widget _behaviorStatItem({required String title, required String value, required IconData icon, required Color color}) { + Widget _behaviorStatItem( + {required String title, + required String value, + required IconData icon, + required Color color}) { return Column( children: [ Container( @@ -318,18 +336,22 @@ class StatisticsDashboard extends StatelessWidget { child: Icon(icon, color: color, size: 24), ), const SizedBox(height: 8), - Text(value, style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16, color: FinanceDesignSystem.primaryDark)), - Text(title, style: const TextStyle(fontSize: 12, color: FinanceDesignSystem.textSecondary)), + Text(value, + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 16, + color: FinanceDesignSystem.primaryDark)), + Text(title, + style: TextStyle( + fontSize: 12, color: FinanceDesignSystem.textSecondary)), ], ); } // ═══════ قسم الإنجازات ═══════ Widget _buildAchievementsSection(GamificationController gc) { - final unlockedAch = - gc.achievements.where((a) => a.isUnlocked).toList(); - final lockedAch = - gc.achievements.where((a) => !a.isUnlocked).toList(); + final unlockedAch = gc.achievements.where((a) => a.isUnlocked).toList(); + final lockedAch = gc.achievements.where((a) => !a.isUnlocked).toList(); return Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -346,7 +368,7 @@ class StatisticsDashboard extends StatelessWidget { ), child: Text( '${gc.unlockedCount}/${gc.totalAchievements}', - style: const TextStyle( + style: TextStyle( color: FinanceDesignSystem.accentBlue, fontWeight: FontWeight.bold, fontSize: 12, @@ -397,9 +419,8 @@ class StatisticsDashboard extends StatelessWidget { width: 50, height: 50, decoration: BoxDecoration( - color: unlocked - ? ach.color.withOpacity(0.15) - : Colors.grey.shade200, + color: + unlocked ? ach.color.withOpacity(0.15) : Colors.grey.shade200, borderRadius: BorderRadius.circular(14), ), child: Icon( diff --git a/lib/views/home/statistics/widgets/daily_goal_widget.dart b/lib/views/home/statistics/widgets/daily_goal_widget.dart index 56da026..53a53b5 100644 --- a/lib/views/home/statistics/widgets/daily_goal_widget.dart +++ b/lib/views/home/statistics/widgets/daily_goal_widget.dart @@ -13,7 +13,7 @@ class DailyGoalWidget extends StatelessWidget { return Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( - color: Colors.white, + color: FinanceDesignSystem.cardColor, borderRadius: BorderRadius.circular(FinanceDesignSystem.cardRadius), boxShadow: [ BoxShadow( @@ -55,17 +55,17 @@ class DailyGoalWidget extends StatelessWidget { children: [ Text( 'Daily Goal'.tr, - style: const TextStyle( + style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: FinanceDesignSystem.primaryDark, ), ), Text( - 'الهدف اليومي'.tr, + 'Daily Goal'.tr, style: TextStyle( fontSize: 11, - color: Colors.grey.shade500, + color: FinanceDesignSystem.textSecondary, ), ), ], @@ -80,13 +80,11 @@ class DailyGoalWidget extends StatelessWidget { padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), decoration: BoxDecoration( - color: Colors.grey.shade100, + color: FinanceDesignSystem.backgroundColor, borderRadius: BorderRadius.circular(8), ), child: Text( - controller.dailyGoal > 0 - ? 'Edit'.tr - : 'Set Goal'.tr, + controller.dailyGoal > 0 ? 'Edit'.tr : 'Set Goal'.tr, style: TextStyle( fontSize: 12, fontWeight: FontWeight.w600, @@ -121,7 +119,7 @@ class DailyGoalWidget extends StatelessWidget { style: TextStyle( fontSize: 16, fontWeight: FontWeight.w500, - color: Colors.grey.shade400, + color: FinanceDesignSystem.textMuted, ), ), ], @@ -135,7 +133,7 @@ class DailyGoalWidget extends StatelessWidget { height: 12, width: double.infinity, decoration: BoxDecoration( - color: Colors.grey.shade100, + color: FinanceDesignSystem.backgroundColor, borderRadius: BorderRadius.circular(6), ), ), @@ -197,7 +195,7 @@ class DailyGoalWidget extends StatelessWidget { const SizedBox(width: 4), Text( 'Goal Achieved!'.tr, - style: const TextStyle( + style: TextStyle( fontSize: 12, fontWeight: FontWeight.bold, color: FinanceDesignSystem.successGreen, @@ -210,7 +208,7 @@ class DailyGoalWidget extends StatelessWidget { '${'Remaining:'.tr} ${(controller.dailyGoal - controller.dailyEarnings).clamp(0, double.infinity).toStringAsFixed(0)} ${'SYP'.tr}', style: TextStyle( fontSize: 11, - color: Colors.grey.shade500, + color: FinanceDesignSystem.textSecondary, ), ), ], @@ -228,6 +226,7 @@ class DailyGoalWidget extends StatelessWidget { ); Get.defaultDialog( + backgroundColor: FinanceDesignSystem.cardColor, title: 'Set Daily Goal'.tr, titleStyle: FinanceDesignSystem.headingStyle, content: Column( @@ -252,13 +251,11 @@ class DailyGoalWidget extends StatelessWidget { suffixText: 'SYP'.tr, border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), - borderSide: - BorderSide(color: Colors.grey.shade300), + borderSide: BorderSide(color: FinanceDesignSystem.borderColor), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), - borderSide: - const BorderSide(color: FinanceDesignSystem.accentBlue), + borderSide: BorderSide(color: FinanceDesignSystem.accentBlue), ), ), ), @@ -270,7 +267,8 @@ class DailyGoalWidget extends StatelessWidget { return ActionChip( label: Text('$goal'), labelStyle: const TextStyle(fontSize: 12), - backgroundColor: FinanceDesignSystem.accentBlue.withOpacity(0.1), + backgroundColor: + FinanceDesignSystem.accentBlue.withOpacity(0.1), side: BorderSide.none, onPressed: () { textController.text = goal.toString(); @@ -291,16 +289,15 @@ class DailyGoalWidget extends StatelessWidget { style: ElevatedButton.styleFrom( backgroundColor: FinanceDesignSystem.accentBlue, foregroundColor: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12)), + shape: + RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 12), ), child: Text('Save'.tr), ), cancel: TextButton( onPressed: () => Get.back(), - child: Text('Cancel'.tr, - style: const TextStyle(color: Colors.grey)), + child: Text('Cancel'.tr, style: const TextStyle(color: Colors.grey)), ), ); } diff --git a/lib/views/home/statistics/widgets/level_progress_widget.dart b/lib/views/home/statistics/widgets/level_progress_widget.dart index 75af64a..15775c7 100644 --- a/lib/views/home/statistics/widgets/level_progress_widget.dart +++ b/lib/views/home/statistics/widgets/level_progress_widget.dart @@ -17,8 +17,12 @@ class LevelProgressWidget extends StatelessWidget { padding: const EdgeInsets.all(20), decoration: BoxDecoration( gradient: LinearGradient( - colors: [level.color.withOpacity(0.08), level.gradientEnd.withOpacity(0.04)], - begin: Alignment.topLeft, end: Alignment.bottomRight, + colors: [ + level.color.withOpacity(0.08), + level.gradientEnd.withOpacity(0.04) + ], + begin: Alignment.topLeft, + end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(FinanceDesignSystem.cardRadius), border: Border.all(color: level.color.withOpacity(0.2), width: 1.5), @@ -29,17 +33,27 @@ class LevelProgressWidget extends StatelessWidget { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text('Driver Level'.tr, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: FinanceDesignSystem.primaryDark)), + Text('Driver Level'.tr, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + color: FinanceDesignSystem.primaryDark)), Container( - padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 8), + padding: + const EdgeInsets.symmetric(horizontal: 14, vertical: 8), decoration: BoxDecoration( - gradient: LinearGradient(colors: [level.color, level.gradientEnd]), + gradient: + LinearGradient(colors: [level.color, level.gradientEnd]), borderRadius: BorderRadius.circular(20), ), child: Row(mainAxisSize: MainAxisSize.min, children: [ Text(level.emoji, style: const TextStyle(fontSize: 16)), const SizedBox(width: 6), - Text(isAr ? level.nameAr : level.nameEn, style: const TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 13)), + Text(isAr ? level.nameAr : level.nameEn, + style: const TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 13)), ]), ), ], @@ -50,42 +64,94 @@ class LevelProgressWidget extends StatelessWidget { final lvl = DriverLevels.all[i]; final isCurrent = lvl.id == level.id; final isPast = DriverLevels.all.indexOf(level) > i; - return Expanded(child: Container( - margin: const EdgeInsets.symmetric(horizontal: 2), height: 8, + return Expanded( + child: Container( + margin: const EdgeInsets.symmetric(horizontal: 2), + height: 8, decoration: BoxDecoration( - color: isCurrent ? lvl.color : isPast ? lvl.color.withOpacity(0.6) : Colors.grey.shade200, + color: isCurrent + ? lvl.color + : isPast + ? lvl.color.withOpacity(0.6) + : FinanceDesignSystem.backgroundColor, borderRadius: BorderRadius.circular(4), ), )); }), ), const SizedBox(height: 6), - Row(children: DriverLevels.all.map((l) => Expanded(child: Text(l.emoji, textAlign: TextAlign.center, style: TextStyle(fontSize: l.id == level.id ? 16 : 12)))).toList()), + Row( + children: DriverLevels.all + .map((l) => Expanded( + child: Text(l.emoji, + textAlign: TextAlign.center, + style: + TextStyle(fontSize: l.id == level.id ? 16 : 12)))) + .toList()), const SizedBox(height: 16), if (next != null) ...[ Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text('${'Next Level:'.tr} ${isAr ? next.nameAr : next.nameEn}', style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: Colors.grey.shade700)), - Text('${(controller.progressToNext * 100).toStringAsFixed(0)}%', style: TextStyle(fontSize: 12, fontWeight: FontWeight.bold, color: level.color)), + Text('${'Next Level:'.tr} ${isAr ? next.nameAr : next.nameEn}', + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w600, + color: FinanceDesignSystem.textSecondary)), + Text('${(controller.progressToNext * 100).toStringAsFixed(0)}%', + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.bold, + color: level.color)), ]), const SizedBox(height: 8), Stack(children: [ - Container(height: 10, decoration: BoxDecoration(color: Colors.grey.shade100, borderRadius: BorderRadius.circular(5))), - LayoutBuilder(builder: (ctx, c) => AnimatedContainer( - duration: const Duration(milliseconds: 800), curve: Curves.easeOutCubic, height: 10, - width: c.maxWidth * controller.progressToNext, - decoration: BoxDecoration(gradient: LinearGradient(colors: [level.color, level.gradientEnd]), borderRadius: BorderRadius.circular(5)), - )), + Container( + height: 10, + decoration: BoxDecoration( + color: FinanceDesignSystem.backgroundColor, + borderRadius: BorderRadius.circular(5))), + LayoutBuilder( + builder: (ctx, c) => AnimatedContainer( + duration: const Duration(milliseconds: 800), + curve: Curves.easeOutCubic, + height: 10, + width: c.maxWidth * controller.progressToNext, + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [level.color, level.gradientEnd]), + borderRadius: BorderRadius.circular(5)), + )), ]), const SizedBox(height: 6), - Text('${controller.totalPoints} / ${next.minPoints} ${'Points'.tr}', style: TextStyle(fontSize: 11, color: Colors.grey.shade500, fontFamily: 'digit')), + Text('${controller.totalPoints} / ${next.minPoints} ${'Points'.tr}', + style: TextStyle( + fontSize: 11, + color: FinanceDesignSystem.textMuted, + fontFamily: 'digit')), ] else - Center(child: Text('🏆 ${'Maximum Level Reached!'.tr}', style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold, color: level.color))), + Center( + child: Text('🏆 ${'Maximum Level Reached!'.tr}', + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.bold, + color: level.color))), const SizedBox(height: 16), - Wrap(spacing: 6, runSpacing: 6, children: level.perks.map((p) => Container( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5), - decoration: BoxDecoration(color: level.color.withOpacity(0.1), borderRadius: BorderRadius.circular(12)), - child: Text(p.tr, style: TextStyle(fontSize: 10, fontWeight: FontWeight.w600, color: level.color.withOpacity(0.8))), - )).toList()), + Wrap( + spacing: 6, + runSpacing: 6, + children: level.perks + .map((p) => Container( + padding: const EdgeInsets.symmetric( + horizontal: 10, vertical: 5), + decoration: BoxDecoration( + color: level.color.withOpacity(0.1), + borderRadius: BorderRadius.circular(12)), + child: Text(p.tr, + style: TextStyle( + fontSize: 10, + fontWeight: FontWeight.w600, + color: level.color.withOpacity(0.8))), + )) + .toList()), ], ), ); diff --git a/lib/views/home/statistics/widgets/monthly_chart_widget.dart b/lib/views/home/statistics/widgets/monthly_chart_widget.dart index 679611d..7fce035 100644 --- a/lib/views/home/statistics/widgets/monthly_chart_widget.dart +++ b/lib/views/home/statistics/widgets/monthly_chart_widget.dart @@ -14,63 +14,114 @@ class MonthlyChartWidget extends StatelessWidget { return Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( - color: Colors.white, + color: FinanceDesignSystem.cardColor, borderRadius: BorderRadius.circular(FinanceDesignSystem.cardRadius), - boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 10, offset: const Offset(0, 4))], + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.03), + blurRadius: 10, + offset: const Offset(0, 4)) + ], ), - child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text('Monthly Report'.tr, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: FinanceDesignSystem.primaryDark)), + child: + Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + Text('Monthly Report'.tr, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + color: FinanceDesignSystem.primaryDark)), const SizedBox(height: 16), // Summary Row Row(children: [ - _summaryTile('Total Earnings'.tr, '${sc.monthlyTotalEarnings.toStringAsFixed(0)} ${'SYP'.tr}', FinanceDesignSystem.successGreen), + _summaryTile( + 'Total Earnings'.tr, + '${sc.monthlyTotalEarnings.toStringAsFixed(0)} ${'SYP'.tr}', + FinanceDesignSystem.successGreen), const SizedBox(width: 12), - _summaryTile('Total Trips'.tr, '${sc.monthlyTotalTrips}', FinanceDesignSystem.accentBlue), + _summaryTile('Total Trips'.tr, '${sc.monthlyTotalTrips}', + FinanceDesignSystem.accentBlue), const SizedBox(width: 12), - _summaryTile('Best Day'.tr, '${sc.bestDay}', const Color(0xFFFFD700)), + _summaryTile( + 'Best Day'.tr, '${sc.bestDay}', const Color(0xFFFFD700)), ]), const SizedBox(height: 20), // Monthly Earnings Line Chart SizedBox( height: 200, child: sc.monthlyEarnings.isEmpty - ? Center(child: Text('No data yet'.tr, style: TextStyle(color: Colors.grey.shade400))) + ? Center( + child: Text('No data yet'.tr, + style: TextStyle(color: Colors.grey.shade400))) : LineChart(LineChartData( lineTouchData: LineTouchData( enabled: true, touchTooltipData: LineTouchTooltipData( - getTooltipItems: (spots) => spots.map((s) => LineTooltipItem( - '${s.y.toStringAsFixed(0)} ${'SYP'.tr}', - const TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 12), - )).toList(), + getTooltipItems: (spots) => spots + .map((s) => LineTooltipItem( + '${s.y.toStringAsFixed(0)} ${'SYP'.tr}', + const TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 12), + )) + .toList(), ), ), - gridData: FlGridData(show: true, drawVerticalLine: false, - getDrawingHorizontalLine: (v) => FlLine(color: Colors.grey.shade100, strokeWidth: 1), + gridData: FlGridData( + show: true, + drawVerticalLine: false, + getDrawingHorizontalLine: (v) => FlLine( + color: FinanceDesignSystem.borderColor, + strokeWidth: 1), ), titlesData: FlTitlesData( - bottomTitles: AxisTitles(sideTitles: SideTitles(showTitles: true, interval: 5, - getTitlesWidget: (v, m) => Padding(padding: const EdgeInsets.only(top: 8), - child: Text('${v.toInt()}', style: TextStyle(fontSize: 10, color: Colors.grey.shade500)), + bottomTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + interval: 5, + getTitlesWidget: (v, m) => Padding( + padding: const EdgeInsets.only(top: 8), + child: Text('${v.toInt()}', + style: TextStyle( + fontSize: 10, + color: FinanceDesignSystem.textSecondary)), ), )), - leftTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)), - topTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)), - rightTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)), + leftTitles: const AxisTitles( + sideTitles: SideTitles(showTitles: false)), + topTitles: const AxisTitles( + sideTitles: SideTitles(showTitles: false)), + rightTitles: const AxisTitles( + sideTitles: SideTitles(showTitles: false)), ), borderData: FlBorderData(show: false), lineBarsData: [ LineChartBarData( - spots: sc.monthlyEarnings.map((e) => FlSpot(e.day.toDouble(), e.pricePerDay)).toList(), - isCurved: true, curveSmoothness: 0.3, - color: FinanceDesignSystem.accentBlue, barWidth: 3, - dotData: FlDotData(show: true, getDotPainter: (s, p, d, i) => - FlDotCirclePainter(radius: 3, color: FinanceDesignSystem.accentBlue, strokeWidth: 1, strokeColor: Colors.white), + spots: sc.monthlyEarnings + .map((e) => + FlSpot(e.day.toDouble(), e.pricePerDay)) + .toList(), + isCurved: true, + curveSmoothness: 0.3, + color: FinanceDesignSystem.accentBlue, + barWidth: 3, + dotData: FlDotData( + show: true, + getDotPainter: (s, p, d, i) => FlDotCirclePainter( + radius: 3, + color: FinanceDesignSystem.accentBlue, + strokeWidth: 1, + strokeColor: Colors.white), ), belowBarData: BarAreaData( show: true, - gradient: LinearGradient(begin: Alignment.topCenter, end: Alignment.bottomCenter, - colors: [FinanceDesignSystem.accentBlue.withOpacity(0.2), FinanceDesignSystem.accentBlue.withOpacity(0.0)], + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + FinanceDesignSystem.accentBlue.withOpacity(0.2), + FinanceDesignSystem.accentBlue.withOpacity(0.0) + ], ), ), ), @@ -87,11 +138,20 @@ class MonthlyChartWidget extends StatelessWidget { return Expanded( child: Container( padding: const EdgeInsets.all(10), - decoration: BoxDecoration(color: color.withOpacity(0.08), borderRadius: BorderRadius.circular(12)), + decoration: BoxDecoration( + color: color.withOpacity(0.08), + borderRadius: BorderRadius.circular(12)), child: Column(children: [ - Text(value, style: TextStyle(fontSize: 14, fontWeight: FontWeight.w800, color: color)), + Text(value, + style: TextStyle( + fontSize: 14, fontWeight: FontWeight.w800, color: color)), const SizedBox(height: 2), - Text(label, style: TextStyle(fontSize: 9, color: Colors.grey.shade600), textAlign: TextAlign.center, maxLines: 1, overflow: TextOverflow.ellipsis), + Text(label, + style: TextStyle( + fontSize: 9, color: FinanceDesignSystem.textSecondary), + textAlign: TextAlign.center, + maxLines: 1, + overflow: TextOverflow.ellipsis), ]), ), ); diff --git a/lib/views/home/statistics/widgets/stat_summary_card.dart b/lib/views/home/statistics/widgets/stat_summary_card.dart index e7fedd4..79eb172 100644 --- a/lib/views/home/statistics/widgets/stat_summary_card.dart +++ b/lib/views/home/statistics/widgets/stat_summary_card.dart @@ -20,7 +20,7 @@ class StatSummaryCard extends StatelessWidget { return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( - color: Colors.white, + color: FinanceDesignSystem.cardColor, borderRadius: BorderRadius.circular(FinanceDesignSystem.cardRadius), boxShadow: [ BoxShadow( @@ -68,7 +68,7 @@ class StatSummaryCard extends StatelessWidget { label, style: TextStyle( fontSize: 11, - color: Colors.grey.shade500, + color: FinanceDesignSystem.textSecondary, fontWeight: FontWeight.w500, ), maxLines: 1, diff --git a/lib/views/home/statistics/widgets/today_chart_widget.dart b/lib/views/home/statistics/widgets/today_chart_widget.dart index ae6b8ce..cde2a9a 100644 --- a/lib/views/home/statistics/widgets/today_chart_widget.dart +++ b/lib/views/home/statistics/widgets/today_chart_widget.dart @@ -13,26 +13,42 @@ class TodayChartWidget extends StatelessWidget { return Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( - color: Colors.white, + color: FinanceDesignSystem.cardColor, borderRadius: BorderRadius.circular(FinanceDesignSystem.cardRadius), boxShadow: [ - BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 10, offset: const Offset(0, 4)), + BoxShadow( + color: Colors.black.withOpacity(0.03), + blurRadius: 10, + offset: const Offset(0, 4)), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text('Today Overview'.tr, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: FinanceDesignSystem.primaryDark)), + Text('Today Overview'.tr, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + color: FinanceDesignSystem.primaryDark)), const SizedBox(height: 4), - Text('نظرة عامة على اليوم'.tr, style: TextStyle(fontSize: 11, color: Colors.grey.shade500)), + Text('Summary of your daily activity'.tr, + style: TextStyle( + fontSize: 11, color: FinanceDesignSystem.textSecondary)), const SizedBox(height: 20), - _buildRow(Icons.monetization_on_rounded, 'Earnings'.tr, '${hc.totalMoneyToday} ${'SYP'.tr}', FinanceDesignSystem.successGreen), + _buildRow( + Icons.monetization_on_rounded, + 'Earnings'.tr, + '${hc.totalMoneyToday} ${'SYP'.tr}', + FinanceDesignSystem.successGreen), const Divider(height: 24), - _buildRow(Icons.local_taxi_rounded, 'Rides'.tr, hc.countRideToday, FinanceDesignSystem.accentBlue), + _buildRow(Icons.local_taxi_rounded, 'Rides'.tr, hc.countRideToday, + FinanceDesignSystem.accentBlue), const Divider(height: 24), - Obx(() => _buildRow(Icons.timer_rounded, 'Online Duration'.tr, hc.totalDurationDisplay.value, const Color(0xFFFF9800))), + Obx(() => _buildRow(Icons.timer_rounded, 'Online Duration'.tr, + hc.totalDurationDisplay.value, const Color(0xFFFF9800))), const Divider(height: 24), - _buildRow(Icons.cancel_outlined, 'Refused'.tr, hc.countRefuse, FinanceDesignSystem.dangerRed), + _buildRow(Icons.cancel_outlined, 'Refused'.tr, hc.countRefuse, + FinanceDesignSystem.dangerRed), ], ), ); @@ -45,12 +61,24 @@ class TodayChartWidget extends StatelessWidget { children: [ Container( padding: const EdgeInsets.all(8), - decoration: BoxDecoration(color: color.withOpacity(0.1), borderRadius: BorderRadius.circular(10)), + decoration: BoxDecoration( + color: color.withOpacity(0.1), + borderRadius: BorderRadius.circular(10)), child: Icon(icon, color: color, size: 20), ), const SizedBox(width: 14), - Expanded(child: Text(label, style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: Colors.grey.shade700))), - Text(value, style: TextStyle(fontSize: 16, fontWeight: FontWeight.w800, color: FinanceDesignSystem.primaryDark, fontFamily: 'digit')), + Expanded( + child: Text(label, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + color: FinanceDesignSystem.primaryDark))), + Text(value, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w800, + color: FinanceDesignSystem.primaryDark, + fontFamily: 'digit')), ], ); } diff --git a/lib/views/home/statistics/widgets/weekly_chart_widget.dart b/lib/views/home/statistics/widgets/weekly_chart_widget.dart index 874cbb8..3fc7a3b 100644 --- a/lib/views/home/statistics/widgets/weekly_chart_widget.dart +++ b/lib/views/home/statistics/widgets/weekly_chart_widget.dart @@ -4,7 +4,6 @@ import 'package:fl_chart/fl_chart.dart'; import '../../../../constant/finance_design_system.dart'; import '../../../../controller/home/statistics/statistics_controller.dart'; - class WeeklyChartWidget extends StatelessWidget { const WeeklyChartWidget({super.key}); @@ -15,32 +14,56 @@ class WeeklyChartWidget extends StatelessWidget { return Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( - color: Colors.white, + color: FinanceDesignSystem.cardColor, borderRadius: BorderRadius.circular(FinanceDesignSystem.cardRadius), - boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 10, offset: const Offset(0, 4))], + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.03), + blurRadius: 10, + offset: const Offset(0, 4)) + ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text('Weekly Earnings'.tr, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: FinanceDesignSystem.primaryDark)), + Text('Weekly Earnings'.tr, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + color: FinanceDesignSystem.primaryDark)), Container( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4), - decoration: BoxDecoration(color: FinanceDesignSystem.successGreen.withOpacity(0.1), borderRadius: BorderRadius.circular(12)), - child: Text('${sc.weeklyEarnings.toStringAsFixed(0)} ${'SYP'.tr}', style: const TextStyle(fontSize: 12, fontWeight: FontWeight.bold, color: FinanceDesignSystem.successGreen)), + padding: + const EdgeInsets.symmetric(horizontal: 10, vertical: 4), + decoration: BoxDecoration( + color: FinanceDesignSystem.successGreen.withOpacity(0.1), + borderRadius: BorderRadius.circular(12)), + child: Text( + '${sc.weeklyEarnings.toStringAsFixed(0)} ${'SYP'.tr}', + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.bold, + color: FinanceDesignSystem.successGreen)), ), ]), const SizedBox(height: 8), Row(children: [ - _miniStat(Icons.local_taxi_rounded, '${sc.weeklyTrips}', 'Rides'.tr, FinanceDesignSystem.accentBlue), + _miniStat(Icons.local_taxi_rounded, '${sc.weeklyTrips}', + 'Rides'.tr, FinanceDesignSystem.accentBlue), const SizedBox(width: 16), - _miniStat(Icons.timer_rounded, '${sc.weeklyHours.toStringAsFixed(1)}h', 'Hours'.tr, const Color(0xFFFF9800)), + _miniStat( + Icons.timer_rounded, + '${sc.weeklyHours.toStringAsFixed(1)}h', + 'Hours'.tr, + const Color(0xFFFF9800)), ]), const SizedBox(height: 20), SizedBox( height: 180, child: sc.weeklyStats.isEmpty - ? Center(child: Text('No data yet'.tr, style: TextStyle(color: Colors.grey.shade400))) + ? Center( + child: Text('No data yet'.tr, + style: TextStyle(color: Colors.grey.shade400))) : BarChart( BarChartData( alignment: BarChartAlignment.spaceAround, @@ -48,24 +71,43 @@ class WeeklyChartWidget extends StatelessWidget { barTouchData: BarTouchData( enabled: true, touchTooltipData: BarTouchTooltipData( - getTooltipItem: (group, gi, rod, ri) => BarTooltipItem( + getTooltipItem: (group, gi, rod, ri) => + BarTooltipItem( '${rod.toY.toStringAsFixed(0)} ${'SYP'.tr}', - const TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 12), + const TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 12), ), ), ), titlesData: FlTitlesData( show: true, - bottomTitles: AxisTitles(sideTitles: SideTitles(showTitles: true, getTitlesWidget: (v, m) { - final idx = v.toInt(); - if (idx >= 0 && idx < sc.weeklyStats.length) { - return Padding(padding: const EdgeInsets.only(top: 8), child: Text(sc.weeklyStats[idx].dayName.tr, style: TextStyle(fontSize: 10, color: Colors.grey.shade500))); - } - return const SizedBox.shrink(); - })), - leftTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)), - topTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)), - rightTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)), + bottomTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + getTitlesWidget: (v, m) { + final idx = v.toInt(); + if (idx >= 0 && + idx < sc.weeklyStats.length) { + return Padding( + padding: + const EdgeInsets.only(top: 8), + child: Text( + sc.weeklyStats[idx].dayName.tr, + style: TextStyle( + fontSize: 10, + color: FinanceDesignSystem + .textSecondary))); + } + return const SizedBox.shrink(); + })), + leftTitles: const AxisTitles( + sideTitles: SideTitles(showTitles: false)), + topTitles: const AxisTitles( + sideTitles: SideTitles(showTitles: false)), + rightTitles: const AxisTitles( + sideTitles: SideTitles(showTitles: false)), ), borderData: FlBorderData(show: false), gridData: const FlGridData(show: false), @@ -76,12 +118,22 @@ class WeeklyChartWidget extends StatelessWidget { BarChartRodData( toY: stat.earnings, width: 20, - borderRadius: const BorderRadius.vertical(top: Radius.circular(6)), + borderRadius: const BorderRadius.vertical( + top: Radius.circular(6)), gradient: LinearGradient( - begin: Alignment.bottomCenter, end: Alignment.topCenter, + begin: Alignment.bottomCenter, + end: Alignment.topCenter, colors: isToday - ? [FinanceDesignSystem.accentBlue, const Color(0xFF82B1FF)] - : [FinanceDesignSystem.primaryDark.withOpacity(0.6), FinanceDesignSystem.primaryDark.withOpacity(0.3)], + ? [ + FinanceDesignSystem.accentBlue, + const Color(0xFF82B1FF) + ] + : [ + FinanceDesignSystem.primaryDark + .withOpacity(0.6), + FinanceDesignSystem.primaryDark + .withOpacity(0.3) + ], ), ), ]); @@ -100,9 +152,15 @@ class WeeklyChartWidget extends StatelessWidget { return Row(children: [ Icon(icon, size: 16, color: color), const SizedBox(width: 4), - Text(value, style: TextStyle(fontSize: 13, fontWeight: FontWeight.bold, color: FinanceDesignSystem.primaryDark)), + Text(value, + style: TextStyle( + fontSize: 13, + fontWeight: FontWeight.bold, + color: FinanceDesignSystem.primaryDark)), const SizedBox(width: 4), - Text(label, style: TextStyle(fontSize: 11, color: Colors.grey.shade500)), + Text(label, + style: TextStyle( + fontSize: 11, color: FinanceDesignSystem.textSecondary)), ]); } diff --git a/lib/views/lang/languages.dart b/lib/views/lang/languages.dart index 3532393..a04cbe8 100755 --- a/lib/views/lang/languages.dart +++ b/lib/views/lang/languages.dart @@ -106,7 +106,7 @@ class Language extends StatelessWidget { alignment: Alignment.center, child: Text( flagIcon, - style: const TextStyle( + style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: FinanceDesignSystem.primaryDark, diff --git a/pubspec.lock b/pubspec.lock index 11a51be..61fb81d 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -2160,7 +2160,7 @@ packages: source: hosted version: "0.7.0" url_launcher: - dependency: transitive + dependency: "direct main" description: name: url_launcher sha256: f6a7e5c4835bb4e3026a04793a4199ca2d14c739ec378fdfe23fc8075d0439f8 diff --git a/pubspec.yaml b/pubspec.yaml index 2996f01..37363b3 100755 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -72,6 +72,7 @@ dependencies: share_plus: ^12.0.2 sign_in_with_apple: ^7.0.1 socket_io_client: ^1.0.2 + url_launcher: ^6.3.1 vibration: ^3.1.8 video_player: ^2.9.2 wakelock_plus: