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/controller/dynamicMenu/dynamic_menu_controller.dart'; import 'package:marco/helpers/utils/mixins/ui_mixin.dart'; import 'package:marco/helpers/widgets/my_card.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(); final DynamicMenuController menuController = Get.put(DynamicMenuController()); 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: Obx(() { if (menuController.isLoading.value) { return const Center(child: CircularProgressIndicator()); } if (menuController.hasError.value || menuController.menuItems.isEmpty) { return const Center( child: Text( "Failed to load menus. Please try again later.", style: TextStyle(color: Colors.red), ), ); } // ✅ Only allow finance cards if "Expense" menu is allowed final isExpenseAllowed = menuController.isMenuAllowed("Expense"); if (!isExpenseAllowed) { return const Center( child: Text( "You don’t have access to the Finance section.", style: TextStyle(color: Colors.grey), ), ); } return SingleChildScrollView( padding: const EdgeInsets.all(16), child: _buildFinanceModulesCompact(), ); }), ), ); } // --- Finance Modules (Compact Dashboard-style) --- Widget _buildFinanceModulesCompact() { final stats = [ _FinanceStatItem(LucideIcons.badge_dollar_sign, "Expense", contentTheme.info, "/dashboard/expense-main-page"), _FinanceStatItem(LucideIcons.receipt_text, "Payment Request", contentTheme.primary, "/dashboard/payment-request"), _FinanceStatItem(LucideIcons.wallet, "Advance Payment", contentTheme.warning, "/dashboard/advance-payment"), ]; final projectSelected = projectController.selectedProject != null; return LayoutBuilder(builder: (context, constraints) { int crossAxisCount = (constraints.maxWidth ~/ 80).clamp(2, 4); double cardWidth = (constraints.maxWidth - (crossAxisCount - 1) * 6) / crossAxisCount; return Wrap( spacing: 6, runSpacing: 6, alignment: WrapAlignment.end, children: stats .map((stat) => _buildFinanceModuleCard(stat, projectSelected, cardWidth)) .toList(), ); }); } Widget _buildFinanceModuleCard( _FinanceStatItem stat, bool isProjectSelected, double width) { final bool isEnabled = isProjectSelected; return Opacity( opacity: isEnabled ? 1.0 : 0.4, child: IgnorePointer( ignoring: !isEnabled, child: InkWell( onTap: () => _onCardTap(stat, isEnabled), borderRadius: BorderRadius.circular(5), child: MyCard.bordered( width: width, height: 60, paddingAll: 4, borderRadiusAll: 5, border: Border.all(color: Colors.grey.withOpacity(0.15)), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( padding: const EdgeInsets.all(4), decoration: BoxDecoration( color: stat.color.withOpacity(0.1), borderRadius: BorderRadius.circular(4), ), child: Icon( stat.icon, size: 16, color: stat.color, ), ), MySpacing.height(4), Flexible( child: Text( stat.title, textAlign: TextAlign.center, style: const TextStyle( fontSize: 10, overflow: TextOverflow.ellipsis, ), maxLines: 2, softWrap: true, ), ), ], ), ), ), ), ); } void _onCardTap(_FinanceStatItem statItem, bool isEnabled) { if (!isEnabled) { Get.defaultDialog( title: "No Project Selected", middleText: "Please select a project before accessing this section.", confirm: ElevatedButton( onPressed: () => Get.back(), child: const Text("OK"), ), ); } else { Get.toNamed(statItem.route); } } } class _FinanceStatItem { final IconData icon; final String title; final Color color; final String route; _FinanceStatItem(this.icon, this.title, this.color, this.route); }