chitfund/luckychit/lib/interfaces/manager/manager_dashboard.dart

590 lines
17 KiB
Dart

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 '../../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 '../../test_animated_draw.dart';
import '../../features/recordings/recordings_page.dart';
class ManagerDashboard extends StatelessWidget {
const ManagerDashboard({super.key});
@override
Widget build(BuildContext context) {
// Initialize services
Get.put(ChitGroupService());
if (!Get.isRegistered<NotificationService>()) {
Get.put(NotificationService());
}
// Load data on first build
WidgetsBinding.instance.addPostFrameCallback((_) {
ChitGroupService.to.loadManagerChitGroups();
NotificationService.to.loadUnreadCount();
});
return Scaffold(
backgroundColor: Colors.grey.shade50,
appBar: AppBar(
title: Text(
'Manager Dashboard',
style: TextStyle(
fontSize: 18.sp,
fontWeight: FontWeight.w600,
),
),
backgroundColor: Colors.green.shade600,
foregroundColor: Colors.white,
elevation: 2,
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: 'Notifications',
);
}),
IconButton(
icon: Icon(Icons.videocam, size: 24.w),
onPressed: () => Get.to(() => const RecordingsPage()),
tooltip: 'View Draw Recordings',
),
IconButton(
icon: Icon(Icons.logout, size: 24.w),
onPressed: () => _showLogoutDialog(context),
),
],
),
drawer: MediaQuery.of(context).size.width < 800 ? _buildDrawer() : null,
body: LayoutBuilder(
builder: (context, constraints) {
if (constraints.maxWidth < 800) {
// Mobile Layout
return _buildMobileLayout();
} else {
// Desktop Layout
return _buildDesktopLayout();
}
},
),
floatingActionButton: FloatingActionButton(
onPressed: () {
Get.to(() => const TestAnimatedDraw());
},
backgroundColor: Colors.purple.shade600,
foregroundColor: Colors.white,
child: const Icon(Icons.casino),
tooltip: 'Test Animated Draw',
),
);
}
Widget _buildMobileLayout() {
return Obx(() {
final service = ChitGroupService.to;
// Show skeleton loader while loading
if (service.isLoading.value) {
return const SkeletonDashboard();
}
// Show empty state if no groups
if (service.chitGroups.isEmpty) {
return EmptyStateWidget(
type: EmptyStateType.noGroups,
actionLabel: 'Create Your First Group',
onActionPressed: () => _showCreateGroupDialog(Get.context!),
);
}
// Show dashboard content
return RefreshIndicator(
onRefresh: () async {
await service.loadManagerChitGroups();
},
child: SingleChildScrollView(
padding: EdgeInsets.all(16.w),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Welcome Section
_buildWelcomeSection(),
SizedBox(height: 24.h),
// Statistics Cards - Mobile Grid
_buildMobileStatsGrid(),
SizedBox(height: 24.h),
// Quick Actions
_buildQuickActionsSection(),
SizedBox(height: 24.h),
// Recent Activities
_buildRecentActivitiesSection(),
],
),
),
);
});
}
Widget _buildDesktopLayout() {
return Row(
children: [
// Sidebar - Fixed width that scales better
Container(
width: 250.w,
decoration: BoxDecoration(
color: Colors.grey.shade100,
border: Border(
right: BorderSide(color: Colors.grey.shade300, width: 1),
),
),
child: _buildSidebar(),
),
// Main Content
Expanded(
child: SingleChildScrollView(
padding: EdgeInsets.all(20.w),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildWelcomeSection(),
SizedBox(height: 24.h),
_buildDesktopStatsGrid(),
SizedBox(height: 24.h),
_buildDesktopActivitiesAndActions(),
],
),
),
),
],
);
}
Widget _buildDrawer() {
return Drawer(
child: _buildSidebar(),
);
}
Widget _buildSidebar() {
return Column(
children: [
// User Info
Container(
padding: EdgeInsets.all(20.w),
child: Column(
children: [
CircleAvatar(
radius: 32.r,
backgroundColor: Colors.green.shade600,
child: Icon(
Icons.person,
size: 32.w,
color: Colors.white,
),
),
SizedBox(height: 12.h),
Obx(() => Text(
AuthService.to.currentUser.value?.fullName ?? 'Manager',
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w600,
),
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
maxLines: 2,
)),
SizedBox(height: 4.h),
Text(
'Chit Fund Manager',
style: TextStyle(
fontSize: 14.sp,
color: Colors.grey.shade600,
),
),
],
),
),
Divider(height: 1.h),
// Navigation Menu
Expanded(
child: ListView(
padding: EdgeInsets.zero,
children: [
_buildMenuItem(
icon: Icons.dashboard,
title: 'Dashboard',
isSelected: true,
onTap: () {},
),
_buildMenuItem(
icon: Icons.group,
title: 'My Chitfunds',
onTap: () => Get.to(() => const ChitGroupsPage()),
),
_buildMenuItem(
icon: Icons.people,
title: 'Members',
onTap: () {},
),
_buildMenuItem(
icon: Icons.payment,
title: 'Payments',
onTap: () {},
),
_buildMenuItem(
icon: Icons.casino,
title: 'Lottery Draws',
onTap: () {},
),
_buildMenuItem(
icon: Icons.analytics,
title: 'Reports',
onTap: () {},
),
_buildMenuItem(
icon: Icons.settings,
title: 'Settings',
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() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Welcome back!',
style: TextStyle(
fontSize: 20.sp,
fontWeight: FontWeight.bold,
color: Colors.grey.shade800,
),
),
SizedBox(height: 8.h),
Text(
'Here\'s what\'s happening with your chit funds today.',
style: TextStyle(
fontSize: 14.sp,
color: Colors.grey.shade600,
),
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
],
);
}
Widget _buildMobileStatsGrid() {
return Obx(() {
final groups = ChitGroupService.to.chitGroups;
final totalMembers = groups.fold<int>(0, (sum, group) => sum + (group.members?.length ?? 0));
return Row(
children: [
Expanded(
child: InteractiveStatsCard(
title: 'Total Chitfunds',
value: groups.length.toString(),
icon: Icons.account_balance_wallet,
color: Colors.green.shade600,
onTap: () => _navigateToGroups(),
),
),
SizedBox(width: 12.w),
Expanded(
child: InteractiveStatsCard(
title: 'Total Members',
value: totalMembers.toString(),
icon: Icons.people,
color: Colors.blue.shade600,
onTap: () => _navigateToMembers(),
),
),
],
);
});
}
Widget _buildDesktopStatsGrid() {
return Obx(() {
final groups = ChitGroupService.to.chitGroups;
final totalMembers = groups.fold<int>(0, (sum, group) => sum + (group.members?.length ?? 0));
return Row(
children: [
Expanded(
child: InteractiveStatsCard(
title: 'Total Chitfunds',
value: groups.length.toString(),
icon: Icons.account_balance_wallet,
color: Colors.green.shade600,
onTap: () => _navigateToGroups(),
),
),
SizedBox(width: 16.w),
Expanded(
child: InteractiveStatsCard(
title: 'Total Members',
value: totalMembers.toString(),
icon: Icons.people,
color: Colors.blue.shade600,
onTap: () => _navigateToMembers(),
),
),
],
);
});
}
Widget _buildQuickActionsSection() {
return Card(
child: Padding(
padding: EdgeInsets.all(20.w),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Quick Actions',
style: TextStyle(
fontSize: 18.sp,
fontWeight: FontWeight.w600,
),
),
SizedBox(height: 16.h),
Column(
children: [
QuickActionCard(
title: 'Create New Chitfund',
subtitle: 'Start a new chit fund group',
icon: Icons.group_add,
color: Colors.green.shade600,
onTap: () => _showCreateGroupDialog(Get.context!),
),
QuickActionCard(
title: 'Import Existing Chitfund',
subtitle: 'Add a group that already started',
icon: Icons.upload,
color: Colors.blue.shade600,
onTap: () => _showImportGroupDialog(Get.context!),
),
QuickActionCard(
title: 'View All Chitfunds',
subtitle: 'Manage your existing groups',
icon: Icons.list,
color: Colors.teal.shade600,
onTap: () => _navigateToGroups(),
),
QuickActionCard(
title: 'Manage Members',
subtitle: 'Add or remove members',
icon: Icons.people,
color: Colors.orange.shade600,
onTap: () => _navigateToMembers(),
),
QuickActionCard(
title: 'Payment Records',
subtitle: 'Track all transactions',
icon: Icons.payment,
color: Colors.purple.shade600,
onTap: () => _navigateToPayments(),
),
],
),
],
),
),
);
}
Widget _buildRecentActivitiesSection() {
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() {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Recent Activities
Expanded(
flex: 2,
child: _buildRecentActivitiesSection(),
),
SizedBox(width: 16.w),
// Quick Actions
Expanded(
flex: 1,
child: _buildQuickActionsSection(),
),
],
);
}
void _showLogoutDialog(BuildContext context) {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('Logout'),
content: const Text('Are you sure you want to logout?'),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: const Text('Cancel'),
),
ElevatedButton(
onPressed: () {
Navigator.of(context).pop();
AuthService.to.logout();
},
style: ElevatedButton.styleFrom(
backgroundColor: Colors.red,
foregroundColor: Colors.white,
),
child: const Text('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(
'Group imported! Now add members and backfill past data.',
title: 'Success',
);
}
});
}
void _navigateToGroups() {
Get.to(() => const ChitGroupsPage());
}
void _navigateToMembers() {
SnackbarUtil.showInfo(
'Members page will be implemented next',
title: 'Coming Soon',
);
}
void _navigateToPayments() {
SnackbarUtil.showInfo(
'Payments page will be implemented next',
title: 'Coming Soon',
);
}
}