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

411 lines
14 KiB
Dart

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import '../../core/services/chit_group_service.dart';
import '../../core/models/chit_group.dart';
import '../../core/design_system/app_components/app_scaffold.dart';
import '../../core/design_system/app_components/state_view.dart';
import '../../shared/widgets/empty_state_widget.dart';
import 'create_group_dialog.dart';
import 'import_existing_group_dialog.dart';
import 'member_selection_dialog.dart';
import 'group_details_page.dart';
import 'combined_draw_dialog.dart';
import '../../l10n/l10n_x.dart';
class ChitGroupsPage extends StatelessWidget {
const ChitGroupsPage({super.key});
@override
Widget build(BuildContext context) {
final l = context.l10n;
final scheme = Theme.of(context).colorScheme;
return AppScaffold(
title: l.pageMyChitfunds,
actions: [
PopupMenuButton<String>(
icon: Icon(Icons.add, size: 24.w),
onSelected: (value) {
if (value == 'create') {
_showCreateGroupDialog(context);
} else if (value == 'import') {
_showImportGroupDialog(context);
}
},
itemBuilder: (context) => [
PopupMenuItem(
value: 'create',
child: Row(
children: [
Icon(Icons.add_circle, color: scheme.primary, size: 20.w),
SizedBox(width: 12.w),
Text(l.createNewGroupMenu),
],
),
),
PopupMenuItem(
value: 'import',
child: Row(
children: [
Icon(Icons.upload, color: scheme.secondary, size: 20.w),
SizedBox(width: 12.w),
Text(l.importExistingGroupMenu),
],
),
),
],
),
],
body: Obx(() {
final service = ChitGroupService.to;
return StateView(
isLoading: service.isLoading.value,
isEmpty: service.chitGroups.isEmpty,
emptyType: EmptyStateType.noGroups,
onRetry: () => service.loadManagerChitGroups(),
child: RefreshIndicator(
onRefresh: () => service.loadManagerChitGroups(),
child: ListView.builder(
padding: EdgeInsets.all(12.w),
itemCount: service.chitGroups.length,
itemBuilder: (context, index) {
final group = service.chitGroups[index];
return _buildGroupCard(context, group);
},
),
),
);
}),
);
}
Widget _buildGroupCard(BuildContext context, ChitGroup group) {
return Card(
margin: EdgeInsets.only(bottom: 12.h),
elevation: 2,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12.r),
),
child: InkWell(
onTap: () => _showGroupDetails(context, group),
borderRadius: BorderRadius.circular(12.r),
child: Padding(
padding: EdgeInsets.all(16.w),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Text(
group.name,
style: TextStyle(
fontSize: 18.sp,
fontWeight: FontWeight.w600,
color: Colors.grey.shade800,
),
),
),
_buildStatusChip(group.status),
],
),
SizedBox(height: 16.h),
// Group details - Mobile optimized layout
Column(
children: [
Row(
children: [
Expanded(
child: _buildDetailItem(
'Total Value',
'${group.totalValue.toStringAsFixed(0)}',
Icons.currency_rupee,
),
),
SizedBox(width: 8.w),
Expanded(
child: _buildDetailItem(
'Monthly',
'${group.monthlyInstallment.toStringAsFixed(0)}',
Icons.payment,
),
),
],
),
SizedBox(height: 12.h),
Row(
children: [
Expanded(
child: _buildDetailItem(
'Members',
'${group.currentMemberCount}/${group.maxMembers}',
Icons.people,
),
),
SizedBox(width: 8.w),
Expanded(
child: _buildDetailItem(
'Duration',
'${group.durationMonths} months',
Icons.calendar_today,
),
),
],
),
],
),
SizedBox(height: 16.h),
// Action buttons - Mobile optimized
if (group.isForming) ...[
Column(
children: [
SizedBox(
width: double.infinity,
child: ElevatedButton.icon(
onPressed: () => _showAddMemberDialog(context, group),
icon: Icon(Icons.person_add, size: 18.w),
label: Text(
'Add Member',
style: TextStyle(fontSize: 14.sp, fontWeight: FontWeight.w500),
),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blue.shade600,
foregroundColor: Colors.white,
padding: EdgeInsets.symmetric(vertical: 12.h),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.r),
),
),
),
),
SizedBox(height: 8.h),
SizedBox(
width: double.infinity,
child: ElevatedButton.icon(
onPressed: group.canStart ? () => _startGroup(group) : null,
icon: Icon(Icons.play_arrow, size: 18.w),
label: Text(
'Start Group',
style: TextStyle(fontSize: 14.sp, fontWeight: FontWeight.w500),
),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.green.shade600,
foregroundColor: Colors.white,
padding: EdgeInsets.symmetric(vertical: 12.h),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.r),
),
),
),
),
],
),
] else if (group.isActive) ...[
Column(
children: [
SizedBox(
width: double.infinity,
child: ElevatedButton.icon(
onPressed: () => _showGroupDetails(context, group),
icon: Icon(Icons.visibility, size: 18.w),
label: Text(
'View Details',
style: TextStyle(fontSize: 14.sp, fontWeight: FontWeight.w500),
),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.orange.shade600,
foregroundColor: Colors.white,
padding: EdgeInsets.symmetric(vertical: 12.h),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.r),
),
),
),
),
SizedBox(height: 8.h),
SizedBox(
width: double.infinity,
child: ElevatedButton.icon(
onPressed: () => _conductDraw(context, group),
icon: Icon(Icons.casino, size: 18.w),
label: Text(
'Conduct Draw',
style: TextStyle(fontSize: 14.sp, fontWeight: FontWeight.w500),
),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.purple.shade600,
foregroundColor: Colors.white,
padding: EdgeInsets.symmetric(vertical: 12.h),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.r),
),
),
),
),
],
),
] else ...[
SizedBox(
width: double.infinity,
child: ElevatedButton.icon(
onPressed: () => _showGroupDetails(context, group),
icon: Icon(Icons.visibility, size: 18.w),
label: Text(
'View Details',
style: TextStyle(fontSize: 14.sp, fontWeight: FontWeight.w500),
),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.grey.shade600,
foregroundColor: Colors.white,
padding: EdgeInsets.symmetric(vertical: 12.h),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.r),
),
),
),
),
],
],
),
),
),
);
}
Widget _buildStatusChip(String status) {
Color color;
String label;
switch (status) {
case 'forming':
color = Colors.orange;
label = 'Forming';
break;
case 'active':
color = Colors.green;
label = 'Active';
break;
case 'completed':
color = Colors.grey;
label = 'Completed';
break;
default:
color = Colors.grey;
label = status;
}
return Container(
padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 6.h),
decoration: BoxDecoration(
color: color.withOpacity(0.1),
borderRadius: BorderRadius.circular(16.r),
border: Border.all(color: color, width: 1.5),
),
child: Text(
label,
style: TextStyle(
color: color,
fontSize: 14.sp,
fontWeight: FontWeight.w600,
),
),
);
}
Widget _buildDetailItem(String label, String value, IconData icon) {
return Container(
padding: EdgeInsets.all(12.w),
decoration: BoxDecoration(
color: Colors.grey.shade50,
borderRadius: BorderRadius.circular(8.r),
border: Border.all(color: Colors.grey.shade200),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(icon, size: 18.w, color: Colors.grey.shade600),
SizedBox(width: 6.w),
Expanded(
child: Text(
label,
style: TextStyle(
fontSize: 14.sp,
color: Colors.grey.shade600,
fontWeight: FontWeight.w500,
),
overflow: TextOverflow.ellipsis,
),
),
],
),
SizedBox(height: 8.h),
Text(
value,
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w600,
color: Colors.grey.shade800,
),
overflow: TextOverflow.ellipsis,
),
],
),
);
}
void _showCreateGroupDialog(BuildContext context) {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => const CreateGroupDialog(),
);
}
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();
}
});
}
void _showAddMemberDialog(BuildContext context, ChitGroup group) {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => MemberSelectionDialog(group: group),
);
}
void _showGroupDetails(BuildContext context, ChitGroup group) {
Get.to(() => GroupDetailsPage(group: group));
}
void _startGroup(ChitGroup group) async {
final success = await ChitGroupService.to.startChitGroup(group.id);
if (success) {
Get.snackbar('Success', 'Chit group started successfully');
}
}
void _conductDraw(BuildContext context, ChitGroup group) {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => CombinedDrawDialog(group: group),
);
}
}