import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; import 'package:line_icons/line_icons.dart'; import '../../../../common/theme/theme.dart'; class FinanceCashFlow extends StatelessWidget { const FinanceCashFlow({super.key}); @override Widget build(BuildContext context) { return Container( margin: const EdgeInsets.all(16), padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: AppColor.white, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: AppColor.textLight.withOpacity(0.1), spreadRadius: 1, blurRadius: 8, offset: const Offset(0, 2), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( children: [ Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( gradient: LinearGradient( colors: AppColor.primaryGradient, ), borderRadius: BorderRadius.circular(8), ), child: const Icon( LineIcons.areaChart, color: AppColor.white, size: 20, ), ), const SizedBox(width: 12), Text( 'Analisis Cash Flow', style: AppStyle.lg.copyWith(fontWeight: FontWeight.bold), ), ], ), IconButton( onPressed: () {}, icon: const Icon( LineIcons.alternateExternalLink, color: AppColor.primary, ), ), ], ), const SizedBox(height: 20), // Cash Flow Indicators Row( children: [ Expanded( child: _buildCashFlowIndicator( 'Cash In', 'Rp 28.5M', LineIcons.arrowUp, AppColor.success, ), ), const SizedBox(width: 16), Expanded( child: _buildCashFlowIndicator( 'Cash Out', 'Rp 21.2M', LineIcons.arrowDown, AppColor.error, ), ), const SizedBox(width: 16), Expanded( child: _buildCashFlowIndicator( 'Net Flow', 'Rp 7.3M', LineIcons.equals, AppColor.info, ), ), ], ), const SizedBox(height: 20), // FL Chart Implementation Container( height: 200, padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: AppColor.background, borderRadius: BorderRadius.circular(12), border: Border.all(color: AppColor.borderLight), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Grafik Cash Flow 7 Hari Terakhir', style: AppStyle.sm.copyWith( color: AppColor.textSecondary, fontWeight: FontWeight.w600, ), ), const SizedBox(height: 16), Expanded( child: LineChart( LineChartData( gridData: FlGridData( show: true, drawVerticalLine: false, horizontalInterval: 5000000, // 5M interval getDrawingHorizontalLine: (value) { return FlLine( color: AppColor.borderLight, strokeWidth: 1, ); }, ), titlesData: FlTitlesData( show: true, rightTitles: AxisTitles( sideTitles: SideTitles(showTitles: false), ), topTitles: AxisTitles( sideTitles: SideTitles(showTitles: false), ), bottomTitles: AxisTitles( sideTitles: SideTitles( showTitles: true, reservedSize: 30, interval: 1, getTitlesWidget: (double value, TitleMeta meta) { const style = TextStyle( color: AppColor.textSecondary, fontWeight: FontWeight.w500, fontSize: 10, ); Widget text; switch (value.toInt()) { case 0: text = const Text('Sen', style: style); break; case 1: text = const Text('Sel', style: style); break; case 2: text = const Text('Rab', style: style); break; case 3: text = const Text('Kam', style: style); break; case 4: text = const Text('Jum', style: style); break; case 5: text = const Text('Sab', style: style); break; case 6: text = const Text('Min', style: style); break; default: text = const Text('', style: style); break; } return SideTitleWidget(meta: meta, child: text); }, ), ), leftTitles: AxisTitles( sideTitles: SideTitles( showTitles: true, interval: 10000000, // 10M interval reservedSize: 42, getTitlesWidget: (double value, TitleMeta meta) { return Text( '${(value / 1000000).toInt()}M', style: const TextStyle( color: AppColor.textSecondary, fontWeight: FontWeight.w500, fontSize: 10, ), textAlign: TextAlign.left, ); }, ), ), ), borderData: FlBorderData( show: true, border: Border.all(color: AppColor.borderLight), ), minX: 0, maxX: 6, minY: -5000000, maxY: 30000000, lineBarsData: [ // Cash In Line LineChartBarData( spots: const [ FlSpot(0, 25000000), // Monday FlSpot(1, 22000000), // Tuesday FlSpot(2, 28000000), // Wednesday FlSpot(3, 24000000), // Thursday FlSpot(4, 30000000), // Friday FlSpot(5, 18000000), // Saturday FlSpot(6, 26000000), // Sunday ], isCurved: true, gradient: LinearGradient( colors: [ AppColor.success.withOpacity(0.8), AppColor.success, ], ), barWidth: 3, isStrokeCapRound: true, dotData: FlDotData( show: true, getDotPainter: (spot, percent, barData, index) { return FlDotCirclePainter( radius: 4, color: AppColor.success, strokeWidth: 2, strokeColor: AppColor.white, ); }, ), belowBarData: BarAreaData( show: true, gradient: LinearGradient( colors: [ AppColor.success.withOpacity(0.1), AppColor.success.withOpacity(0.0), ], begin: Alignment.topCenter, end: Alignment.bottomCenter, ), ), ), // Cash Out Line LineChartBarData( spots: const [ FlSpot(0, 20000000), // Monday FlSpot(1, 18000000), // Tuesday FlSpot(2, 23000000), // Wednesday FlSpot(3, 19000000), // Thursday FlSpot(4, 25000000), // Friday FlSpot(5, 15000000), // Saturday FlSpot(6, 21000000), // Sunday ], isCurved: true, gradient: LinearGradient( colors: [ AppColor.error.withOpacity(0.8), AppColor.error, ], ), barWidth: 3, isStrokeCapRound: true, dotData: FlDotData( show: true, getDotPainter: (spot, percent, barData, index) { return FlDotCirclePainter( radius: 4, color: AppColor.error, strokeWidth: 2, strokeColor: AppColor.white, ); }, ), ), // Net Flow Line LineChartBarData( spots: const [ FlSpot(0, 5000000), // Monday FlSpot(1, 4000000), // Tuesday FlSpot(2, 5000000), // Wednesday FlSpot(3, 5000000), // Thursday FlSpot(4, 5000000), // Friday FlSpot(5, 3000000), // Saturday FlSpot(6, 5000000), // Sunday ], isCurved: true, gradient: LinearGradient( colors: [ AppColor.info.withOpacity(0.8), AppColor.info, ], ), barWidth: 3, isStrokeCapRound: true, dotData: FlDotData( show: true, getDotPainter: (spot, percent, barData, index) { return FlDotCirclePainter( radius: 4, color: AppColor.info, strokeWidth: 2, strokeColor: AppColor.white, ); }, ), ), ], ), ), ), const SizedBox(height: 12), // Legend Row( mainAxisAlignment: MainAxisAlignment.center, children: [ _buildChartLegend('Cash In', AppColor.success), const SizedBox(width: 20), _buildChartLegend('Cash Out', AppColor.error), const SizedBox(width: 20), _buildChartLegend('Net Flow', AppColor.info), ], ), ], ), ), ], ), ); } Widget _buildChartLegend(String label, Color color) { return Row( mainAxisSize: MainAxisSize.min, children: [ Container( width: 12, height: 12, decoration: BoxDecoration(color: color, shape: BoxShape.circle), ), const SizedBox(width: 6), Text( label, style: AppStyle.xs.copyWith( color: AppColor.textSecondary, fontWeight: FontWeight.w500, ), ), ], ); } Widget _buildCashFlowIndicator( String label, String amount, IconData icon, Color color, ) { return Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: color.withOpacity(0.05), borderRadius: BorderRadius.circular(12), border: Border.all(color: color.withOpacity(0.2)), ), child: Column( children: [ Icon(icon, color: color, size: 20), const SizedBox(height: 8), Text( label, style: AppStyle.xs.copyWith(color: AppColor.textSecondary), ), const SizedBox(height: 4), Text( amount, style: AppStyle.md.copyWith( fontWeight: FontWeight.bold, color: color, ), ), ], ), ); } }