import 'package:flutter/material.dart'; import 'package:supplier_new/common/settings.dart'; import 'package:supplier_new/plans/edit_plan_requests.dart'; class AcceptPlanRequests extends StatefulWidget { var order; var status; AcceptPlanRequests({this.order, this.status}); @override State createState() => _AcceptPlanRequestsState(); } class _AcceptPlanRequestsState extends State { int advancePayable = 0; //int advance =0; double amountToPayAfterDelivery = 0.0; String paymentMode = "after_delivery"; // advance | credit | after_delivery TextEditingController advanceAmountCtrl = TextEditingController(); TextEditingController creditLimitCtrl = TextEditingController(); final TextEditingController tankerPriceController = TextEditingController(); final List> paymentTypes = [ {"key": "advance", "label": "Advance"}, {"key": "after_delivery", "label": "After Delivery"}, {"key": "credit", "label": "Credit"}, ]; String? advanceError; String? creditError; @override void initState() { // TODO: implement initState tankerPriceController.text = '${widget.order.quoted_amount}'; super.initState(); } Future showAdvanceSelectionBottomSheet(BuildContext context) async { await showModalBottomSheet( context: context, isScrollControlled: true, backgroundColor: Colors.transparent, builder: (ctx) { return StatefulBuilder( builder: (context, setStateSB) { return Container( padding: EdgeInsets.fromLTRB( 16, 16, 16, MediaQuery.of(context).viewInsets.bottom + 16), decoration: const BoxDecoration( color: Colors.white, borderRadius: BorderRadius.vertical(top: Radius.circular(16)), ), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Center( child: Container( width: 40, height: 4, decoration: BoxDecoration( color: Colors.grey[400], borderRadius: BorderRadius.circular(2), ), ), ), const SizedBox(height: 16), Text( "SELECT PAYMENT MODE", style: fontTextStyle( 10, const Color(0XFF2D2E30), FontWeight.w600), ), RadioListTile( title: Text("Advance", style: fontTextStyle(14, Colors.black, FontWeight.w400)), value: "advance", groupValue: paymentMode, onChanged: (v) { setStateSB(() => paymentMode = v!); }, ), if (paymentMode == "advance") TextField( controller: advanceAmountCtrl, keyboardType: TextInputType.number, decoration: const InputDecoration( hintText: "Enter advance amount", ), ), RadioListTile( title: Text("After Delivery", style: fontTextStyle(14, Colors.black, FontWeight.w400)), value: "after_delivery", groupValue: paymentMode, onChanged: (v) { setStateSB(() => paymentMode = v!); }, ), RadioListTile( title: Text("Credit", style: fontTextStyle(14, Colors.black, FontWeight.w400)), value: "credit", groupValue: paymentMode, onChanged: (v) { setStateSB(() => paymentMode = v!); }, ), if (paymentMode == "credit") TextField( controller: creditLimitCtrl, keyboardType: TextInputType.number, decoration: const InputDecoration( hintText: "Enter credit limit", ), ), const SizedBox(height: 12), ElevatedButton( onPressed: () { // 🔐 VALIDATION AT SELECTION TIME if (paymentMode == "advance" && advanceAmountCtrl.text.trim().isEmpty) { AppSettings.longFailedToast("Please enter advance amount"); return; } if (paymentMode == "credit" && creditLimitCtrl.text.trim().isEmpty) { AppSettings.longFailedToast("Please enter credit limit"); return; } // ✅ Valid → update main screen & close setState(() {}); Navigator.pop(context); }, style: ElevatedButton.styleFrom( backgroundColor: Color(0XFF0A9E04), foregroundColor: Color(0XFFFFFFFF), padding: EdgeInsets.symmetric(vertical: 10,horizontal: 16), ), child: Text( "Confirm", style: fontTextStyle( 14, const Color(0XFFFFFFFF), FontWeight.w400), ), ), ], ), ); }, ); }, ); } bool isPaymentValid() { if (paymentMode == "advance") { return advanceAmountCtrl.text.trim().isNotEmpty; } if (paymentMode == "credit") { return creditLimitCtrl.text.trim().isNotEmpty; } return true; // after_delivery } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, extendBodyBehindAppBar: true, appBar: AppBar( backgroundColor: Colors.transparent, elevation: 0, scrolledUnderElevation: 0, title: Text( '', style: fontTextStyle(16, Color(0XFF2A2A2A), FontWeight.w600), ), iconTheme: IconThemeData(color: Color(0XFF2A2A2A)), actions: [ Row( children: [ Padding( padding: EdgeInsets.fromLTRB(0, 10, 10, 10), child: IconButton( icon: Image.asset( 'images/help_appbar.png', height: 20, width: 20, color: Color(0XFFFFFFFF), ), onPressed: () {}, ), ) ], ) ], leading: GestureDetector( onTap: () { Navigator.pop(context); }, child: Padding( padding: const EdgeInsets.fromLTRB(8, 8, 8, 8), // Add padding if needed child: Image.asset( 'images/backbutton_appbar.png', // Replace with your image path fit: BoxFit.contain, color: Color(0XFFFFFFFF), height: 24, width: 24, ), ), ), ), body: SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ /// 🔹 Top Card with Image Stack( clipBehavior: Clip.none, children: [ /// 🔹 Background Image ClipRRect( borderRadius: const BorderRadius.only( bottomLeft: Radius.circular(0), bottomRight: Radius.circular(0), ), child: Image.asset( "images/building.png", height: 220, width: double.infinity, fit: BoxFit.cover, ), ), /// 🔹 Floating Info Card (half on image, half below) Positioned( bottom: -40, // pulls the card out by 40px left: 12, right: 12, child: Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: Colors.black12, blurRadius: 6, offset: Offset(0, 3), ), ], ), child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( padding: const EdgeInsets.symmetric( horizontal: 8, vertical: 4), decoration: BoxDecoration( color: Color(0XFFFFFFFF), borderRadius: BorderRadius.circular(4), border: Border.all( color: widget.status.statusColor, width: 0.5, ), ), child: Text(widget.status.status, style: fontTextStyle( 12, widget.status.statusColor, FontWeight.w500)), ), Text( widget.order.building_name, style: fontTextStyle( 20, const Color(0XFF2D2E30), FontWeight.w600), ), SizedBox(height: 4), Text( widget.order.displayAddress, style: fontTextStyle( 12, const Color(0XFF939495), FontWeight.w400), ), ], ), const Spacer(), Text( widget.order.distanceInKm.toString() + 'Km', style: fontTextStyle( 12, const Color(0XFF939495), FontWeight.w400), ), ], ), ), ), ], ), SizedBox( height: MediaQuery.of(context).size.height * .08, ), /// 🔹 Order Details Padding( padding: EdgeInsets.fromLTRB(16, 0, 16, 0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "PLAN DETAILS", style: fontTextStyle( 10, const Color(0XFF2D2E30), FontWeight.w600), ), SizedBox( height: MediaQuery.of(context).size.height * .011, ), _twoFields(tankerPriceController, "Tanker Price", 'images/price.png', false, null, null, null, null), Container( margin: const EdgeInsets.only(right: 8), decoration: BoxDecoration( color: const Color(0XFFFFFFFF), borderRadius: BorderRadius.circular(8), border: Border.all(color: const Color(0XFFC3C4C4)), ), child: Padding( padding: const EdgeInsets.all(4), child: GestureDetector( onTap: () => showAdvanceSelectionBottomSheet(context), behavior: HitTestBehavior.opaque, child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ // LEFT CONTENT Expanded( child: Stack( alignment: Alignment.centerRight, children: [ _detailTwoRow( "Payment Type", paymentMode == "advance" ? "Advance - ₹${advanceAmountCtrl.text.isEmpty ? "0" : advanceAmountCtrl.text}" : paymentMode == "credit" ? "Credit - ₹${creditLimitCtrl.text.isEmpty ? "0" : creditLimitCtrl.text}" : "After Delivery", "images/advance.png", "", "", "", ), // ⬇️ Arrow FIXED near text Padding( padding: const EdgeInsets.only(right: 8), child: Image.asset( 'images/downarrow.png', height: 18, width: 18, color: const Color(0XFFC3C4C4), ), ), ], ), ), // ✏ Edit icon at far right Image.asset( 'images/edit.png', height: 18, width: 18, color: const Color(0XFFC3C4C4), ), ], ), ), ), ), /* _detailTwoRow( "Tanker Price", "₹${AppSettings.formDouble(widget.order.quoted_amount) ?? ''}", "images/financialsBottomIcon.png", "", "", ""),*/ SizedBox( height: MediaQuery.of(context).size.height * .02, ), _detailTwoRow( "Water Type", "${widget.order.type_of_water}", "images/water.png", "Capacity", "${widget.order.capacity}", "images/capacity.png", ), SizedBox( height: MediaQuery.of(context).size.height * .02, ), _detailTwoRow( "Start Date", "${widget.order.startDate}", "images/time.png", "End Date", "${widget.order.endDate}", "images/time.png", ), SizedBox( height: MediaQuery.of(context).size.height * .02, ), _detailTwoRow("Frequency", "${widget.order.quantity}", "images/quantity.png", "", "", ""), ], ), ), /// 🔹 Additional Details Padding( padding: EdgeInsets.fromLTRB(16, 16, 16, 16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "ADDITIONAL DETAILS", style: fontTextStyle( 10, const Color(0XFF2D2E30), FontWeight.w600), ), SizedBox( height: MediaQuery.of(context).size.height * .011, ), Text('Total tankers for this plan are ${widget.order.dates.length}', style: fontTextStyle( 12, const Color(0xFF939495), FontWeight.w400),) ], )), /// 🔹 Payment Summary Padding( padding: EdgeInsets.fromLTRB(16, 0, 16, 16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "PAYMENT SUMMARY", style: fontTextStyle( 10, const Color(0XFF2D2E30), FontWeight.w600), ), SizedBox( height: MediaQuery.of(context).size.height * .011, ), ValueListenableBuilder( valueListenable: tankerPriceController, builder: (context, value, _) { final int tankerCount = widget.order.dates.length; final int price = int.tryParse(value.text.isEmpty ? "0" : value.text) ?? 0; return Text.rich( TextSpan( children: [ TextSpan( text: "Total amount for all plan orders ", style: fontTextStyle( 12, const Color(0xFF939495), FontWeight.w400)), TextSpan( text: '$tankerCount × $price = ${tankerCount * price}', style: fontTextStyle( 12, const Color(0xFF515253), FontWeight.w500)), ], ), textAlign: TextAlign.center, ); }, ), /* SizedBox( height: MediaQuery.of(context).size.height * .004, ), _detailRow("Total Amount", "₹ " + totalFare.toString()), SizedBox( height: MediaQuery.of(context).size.height * .004, ), Divider( color: Color(0XFF646566), thickness: 0.3, ), SizedBox( height: MediaQuery.of(context).size.height * .004, ), _detailRow("Booking Charges Payable", '₹${AppSettings.formDouble(advancePayable.toString()) ?? ''}'), SizedBox( height: MediaQuery.of(context).size.height * .004, ), _detailRow("Amount to Pay (After Delivery)", '₹${AppSettings.formDouble(amountToPayAfterDelivery.toString()) ?? ''}'),*/ ], ), ), const SizedBox(height: 80), // space for bottom buttons ], ), ), /// 🔹 Bottom Action Buttons bottomNavigationBar: Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), decoration: BoxDecoration( color: Color(0XFFFFFFFF), border: Border(top: BorderSide(color: Color(0XFFF5F6F6))), ), child: Row( children: [ Expanded( child: OutlinedButton( style: OutlinedButton.styleFrom( foregroundColor: Color(0XFFE2483D), backgroundColor: Colors.white, side: BorderSide(color: Color(0XFFE2483D)), padding: EdgeInsets.symmetric(vertical: 10), ), onPressed: () { /*Navigator.push( context, MaterialPageRoute( builder: (_) => EditPlanRequests( order: widget.order, status: widget.status, ), ), );*/ Navigator.pop(context); }, child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Image.asset('images/cross.png', height: 20, width: 20), SizedBox(width: 4), Text( "Cancel", style: fontTextStyle( 14, const Color(0XFF000000), FontWeight.w400), ), ], ), ), ), SizedBox(width: 8), Expanded( child: OutlinedButton( style: OutlinedButton.styleFrom( foregroundColor: Color(0XFFFFFFFF), backgroundColor: Color(0XFFE2483D), side: BorderSide(color: Color(0XFFE2483D)), padding: EdgeInsets.symmetric(vertical: 10), ), onPressed: () async { /*AppSettings.preLoaderDialog(context); bool isOnline = await AppSettings.internetConnectivity(); if (isOnline) { var payload = new Map(); payload["supplierId"] = AppSettings.supplierId; payload["amount"] = int.parse(widget.order.quoted_amount); payload["delivery_charges"] = advance; payload["action"] = 'reject'; bool status = await AppSettings.acceptOrderRequests( payload, widget.order.dbId); try { if (status) { Navigator.of(context,rootNavigator: true).pop(); AppSettings.longSuccessToast("Order request rejected Successfully"); Navigator.pop(context, true); } else{ Navigator.of(context,rootNavigator: true).pop(); AppSettings.longFailedToast("reject of order request Failed"); } } catch (e) { Navigator.of(context,rootNavigator: true).pop(); print(e); } } else{ Navigator.of(context,rootNavigator: true).pop(); AppSettings.longFailedToast("Please Check internet"); }*/ showRejectBottomSheet(context); }, child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Image.asset('images/cross.png', height: 20, width: 20,color: Color(0XFFFFFFFF),), SizedBox(width: 4), Text( "Reject", style: fontTextStyle( 14, const Color(0XFFFFFFFF), FontWeight.w400), ), ], ), ), ), SizedBox(width: 8), Expanded( child: ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: Color(0XFF0A9E04), foregroundColor: Color(0XFFFFFFFF), padding: EdgeInsets.symmetric(vertical: 10), ), onPressed: () async { AppSettings.preLoaderDialog(context); bool isOnline = await AppSettings.internetConnectivity(); if (!isOnline) { Navigator.of(context, rootNavigator: true).pop(); AppSettings.longFailedToast("Please Check internet"); return; } if (!isPaymentValid()) { Navigator.of(context, rootNavigator: true).pop(); AppSettings.longFailedToast( paymentMode == "advance" ? "Please enter advance amount" : "Please enter credit limit", ); return; } try { final Map payload = {}; payload["action"] = "accept"; payload["actual_price"] = int.parse(widget.order.quoted_amount); payload["bidding_price"] = int.parse(tankerPriceController.text); if (paymentMode == "advance") { payload["payment_type"] = "advance"; payload["adavnce_amount"] = int.tryParse(advanceAmountCtrl.text) ?? 0; } else if (paymentMode == "credit") { payload["payment_type"] = "credit"; payload["adavnce_amount"] = int.tryParse(creditLimitCtrl.text) ?? 0; } else { payload["payment_type"] = "after_delivery"; payload["adavnce_amount"] = 0; } bool status = await AppSettings.acceptPlanRequests( payload, widget.order.dbId, ); Navigator.of(context, rootNavigator: true).pop(); if (status) { Navigator.pop(context, true); } else { AppSettings.longFailedToast("Accept of plan request Failed"); } } catch (e) { Navigator.of(context, rootNavigator: true).pop(); AppSettings.longFailedToast("Something went wrong"); } }, child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Image.asset('images/rite.png', height: 20, width: 20), SizedBox(width: 4), Text( "Accept", style: fontTextStyle( 14, const Color(0XFFFFFFFF), FontWeight.w400), ), ], ), ), ), ], )), ); } Widget _textField(TextEditingController? controller, String? label, String? path, bool readOnly) { return Container( margin: const EdgeInsets.only(bottom: 12), child: TextField( controller: controller, cursorColor: primaryColor, readOnly: readOnly, decoration: InputDecoration( counterText: '', filled: false, fillColor: Colors.white, prefixIcon: Padding( padding: const EdgeInsets.symmetric(horizontal: 6.0, vertical: 6.0), child: SizedBox( width: 18, height: 18, child: Image.asset( path!, fit: BoxFit.contain, color: Color(0XFFC3C4C4), ), ), ), prefixIconConstraints: BoxConstraints( minWidth: 24, minHeight: 24, ), suffixIcon: readOnly ? null : Padding( padding: const EdgeInsets.only(right: 8), child: Image.asset( 'images/edit.png', height: 18, width: 18, color: const Color(0XFFC3C4C4), ), ), suffixIconConstraints: BoxConstraints( minWidth: 24, minHeight: 24, ), border: OutlineInputBorder( borderRadius: BorderRadius.circular(4.0), borderSide: BorderSide( color: Color(0XFFC3C4C4), width: 1, )), focusedBorder: !readOnly ? OutlineInputBorder( borderRadius: BorderRadius.circular(4.0), borderSide: BorderSide( color: Color(0XFF8270DB), width: 1, ), ) : OutlineInputBorder( borderRadius: BorderRadius.circular(4.0), borderSide: BorderSide( color: Color(0XFFC3C4C4), width: 1, ), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(4.0), borderSide: BorderSide(color: Color(0XFFC3C4C4)), ), labelText: label, labelStyle: fontTextStyle(12, Color(0XFF646566), FontWeight.w400), /* TextStyle(color: greyColor, fontWeight: FontWeight.bold //<-- SEE HERE ),*/ ), style: fontTextStyle(12, Color(0XFF343637), FontWeight.w500), ), ); } Widget _twoFields( TextEditingController? controller1, String? label1, String? path1, bool? readOnly1, TextEditingController? controller2, String? label2, String? path2, bool? readOnly2) { return Row( children: [ Expanded( child: _textField(controller1, label1, path1, readOnly1!), ), const SizedBox(width: 10), if (controller2 != null) Expanded( child: _textField(controller2, label2, path2, readOnly2!), ), ], ); } /// 🔹 Helper widget for rows Widget _detailRow(String title, String value) { return Padding( padding: const EdgeInsets.symmetric(vertical: 0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( title, style: fontTextStyle(12, const Color(0XFF646566), FontWeight.w400), ), Text( value, style: fontTextStyle(12, const Color(0XFF2D2E30), FontWeight.w500), ), ], ), ); } Widget _detailTwoRow( String title1, String value1, String path1, String title2, String value2, String path2, { EdgeInsetsGeometry padding = const EdgeInsets.symmetric(vertical: 6), }) { final titleStyle = fontTextStyle(12, Color(0XFF646566), FontWeight.w400); final valueStyle = fontTextStyle(12, Color(0XFF343637), FontWeight.w500); Widget _col(String t, String v, String path) { return Expanded( child: Padding( padding: const EdgeInsets.only(right: 8.0), child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ if (path.isNotEmpty) Image.asset( path, fit: BoxFit.contain, height: 20, width: 20, color: const Color(0XFFC3C4C4), ), if (path.isNotEmpty) const SizedBox(width: 6), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(t, style: titleStyle, maxLines: 1, overflow: TextOverflow.ellipsis), Text(v, style: valueStyle, maxLines: 1, overflow: TextOverflow.ellipsis), ], ), ) ], ), ), ); } return Padding( padding: padding, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ _col(title1, value1, path1), _col(title2, value2, path2), ], ), ); } Future showRejectBottomSheet(BuildContext context) { final reasons = [ "I got a better deal", "The price is not reasonable", "I do not have the capacity to deliver", "I do not have drivers to deliver", "Others", ]; String? selectedReason; return showModalBottomSheet( context: context, isScrollControlled: true, backgroundColor: Colors.transparent, builder: (ctx) { return Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 20), decoration: const BoxDecoration( color: Colors.white, borderRadius: BorderRadius.vertical(top: Radius.circular(16)), ), child: StatefulBuilder( builder: (context, setState) { return SafeArea( top: false, child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ // drag handle Center( child: Container( width: 40, height: 4, decoration: BoxDecoration( color: Colors.grey[400], borderRadius: BorderRadius.circular(2), ), ), ), const SizedBox(height: 20), Text( "REASON FOR REJECTION", style: fontTextStyle( 10, const Color(0XFF2D2E30), FontWeight.w600), ), const SizedBox(height: 8), // reasons ...reasons.map( (reason) => RadioListTile( contentPadding: EdgeInsets.zero, title: Text( reason, style: fontTextStyle( 14, const Color(0XFF2D2E30), FontWeight.w400), ), value: reason, activeColor: const Color(0XFFE2483D), groupValue: selectedReason, onChanged: (v) => setState(() => selectedReason = v), ), ), const SizedBox(height: 12), Row( children: [ Expanded( child: OutlinedButton( onPressed: () => Navigator.pop(context, null), style: OutlinedButton.styleFrom( padding: const EdgeInsets.symmetric(vertical: 14), side: const BorderSide(color: Color(0XFFFFFFFF)), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(24), ), ), child: Text( "Cancel", style: fontTextStyle( 14, const Color(0XFF939495), FontWeight.w600), ), ), ), const SizedBox(width: 12), Expanded( child: ElevatedButton( onPressed: selectedReason == null ? null : () => Navigator.pop(context, selectedReason), style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFFE2483D), disabledBackgroundColor: Color(0xFFE2483D), padding: const EdgeInsets.symmetric(vertical: 14), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(24), ), ), child: Text( "Reject Request", style: fontTextStyle( 14, const Color(0XFFFFFFFF), FontWeight.w600), ), ), ), ], ), ], ), ); }, ), ); }, ); } }