fixed draw issues
This commit is contained in:
parent
d01cc13edc
commit
1b1ead0c11
|
|
@ -146,6 +146,16 @@ const createMonthlyDraw = async (req, res) => {
|
||||||
message: 'Selected winner is not a member of this group'
|
message: 'Selected winner is not a member of this group'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if this member has already won
|
||||||
|
if (wonMemberIds.includes(winner_id)) {
|
||||||
|
return res.status(400).json({
|
||||||
|
success: false,
|
||||||
|
message: `${selectedWinner.User.full_name} has already won in a previous draw. Each member can only win once.`,
|
||||||
|
alreadyWon: true,
|
||||||
|
winnerName: selectedWinner.User.full_name
|
||||||
|
});
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Regular draw - provably fair random selection
|
// Regular draw - provably fair random selection
|
||||||
serverSeed = crypto.randomBytes(32).toString('hex');
|
serverSeed = crypto.randomBytes(32).toString('hex');
|
||||||
|
|
|
||||||
|
|
@ -83,12 +83,24 @@ class _AddPastDrawDialogState extends State<AddPastDrawDialog> {
|
||||||
title: 'Success',
|
title: 'Success',
|
||||||
);
|
);
|
||||||
Get.back(result: true);
|
Get.back(result: true);
|
||||||
|
} else {
|
||||||
|
// Check if it's a duplicate winner error
|
||||||
|
final isAlreadyWon = response['alreadyWon'] ?? false;
|
||||||
|
final winnerName = response['winnerName'] ?? '';
|
||||||
|
|
||||||
|
if (isAlreadyWon && winnerName.isNotEmpty) {
|
||||||
|
SnackbarUtil.showError(
|
||||||
|
'$winnerName has already won in a previous draw.\nEach member can only win once.',
|
||||||
|
title: 'Duplicate Winner',
|
||||||
|
duration: const Duration(seconds: 4),
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
SnackbarUtil.showError(
|
SnackbarUtil.showError(
|
||||||
response['message'] ?? 'Failed to add draw',
|
response['message'] ?? 'Failed to add draw',
|
||||||
title: 'Error',
|
title: 'Error',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
SnackbarUtil.showError('Error: ${e.toString()}');
|
SnackbarUtil.showError('Error: ${e.toString()}');
|
||||||
} finally {
|
} finally {
|
||||||
|
|
@ -223,6 +235,10 @@ class _AddPastDrawDialogState extends State<AddPastDrawDialog> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get list of members who have already won
|
||||||
|
final monthlyDraws = Get.find<ChitGroupService>().monthlyDraws;
|
||||||
|
final winnerIds = monthlyDraws.map((draw) => draw.winnerId).where((id) => id != null).toSet();
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
constraints: BoxConstraints(
|
constraints: BoxConstraints(
|
||||||
maxHeight: 300.h, // Limit height for scrolling
|
maxHeight: 300.h, // Limit height for scrolling
|
||||||
|
|
@ -237,10 +253,11 @@ class _AddPastDrawDialogState extends State<AddPastDrawDialog> {
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final member = members[index];
|
final member = members[index];
|
||||||
final isSelected = member.userId == _selectedMemberId;
|
final isSelected = member.userId == _selectedMemberId;
|
||||||
|
final hasAlreadyWon = winnerIds.contains(member.userId);
|
||||||
final isLast = index == members.length - 1;
|
final isLast = index == members.length - 1;
|
||||||
|
|
||||||
return InkWell(
|
return InkWell(
|
||||||
onTap: () {
|
onTap: hasAlreadyWon ? null : () {
|
||||||
setState(() {
|
setState(() {
|
||||||
_selectedMemberId = member.userId;
|
_selectedMemberId = member.userId;
|
||||||
});
|
});
|
||||||
|
|
@ -255,7 +272,9 @@ class _AddPastDrawDialogState extends State<AddPastDrawDialog> {
|
||||||
vertical: 14.h,
|
vertical: 14.h,
|
||||||
),
|
),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: isSelected ? Colors.green.shade50 : null,
|
color: hasAlreadyWon
|
||||||
|
? Colors.grey.shade100
|
||||||
|
: (isSelected ? Colors.green.shade50 : null),
|
||||||
border: !isLast ? Border(
|
border: !isLast ? Border(
|
||||||
bottom: BorderSide(color: Colors.grey.shade200),
|
bottom: BorderSide(color: Colors.grey.shade200),
|
||||||
) : null,
|
) : null,
|
||||||
|
|
@ -263,8 +282,12 @@ class _AddPastDrawDialogState extends State<AddPastDrawDialog> {
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Icon(
|
Icon(
|
||||||
isSelected ? Icons.radio_button_checked : Icons.radio_button_unchecked,
|
hasAlreadyWon
|
||||||
color: isSelected ? Colors.green.shade600 : Colors.grey.shade400,
|
? Icons.block
|
||||||
|
: (isSelected ? Icons.radio_button_checked : Icons.radio_button_unchecked),
|
||||||
|
color: hasAlreadyWon
|
||||||
|
? Colors.grey.shade400
|
||||||
|
: (isSelected ? Colors.green.shade600 : Colors.grey.shade400),
|
||||||
size: 24.w,
|
size: 24.w,
|
||||||
),
|
),
|
||||||
SizedBox(width: 12.w),
|
SizedBox(width: 12.w),
|
||||||
|
|
@ -272,20 +295,48 @@ class _AddPastDrawDialogState extends State<AddPastDrawDialog> {
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
member.user?.fullName ?? 'Unknown',
|
member.user?.fullName ?? 'Unknown',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 16.sp,
|
fontSize: 16.sp,
|
||||||
fontWeight: isSelected ? FontWeight.w600 : FontWeight.normal,
|
fontWeight: isSelected ? FontWeight.w600 : FontWeight.normal,
|
||||||
|
color: hasAlreadyWon ? Colors.grey.shade500 : null,
|
||||||
|
decoration: hasAlreadyWon ? TextDecoration.lineThrough : null,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
if (hasAlreadyWon) ...[
|
||||||
|
Container(
|
||||||
|
padding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 6.w,
|
||||||
|
vertical: 2.h,
|
||||||
|
),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.orange.shade100,
|
||||||
|
borderRadius: BorderRadius.circular(4.r),
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
'Already Won',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 10.sp,
|
||||||
|
color: Colors.orange.shade800,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
),
|
||||||
if (member.user?.mobileNumber != null) ...[
|
if (member.user?.mobileNumber != null) ...[
|
||||||
SizedBox(height: 2.h),
|
SizedBox(height: 2.h),
|
||||||
Text(
|
Text(
|
||||||
member.user!.mobileNumber,
|
member.user!.mobileNumber,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 13.sp,
|
fontSize: 13.sp,
|
||||||
color: Colors.grey.shade600,
|
color: hasAlreadyWon ? Colors.grey.shade400 : Colors.grey.shade600,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue