import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import '../api/KasbonApi.dart'; const _bg = Color(0xFFF9FAFB); const _bg1 = Color(0xFFFFFFFF); const _bg2 = Color(0xFFF3F4F6); const _green = Color(0xFF10B981); const _greenDim = Color(0x1A10B981); const _cyan = Color(0xFF06B6D4); const _cyanDim = Color(0x1A06B6D4); const _amber = Color(0xFFF59E0B); const _amberDim = Color(0x1AF59E0B); const _rose = Color(0xFFEF4444); const _roseDim = Color(0x1AEF4444); const _t1 = Color(0xFF111827); const _t2 = Color(0xFF6B7280); const _t3 = Color(0xFF9CA3AF); const _line2 = Color(0xFFE5E7EB); class KasbonRiwayatScreen extends StatefulWidget { const KasbonRiwayatScreen({super.key}); @override State createState() => _KasbonRiwayatScreenState(); } class _KasbonRiwayatScreenState extends State { final KasbonApi _apiService = KasbonApi(); List _riwayat = []; Map? _statistik; bool _isLoading = false; @override void initState() { super.initState(); _fetchData(); } Future _fetchData() async { setState(() => _isLoading = true); try { final results = await Future.wait([ _apiService.getRiwayat(), _fetchStatistik(), ]); if (mounted) { setState(() { final resRiwayat = results[0] as Map?; final resStat = results[1] as Map?; if (resRiwayat != null && resRiwayat['success'] == true) { // Laravel paginate structure final rawData = resRiwayat['data']; if (rawData is Map && rawData.containsKey('data')) { _riwayat = rawData['data'] ?? []; } else { _riwayat = rawData ?? []; } } if (resStat != null) { _statistik = resStat; } _isLoading = false; }); } } catch (e) { if (mounted) setState(() => _isLoading = false); } } Future?> _fetchStatistik() async { // API Route: /kasbon/statistik try { final response = await _apiService.getStatistik(); // Use the new method return response['data']; } catch (e) { return null; } } String _formatCurrency(dynamic amount) { final formatter = NumberFormat.currency(locale: 'id_ID', symbol: 'Rp ', decimalDigits: 0); return formatter.format(amount ?? 0); } @override Widget build(BuildContext context) { return _isLoading ? const Center(child: CircularProgressIndicator(color: _rose)) : RefreshIndicator( onRefresh: _fetchData, color: _rose, backgroundColor: _bg1, child: CustomScrollView( slivers: [ // STATS SECTION SliverToBoxAdapter( child: Padding( padding: const EdgeInsets.all(20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text('RINGKASAN KASBON', style: TextStyle(color: _t3, fontSize: 10, fontWeight: FontWeight.w900, letterSpacing: 1.5)), const SizedBox(height: 12), _buildTotalKasbonCard(), ], ), ), ), // LIST SECTION SliverToBoxAdapter( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 20), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text('RIWAYAT PINJAMAN', style: TextStyle(color: _t3, fontSize: 10, fontWeight: FontWeight.w900, letterSpacing: 1.5)), Text('${_riwayat.length} Transaksi', style: const TextStyle(color: _t2, fontSize: 10)), ], ), ), ), const SliverPadding(padding: EdgeInsets.only(top: 12)), _riwayat.isEmpty ? SliverToBoxAdapter(child: _buildEmptyState()) : SliverList( delegate: SliverChildBuilderDelegate( (context, i) => Padding( padding: const EdgeInsets.symmetric(horizontal: 20), child: _buildKasbonCard(_riwayat[i]), ), childCount: _riwayat.length, ), ), const SliverPadding(padding: EdgeInsets.only(bottom: 32)), ], ), ); } Widget _buildTotalKasbonCard() { final outstanding = _statistik?['total_hutang'] ?? _statistik?['outstanding_kasbon'] ?? 0; return Container( padding: const EdgeInsets.all(24), decoration: BoxDecoration( gradient: LinearGradient( colors: [_rose, _rose.withOpacity(0.7)], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(20), boxShadow: [ BoxShadow(color: _rose.withOpacity(0.3), blurRadius: 15, offset: const Offset(0, 8)), ], ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text('Sisa Hutang Kasbon', style: TextStyle(color: Colors.white70, fontSize: 12, fontWeight: FontWeight.w500)), const SizedBox(height: 6), Text(_formatCurrency(outstanding), style: const TextStyle(color: Colors.white, fontSize: 24, fontWeight: FontWeight.w900, letterSpacing: -0.5)), ], ), Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Colors.white.withOpacity(0.2), borderRadius: BorderRadius.circular(14), ), child: const Icon(Icons.money_off_rounded, color: Colors.white, size: 28), ), ], ), ); } Widget _buildEmptyState() { return Padding( padding: const EdgeInsets.only(top: 40), child: Center( child: Column( children: [ Icon(Icons.history_rounded, size: 48, color: _t3), const SizedBox(height: 12), const Text('Belum ada riwayat kasbon', style: TextStyle(color: _t2, fontSize: 13)), ], ), ), ); } Widget _buildKasbonCard(dynamic item) { final bool isLunas = item['status'] == 'Lunas'; return Container( margin: const EdgeInsets.only(bottom: 12), padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: _bg1, borderRadius: BorderRadius.circular(16), border: Border.all(color: _line2), ), child: Row( children: [ Container( width: 44, height: 44, decoration: BoxDecoration( color: isLunas ? _greenDim : _roseDim, borderRadius: BorderRadius.circular(12), border: Border.all(color: (isLunas ? _green : _rose).withOpacity(0.3)), ), child: Icon(isLunas ? Icons.check_circle_rounded : Icons.pending_rounded, color: isLunas ? _green : _rose, size: 20), ), const SizedBox(width: 14), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(_formatCurrency(item['nominal']), style: const TextStyle(color: _t1, fontWeight: FontWeight.w800, fontSize: 15)), const SizedBox(height: 4), Text(item['keperluan'] ?? 'Tanpa keterangan', style: const TextStyle(color: _t2, fontSize: 12), maxLines: 1, overflow: TextOverflow.ellipsis), const SizedBox(height: 4), Text(item['tanggal'] ?? '-', style: const TextStyle(color: _t3, fontSize: 10)), ], ), ), Container( padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4), decoration: BoxDecoration( color: isLunas ? _greenDim : _roseDim, borderRadius: BorderRadius.circular(8), border: Border.all(color: (isLunas ? _green : _rose).withOpacity(0.25)), ), child: Text(item['status_label']?.toUpperCase() ?? '-', style: TextStyle( color: isLunas ? _green : _rose, fontSize: 10, fontWeight: FontWeight.w900, letterSpacing: 0.5)), ), ], ), ); } }