import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:siro_admin/constant/colors.dart'; import 'package:siro_admin/controller/admin/analytics_v2_controller.dart'; import 'package:intl/intl.dart'; class AdvancedAnalyticsPage extends StatelessWidget { const AdvancedAnalyticsPage({super.key}); @override Widget build(BuildContext context) { final controller = Get.put(AnalyticsV2Controller()); return Scaffold( backgroundColor: AppColor.bg, appBar: AppBar( title: const Text('التحليلات المتقدمة', style: TextStyle(fontWeight: FontWeight.bold)), backgroundColor: AppColor.surface, elevation: 0, centerTitle: true, actions: [ IconButton( icon: const Icon(Icons.refresh_rounded), onPressed: () => controller.fetchAllAnalytics(), ) ], ), body: GetBuilder( builder: (ctrl) { if (ctrl.isLoading) { return const Center( child: CircularProgressIndicator(color: AppColor.accent)); } return SingleChildScrollView( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildSummarySection(ctrl.revenueData['summary']), const SizedBox(height: 24), _buildSectionTitle('إيرادات آخر 30 يوم'), _buildRevenueChart(ctrl.revenueData['daily'] ?? []), const SizedBox(height: 32), _buildSectionTitle('نمو المستخدمين (آخر 30 يوم)'), _buildGrowthChart(ctrl.growthData), const SizedBox(height: 32), _buildSectionTitle('أفضل 10 سائقين (حسب الرحلات)'), _buildTopDriversList(ctrl.topDrivers), const SizedBox(height: 40), ], ), ); }, ), ); } Widget _buildSectionTitle(String title) { return Padding( padding: const EdgeInsets.only(bottom: 16), child: Text( title, style: const TextStyle( color: AppColor.textPrimary, fontSize: 16, fontWeight: FontWeight.bold, ), ), ); } Widget _buildSummarySection(Map? summary) { if (summary == null) return const SizedBox(); return Row( children: [ _buildSummaryCard('إجمالي الإيرادات', '${summary['total_revenue_all'] ?? 0}', AppColor.info), const SizedBox(width: 12), _buildSummaryCard('صافي الربح', '${summary['total_profit_all'] ?? 0}', AppColor.success), ], ); } Widget _buildSummaryCard(String title, String value, Color color) { return Expanded( child: Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: AppColor.surface, borderRadius: BorderRadius.circular(20), border: Border.all(color: color.withOpacity(0.3)), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(title, style: const TextStyle( color: AppColor.textSecondary, fontSize: 12)), const SizedBox(height: 8), Text(value, style: TextStyle( color: color, fontSize: 22, fontWeight: FontWeight.bold)), ], ), ), ); } Widget _buildRevenueChart(List daily) { if (daily.isEmpty) return const Center(child: Text('لا توجد بيانات')); List revenueSpots = []; List profitSpots = []; for (int i = 0; i < daily.length; i++) { revenueSpots.add(FlSpot(i.toDouble(), double.tryParse(daily[i]['total_revenue'].toString()) ?? 0)); profitSpots.add(FlSpot(i.toDouble(), double.tryParse(daily[i]['company_profit'].toString()) ?? 0)); } return Container( height: 300, padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: AppColor.surface, borderRadius: BorderRadius.circular(24), ), child: LineChart( LineChartData( gridData: FlGridData( show: true, drawVerticalLine: false, getDrawingHorizontalLine: (v) => FlLine(color: AppColor.divider, strokeWidth: 1)), titlesData: FlTitlesData( show: true, rightTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)), topTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)), bottomTitles: AxisTitles( sideTitles: SideTitles( showTitles: true, getTitlesWidget: (val, meta) { if (val.toInt() % 7 == 0 && val.toInt() < daily.length) { return Text( daily[val.toInt()]['date'].toString().substring(8), style: const TextStyle( color: AppColor.textSecondary, fontSize: 10)); } return const SizedBox(); }, ), ), ), borderData: FlBorderData(show: false), lineBarsData: [ LineChartBarData( spots: revenueSpots, isCurved: true, color: AppColor.info, barWidth: 3, isStrokeCapRound: true, dotData: const FlDotData(show: false), belowBarData: BarAreaData( show: true, color: AppColor.info.withOpacity(0.1)), ), LineChartBarData( spots: profitSpots, isCurved: true, color: AppColor.success, barWidth: 3, isStrokeCapRound: true, dotData: const FlDotData(show: false), belowBarData: BarAreaData( show: true, color: AppColor.success.withOpacity(0.1)), ), ], ), ), ); } Widget _buildGrowthChart(Map data) { final passengers = data['passenger_daily'] as List? ?? []; final drivers = data['driver_daily'] as List? ?? []; if (passengers.isEmpty && drivers.isEmpty) return const Center(child: Text('لا توجد بيانات')); List barGroups = []; int maxLength = passengers.length > drivers.length ? passengers.length : drivers.length; for (int i = 0; i < maxLength; i++) { double pCount = i < passengers.length ? double.tryParse(passengers[i]['new_passengers'].toString()) ?? 0 : 0; double dCount = i < drivers.length ? double.tryParse(drivers[i]['new_drivers'].toString()) ?? 0 : 0; barGroups.add( BarChartGroupData( x: i, barRods: [ BarChartRodData( toY: pCount, color: AppColor.info, width: 8, borderRadius: BorderRadius.circular(4)), BarChartRodData( toY: dCount, color: AppColor.warning, width: 8, borderRadius: BorderRadius.circular(4)), ], ), ); } return Container( height: 250, padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: AppColor.surface, borderRadius: BorderRadius.circular(24), ), child: BarChart( BarChartData( barGroups: barGroups, borderData: FlBorderData(show: false), titlesData: FlTitlesData( show: true, rightTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)), topTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)), bottomTitles: AxisTitles( sideTitles: SideTitles( showTitles: true, getTitlesWidget: (val, meta) { if (val.toInt() % 7 == 0 && val.toInt() < passengers.length) { return Text( passengers[val.toInt()]['date'].toString().substring(8), style: const TextStyle( color: AppColor.textSecondary, fontSize: 10)); } return const SizedBox(); }, ), ), ), ), ), ); } Widget _buildTopDriversList(List drivers) { if (drivers.isEmpty) return const Center(child: Text('لا توجد بيانات')); return ListView.builder( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), itemCount: drivers.length, itemBuilder: (ctx, i) { final d = drivers[i]; return Container( margin: const EdgeInsets.only(bottom: 12), padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: AppColor.surface, borderRadius: BorderRadius.circular(16), ), child: Row( children: [ CircleAvatar( backgroundColor: AppColor.accent.withOpacity(0.1), child: Text('${i + 1}', style: const TextStyle( color: AppColor.accent, fontWeight: FontWeight.bold)), ), const SizedBox(width: 16), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('${d['first_name']} ${d['last_name']}', style: const TextStyle( color: AppColor.textPrimary, fontWeight: FontWeight.bold)), Text(d['phone'] ?? '', style: const TextStyle( color: AppColor.textSecondary, fontSize: 12)), ], ), ), Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ Text('${d['completed_rides']} رحلة', style: const TextStyle( color: AppColor.info, fontWeight: FontWeight.bold)), Text('${d['total_revenue']} ل.س', style: const TextStyle( color: AppColor.success, fontSize: 12, fontWeight: FontWeight.bold)), ], ), ], ), ); }, ); } }