Files
intaleq_driver/lib/views/home/statistics/statistics_dashboard.dart

499 lines
18 KiB
Dart

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:sefer_driver/constant/finance_design_system.dart';
import 'package:sefer_driver/controller/gamification/gamification_controller.dart';
import 'package:sefer_driver/controller/home/statistics/statistics_controller.dart';
import 'widgets/stat_summary_card.dart';
import 'widgets/daily_goal_widget.dart';
import 'widgets/level_progress_widget.dart';
import 'widgets/today_chart_widget.dart';
import 'widgets/weekly_chart_widget.dart';
import 'widgets/monthly_chart_widget.dart';
class StatisticsDashboard extends StatelessWidget {
StatisticsDashboard({super.key});
final GamificationController gamController =
Get.put(GamificationController());
final StatisticsController statsController =
Get.put(StatisticsController());
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: FinanceDesignSystem.backgroundColor,
body: GetBuilder<GamificationController>(
builder: (gc) {
if (gc.isLoading) {
return const 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,
),
),
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,
),
),
],
),
),
],
),
),
),
// ═══════ المحتوى ═══════
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),
// 3. تقدم المستوى
LevelProgressWidget(controller: gc),
const SizedBox(
height: FinanceDesignSystem.verticalSectionPadding),
// 4. إحصائيات اليوم
TodayChartWidget(),
const SizedBox(
height: FinanceDesignSystem.verticalSectionPadding),
// 5. الرسم البياني الأسبوعي
const WeeklyChartWidget(),
const SizedBox(
height: FinanceDesignSystem.verticalSectionPadding),
// 6. التقرير الشهري
const MonthlyChartWidget(),
const SizedBox(
height: FinanceDesignSystem.verticalSectionPadding),
// 7. تقييم سلوك القيادة
_buildBehaviorSection(gc),
const SizedBox(
height: FinanceDesignSystem.verticalSectionPadding),
// 8. الإنجازات
_buildAchievementsSection(gc),
]),
),
),
],
);
},
),
);
}
// ═══════ بطاقات الإحصائيات ═══════
Widget _buildSummaryCards(GamificationController gc) {
return GridView.count(
crossAxisCount: 2,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
crossAxisSpacing: 12,
mainAxisSpacing: 12,
childAspectRatio: 1.5,
children: [
StatSummaryCard(
icon: Icons.local_taxi_rounded,
label: 'Total Trips'.tr,
value: gc.totalTrips.toString(),
color: FinanceDesignSystem.accentBlue,
),
StatSummaryCard(
icon: Icons.star_rounded,
label: 'Rating'.tr,
value: gc.averageRating.toStringAsFixed(1),
color: const Color(0xFFFFD700),
),
StatSummaryCard(
icon: Icons.whatshot_rounded,
label: 'Day Streak'.tr,
value: '${gc.consecutiveDays}',
color: const Color(0xFFFF5722),
),
StatSummaryCard(
icon: Icons.people_rounded,
label: 'Referrals'.tr,
value: gc.totalReferrals.toString(),
color: const Color(0xFF9C27B0),
),
],
);
}
// ═══════ قسم تقييم السلوك ═══════
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;
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))],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
const Icon(Icons.shield_rounded, color: FinanceDesignSystem.accentBlue),
const SizedBox(width: 8),
Text('Driving Behavior'.tr, style: FinanceDesignSystem.headingStyle),
],
),
Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
decoration: BoxDecoration(
color: statusColor.withOpacity(0.1),
borderRadius: BorderRadius.circular(20),
),
child: Text(
statusText,
style: TextStyle(
color: statusColor,
fontWeight: FontWeight.bold,
fontSize: 12,
),
),
),
],
),
const SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_behaviorStatItem(
title: 'Score'.tr,
value: '${gc.behaviorScore}%',
icon: Icons.speed_rounded,
color: FinanceDesignSystem.accentBlue,
),
_behaviorStatItem(
title: 'Max Speed'.tr,
value: '${gc.maxSpeed.toStringAsFixed(0)} km/h',
icon: Icons.directions_car_rounded,
color: Colors.orange,
),
_behaviorStatItem(
title: 'Hard Brakes'.tr,
value: '${gc.hardBrakes}',
icon: Icons.warning_rounded,
color: Colors.red,
),
],
),
const SizedBox(height: 16),
ClipRRect(
borderRadius: BorderRadius.circular(8),
child: LinearProgressIndicator(
value: gc.behaviorScore / 100,
backgroundColor: FinanceDesignSystem.backgroundColor,
valueColor: AlwaysStoppedAnimation<Color>(statusColor),
minHeight: 8,
),
),
],
),
);
}
Widget _behaviorStatItem({required String title, required String value, required IconData icon, required Color color}) {
return Column(
children: [
Container(
padding: const EdgeInsets.all(10),
decoration: BoxDecoration(
color: color.withOpacity(0.1),
shape: BoxShape.circle,
),
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)),
],
);
}
// ═══════ قسم الإنجازات ═══════
Widget _buildAchievementsSection(GamificationController gc) {
final unlockedAch =
gc.achievements.where((a) => a.isUnlocked).toList();
final lockedAch =
gc.achievements.where((a) => !a.isUnlocked).toList();
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('Achievements'.tr, style: FinanceDesignSystem.headingStyle),
Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
decoration: BoxDecoration(
color: FinanceDesignSystem.accentBlue.withOpacity(0.1),
borderRadius: BorderRadius.circular(20),
),
child: Text(
'${gc.unlockedCount}/${gc.totalAchievements}',
style: const TextStyle(
color: FinanceDesignSystem.accentBlue,
fontWeight: FontWeight.bold,
fontSize: 12,
),
),
),
],
),
const SizedBox(height: 16),
// الإنجازات المفتوحة
if (unlockedAch.isNotEmpty) ...[
...unlockedAch.map((a) => _buildAchievementCard(a, true)),
const SizedBox(height: 16),
],
// الإنجازات المقفلة
...lockedAch.map((a) => _buildAchievementCard(a, false)),
],
);
}
Widget _buildAchievementCard(Achievement ach, bool unlocked) {
final isAr = Get.locale?.languageCode == 'ar';
return Container(
margin: const EdgeInsets.only(bottom: 12),
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: unlocked ? Colors.white : Colors.grey.shade50,
borderRadius: BorderRadius.circular(FinanceDesignSystem.cardRadius),
border: unlocked
? Border.all(color: ach.color.withOpacity(0.3), width: 1.5)
: null,
boxShadow: unlocked
? [
BoxShadow(
color: ach.color.withOpacity(0.1),
blurRadius: 10,
offset: const Offset(0, 4),
),
]
: null,
),
child: Row(
children: [
// أيقونة الإنجاز
Container(
width: 50,
height: 50,
decoration: BoxDecoration(
color: unlocked
? ach.color.withOpacity(0.15)
: Colors.grey.shade200,
borderRadius: BorderRadius.circular(14),
),
child: Icon(
ach.icon,
color: unlocked ? ach.color : Colors.grey.shade400,
size: 26,
),
),
const SizedBox(width: 14),
// المعلومات
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
isAr ? ach.titleAr : ach.titleEn,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 14,
color: unlocked
? FinanceDesignSystem.primaryDark
: Colors.grey.shade500,
),
),
const SizedBox(height: 2),
Text(
isAr ? ach.descriptionAr : ach.descriptionEn,
style: TextStyle(
fontSize: 11,
color: Colors.grey.shade500,
),
),
if (!unlocked) ...[
const SizedBox(height: 8),
// شريط التقدم
Stack(
children: [
Container(
height: 6,
decoration: BoxDecoration(
color: Colors.grey.shade200,
borderRadius: BorderRadius.circular(3),
),
),
FractionallySizedBox(
widthFactor: ach.progress,
child: Container(
height: 6,
decoration: BoxDecoration(
color: ach.color.withOpacity(0.6),
borderRadius: BorderRadius.circular(3),
),
),
),
],
),
const SizedBox(height: 4),
Text(
'${ach.currentProgress}/${ach.target}',
style: TextStyle(
fontSize: 10,
color: Colors.grey.shade400,
fontWeight: FontWeight.w600,
),
),
],
],
),
),
// أيقونة الحالة
if (unlocked)
Container(
padding: const EdgeInsets.all(6),
decoration: BoxDecoration(
color: ach.color.withOpacity(0.15),
shape: BoxShape.circle,
),
child: Icon(
Icons.check_rounded,
color: ach.color,
size: 18,
),
)
else
Icon(
Icons.lock_outline_rounded,
color: Colors.grey.shade300,
size: 20,
),
],
),
);
}
}