import 'package:flutter/material.dart'; import 'package:flutter_lucide/flutter_lucide.dart'; import 'package:get/get.dart'; import 'package:marco/controller/project_controller.dart'; import 'package:marco/helpers/utils/mixins/ui_mixin.dart'; import 'package:marco/helpers/widgets/my_spacing.dart'; import 'package:marco/helpers/widgets/my_text.dart'; class FinanceScreen extends StatefulWidget { const FinanceScreen({super.key}); @override State createState() => _FinanceScreenState(); } class _FinanceScreenState extends State with UIMixin, TickerProviderStateMixin { final projectController = Get.find(); late AnimationController _animationController; late Animation _fadeAnimation; @override void initState() { super.initState(); _animationController = AnimationController( duration: const Duration(milliseconds: 800), vsync: this, ); _fadeAnimation = CurvedAnimation( parent: _animationController, curve: Curves.easeInOut, ); _animationController.forward(); } @override void dispose() { _animationController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: const Color(0xFFF8F9FA), appBar: PreferredSize( preferredSize: const Size.fromHeight(72), child: AppBar( backgroundColor: const Color(0xFFF5F5F5), elevation: 0.5, automaticallyImplyLeading: false, titleSpacing: 0, title: Padding( padding: MySpacing.xy(16, 0), child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ IconButton( icon: const Icon(Icons.arrow_back_ios_new, color: Colors.black, size: 20), onPressed: () => Get.offNamed('/dashboard'), ), MySpacing.width(8), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ MyText.titleLarge( 'Finance', fontWeight: 700, color: Colors.black, ), MySpacing.height(2), GetBuilder( builder: (projectController) { final projectName = projectController.selectedProject?.name ?? 'Select Project'; return Row( children: [ const Icon(Icons.work_outline, size: 14, color: Colors.grey), MySpacing.width(4), Expanded( child: MyText.bodySmall( projectName, fontWeight: 600, overflow: TextOverflow.ellipsis, color: Colors.grey[700], ), ), ], ); }, ), ], ), ), ], ), ), ), ), body: FadeTransition( opacity: _fadeAnimation, child: SingleChildScrollView( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildWelcomeSection(), MySpacing.height(24), _buildFinanceModules(), MySpacing.height(24), _buildQuickStatsSection(), ], ), ), ), ); } Widget _buildWelcomeSection() { final projectSelected = projectController.selectedProject != null; return Container( width: double.infinity, padding: const EdgeInsets.all(20), decoration: BoxDecoration( gradient: LinearGradient( colors: [ contentTheme.primary.withValues(alpha: 0.1), contentTheme.info.withValues(alpha: 0.05), ], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(16), border: Border.all( color: contentTheme.primary.withValues(alpha: 0.2), width: 1, ), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Container( padding: const EdgeInsets.all(10), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: contentTheme.primary.withValues(alpha: 0.1), blurRadius: 8, offset: const Offset(0, 2), ), ], ), child: Icon( LucideIcons.landmark, color: contentTheme.primary, size: 24, ), ), MySpacing.width(12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ MyText.titleMedium( 'Financial Management', fontWeight: 700, color: Colors.black87, ), MySpacing.height(2), MyText.bodySmall( projectSelected ? 'Manage your project finances' : 'Select a project to get started', color: Colors.grey[600], ), ], ), ), ], ), if (!projectSelected) ...[ MySpacing.height(12), Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), decoration: BoxDecoration( color: Colors.orange.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(8), border: Border.all(color: Colors.orange.withValues(alpha: 0.3)), ), child: Row( children: [ Icon( LucideIcons.badge_alert, size: 16, color: Colors.orange[700], ), MySpacing.width(8), Expanded( child: MyText.bodySmall( 'Please select a project to access finance modules', color: Colors.orange[700], fontWeight: 500, ), ), ], ), ), ], ], ), ); } Widget _buildFinanceModules() { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ MyText.titleMedium( 'Finance Modules', fontWeight: 700, color: Colors.black87, ), MySpacing.height(4), MyText.bodySmall( 'Select a module to manage', color: Colors.grey[600], ), MySpacing.height(16), _buildModuleGrid(), ], ); } Widget _buildModuleGrid() { final stats = [ _FinanceStatItem( LucideIcons.badge_dollar_sign, "Expense", "Track and manage expenses", contentTheme.info, "/dashboard/expense-main-page", ), _FinanceStatItem( LucideIcons.receipt_text, "Payment Request", "Submit payment requests", contentTheme.primary, "/dashboard/payment-request", ), _FinanceStatItem( LucideIcons.wallet, "Advance Payment", "Manage advance payments", contentTheme.warning, "/dashboard/advance-payment", ), ]; final projectSelected = projectController.selectedProject != null; return GridView.builder( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, crossAxisSpacing: 12, mainAxisSpacing: 12, childAspectRatio: 1.1, ), itemCount: stats.length, itemBuilder: (context, index) { return _buildModernFinanceCard( stats[index], projectSelected, index, ); }, ); } Widget _buildModernFinanceCard( _FinanceStatItem statItem, bool isProjectSelected, int index, ) { final bool isEnabled = isProjectSelected; return TweenAnimationBuilder( duration: Duration(milliseconds: 400 + (index * 100)), tween: Tween(begin: 0.0, end: 1.0), curve: Curves.easeOutCubic, builder: (context, value, child) { return Transform.scale( scale: value, child: Opacity( opacity: isEnabled ? 1.0 : 0.5, child: Material( color: Colors.transparent, child: InkWell( onTap: () => _onCardTap(statItem, isEnabled), borderRadius: BorderRadius.circular(16), child: Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), border: Border.all( color: isEnabled ? statItem.color.withValues(alpha: 0.2) : Colors.grey.withValues(alpha: 0.2), width: 1.5, ), ), child: Stack( children: [ // Content Padding( padding: const EdgeInsets.all(16), child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( padding: const EdgeInsets.all(12), child: Icon( statItem.icon, size: 28, color: statItem.color, ), ), MySpacing.height(12), MyText.titleSmall( statItem.title, fontWeight: 700, color: Colors.black87, maxLines: 1, overflow: TextOverflow.ellipsis, ), MySpacing.height(4), if (isEnabled) Row( children: [ MyText.bodySmall( 'View Details', color: statItem.color, fontWeight: 600, fontSize: 11, ), MySpacing.width(4), Icon( LucideIcons.arrow_right, size: 14, color: statItem.color, ), ], ), ], ), ), // Lock icon for disabled state if (!isEnabled) Positioned( top: 12, right: 12, child: Container( padding: const EdgeInsets.all(4), decoration: BoxDecoration( color: Colors.grey[200], borderRadius: BorderRadius.circular(6), ), child: Icon( LucideIcons.lock, size: 14, color: Colors.grey[600], ), ), ), ], ), ), ), ), ), ); }, ); } Widget _buildQuickStatsSection() { final projectSelected = projectController.selectedProject != null; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ MyText.titleMedium( 'Quick Stats', fontWeight: 700, color: Colors.black87, ), MySpacing.height(4), MyText.bodySmall( 'Overview of your finances', color: Colors.grey[600], ), MySpacing.height(16), _buildStatsRow(projectSelected), ], ); } Widget _buildStatsRow(bool projectSelected) { final stats = [ _QuickStat( icon: LucideIcons.trending_up, label: 'Total Expenses', value: projectSelected ? '₹0' : '--', color: contentTheme.danger, ), _QuickStat( icon: LucideIcons.clock, label: 'Pending', value: projectSelected ? '0' : '--', color: contentTheme.warning, ), ]; return Row( children: stats .map((stat) => Expanded( child: Padding( padding: const EdgeInsets.only(right: 8), child: _buildStatCard(stat, projectSelected), ), )) .toList(), ); } Widget _buildStatCard(_QuickStat stat, bool isEnabled) { return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), border: Border.all( color: stat.color.withValues(alpha: 0.2), width: 1, ), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: stat.color.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(8), ), child: Icon( stat.icon, size: 20, color: stat.color, ), ), MySpacing.height(12), MyText.bodySmall( stat.label, color: Colors.grey[600], fontSize: 11, ), MySpacing.height(4), MyText.titleLarge( stat.value, fontWeight: 700, color: isEnabled ? Colors.black87 : Colors.grey[400], ), ], ), ); } void _onCardTap(_FinanceStatItem statItem, bool isEnabled) { if (!isEnabled) { Get.dialog( Dialog( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), ), child: Padding( padding: const EdgeInsets.all(24), child: Column( mainAxisSize: MainAxisSize.min, children: [ Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.orange.withValues(alpha: 0.1), shape: BoxShape.circle, ), child: Icon( LucideIcons.badge_alert, color: Colors.orange[700], size: 32, ), ), MySpacing.height(16), MyText.titleMedium( "No Project Selected", fontWeight: 700, color: Colors.black87, textAlign: TextAlign.center, ), MySpacing.height(8), MyText.bodyMedium( "Please select a project before accessing this section.", color: Colors.grey[600], textAlign: TextAlign.center, ), MySpacing.height(24), SizedBox( width: double.infinity, child: ElevatedButton( onPressed: () => Get.back(), style: ElevatedButton.styleFrom( backgroundColor: contentTheme.primary, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 12), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), elevation: 0, ), child: MyText.bodyMedium( "OK", color: Colors.white, fontWeight: 600, ), ), ), ], ), ), ), ); return; } Get.toNamed(statItem.route); } } class _FinanceStatItem { final IconData icon; final String title; final String subtitle; final Color color; final String route; _FinanceStatItem( this.icon, this.title, this.subtitle, this.color, this.route, ); } class _QuickStat { final IconData icon; final String label; final String value; final Color color; _QuickStat({ required this.icon, required this.label, required this.value, required this.color, }); }