import 'package:flutter/material.dart'; import 'report_controller.dart'; class ReportScreen extends StatefulWidget { const ReportScreen({super.key}); @override State createState() => _ReportScreenState(); } class _ReportScreenState extends State { late final ReportController _controller; @override void initState() { super.initState(); _controller = ReportController(); } @override Widget build(BuildContext context) { return AnimatedBuilder( animation: _controller, builder: (context, _) { return Scaffold( backgroundColor: const Color(0xFFF5F5F5), appBar: AppBar( backgroundColor: const Color(0xFFA89080), elevation: 0, leading: IconButton( icon: const Icon(Icons.arrow_back, color: Colors.white), onPressed: () => Navigator.pop(context), ), title: const Text( 'Laporan & Analitik', style: TextStyle( color: Colors.white, fontSize: 18, fontWeight: FontWeight.w700, ), ), centerTitle: false, ), body: SingleChildScrollView( child: Column( children: [ Container( color: Colors.white, padding: const EdgeInsets.all(16), child: Row( children: [ const Text( 'Period:', style: TextStyle( fontSize: 12, fontWeight: FontWeight.w600, color: Color(0xFF1F2937), ), ), const SizedBox(width: 8), Container( decoration: BoxDecoration( border: Border.all( color: const Color(0xFFE5E7EB), width: 1, ), borderRadius: BorderRadius.circular(8), ), padding: const EdgeInsets.symmetric(horizontal: 12), child: DropdownButtonHideUnderline( child: DropdownButton( value: _controller.selectedPeriod, items: _controller.periods .map( (period) => DropdownMenuItem( value: period, child: Text( _controller.capitalize(period), ), ), ) .toList(), onChanged: (value) { if (value != null) { _controller.setSelectedPeriod(value); } }, ), ), ), ], ), ), Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 2), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'Grafik Penjualan', style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xFF1F2937), ), ), const SizedBox(height: 2), Text( '6 ${_controller.selectedPeriod}', style: const TextStyle( fontSize: 12, color: Color(0xFF9CA3AF), ), ), ], ), const Icon( Icons.trending_up, color: Color(0xFF10B981), size: 20, ), ], ), const SizedBox(height: 20), Container( height: 200, decoration: BoxDecoration( color: const Color(0xFFF9FAFB), borderRadius: BorderRadius.circular(8), ), child: Center( child: Text( '[Area Chart: Sales Data by ${_controller.capitalize(_controller.selectedPeriod)}]', style: const TextStyle( color: Color(0xFFD1D5DB), fontSize: 12, ), ), ), ), const SizedBox(height: 12), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun'] .map( (month) => Text( month, style: const TextStyle( fontSize: 11, color: Color(0xFF9CA3AF), ), ), ) .toList(), ), ], ), ), const SizedBox(height: 16), Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 2), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'Statistik Penjualan', style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xFF1F2937), ), ), const SizedBox(height: 16), GridView.count( crossAxisCount: 2, shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), mainAxisSpacing: 12, crossAxisSpacing: 12, children: [ _buildStatItem( icon: Icons.shopping_bag, label: 'Total Stock In', value: '150', color: const Color(0xFF2563EB), ), _buildStatItem( icon: Icons.attach_money, label: 'Total Penjualan', value: 'Rp 2.5M', color: const Color(0xFF10B981), ), _buildStatItem( icon: Icons.trending_up, label: 'Rata-rata', value: 'Rp 16K', color: const Color(0xFFFB923C), ), _buildStatItem( icon: Icons.inventory_2, label: 'Produk Terjual', value: '8', color: const Color(0xFFA89080), ), ], ), ], ), ), const SizedBox(height: 16), Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 2), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'Top 5 Produk Terlaris', style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xFF1F2937), ), ), const SizedBox(height: 16), ..._controller.topProducts .asMap() .entries .map( (entry) => _buildTopProductItem( rank: entry.key + 1, name: entry.value.$1, quantity: entry.value.$2, ), ) .toList() .expand( (item) => [item, const SizedBox(height: 12)], ) .toList(), ], ), ), const SizedBox(height: 24), ], ), ), ], ), ), bottomNavigationBar: BottomNavigationBar( currentIndex: 4, type: BottomNavigationBarType.fixed, onTap: (index) { switch (index) { case 0: Navigator.popUntil(context, (route) => route.isFirst); break; case 1: Navigator.pushNamed(context, '/products'); break; case 2: Navigator.pushNamed(context, '/transaction'); break; case 3: Navigator.pushNamed(context, '/prediction'); break; case 5: Navigator.pushNamed(context, '/settings'); break; } }, items: const [ BottomNavigationBarItem( icon: Icon(Icons.home_outlined), label: 'Dashboard', ), BottomNavigationBarItem( icon: Icon(Icons.shopping_bag_outlined), label: 'Produk', ), BottomNavigationBarItem( icon: Icon(Icons.shopping_cart_outlined), label: 'Stock In', ), BottomNavigationBarItem( icon: Icon(Icons.trending_up_outlined), label: 'Prediksi', ), BottomNavigationBarItem( icon: Icon(Icons.description_outlined), label: 'Laporan', ), BottomNavigationBarItem( icon: Icon(Icons.settings_outlined), label: 'Pengaturan', ), ], ), ); }, ); } Widget _buildStatItem({ required IconData icon, required String label, required String value, required Color color, }) { return Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: color.withOpacity(0.1), borderRadius: BorderRadius.circular(12), border: Border.all(color: color.withOpacity(0.2), width: 1), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Container( width: 36, height: 36, decoration: BoxDecoration( color: color.withOpacity(0.15), borderRadius: BorderRadius.circular(8), ), child: Icon(icon, color: color, size: 18), ), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( value, style: TextStyle( fontSize: 14, fontWeight: FontWeight.w700, color: color, ), ), const SizedBox(height: 2), Text( label, style: const TextStyle( fontSize: 11, color: Color(0xFF9CA3AF), fontWeight: FontWeight.w500, ), ), ], ), ], ), ); } Widget _buildTopProductItem({ required int rank, required String name, required int quantity, }) { return Row( children: [ Container( width: 32, height: 32, decoration: BoxDecoration( color: const Color(0xFFA89080), borderRadius: BorderRadius.circular(8), ), child: Center( child: Text( rank.toString(), style: const TextStyle( color: Colors.white, fontSize: 12, fontWeight: FontWeight.w700, ), ), ), ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( name, style: const TextStyle( fontSize: 13, fontWeight: FontWeight.w600, color: Color(0xFF1F2937), ), ), Text( '$quantity unit', style: const TextStyle(fontSize: 11, color: Color(0xFF9CA3AF)), ), ], ), ), Container( padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4), decoration: BoxDecoration( color: const Color(0xFFA89080).withOpacity(0.1), borderRadius: BorderRadius.circular(6), ), child: Text( '${((quantity / 25) * 100).toStringAsFixed(0)}%', style: const TextStyle( fontSize: 11, fontWeight: FontWeight.w600, color: Color(0xFFA89080), ), ), ), ], ); } @override void dispose() { _controller.dispose(); super.dispose(); } }