import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:gen_service/Notifiers/TransactionsProvider.dart'; import 'package:razorpay_flutter/razorpay_flutter.dart'; import '../../Notifiers/PayAmountProvider.dart'; import '../../Utility/AppColors.dart'; import '../../Utility/CustomSnackbar.dart'; import '../../Utility/SharedpreferencesService.dart'; class BillDetailScreen extends StatefulWidget { final String sessionId; final String accId; final String billId; const BillDetailScreen({ super.key, required this.sessionId, required this.accId, required this.billId, }); @override State createState() => _BillDetailScreenState(); } class _BillDetailScreenState extends State { late Razorpay _razorpay; bool? isSuccess; var paymentMethod = ""; var User_contact = "0"; final prefs = SharedPreferencesService.instance; @override void initState() { super.initState(); _razorpay =Razorpay(); Future.microtask(() { final provider = Provider.of(context, listen: false); provider.fetchBillDetails(widget.accId, widget.sessionId, widget.billId); }); } //_________________________________________________________ void _handlePaymentSuccess(PaymentSuccessResponse response) { setState(() async { final provider = Provider.of(context, listen: false); await provider.getPaymentStatus( sessionId: widget.sessionId, empId: widget.accId, razorpayOrderId: response.orderId.toString() ); final data = provider.statusResponse; // Navigator.push( // context, // MaterialPageRoute(builder: (context) => PaymentSuccessFaillScreen( // total: "${data?.amount}", // date: "${data?.date}", // payMode: "UPI", // status: "Success", // )), // ); _razorpay.clear(); CustomSnackBar.showSuccess( context: context, message: data?.message ?? "Payment Success!", ); // buttonLoading = false; }); } void _handlePaymentError(PaymentFailureResponse response) { setState(() async { // Navigator.push( // context, // MaterialPageRoute(builder: (context) => PaymentSuccessFaillScreen( // total: "${data?.amount}", // date: "${data?.date}", // payMode: "UPI", // status: "Fail", // )), // ); CustomSnackBar.showError( context: context, message: "Payment failed, please try again.", ); }); _razorpay.clear(); CustomSnackBar.showError( context: context, message: "Payment failed, please try again.", ); } void _handleExternalWallet(ExternalWalletResponse response) { _razorpay.clear(); } Future payAmountFunction(String amount, String id) async { try { final provider = Provider.of(context, listen: false); await provider.payAmount( sessionId: widget.sessionId, empId: widget.accId, amount: amount, refType: "Payment", refId: id, ); final data = provider.payResponse; if (data != null) { if (data.error == "0") { openCheckout(data.orderId, data.razorKey!); } else { CustomSnackBar.showError( context: context, message: "${data.message}", ); debugPrint("❌ Could not Complete Payment: ${data.message}"); } } else { debugPrint("❌ No response received from PayAmount API"); } } catch (e) { debugPrint("❌ 'Error occurred: $e'"); } } //razorpay payments__________________________________________________________ void openCheckout(razorPayOrderId, String razorpayKey) async { final String? mobNumber = await prefs.getString("mob_number"); _razorpay.on(Razorpay.EVENT_PAYMENT_SUCCESS, _handlePaymentSuccess); _razorpay.on(Razorpay.EVENT_PAYMENT_ERROR, _handlePaymentError); _razorpay.on(Razorpay.EVENT_EXTERNAL_WALLET, _handleExternalWallet); // _buildCheckWidget(); Map options = { 'key': razorpayKey, 'amount': int.parse("${((0) * 100).round()}"), 'name': 'Gen Service', 'order_id': razorPayOrderId, 'description': "Bill", 'currency': 'INR', 'method': 'upi', 'prefill': {'contact': mobNumber, 'email': ''} }; // print(options); try { _razorpay.open(options); } catch (e, s) { // FirebaseCrashlytics.instance.log('Error occurred: $e'); // FirebaseCrashlytics.instance.recordError(e, s); debugPrint(e.toString()); } } void verifyPayment(String orderId) { isSuccess = true; setState(() { // toast(context, "Order Placed Successfully"); // print("Verify Payment"); }); _razorpay.clear(); } // void onError(CFErrorResponse errorResponse, String orderId) { // isSuccess = false; // setState(() { // // print(errorResponse.getMessage()); // // print("Error while making payment"); // }); // } @override Widget build(BuildContext context) { return Consumer( builder: (context, provider, _) { if (provider.isBillLoading) { return const Scaffold( body: Center(child: CircularProgressIndicator()), ); } final billResponse = provider.billDetail; final details = billResponse?.billDetails; final products = billResponse?.billProducts ?? []; if (details == null) { return const Scaffold( body: Center(child: Text("No Bill Details Found")), ); } return Scaffold( appBar: AppBar( backgroundColor: Colors.white, elevation: 0, title: const Text( "Bill Details", style: TextStyle( fontSize: 16, color: Colors.black87, fontFamily: "Poppins", fontWeight: FontWeight.w500, ), ), leading: IconButton( icon: const Icon(Icons.arrow_back_ios_new, color: Colors.black87), onPressed: () => Navigator.pop(context), ), ), backgroundColor: Colors.white, body: SingleChildScrollView( padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 14), child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ // Pending Icon Container( height: 70, width: 70, decoration: const BoxDecoration( color: Color(0xFFFFEBEB), shape: BoxShape.circle, ), child: const Icon( Icons.access_time_filled, color: Colors.redAccent, size: 55, ), ), const SizedBox(height: 14), // Amount Text( "₹${details.totalAmount}", style: const TextStyle( fontSize: 32, fontFamily: "Poppins", fontWeight: FontWeight.w600, color: Colors.black, ), ), const SizedBox(height: 6), const Text( "Pending Balance", style: TextStyle( fontSize: 15, fontFamily: "Poppins", color: Colors.black54, ), ), const SizedBox(height: 8), const SizedBox(height: 16), const Divider(thickness: 1, color: Color(0xFFE6E6E6)), _buildSectionTitle("Product Names"), // Product Names if (products.isNotEmpty) Column( children: products .map( (product) => Padding( padding: const EdgeInsets.symmetric(vertical: 2), child: _buildProductItem( product.partName.toString(), product.price.toString(), product.qty.toString(), product.totalPrice.toString() ) ), ) .toList(), ), const SizedBox(height: 16), const Divider(thickness: 1, color: Color(0xFFE6E6E6)), const SizedBox(height: 8), // Bill Details _buildSectionTitle("Bill Details"), _buildRow("Date", details.createdDate ?? "--"), _buildRow("Complaint ID", "#${details.compId ?? "--"}", highlight: true), _buildRow("Raise Against", details.raisedAgainst ?? "--"), const SizedBox(height: 14), const Divider(thickness: 1, color: Color(0xFFE6E6E6)), const SizedBox(height: 8), // Amount Details _buildSectionTitle("Amount Details"), _buildRow("Basic Amount", "₹${details.basicAmount ?? "0"}"), _buildRow("CGST Amount", "₹${details.cgst ?? "0"}"), _buildRow("SGST Amount", "₹${details.sgst ?? "0"}"), _buildRow("IGST Amount", "₹${details.igst ?? "0"}"), const SizedBox(height: 14), const Divider(thickness: 1, color: Color(0xFFE6E6E6)), const SizedBox(height: 8), // Bill Summary _buildSectionTitle("Bill Summary"), _buildRow("Bill Balance Amount", "₹${details.balancePaymentAmount ?? "0"}"), const SizedBox(height: 24), // Buttons Row Row( children: [ /// Download Bill Button Expanded( child: OutlinedButton.icon( onPressed: provider.isDownloading ? null : () { provider.downloadBill( context, widget.sessionId, widget.billId, widget.accId, ); }, icon: provider.isDownloading ? const SizedBox( width: 16, height: 16, child: CircularProgressIndicator( color: Colors.black87, strokeWidth: 2, ), ) : const Icon( Icons.download, size: 18, color: Colors.black87, ), label: Text( provider.isDownloading ? "Downloading..." : "Download Bill", style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w500, color: Colors.black87, ), ), style: OutlinedButton.styleFrom( side: const BorderSide(color: Colors.black54, width: 0.6), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(28), ), padding: const EdgeInsets.symmetric(vertical: 18), backgroundColor: Colors.transparent, ), ), ), const SizedBox(width: 12), /// Pay Now Button Expanded( child: ElevatedButton( onPressed: () { if(details.totalAmount == "0.00") { CustomSnackBar.showWarning( context: context, message: "Invalid amount or less then 1", ); }else{ Navigator.pop(context); // handle payment navigation payAmountFunction(details.totalAmount.toString(), details.id.toString()); } }, style: ElevatedButton.styleFrom( backgroundColor: AppColors.amountText, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(28), ), padding: const EdgeInsets.symmetric(vertical: 18), elevation: 0, // Keeps both buttons flat and uniform ), child: const Text( "Pay Now", style: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white, ), ), ), ), ], ), ], ), ), ); }, ); } // 🔹 Helper for Section Titles Widget _buildSectionTitle(String title) { return Align( alignment: Alignment.centerLeft, child: Text( title, style: const TextStyle( fontSize: 15, fontFamily: "Poppins", fontWeight: FontWeight.w600, color: Colors.black, ), ), ); } // 🔹 Helper for Key-Value Rows Widget _buildRow(String title, String value, {bool highlight = false}) { return Padding( padding: const EdgeInsets.symmetric(vertical: 6), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( title, style: const TextStyle( fontSize: 14, fontFamily: "Poppins", color: Colors.black54, ), ), Text( value, style: TextStyle( fontSize: 14, fontFamily: "Poppins", fontWeight: highlight ? FontWeight.w600 : FontWeight.w400, color: highlight ? const Color(0xFF2563EB) : Colors.black87, ), ), ], ), ); } Widget _buildProductItem( String partName, String price, String qty, String totalPrice) { return Padding( padding: const EdgeInsets.symmetric(vertical: 6), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ // Product name Expanded( flex: 3, child: Text( partName, maxLines: 2, style: const TextStyle( fontSize: 14, fontFamily: "Poppins", fontWeight: FontWeight.w500, color: Colors.black87, ), overflow: TextOverflow.ellipsis, ), ), // Qty × Price Expanded( flex: 1, child: Text( "$qty X ₹$price", textAlign: TextAlign.center, style: const TextStyle( fontSize: 14, fontFamily: "Poppins", color: Colors.black54, ), ), ), // Total Price Expanded( flex: 1, child: Text( "₹$totalPrice", textAlign: TextAlign.end, style: const TextStyle( fontSize: 14, fontFamily: "Poppins", fontWeight: FontWeight.bold, color: Colors.black87, ), ), ), ], ), ); } }