import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import '../../core/services/phonepe_service.dart'; import '../../core/models/chit_group.dart'; import '../../core/models/group_member.dart'; /// PhonePe Payment Button Widget /// Displays a PhonePe-branded button that initiates payment class PhonePePaymentButton extends StatelessWidget { final ChitGroup group; final GroupMember member; final int month; final int year; final double amount; final VoidCallback? onSuccess; final VoidCallback? onFailure; const PhonePePaymentButton({ super.key, required this.group, required this.member, required this.month, required this.year, required this.amount, this.onSuccess, this.onFailure, }); @override Widget build(BuildContext context) { final phonePeService = Get.put(PhonePeService()); return Obx(() => ElevatedButton.icon( onPressed: phonePeService.isProcessing ? null : () => _initiatePayment(context, phonePeService), icon: phonePeService.isProcessing ? SizedBox( width: 20.w, height: 20.h, child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation(Colors.white), ), ) : Image.asset( 'assets/images/phonepe_logo.png', // Add PhonePe logo to assets width: 24.w, height: 24.h, errorBuilder: (context, error, stackTrace) { return Icon(Icons.payment, size: 24.w); }, ), label: Text( phonePeService.isProcessing ? 'Processing...' : 'Pay with PhonePe', style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w600, ), ), style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF5F259F), // PhonePe purple foregroundColor: Colors.white, padding: EdgeInsets.symmetric(horizontal: 24.w, vertical: 14.h), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12.r), ), elevation: 3, ), )); } Future _initiatePayment( BuildContext context, PhonePeService phonePeService, ) async { // Show confirmation dialog final confirm = await _showConfirmationDialog(context); if (confirm != true) return; // Initiate payment final result = await phonePeService.initiatePayment( groupId: group.id, userId: member.userId, month: month, year: year, amount: amount, userName: member.user?.fullName ?? 'Member', userMobile: member.user?.mobileNumber ?? '', ); if (result != null && result['status'] == 'success') { // Payment successful Get.snackbar( 'Payment Successful', 'Your payment has been completed successfully', backgroundColor: Colors.green.shade100, colorText: Colors.green.shade800, icon: Icon(Icons.check_circle, color: Colors.green.shade600), snackPosition: SnackPosition.TOP, duration: Duration(seconds: 4), ); onSuccess?.call(); } else { // Payment failed Get.snackbar( 'Payment Failed', phonePeService.error.isNotEmpty ? phonePeService.error : 'Payment could not be completed', backgroundColor: Colors.red.shade100, colorText: Colors.red.shade800, icon: Icon(Icons.error, color: Colors.red.shade600), snackPosition: SnackPosition.TOP, duration: Duration(seconds: 4), ); onFailure?.call(); } } Future _showConfirmationDialog(BuildContext context) { final monthNames = [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ]; return showDialog( context: context, builder: (context) => AlertDialog( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16.r), ), title: Row( children: [ Container( padding: EdgeInsets.all(8.w), decoration: BoxDecoration( color: Color(0xFF5F259F).withOpacity(0.1), borderRadius: BorderRadius.circular(8.r), ), child: Icon( Icons.payment, color: Color(0xFF5F259F), size: 24.w, ), ), SizedBox(width: 12.w), Expanded( child: Text( 'Confirm Payment', style: TextStyle( fontSize: 18.sp, fontWeight: FontWeight.w600, ), ), ), ], ), content: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'You are about to pay:', style: TextStyle( fontSize: 14.sp, color: Colors.grey.shade600, ), ), SizedBox(height: 16.h), _buildDetailRow('Group', group.name), _buildDetailRow('Month', '${monthNames[month - 1]} $year'), _buildDetailRow( 'Amount', '₹${amount.toStringAsFixed(2)}', isHighlight: true, ), SizedBox(height: 16.h), 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: Row( children: [ Icon( Icons.info_outline, size: 18.w, color: Colors.blue.shade700, ), SizedBox(width: 8.w), Expanded( child: Text( 'You will be redirected to PhonePe to complete the payment', style: TextStyle( fontSize: 12.sp, color: Colors.blue.shade700, ), ), ), ], ), ), ], ), actions: [ OutlinedButton( onPressed: () => Navigator.pop(context, false), style: OutlinedButton.styleFrom( padding: EdgeInsets.symmetric(horizontal: 20.w, vertical: 12.h), ), child: Text('Cancel', style: TextStyle(fontSize: 14.sp)), ), ElevatedButton( onPressed: () => Navigator.pop(context, true), style: ElevatedButton.styleFrom( backgroundColor: Color(0xFF5F259F), foregroundColor: Colors.white, padding: EdgeInsets.symmetric(horizontal: 20.w, vertical: 12.h), ), child: Text('Continue', style: TextStyle(fontSize: 14.sp)), ), ], ), ); } Widget _buildDetailRow(String label, String value, {bool isHighlight = false}) { 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: isHighlight ? FontWeight.w700 : FontWeight.w600, color: isHighlight ? Colors.green.shade700 : Colors.grey.shade900, ), ), ], ), ); } } /// Compact PhonePe Icon Button class PhonePeIconButton extends StatelessWidget { final VoidCallback onPressed; final bool isLoading; const PhonePeIconButton({ super.key, required this.onPressed, this.isLoading = false, }); @override Widget build(BuildContext context) { return IconButton( onPressed: isLoading ? null : onPressed, icon: isLoading ? SizedBox( width: 20.w, height: 20.h, child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation(Color(0xFF5F259F)), ), ) : Icon( Icons.payment, color: Color(0xFF5F259F), size: 24.w, ), tooltip: 'Pay with PhonePe', style: IconButton.styleFrom( backgroundColor: Color(0xFF5F259F).withOpacity(0.1), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.r), ), ), ); } }