chitfund/luckychit/lib/interfaces/member/member_payment_dialog.dart

512 lines
18 KiB
Dart

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import '../../core/models/chit_group.dart';
import '../../core/models/group_member.dart';
import '../../shared/widgets/phonepe_payment_button.dart';
import '../../shared/widgets/upi_qr_payment_dialog.dart';
/// Member Payment Dialog
/// Allows members to pay their monthly installments using PhonePe
class MemberPaymentDialog extends StatefulWidget {
final ChitGroup group;
final GroupMember member;
final int? month;
final int? year;
const MemberPaymentDialog({
super.key,
required this.group,
required this.member,
this.month,
this.year,
});
@override
State<MemberPaymentDialog> createState() => _MemberPaymentDialogState();
}
class _MemberPaymentDialogState extends State<MemberPaymentDialog> {
late int _selectedMonth;
late int _selectedYear;
@override
void initState() {
super.initState();
_selectedMonth = widget.month ?? DateTime.now().month;
_selectedYear = widget.year ?? DateTime.now().year;
}
@override
Widget build(BuildContext context) {
final monthNames = [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December'
];
return Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16.r),
),
child: Container(
width: double.infinity,
constraints: BoxConstraints(
maxWidth: 450.w,
maxHeight: 0.8.sh,
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// Header
Container(
padding: EdgeInsets.all(20.w),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Color(0xFF5F259F),
Color(0xFF7E3BB4),
],
),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(16.r),
topRight: Radius.circular(16.r),
),
),
child: Row(
children: [
Container(
padding: EdgeInsets.all(8.w),
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.2),
borderRadius: BorderRadius.circular(8.r),
),
child: Icon(
Icons.payment,
color: Colors.white,
size: 24.w,
),
),
SizedBox(width: 12.w),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Pay Installment',
style: TextStyle(
fontSize: 18.sp,
fontWeight: FontWeight.w600,
color: Colors.white,
),
),
Text(
widget.group.name,
style: TextStyle(
fontSize: 14.sp,
color: Colors.white.withOpacity(0.9),
),
overflow: TextOverflow.ellipsis,
),
],
),
),
IconButton(
onPressed: () => Navigator.of(context).pop(),
icon: Icon(
Icons.close,
size: 24.w,
color: Colors.white,
),
),
],
),
),
// Content
Flexible(
child: SingleChildScrollView(
padding: EdgeInsets.all(20.w),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Payment Details Card
Container(
padding: EdgeInsets.all(16.w),
decoration: BoxDecoration(
color: Colors.grey.shade50,
borderRadius: BorderRadius.circular(12.r),
border: Border.all(color: Colors.grey.shade200),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Payment Details',
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w600,
color: Colors.grey.shade800,
),
),
SizedBox(height: 16.h),
_buildDetailRow(
'Member',
widget.member.user?.fullName ?? 'Unknown',
),
_buildDetailRow(
'Monthly Installment',
'${widget.group.monthlyInstallment.toStringAsFixed(2)}',
),
Divider(height: 24.h),
Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Month',
style: TextStyle(
fontSize: 14.sp,
fontWeight: FontWeight.w600,
color: Colors.grey.shade800,
),
),
SizedBox(height: 8.h),
_buildMonthDropdown(monthNames),
],
),
),
SizedBox(width: 12.w),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Year',
style: TextStyle(
fontSize: 14.sp,
fontWeight: FontWeight.w600,
color: Colors.grey.shade800,
),
),
SizedBox(height: 8.h),
_buildYearDropdown(),
],
),
),
],
),
],
),
),
SizedBox(height: 20.h),
// Amount to Pay
Container(
padding: EdgeInsets.all(16.w),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Colors.green.shade50,
Colors.green.shade100,
],
),
borderRadius: BorderRadius.circular(12.r),
border: Border.all(color: Colors.green.shade300),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Amount to Pay',
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w600,
color: Colors.green.shade900,
),
),
Text(
'${widget.group.monthlyInstallment.toStringAsFixed(2)}',
style: TextStyle(
fontSize: 24.sp,
fontWeight: FontWeight.w800,
color: Colors.green.shade700,
),
),
],
),
),
SizedBox(height: 20.h),
// Benefits Card
Container(
padding: EdgeInsets.all(12.w),
decoration: BoxDecoration(
color: Colors.blue.shade50,
borderRadius: BorderRadius.circular(8.r),
border: Border.all(color: Colors.blue.shade200),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(
Icons.security,
size: 18.w,
color: Colors.blue.shade700,
),
SizedBox(width: 8.w),
Text(
'Secure Payment',
style: TextStyle(
fontSize: 14.sp,
fontWeight: FontWeight.w600,
color: Colors.blue.shade900,
),
),
],
),
SizedBox(height: 8.h),
Text(
'• Instant payment confirmation\n'
'• Secure PhonePe payment gateway\n'
'• Automatic receipt generation',
style: TextStyle(
fontSize: 12.sp,
color: Colors.blue.shade700,
height: 1.5,
),
),
],
),
),
],
),
),
),
// Actions
Container(
padding: EdgeInsets.all(20.w),
decoration: BoxDecoration(
color: Colors.white,
border: Border(
top: BorderSide(color: Colors.grey.shade200),
),
),
child: Column(
children: [
// PhonePe Payment Button
SizedBox(
width: double.infinity,
child: PhonePePaymentButton(
group: widget.group,
member: widget.member,
month: _selectedMonth,
year: _selectedYear,
amount: widget.group.monthlyInstallment,
onSuccess: () {
Navigator.of(context).pop(true);
},
onFailure: () {
// Stay on dialog
},
),
),
SizedBox(height: 12.h),
// Alternative Payment Methods
Row(
children: [
Expanded(child: Divider(color: Colors.grey.shade300)),
Padding(
padding: EdgeInsets.symmetric(horizontal: 12.w),
child: Text(
'or',
style: TextStyle(
fontSize: 12.sp,
color: Colors.grey.shade600,
),
),
),
Expanded(child: Divider(color: Colors.grey.shade300)),
],
),
SizedBox(height: 12.h),
// QR Code Payment Button
SizedBox(
width: double.infinity,
child: OutlinedButton.icon(
onPressed: () {
Navigator.of(context).pop(); // Close current dialog
showDialog(
context: context,
builder: (context) => UPIQRPaymentDialog(
group: widget.group,
member: widget.member,
month: _selectedMonth,
year: _selectedYear,
),
);
},
icon: Icon(Icons.qr_code_2, size: 20.w, color: Colors.purple.shade600),
label: Text(
'Pay via QR Code / Any UPI App',
style: TextStyle(
fontSize: 14.sp,
fontWeight: FontWeight.w600,
color: Colors.purple.shade600,
),
),
style: OutlinedButton.styleFrom(
padding: EdgeInsets.symmetric(vertical: 12.h),
side: BorderSide(color: Colors.purple.shade600),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12.r),
),
),
),
),
SizedBox(height: 8.h),
// Contact Manager Button
SizedBox(
width: double.infinity,
child: TextButton.icon(
onPressed: () {
Get.snackbar(
'Contact Manager',
'Call your group manager for alternative payment methods',
backgroundColor: Colors.blue.shade50,
colorText: Colors.blue.shade900,
icon: Icon(Icons.phone, color: Colors.blue.shade600),
duration: Duration(seconds: 3),
);
},
icon: Icon(Icons.contact_phone, size: 18.w),
label: Text(
'Contact Manager',
style: TextStyle(
fontSize: 13.sp,
fontWeight: FontWeight.w500,
),
),
style: TextButton.styleFrom(
padding: EdgeInsets.symmetric(vertical: 8.h),
),
),
),
],
),
),
],
),
),
);
}
Widget _buildDetailRow(String label, String value) {
return Padding(
padding: EdgeInsets.symmetric(vertical: 6.h),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
label,
style: TextStyle(
fontSize: 14.sp,
color: Colors.grey.shade700,
),
),
Text(
value,
style: TextStyle(
fontSize: 14.sp,
fontWeight: FontWeight.w600,
color: Colors.grey.shade900,
),
),
],
),
);
}
Widget _buildMonthDropdown(List<String> monthNames) {
return DropdownButtonFormField<int>(
value: _selectedMonth,
decoration: InputDecoration(
contentPadding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 8.h),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.r),
borderSide: BorderSide(color: Colors.grey.shade300),
),
filled: true,
fillColor: Colors.white,
),
items: List.generate(12, (index) {
return DropdownMenuItem<int>(
value: index + 1,
child: Text(
monthNames[index],
style: TextStyle(fontSize: 14.sp),
),
);
}),
onChanged: (value) {
setState(() {
_selectedMonth = value!;
});
},
);
}
Widget _buildYearDropdown() {
final currentYear = DateTime.now().year;
final years = List.generate(5, (index) => currentYear - 2 + index);
return DropdownButtonFormField<int>(
value: _selectedYear,
decoration: InputDecoration(
contentPadding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 8.h),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.r),
borderSide: BorderSide(color: Colors.grey.shade300),
),
filled: true,
fillColor: Colors.white,
),
items: years.map((year) {
return DropdownMenuItem<int>(
value: year,
child: Text(
year.toString(),
style: TextStyle(fontSize: 14.sp),
),
);
}).toList(),
onChanged: (value) {
setState(() {
_selectedYear = value!;
});
},
);
}
}