import 'package:flutter/material.dart'; import 'package:bookatanker/common/settings.dart'; import 'package:bookatanker/supplier/payment_example2.dart'; import 'package:bookatanker/supplier/payment_screen.dart'; import 'package:razorpay_flutter/razorpay_flutter.dart'; class PlanDetails extends StatefulWidget { var supplierDetails; PlanDetails({this.supplierDetails}); @override State createState() => _PlanDetailsState(); } class _PlanDetailsState extends State { bool isExpanded = false; double actualPrice = 0.0; int quantity = 0; double deliveryCharges = 0.0; double subtotal = 0.0; double cgst = 0.0; double sgst = 0.0; double total = 0.0; double platformFee = 0.0; double totalTaxes = 0.0; double advance = 0.0; double balance = 0.0; late Razorpay _razorpay; @override void initState() { super.initState(); actualPrice = double.tryParse(widget.supplierDetails.quotedAmount ?? '0') ?? 0; quantity = int.tryParse(widget.supplierDetails.quantity ?? '0') ?? 0; //deliveryCharges = double.tryParse(widget.supplierDetails.bookingCharges ?? '0') ?? 0;; platformFee = 11; subtotal = actualPrice * quantity; cgst = subtotal * 0.09; sgst = subtotal * 0.09; totalTaxes = cgst + sgst; total = subtotal + cgst + sgst + deliveryCharges + platformFee; advance = deliveryCharges; //balance = total - advance; _razorpay = Razorpay(); _razorpay.on(Razorpay.EVENT_PAYMENT_SUCCESS, (PaymentSuccessResponse response) { _handleSuccess(response, widget.supplierDetails); }); _razorpay.on(Razorpay.EVENT_PAYMENT_ERROR, _handleError); _razorpay.on(Razorpay.EVENT_EXTERNAL_WALLET, _handleExternalWallet); } Widget _buildAddressRow(String label, String address, Color color) { return Padding( padding: const EdgeInsets.only(bottom: 8.0), child: Row( children: [ Image.asset( 'images/location_supplier_landing.png', height: 24, width: 24, fit: BoxFit.contain, color: Color(0XFF939495), ), SizedBox( width: MediaQuery.of(context).size.width * .012, ), Text( '$label ', style: fontTextStyle(14, color, FontWeight.bold), ), Expanded( child: Text( address, overflow: TextOverflow.ellipsis, style: fontTextStyle(12, Color(0XFF515253), FontWeight.w400), ), ) ], ), ); } Widget _itemRow(String title, String price, {bool bold = false}) { return Padding( padding: const EdgeInsets.symmetric(vertical: 4.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(title, style: fontTextStyle(12, Color(0XFF646566), FontWeight.w400)), Text(price, style: fontTextStyle(12, Color(0XFF646566), FontWeight.w400)), ], ), ); } void _openCheckout(double amountInRupees) { var options = { 'key': 'rzp_test_1VCCWqEXUHdINz', // Replace with your Razorpay Key 'amount': (amountInRupees * 100) .toInt(), // Convert rupees to paise and ensure integer 'name': 'Test Payment', 'description': 'Water Order', 'prefill': { 'contact': '9876543210', 'email': 'test@example.com', } }; try { _razorpay.open(options); } catch (e) { print('Error: $e'); } } /* void _handleSuccess(PaymentSuccessResponse response) { _showAlert('Payment Successful', 'Payment ID: ${response.paymentId}'); }*/ void _handleSuccess(PaymentSuccessResponse response, dynamic object) async { if (!mounted) return; // ensure widget is still active var payload = {}; payload["action"] = 'accept'; payload["ref_number"] = response.paymentId; payload["payment_type"] = object.paymentType; try { bool status = await AppSettings.acceptPlanRequestsWithPayment(payload, object.dbId); if (!mounted) return; if (status) { AppSettings.longSuccessToast('Accepted'); Navigator.pop(context, true); // Use Navigator safely /* Navigator.pushReplacement( context, MaterialPageRoute( builder: (context) => OrderDetails(supplierDetails: object), ), );*/ } else { AppSettings.longFailedToast('Failed to accept order request'); } } catch (e) { AppSettings.longFailedToast('Error: $e'); } } void _handleError(PaymentFailureResponse response) { _showAlert('Payment Failed', '${response.code} - ${response.message}'); } void _handleExternalWallet(ExternalWalletResponse response) { _showAlert('Wallet Selected', '${response.walletName}'); } void _showAlert(String title, String content) { showDialog( context: context, builder: (_) => AlertDialog( title: Text(title), content: Text(content), actions: [ TextButton(onPressed: () => Navigator.pop(context), child: Text('OK')) ], ), ); } @override void dispose() { _razorpay.clear(); super.dispose(); } @override Widget build(BuildContext context) { final int totalOrders = widget.supplierDetails.dates.length; final double biddingPrice = double.tryParse(widget.supplierDetails.biddingPrice) ?? 0; final double totalAmount = totalOrders * biddingPrice; final num total = totalAmount is num ? totalAmount : num.tryParse(totalAmount.toString()) ?? 0; final num advance = widget.supplierDetails.advanceAmount is num ? widget.supplierDetails.advanceAmount : num.tryParse(widget.supplierDetails.advanceAmount.toString()) ?? 0; final num balance = total - advance; return Scaffold( backgroundColor: Color(0XFFFFFFFF), appBar: AppSettings.supplierAppBarWithoutActions( widget.supplierDetails.supplierName, context), body: SingleChildScrollView( child: Padding( padding: EdgeInsets.fromLTRB(12, 8, 12, 8), child: Column( children: [ _buildAddressRow(widget.supplierDetails.supplierName, '| ' + widget.supplierDetails.address, Color(0XFF4692FD)), Padding( padding: const EdgeInsets.only( left: 8.0, bottom: 4.0), // 👈 Shift right child: Align( alignment: Alignment.centerLeft, child: Image.asset( 'images/Line.png', height: 12, width: 6, fit: BoxFit.contain, ), ), ), _buildAddressRow('Home', '| ' + AppSettings.userAddress, Color(0XFF2D2E30)), SizedBox( height: MediaQuery.of(context).size.height * .012, ), Card( color: Color(0XFFFFFFFF), child: Padding( padding: EdgeInsets.all(4), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ Container( width: double .infinity, // makes it expand within the Card's width decoration: BoxDecoration( borderRadius: BorderRadius.vertical( bottom: Radius.circular(8), top: Radius.circular(8), ), // match Card border gradient: LinearGradient( colors: [ Color(0xFFFFF8DF), Color(0xFFFFFFFF), ], begin: Alignment.topLeft, end: Alignment.bottomRight, ), ), padding: EdgeInsets.symmetric(vertical: 12), alignment: Alignment.center, child: Padding( padding: EdgeInsets.fromLTRB(12, 0, 12, 0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( widget .supplierDetails.supplierName, style: fontTextStyle( 16, Color(0XFF2D2E30), FontWeight.w600)), Text( widget.supplierDetails .distanceInMeters .toString() + ' Km', style: fontTextStyle( 12, Color(0XFF2D2E30), FontWeight.w600)), ], ), Text( widget.supplierDetails.displayAddress, style: fontTextStyle( 12, Color(0XFF515253), FontWeight.w400)), ], ))), SizedBox( height: MediaQuery.of(context).size.height * .012, ), Container( width: double .infinity, // makes it expand within the Card's width decoration: BoxDecoration( color: Color(0XFFF5F6F6), // Same as Card color borderRadius: BorderRadius.circular(4), // Rounded corners border: Border.all( color: Color(0XFFF5F6F6), // Border color width: 0.5, // Border width ), ), padding: EdgeInsets.symmetric(vertical: 4), child: Padding( padding: EdgeInsets.fromLTRB(12, 0, 12, 0), child: Text('ITEMS', style: fontTextStyle(10, Color(0XFF646566), FontWeight.w400)), )), SizedBox( height: MediaQuery.of(context).size.height * .012, ), Padding( padding: EdgeInsets.fromLTRB(4, 0, 4, 0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( widget.supplierDetails.capacity + ' - ' + widget.supplierDetails.typeofwater+' - ' + widget.supplierDetails.frequency+'/week', style: fontTextStyle(12, Color(0XFF2D2E30), FontWeight.w500), ), Row( children: [ Text('Actual Price: ', style: fontTextStyle( 12, Color(0XFF646566), FontWeight.w400),), Text( '₹' + AppSettings.formDouble(widget.supplierDetails.quotedAmount) + '/', style: fontTextStyle(12, Color(0XFF2D2E30), FontWeight.w500), ), Text( widget.supplierDetails.capacity, style: fontTextStyle(12, Color(0XFF2D2E30), FontWeight.w500), ) ], ), Row( children: [ Text('Bidding Price: ', style: fontTextStyle( 12, Color(0XFF646566), FontWeight.w400),), Text( '₹' + AppSettings.formDouble(widget.supplierDetails.biddingPrice) + '/', style: fontTextStyle(12, Color(0XFF2D2E30), FontWeight.w500), ), Text( widget.supplierDetails.capacity, style: fontTextStyle(12, Color(0XFF2D2E30), FontWeight.w500), ) ], ), Row( children: [ Text('Payment Type: ', style: fontTextStyle( 12, Color(0XFF646566), FontWeight.w400),), Text( widget.supplierDetails.paymentType, style: fontTextStyle( 12, Color(0XFF515253), FontWeight.w600), ), ], ), Visibility( visible:widget.supplierDetails.paymentType!='after_delivery' , child: Row( children: [ Text(widget.supplierDetails.paymentType=='credit'?'Credit Limit: ':'Advance Amount: ', style: fontTextStyle( 12, Color(0XFF646566), FontWeight.w400),), Text( widget.supplierDetails.advanceAmount, style: fontTextStyle( 12, Color(0XFF515253), FontWeight.w600), ), ], ),), Text.rich( TextSpan( children: [ TextSpan( text: "Total amount for this plan orders ", style: fontTextStyle( 12, const Color(0xFF939495), FontWeight.w400, ), ), TextSpan( text: '$totalOrders × ${biddingPrice.toStringAsFixed(0)} = ₹${totalAmount.toStringAsFixed(0)}', style: fontTextStyle( 12, const Color(0xFF515253), FontWeight.w500, ), ), ], ), softWrap: true, maxLines: 2, overflow: TextOverflow.visible, textAlign: TextAlign.center, ) ], ) ), SizedBox( height: MediaQuery.of(context).size.height * .012, ), Container( width: double .infinity, // makes it expand within the Card's width decoration: BoxDecoration( color: Color(0XFFF5F6F6), // Same as Card color borderRadius: BorderRadius.circular(4), // Rounded corners border: Border.all( color: Color(0XFFF5F6F6), // Border color width: 0.5, // Border width ), ), padding: EdgeInsets.symmetric(vertical: 4), child: Padding( padding: EdgeInsets.fromLTRB(12, 0, 12, 0), child: Text('DELIVERY DETAILS', style: fontTextStyle(10, Color(0XFF646566), FontWeight.w400)), )), SizedBox( height: MediaQuery.of(context).size.height * .012, ), Padding( padding: EdgeInsets.fromLTRB(4, 0, 4, 0), child: Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'Plan Period', style: fontTextStyle(12, Color(0XFF515253), FontWeight.w500), ), Visibility( visible: widget.supplierDetails.startDate != '', child: Text( widget.supplierDetails.startDate + ' to ' + widget.supplierDetails.endDate, style: fontTextStyle( 12, Color(0XFF232527), FontWeight .w500), ), ) ], ), ], ), ), SizedBox( height: MediaQuery.of(context).size.height * .012, ), Align( alignment: Alignment.center, child: Container( decoration: BoxDecoration( color: Color(0XFFFFFFFF), // Same as Card color borderRadius: BorderRadius.circular( 4), // Rounded corners border: Border.all( color: Color(0XFF939495), // Border color width: 0.5, // Border width ), ), padding: EdgeInsets.symmetric(vertical: 4), child: Padding( padding: EdgeInsets.fromLTRB(12, 0, 12, 0), child: Text('Change Delivery Details', style: fontTextStyle(14, Color(0XFF646566), FontWeight.w500)), )), ), SizedBox( height: MediaQuery.of(context).size.height * .012, ), ], ), ), ), SizedBox( height: MediaQuery.of(context).size.height * .012, ), Card( color: Color(0XFFFFFFFF), child: Padding( padding: EdgeInsets.fromLTRB(12, 12, 12, 12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ Text('SAVINGS', style: fontTextStyle( 10, Color(0XFF646566), FontWeight.w400)), SizedBox( height: MediaQuery.of(context).size.height * .012, ), Row( children: [ Image.asset( 'images/coupon.png', height: 16, width: 16, fit: BoxFit.contain, ), SizedBox( width: MediaQuery.of(context).size.width * .012), Text( 'Apply Coupon', style: fontTextStyle( 12, Color(0XFF2D2E30), FontWeight.w500, ), ), Spacer(), // pushes the arrow to the right Image.asset( 'images/arrow-right.png', height: 20, width: 20, fit: BoxFit.contain, ), ], ), SizedBox( height: MediaQuery.of(context).size.height * .012, ), ], ), )), SizedBox( height: MediaQuery.of(context).size.height * .012, ), Column( children: [ // Header card GestureDetector( onTap: () => setState(() => isExpanded = !isExpanded), child: Card( color: Color(0XFFFFFFFF), child: Padding( padding: EdgeInsets.fromLTRB(12, 12, 12, 12), child: Row( children: [ Image.asset( 'images/receipt.png', height: 16, width: 16, fit: BoxFit.contain, ), SizedBox( width: MediaQuery.of(context).size.width * .012, ), Expanded( child: Text( 'To Pay ₹${AppSettings.moneyConvertion(widget.supplierDetails.advanceAmount.toString())}', style: fontTextStyle(12, Color(0XFF2E302D), FontWeight.w600)), ), isExpanded ? Image.asset( 'images/arrow-up.png', height: 20, width: 20, fit: BoxFit.contain, ) : Image.asset( 'images/arrow-down.png', height: 20, width: 20, fit: BoxFit.contain, ) ], ), ), ), ), AnimatedContainer( duration: Duration(milliseconds: 300), curve: Curves.easeInOut, height: isExpanded ? null : 0, padding: isExpanded ? EdgeInsets.all(0) : EdgeInsets.zero, child: isExpanded ? Card( color: Color(0XFFFFFFFF), child: Padding( padding: EdgeInsets.all(8), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('ITEMS', style: fontTextStyle( 14, Color(0XFF2D2E30), FontWeight.w500)), SizedBox( height: MediaQuery.of(context).size.height * .012, ), _itemRow( widget.supplierDetails.capacity + ' ' + widget .supplierDetails.typeofwater + ' x ' + widget.supplierDetails.quantity, '₹' + AppSettings.moneyConvertion( biddingPrice.toString())), Divider(), _itemRow('Total Amount For Plan', '₹${AppSettings.moneyConvertion(totalAmount.toStringAsFixed(0))}'), _itemRow('Delivery Charges', '₹ 0.0'), //_itemRow('Platform Fee', '₹${AppSettings.moneyConvertion(platformFee.toString())}'), _itemRow('Platform Fee', '₹ 0.0'), _itemRow('Taxes', '₹ 0.0'), Divider(), _itemRow('Total Bill', '₹${AppSettings.moneyConvertion(totalAmount.toString())}', bold: true), Divider(), _itemRow('Advance', '₹${AppSettings.moneyConvertion(widget.supplierDetails.advanceAmount.toString())}'), _itemRow('To pay(after delivery)', '₹${AppSettings.moneyConvertion(balance.toString())}'), ], ), ), ) : null, ), ], ) ], )), ), bottomNavigationBar: Container( decoration: BoxDecoration( color: Colors.white, border: Border( top: BorderSide(color: Color(0XFFC3C4C4), width: 0.8), ), boxShadow: [ BoxShadow( color: Color(0XFFC3C4C4), blurRadius: 0, offset: Offset(0, 0), ), ], ), padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), child: Row( children: [ // Button 1: Pay Advance Expanded( child: ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: Color(0XFF0A9E04), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(24), ), padding: EdgeInsets.symmetric(vertical: 12), // Only vertical padding ), onPressed: () { /*Navigator.push( context, MaterialPageRoute( builder: (context) => RazorpayScreen()), );*/ /*Navigator.push( context, MaterialPageRoute( builder: (context) => PaymentOptionsPage(amount: advance), ), );*/ _openCheckout(double.parse(widget.supplierDetails.advanceAmount)); /*Navigator.push( context, MaterialPageRoute( builder: (context) => UpiIntentLauncher(), ), );*/ }, child: Text( "Pay advance ₹${AppSettings.moneyConvertion(advance.toString())}", style: fontTextStyle(14, Color(0XFFFFFFFF), FontWeight.w600), textAlign: TextAlign.center, ), ), ), SizedBox( width: MediaQuery.of(context).size.width * .012, ),// spacing between buttons // Button 2: Pay Full Expanded( child: ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: Color(0XFF1D7AFC), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(24), ), padding: EdgeInsets.symmetric(vertical: 12), ), onPressed: () { // Handle full payment }, child: Text( "Pay full ₹${AppSettings.moneyConvertion(total.toStringAsFixed(2))}", style: fontTextStyle(14, Color(0XFFFFFFFF), FontWeight.w600), textAlign: TextAlign.center, ), ), ), ], ), ), ); } }