import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; import '../../../../common/theme/theme.dart'; import '../../../components/spacer/spacer.dart'; class ReportSales extends StatelessWidget { const ReportSales({super.key}); @override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.all(24), decoration: BoxDecoration( color: AppColor.surface, borderRadius: BorderRadius.circular(24), boxShadow: [ BoxShadow( color: AppColor.textSecondary.withOpacity(0.1), blurRadius: 20, offset: const Offset(0, 8), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Grafik Penjualan', style: AppStyle.xxl.copyWith( color: AppColor.textPrimary, fontWeight: FontWeight.bold, ), ), const SpaceHeight(4), Text( '7 hari terakhir', style: AppStyle.md.copyWith(color: AppColor.textSecondary), ), ], ), Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: AppColor.primary.withOpacity(0.1), borderRadius: BorderRadius.circular(12), ), child: const Icon( Icons.show_chart, color: AppColor.primary, size: 24, ), ), ], ), const SpaceHeight(20), // Chart Container Container( height: 280, padding: const EdgeInsets.all(16), decoration: BoxDecoration( gradient: LinearGradient( colors: [ AppColor.primary.withOpacity(0.05), AppColor.backgroundLight, ], begin: Alignment.topCenter, end: Alignment.bottomCenter, ), borderRadius: BorderRadius.circular(16), border: Border.all( color: AppColor.primary.withOpacity(0.1), width: 2, ), ), child: LineChart( LineChartData( gridData: FlGridData( show: true, drawHorizontalLine: true, drawVerticalLine: false, horizontalInterval: 500000, getDrawingHorizontalLine: (value) { return FlLine( color: AppColor.border.withOpacity(0.3), strokeWidth: 1, dashArray: [5, 5], ); }, ), titlesData: FlTitlesData( leftTitles: AxisTitles( sideTitles: SideTitles( showTitles: true, reservedSize: 60, getTitlesWidget: (value, meta) { return Text( '${(value / 1000000).toStringAsFixed(1)}M', style: AppStyle.sm.copyWith( color: AppColor.textSecondary, fontWeight: FontWeight.w500, ), ); }, ), ), bottomTitles: AxisTitles( sideTitles: SideTitles( showTitles: true, reservedSize: 32, getTitlesWidget: (value, meta) { const days = [ 'Sen', 'Sel', 'Rab', 'Kam', 'Jum', 'Sab', 'Min', ]; if (value.toInt() >= 0 && value.toInt() < days.length) { return Padding( padding: const EdgeInsets.only(top: 8), child: Text( days[value.toInt()], style: AppStyle.sm.copyWith( color: AppColor.textSecondary, fontWeight: FontWeight.w500, ), ), ); } return const Text(''); }, ), ), rightTitles: AxisTitles( sideTitles: SideTitles(showTitles: false), ), topTitles: AxisTitles( sideTitles: SideTitles(showTitles: false), ), ), borderData: FlBorderData(show: false), minX: 0, maxX: 6, minY: 0, maxY: 3000000, lineBarsData: [ // Main sales line LineChartBarData( spots: [ const FlSpot(0, 1800000), // Senin const FlSpot(1, 2200000), // Selasa const FlSpot(2, 1900000), // Rabu const FlSpot(3, 2600000), // Kamis const FlSpot(4, 2300000), // Jumat const FlSpot(5, 2800000), // Sabtu const FlSpot(6, 2500000), // Minggu ], isCurved: true, curveSmoothness: 0.35, gradient: LinearGradient( colors: [AppColor.primary, AppColor.primaryLight], begin: Alignment.centerLeft, end: Alignment.centerRight, ), barWidth: 4, isStrokeCapRound: true, belowBarData: BarAreaData( show: true, gradient: LinearGradient( colors: [ AppColor.primary.withOpacity(0.3), AppColor.primary.withOpacity(0.1), Colors.transparent, ], begin: Alignment.topCenter, end: Alignment.bottomCenter, ), ), dotData: FlDotData( show: true, getDotPainter: (spot, percent, barData, index) { return FlDotCirclePainter( radius: 6, color: AppColor.surface, strokeWidth: 3, strokeColor: AppColor.primary, ); }, ), ), // Secondary line for comparison LineChartBarData( spots: [ const FlSpot(0, 1500000), const FlSpot(1, 1800000), const FlSpot(2, 1600000), const FlSpot(3, 2100000), const FlSpot(4, 1900000), const FlSpot(5, 2300000), const FlSpot(6, 2100000), ], isCurved: true, curveSmoothness: 0.35, color: AppColor.success.withOpacity(0.7), barWidth: 3, isStrokeCapRound: true, dashArray: [8, 4], belowBarData: BarAreaData(show: false), dotData: FlDotData( show: true, getDotPainter: (spot, percent, barData, index) { return FlDotCirclePainter( radius: 4, color: AppColor.success, strokeWidth: 2, strokeColor: AppColor.surface, ); }, ), ), ], lineTouchData: LineTouchData( enabled: true, touchTooltipData: LineTouchTooltipData( tooltipPadding: const EdgeInsets.all(12), getTooltipItems: (List touchedBarSpots) { return touchedBarSpots.map((barSpot) { final flSpot = barSpot; const days = [ 'Senin', 'Selasa', 'Rabu', 'Kamis', 'Jumat', 'Sabtu', 'Minggu', ]; return LineTooltipItem( '${days[flSpot.x.toInt()]}\n', const TextStyle( color: AppColor.textWhite, fontWeight: FontWeight.bold, fontSize: 14, ), children: [ TextSpan( text: 'Rp ${(flSpot.y / 1000000).toStringAsFixed(1)}M', style: AppStyle.sm.copyWith( color: AppColor.textWhite, fontWeight: FontWeight.w500, ), ), ], ); }).toList(); }, ), touchCallback: (FlTouchEvent event, LineTouchResponse? touchResponse) { // Handle touch events here if needed }, handleBuiltInTouches: true, ), ), ), ), const SpaceHeight(16), // Legend Row( mainAxisAlignment: MainAxisAlignment.center, children: [ _buildLegendItem('Minggu Ini', AppColor.primary), const SpaceWidth(24), _buildLegendItem('Minggu Lalu', AppColor.success), ], ), ], ), ); } Widget _buildLegendItem(String label, Color color) { return Row( mainAxisSize: MainAxisSize.min, children: [ Container( width: 16, height: 3, decoration: BoxDecoration( color: color, borderRadius: BorderRadius.circular(2), ), ), const SpaceWidth(8), Text( label, style: AppStyle.sm.copyWith( color: AppColor.textSecondary, fontWeight: FontWeight.w500, ), ), ], ); } }