import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import '../../core/services/auth_service.dart'; import '../../core/services/chit_group_service.dart'; import '../../core/services/notification_service.dart'; import '../../core/utils/snackbar_util.dart'; import '../../shared/widgets/skeleton_loader.dart'; import '../../shared/widgets/empty_state_widget.dart'; import '../../shared/widgets/interactive_card.dart'; import '../../shared/widgets/notification_badge.dart'; import '../../core/design_system/app_components/state_view.dart'; import '../../core/design_system/app_text.dart'; import '../../features/settings/settings_page.dart'; import '../../features/notifications/notification_center_page.dart'; import 'chit_groups_page.dart'; import 'create_group_page.dart'; import 'import_existing_group_dialog.dart'; import 'members_page.dart'; import '../../test_animated_draw.dart'; import '../../features/recordings/recordings_page.dart'; import '../../l10n/app_localizations.dart'; import '../../l10n/l10n_x.dart'; class ManagerDashboard extends StatelessWidget { const ManagerDashboard({super.key}); @override Widget build(BuildContext context) { final l = context.l10n; final scheme = Theme.of(context).colorScheme; // Initialize services Get.put(ChitGroupService()); if (!Get.isRegistered()) { Get.put(NotificationService()); } // Load data on first build WidgetsBinding.instance.addPostFrameCallback((_) { ChitGroupService.to.loadManagerChitGroups(); NotificationService.to.loadUnreadCount(); }); return Scaffold( appBar: AppBar( title: Text(l.dashboardTitle, style: AppText.title(context)), actions: [ // Notifications with badge Obx(() { final unreadCount = NotificationService.to.unreadCount.value; return IconButton( icon: NotificationBadge( count: unreadCount, child: Icon(Icons.notifications_rounded, size: 24.w), ), onPressed: () => Get.to(() => const NotificationCenterPage()), tooltip: l.notificationsTooltip, ); }), IconButton( icon: Icon(Icons.videocam, size: 24.w), onPressed: () => Get.to(() => const RecordingsPage()), tooltip: l.recordingsTooltip, ), IconButton( icon: Icon(Icons.logout, size: 24.w), onPressed: () => _showLogoutDialog(context), ), ], ), drawer: MediaQuery.of(context).size.width < 800 ? _buildDrawer(context) : null, body: LayoutBuilder( builder: (layoutContext, constraints) { if (constraints.maxWidth < 800) { return _buildMobileLayout(layoutContext); } return _buildDesktopLayout(layoutContext); }, ), floatingActionButton: FloatingActionButton( onPressed: () { Get.to(() => const TestAnimatedDraw()); }, backgroundColor: scheme.tertiary, foregroundColor: scheme.onTertiary, child: const Icon(Icons.casino), tooltip: l.testDrawTooltip, ), ); } Widget _buildMobileLayout(BuildContext context) { return Obx(() { final service = ChitGroupService.to; return StateView( isLoading: service.isLoading.value, isEmpty: service.chitGroups.isEmpty, emptyType: EmptyStateType.noGroups, onRetry: () => service.loadManagerChitGroups(), loading: const SkeletonDashboard(), child: RefreshIndicator( onRefresh: () async { await service.loadManagerChitGroups(); }, child: SingleChildScrollView( padding: EdgeInsets.all(16.w), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildWelcomeSection(context), SizedBox(height: 24.h), _buildRecentActivitiesSection(context), SizedBox(height: 24.h), _buildQuickActionsSection(context), ], ), ), ), ); }); } Widget _buildDesktopLayout(BuildContext context) { final scheme = Theme.of(context).colorScheme; return Row( children: [ Container( width: 250.w, decoration: BoxDecoration( color: scheme.surfaceContainerHighest, border: Border( right: BorderSide(color: scheme.outlineVariant, width: 1), ), ), child: _buildSidebar(context), ), Expanded( child: SingleChildScrollView( padding: EdgeInsets.all(20.w), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildWelcomeSection(context), SizedBox(height: 24.h), _buildDesktopActivitiesAndActions(context), ], ), ), ), ], ); } Widget _buildDrawer(BuildContext context) { return Drawer( child: _buildSidebar(context), ); } Widget _buildSidebar(BuildContext context) { final scheme = Theme.of(context).colorScheme; return Column( children: [ Container( padding: EdgeInsets.all(20.w), child: Column( children: [ CircleAvatar( radius: 32.r, backgroundColor: scheme.primary, child: Icon( Icons.person, size: 32.w, color: scheme.onPrimary, ), ), SizedBox(height: 12.h), Obx(() => Text( AuthService.to.currentUser.value?.fullName ?? context.l10n.managerFallbackName, style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w600, color: scheme.onSurface, ), textAlign: TextAlign.center, overflow: TextOverflow.ellipsis, maxLines: 2, )), SizedBox(height: 4.h), Text( context.l10n.chitFundManagerRole, style: TextStyle( fontSize: 14.sp, color: scheme.onSurfaceVariant, ), ), ], ), ), Divider(height: 1.h), // Navigation Menu Expanded( child: ListView( padding: EdgeInsets.zero, children: [ _buildMenuItem( icon: Icons.dashboard, title: context.l10n.menuDashboard, isSelected: true, onTap: () {}, ), _buildMenuItem( icon: Icons.group, title: context.l10n.menuMyChitfunds, onTap: () => Get.to(() => const ChitGroupsPage()), ), _buildMenuItem( icon: Icons.people, title: context.l10n.menuMembers, onTap: () {}, ), _buildMenuItem( icon: Icons.payment, title: context.l10n.menuPayments, onTap: () {}, ), _buildMenuItem( icon: Icons.casino, title: context.l10n.menuLotteryDraws, onTap: () {}, ), _buildMenuItem( icon: Icons.analytics, title: context.l10n.menuReports, onTap: () {}, ), _buildMenuItem( icon: Icons.settings, title: context.l10n.settingsTitle, onTap: () => Get.to(() => const SettingsPage()), ), ], ), ), ], ); } Widget _buildMenuItem({ required IconData icon, required String title, bool isSelected = false, required VoidCallback onTap, }) { return ListTile( leading: SizedBox( width: 24.w, child: Icon( icon, color: isSelected ? Colors.green.shade600 : Colors.grey.shade600, ), ), title: Text( title, style: TextStyle( color: isSelected ? Colors.green.shade600 : Colors.grey.shade800, fontWeight: isSelected ? FontWeight.w600 : FontWeight.normal, fontSize: 14.sp, ), overflow: TextOverflow.ellipsis, ), selected: isSelected, selectedTileColor: Colors.green.shade50, onTap: onTap, ); } Widget _buildWelcomeSection(BuildContext context) { final l = context.l10n; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( l.welcomeBackTitle, style: AppText.headline(context), ), SizedBox(height: 8.h), Text( l.welcomeBackSubtitle, style: AppText.bodyMuted(context), maxLines: 2, overflow: TextOverflow.ellipsis, ), ], ); } Widget _buildMobileStatsGrid() { // Stats cards removed as per user request return SizedBox.shrink(); } Widget _buildDesktopStatsGrid() { // Stats cards removed as per user request return SizedBox.shrink(); } Widget _buildQuickActionsSection(BuildContext context) { final l = context.l10n; return Card( child: Padding( padding: EdgeInsets.all(20.w), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( l.quickActionsTitle, style: TextStyle( fontSize: 18.sp, fontWeight: FontWeight.w600, ), ), SizedBox(height: 16.h), Column( children: [ QuickActionCard( title: l.qaCreateChitfundTitle, subtitle: l.qaCreateChitfundSubtitle, icon: Icons.group_add, color: Colors.green.shade600, onTap: () => _showCreateGroupDialog(context), ), QuickActionCard( title: l.qaImportChitfundTitle, subtitle: l.qaImportChitfundSubtitle, icon: Icons.upload, color: Colors.blue.shade600, onTap: () => _showImportGroupDialog(context), ), QuickActionCard( title: l.qaViewAllChitfundsTitle, subtitle: l.qaViewAllChitfundsSubtitle, icon: Icons.list, color: Colors.teal.shade600, onTap: () => _navigateToGroups(), ), QuickActionCard( title: l.qaManageMembersTitle, subtitle: l.qaManageMembersSubtitle, icon: Icons.people, color: Colors.orange.shade600, onTap: () => _navigateToMembers(), ), QuickActionCard( title: l.qaPaymentRecordsTitle, subtitle: l.qaPaymentRecordsSubtitle, icon: Icons.payment, color: Colors.purple.shade600, onTap: () => _navigateToPayments(), ), ], ), ], ), ), ); } Widget _buildRecentActivitiesSection(BuildContext context) { final l = context.l10n; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( l.sectionMyChitfunds, style: TextStyle( fontSize: 18.sp, fontWeight: FontWeight.w600, ), ), TextButton.icon( onPressed: _navigateToGroups, icon: Icon(Icons.arrow_forward, size: 18.w), label: Text(l.viewAll, style: TextStyle(fontSize: 14.sp)), ), ], ), SizedBox(height: 12.h), Obx(() { final groups = ChitGroupService.to.chitGroups.take(3).toList(); if (groups.isEmpty) { return Card( child: Padding( padding: EdgeInsets.all(32.w), child: Center( child: Text( l.noChitFundsYetShort, style: TextStyle( fontSize: 14.sp, color: Colors.grey.shade600, ), ), ), ), ); } return Column( children: groups.map((group) => Padding( padding: EdgeInsets.only(bottom: 12.h), child: _buildGroupQuickCard(context, group), )).toList(), ); }), ], ); } Widget _buildGroupQuickCard(BuildContext context, dynamic group) { final l = context.l10n; final status = group.status ?? 'forming'; final statusColor = _getStatusColor(status); return InteractiveCard( onTap: () => Get.to(() => const ChitGroupsPage()), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Expanded( child: Text( group.name ?? 'Unnamed', style: TextStyle( fontSize: 18.sp, fontWeight: FontWeight.w700, color: Colors.grey.shade800, ), maxLines: 1, overflow: TextOverflow.ellipsis, ), ), Container( padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 6.h), decoration: BoxDecoration( color: statusColor.withOpacity(0.1), borderRadius: BorderRadius.circular(16.r), border: Border.all(color: statusColor, width: 1.5), ), child: Text( _getStatusText(l, status), style: TextStyle( fontSize: 12.sp, fontWeight: FontWeight.w600, color: statusColor, ), ), ), ], ), SizedBox(height: 12.h), Row( children: [ _buildQuickInfo( Icons.people, '${group.currentMemberCount}/${group.maxMembers}', Colors.blue.shade600, ), SizedBox(width: 16.w), _buildQuickInfo( Icons.currency_rupee, '₹${_formatAmount(group.monthlyInstallment)}', Colors.green.shade600, ), SizedBox(width: 16.w), _buildQuickInfo( Icons.calendar_month, '${group.durationMonths}m', Colors.orange.shade600, ), ], ), // Quick action buttons if (status.toLowerCase() == 'active') ...[ SizedBox(height: 16.h), Row( children: [ Expanded( child: ElevatedButton.icon( onPressed: () { // Record payment - simplified flow Get.to(() => const ChitGroupsPage()); }, icon: Icon(Icons.payment, size: 18.w), label: Text(l.actionRecord, style: TextStyle(fontSize: 13.sp)), style: ElevatedButton.styleFrom( backgroundColor: Colors.green.shade600, foregroundColor: Colors.white, padding: EdgeInsets.symmetric(vertical: 10.h), ), ), ), SizedBox(width: 8.w), Expanded( child: ElevatedButton.icon( onPressed: () { // Conduct draw Get.to(() => const ChitGroupsPage()); }, icon: Icon(Icons.casino, size: 18.w), label: Text(l.actionDraw, style: TextStyle(fontSize: 13.sp)), style: ElevatedButton.styleFrom( backgroundColor: Colors.purple.shade600, foregroundColor: Colors.white, padding: EdgeInsets.symmetric(vertical: 10.h), ), ), ), SizedBox(width: 8.w), Expanded( child: OutlinedButton( onPressed: () { Get.to(() => const ChitGroupsPage()); }, style: OutlinedButton.styleFrom( padding: EdgeInsets.symmetric(vertical: 10.h), side: BorderSide(color: Colors.grey.shade400), ), child: Text(l.actionView, style: TextStyle(fontSize: 13.sp)), ), ), ], ), ] else ...[ SizedBox(height: 16.h), SizedBox( width: double.infinity, child: OutlinedButton.icon( onPressed: () { Get.to(() => const ChitGroupsPage()); }, icon: Icon(Icons.arrow_forward, size: 18.w), label: Text(l.actionManageGroup, style: TextStyle(fontSize: 14.sp)), style: OutlinedButton.styleFrom( padding: EdgeInsets.symmetric(vertical: 12.h), ), ), ), ], ], ), ); } Widget _buildQuickInfo(IconData icon, String text, Color color) { return Row( mainAxisSize: MainAxisSize.min, children: [ Icon(icon, size: 16.w, color: color), SizedBox(width: 4.w), Text( text, style: TextStyle( fontSize: 13.sp, fontWeight: FontWeight.w600, color: Colors.grey.shade700, ), ), ], ); } Color _getStatusColor(String status) { switch (status.toLowerCase()) { case 'active': return Colors.green.shade600; case 'forming': return Colors.orange.shade600; case 'completed': return Colors.blue.shade600; default: return Colors.grey.shade600; } } String _getStatusText(AppLocalizations l, String status) { switch (status.toLowerCase()) { case 'active': return l.groupStatusActive; case 'forming': return l.groupStatusForming; case 'completed': return l.groupStatusCompleted; default: return status; } } String _formatAmount(dynamic amount) { if (amount == null) return '0'; final value = double.tryParse(amount.toString()) ?? 0.0; if (value >= 100000) { return '${(value / 100000).toStringAsFixed(1)}L'; } else if (value >= 1000) { return '${(value / 1000).toStringAsFixed(0)}K'; } return value.toStringAsFixed(0); } Widget _buildOldRecentActivitiesSection() { return Card( child: Padding( padding: EdgeInsets.all(20.w), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Recent Activities', style: TextStyle( fontSize: 18.sp, fontWeight: FontWeight.w600, ), ), SizedBox(height: 12.h), ActivityCard( title: 'New Member Joined', description: 'A new member joined Group A', time: '2h ago', icon: Icons.person_add, color: Colors.green.shade600, ), ActivityCard( title: 'Payment Received', description: 'Payment received from John Doe', time: '4h ago', icon: Icons.payment, color: Colors.blue.shade600, ), ActivityCard( title: 'Lottery Draw Completed', description: 'Draw completed for Group B', time: '1d ago', icon: Icons.casino, color: Colors.orange.shade600, ), ActivityCard( title: 'Group Created', description: 'New group "Group C" created', time: '2d ago', icon: Icons.group_add, color: Colors.purple.shade600, ), ], ), ), ); } Widget _buildDesktopActivitiesAndActions(BuildContext context) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // My Chitfunds (full width on desktop) _buildRecentActivitiesSection(context), SizedBox(height: 24.h), // Quick Actions (below chitfunds) _buildQuickActionsSection(context), ], ); } void _showLogoutDialog(BuildContext context) { showDialog( context: context, builder: (dialogContext) { final l = dialogContext.l10n; return AlertDialog( title: Text(l.logoutConfirmTitle), content: Text(l.logoutConfirmMessage), actions: [ TextButton( onPressed: () => Navigator.of(dialogContext).pop(), child: Text(l.cancel), ), ElevatedButton( onPressed: () { Navigator.of(dialogContext).pop(); AuthService.to.logout(); }, style: ElevatedButton.styleFrom( backgroundColor: Colors.red, foregroundColor: Colors.white, ), child: Text(l.logout), ), ], ); }, ); } void _showCreateGroupDialog(BuildContext context) { Get.to(() => const CreateGroupPage()); } void _showImportGroupDialog(BuildContext context) { showDialog( context: context, barrierDismissible: false, builder: (context) => const ImportExistingGroupDialog(), ).then((result) { if (result == true) { // Reload groups after successful import ChitGroupService.to.loadManagerChitGroups(); SnackbarUtil.showSuccess( L10nSvc.of().groupImportedMessage, title: L10nSvc.of().groupImportedTitle, ); } }); } void _navigateToGroups() { Get.to(() => const ChitGroupsPage()); } void _navigateToMembers() { Get.to(() => const MembersPage()); } void _navigateToPayments() { SnackbarUtil.showInfo( L10nSvc.of().paymentsPageComingSoon, title: L10nSvc.of().comingSoonTitle, ); } }