import 'dart:convert'; import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:bookatanker/supplier/order_details.dart'; import '../common/settings.dart'; import 'supplier_orders_model.dart'; class OrderRequestsPage extends StatefulWidget { const OrderRequestsPage({super.key}); @override State createState() => _OrderRequestsPageState(); } class _OrderRequestsPageState extends State { bool isSupplierOrdersDataLoading = false; List supplierOrdersList = []; List acceptedOrders = []; List acceptedByUserOrders = []; List rejectedOrders = []; void groupOrdersByStatus() { acceptedOrders = supplierOrdersList .where((order) => order.status == "accept") // adjust field name .toList(); acceptedByUserOrders = supplierOrdersList .where( (order) => order.status == "accepted_by_user") // adjust field name .toList(); rejectedOrders = supplierOrdersList .where( (order) => order.status == "rejected_by_user") // adjust field name .toList(); } @override void initState() { // TODO: implement initState super.initState(); getAcceptedOrdersFromSupplier(); } Future getAcceptedOrdersFromSupplier() async { isSupplierOrdersDataLoading = true; var response1 = await AppSettings.getAcceptedOrdersDataFromSupplier(); var json = jsonDecode(response1); setState(() { supplierOrdersList = (json['data'] as List) .map((model) => SupplierOrdersModel.fromJson(model)) .toList(); groupOrdersByStatus(); isSupplierOrdersDataLoading = false; }); } String getOrderTimeOnly(String orderTimeStr) { if (orderTimeStr.isEmpty) return ""; try { final format = DateFormat("dd-MM-yyyy HH:mm"); final orderTime = format.parse(orderTimeStr); final now = DateTime.now(); final difference = now.difference(orderTime); if (difference.inDays < 2) { return "New"; } else if (difference.inDays < 10) { final remaining = 10 - difference.inDays; return "Expires in ${remaining}d"; } else { return "Expired"; } } catch (e) { return ""; } } showRejectOrdersDialog(var object) async { return showDialog( context: context, barrierDismissible: false, builder: (BuildContext context) { return StatefulBuilder( builder: (BuildContext context, StateSetter setState) { return AlertDialog( backgroundColor: Color(0XFFFFFFFF),// Set your desired background color shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), // Optional: Rounded corners ), title: Center( child: Text('Reject Order Request' ,style: fontTextStyle(16,Color(0XFF3B3B3B),FontWeight.w600),), ), content: SingleChildScrollView( child: ListBody( children: [ Container( child: Text('Do u want to reject order request',style: fontTextStyle(14,Color(0XFF101214),FontWeight.w600),), ), ], ), ), actions: [ Center( child: Row( mainAxisSize: MainAxisSize.min, children: [ Expanded(child: GestureDetector( onTap: (){ Navigator.pop(context); }, child: Container( decoration: BoxDecoration( shape: BoxShape.rectangle, color: Color(0XFFFFFFFF), border: Border.all( width: 1, color: Color(0XFF1D7AFC)), borderRadius: BorderRadius.circular( 12, )), alignment: Alignment.center, child: Visibility( visible: true, child: Padding( padding: EdgeInsets.fromLTRB(16,12,16,12), child: Text('Cancel', style: fontTextStyle(12, Color(0XFF1D7AFC), FontWeight.w600)), ), ), ), ),), SizedBox(width:MediaQuery.of(context).size.width * .016,), Expanded(child: GestureDetector( onTap: ()async{ var payload = {}; payload["supplierId"] = object.supplierId; payload["action"] = 'reject'; payload["paymentId"] = ''; try { bool status = await AppSettings.acceptOrderRequests(payload, object.dbId); if (!mounted) return; if (status) { AppSettings.longSuccessToast('Rejected'); Navigator.pop(context); getAcceptedOrdersFromSupplier(); } else { AppSettings.longFailedToast('Failed to reject order request'); } } catch (e) { AppSettings.longFailedToast('Error: $e'); } }, child: Container( decoration: BoxDecoration( shape: BoxShape.rectangle, color: Color(0XFFE2483D), border: Border.all( width: 1, color: Color(0XFFE2483D)), borderRadius: BorderRadius.circular( 12, )), alignment: Alignment.center, child: Visibility( visible: true, child: Padding( padding: EdgeInsets.fromLTRB(16,12,16,12), child: Text( 'Reject', style: fontTextStyle( 12, Color(0XFFFFFFFF), FontWeight.w600)), ), ), ) ),) ], ), ), ], ); }); }, ); } Widget orderCard(SupplierOrdersModel order) { final orderDateTime = "${order.acceptedTime}".trim(); final statusTime = getOrderTimeOnly(orderDateTime); // status badge color Color statusColor = Color(0xFF1D7AFC); if (statusTime == "Expired") statusColor = Color(0xFF757575); else if (statusTime == "New") statusColor = Color(0XFF1D7AFC); else if (statusTime.endsWith("m")) statusColor = Color(0XFFE56910); return Padding( padding: EdgeInsets.all(10), child: Container( decoration: BoxDecoration( color: Color(0XFFFFFFFF), // Same as Card color borderRadius: BorderRadius.circular(12), // Rounded corners border: Border.all( color: Color(0XFF9F9F9F), // Border color width: 0.5, // Border width ), ), //color: Color(0XFFFFFFFF), child: Padding( padding: EdgeInsets.all(16), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Visibility( visible: order.supplierName != '', child: Text( order.supplierName, style: fontTextStyle( 14, Color(0XFF343637), FontWeight.w600), ), ), Visibility( visible: statusTime.isNotEmpty, child: Padding( padding: const EdgeInsets.only(top: 4.0, bottom: 4.0), child: Container( padding: EdgeInsets.symmetric(horizontal: 6, vertical: 2), decoration: BoxDecoration( color: statusColor, borderRadius: BorderRadius.circular(4), ), child: Text( statusTime, style: fontTextStyle( 10, Colors.white, FontWeight.w500), ), ), ), ), ], ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Visibility( visible: order.displayAddress != '', child: Text( order.displayAddress, style: fontTextStyle( 10, Color(0XFF646566), FontWeight.w400), ), ), Visibility( visible: order.date != '', child: Text( order.date + ' ' + order.time, style: fontTextStyle( 9, Color(0XFF646566), FontWeight.w400), ), ), ], ), SizedBox( height: MediaQuery.of(context).size.height * .012, ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ Container( padding: EdgeInsets.symmetric(horizontal: 4, vertical: 2), decoration: BoxDecoration( color: order.typeofwater.toString().toLowerCase() == 'bore water' ? Color(0xFF8877DD) : Color(0xFFCA86B0), borderRadius: BorderRadius.circular(4), border: Border.all( width: 1, color: order.typeofwater.toString().toLowerCase() == 'bore water' ? Color(0xFF8877DD) : Color(0xFFCA86B0), ), ), child: AutoSizeText( capitalizeFirst(order.typeofwater), maxLines: 1, overflow: TextOverflow.ellipsis, style: fontTextStyle( 12, Color(0xFFFFFFFF), FontWeight.w400), ), ), Row( children: [ Text( '₹' + AppSettings.formDouble(order.quotedAmount) + '/', style: fontTextStyle( 20, Color(0XFF515253), FontWeight.w600), ), Text( order.capacity, style: fontTextStyle( 12, Color(0XFF2D2E30), FontWeight.w600), ) ], ), ], ), Row( children: [ GestureDetector( onTap: statusTime == "Expired" ? null : () { showRejectOrdersDialog(order); }, child: ColorFiltered( colorFilter: statusTime == "Expired" ? ColorFilter.mode( Color(0XFF9F9F9F), BlendMode.srcIn) : ColorFilter.mode( Colors.transparent, BlendMode.multiply), child: Image.asset( 'images/wrong_button.png', width: 44, height: 44, ), ), ), SizedBox( width: MediaQuery.of(context).size.width * .012, ), GestureDetector( onTap: statusTime == "Expired" ? null : () { //showAcceptOrdersDialog(order); Navigator.push( context, MaterialPageRoute( builder: (context) => OrderDetails( supplierDetails: order, ), ), ); }, child: ColorFiltered( colorFilter: statusTime == "Expired" ? ColorFilter.mode( Color(0XFF9F9F9F), BlendMode.srcIn) : ColorFilter.mode( Colors.transparent, BlendMode.multiply), child: Image.asset( 'images/right_button.png', width: 44, height: 44, ), ), ), ], ) ], ) ], )), ), ); } Widget acceptedOrdersCard(SupplierOrdersModel order) { final orderDateTime = "${order.acceptedTime}".trim(); final statusTime = getOrderTimeOnly(orderDateTime); // status badge color Color statusColor = Color(0xFF1D7AFC); if (statusTime == "Expired") statusColor = Color(0xFF757575); else if (statusTime == "New") statusColor = Color(0XFF1D7AFC); else if (statusTime.endsWith("m")) statusColor = Color(0XFFE56910); return Padding( padding: EdgeInsets.all(10), child: Container( decoration: BoxDecoration( color: Color(0XFFFFFFFF), // Same as Card color borderRadius: BorderRadius.circular(12), // Rounded corners border: Border.all( color: Color(0XFF9F9F9F), // Border color width: 0.5, // Border width ), ), //color: Color(0XFFFFFFFF), child: Padding( padding: EdgeInsets.all(16), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Visibility( visible: order.supplierName != '', child: Text( order.supplierName, style: fontTextStyle( 14, Color(0XFF343637), FontWeight.w600), ), ), Visibility( visible: order.date != '', child: Text( order.date + ' ' + order.time, style: fontTextStyle( 9, Color(0XFF646566), FontWeight.w400), ), ), ], ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Visibility( visible: order.displayAddress != '', child: Text( order.displayAddress, style: fontTextStyle( 10, Color(0XFF646566), FontWeight.w400), ), ), Row( children: [ Image.asset( 'images/paid.png', fit: BoxFit.cover, width: 16, // Match the diameter of the CircleAvatar height: 16, ), SizedBox( width: MediaQuery.of(context).size.width * .004, ), Text(capitalizeFirst('Paid'), style: fontTextStyle(12, Color(0XFF515253), FontWeight.w400)), SizedBox( width: MediaQuery.of(context).size.width * .012, ), Text( '₹' + AppSettings.formDouble(order.advancePaid), style: fontTextStyle( 12, Color(0XFF515253), FontWeight.w400), ), ], ) ], ), SizedBox( height: MediaQuery.of(context).size.height * .004, ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Container( padding: EdgeInsets.symmetric(horizontal: 4, vertical: 2), decoration: BoxDecoration( color: order.typeofwater.toString().toLowerCase() == 'bore water' ? Color(0xFF8877DD) : Color(0xFFCA86B0), borderRadius: BorderRadius.circular(4), border: Border.all( width: 1, color: order.typeofwater.toString().toLowerCase() == 'bore water' ? Color(0xFF8877DD) : Color(0xFFCA86B0), ), ), child: AutoSizeText( capitalizeFirst(order.typeofwater), maxLines: 1, overflow: TextOverflow.ellipsis, style: fontTextStyle(12, Color(0xFFFFFFFF), FontWeight.w400), ), ), Row( children: [ Image.asset( 'images/warning.png', fit: BoxFit.cover, width: 16, // Match the diameter of the CircleAvatar height: 16, ), SizedBox( width: MediaQuery.of(context).size.width * .004, ), Text(capitalizeFirst('Due'), style: fontTextStyle(12, Color(0XFF515253), FontWeight.w400)), SizedBox( width: MediaQuery.of(context).size.width * .012, ), Text( '₹' + AppSettings.formDouble(order.advancePaid), style: fontTextStyle( 12, Color(0XFF515253), FontWeight.w400), ), ], ) ], ), Row( children: [ Text( '₹' + AppSettings.formDouble(order.quotedAmount) + '/', style: fontTextStyle(20, Color(0XFF515253), FontWeight.w600), ), Text( order.capacity, style: fontTextStyle(12, Color(0XFF2D2E30), FontWeight.w600), ), ], ), ], ), ), ], ) ], )), ), ); } Widget rejectedOrdersCard(SupplierOrdersModel order) { final orderDateTime = "${order.acceptedTime}".trim(); final statusTime = getOrderTimeOnly(orderDateTime); // status badge color Color statusColor = Color(0xFF1D7AFC); if (statusTime == "Expired") statusColor = Color(0xFF757575); else if (statusTime == "New") statusColor = Color(0XFF1D7AFC); else if (statusTime.endsWith("m")) statusColor = Color(0XFFE56910); return Padding( padding: EdgeInsets.all(10), child: Container( decoration: BoxDecoration( color: Color(0XFFFFFFFF), // Same as Card color borderRadius: BorderRadius.circular(12), // Rounded corners border: Border.all( color: Color(0XFF9F9F9F), // Border color width: 0.5, // Border width ), ), //color: Color(0XFFFFFFFF), child: Padding( padding: EdgeInsets.all(16), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Visibility( visible: order.supplierName != '', child: Text( order.supplierName, style: fontTextStyle( 14, Color(0XFF343637), FontWeight.w600), ), ), Visibility( visible: order.date != '', child: Text( order.date + ' ' + order.time, style: fontTextStyle( 9, Color(0XFF646566), FontWeight.w400), ), ), ], ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Visibility( visible: order.displayAddress != '', child: Text( order.displayAddress, style: fontTextStyle( 10, Color(0XFF646566), FontWeight.w400), ), ), ], ), SizedBox( height: MediaQuery.of(context).size.height * .004, ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Container( padding: EdgeInsets.symmetric(horizontal: 4, vertical: 2), decoration: BoxDecoration( color: order.typeofwater.toString().toLowerCase() == 'bore water' ? Color(0xFF8877DD) : Color(0xFFCA86B0), borderRadius: BorderRadius.circular(4), border: Border.all( width: 1, color: order.typeofwater.toString().toLowerCase() == 'bore water' ? Color(0xFF8877DD) : Color(0xFFCA86B0), ), ), child: AutoSizeText( capitalizeFirst(order.typeofwater), maxLines: 1, overflow: TextOverflow.ellipsis, style: fontTextStyle(12, Color(0xFFFFFFFF), FontWeight.w400), ), ), ], ), Row( children: [ Text( '₹' + AppSettings.formDouble(order.quotedAmount) + '/', style: fontTextStyle(20, Color(0XFF515253), FontWeight.w600), ), Text( order.capacity, style: fontTextStyle(12, Color(0XFF2D2E30), FontWeight.w600), ), ], ), ], ), ), ], ) ], )), ), ); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Color(0XFFFFFFFF), appBar: AppSettings.supplierAppBarWithoutActions('Order Requests', context), body: Center( child: isSupplierOrdersDataLoading ? Center( child: CircularProgressIndicator( color: primaryColor, strokeWidth: 5.0, ), ) : supplierOrdersList.length != 0 ? Column( children: [ Expanded( child: ListView( children: [ // Accepted by User Orders if (acceptedByUserOrders.isNotEmpty) ...[ Padding( padding: EdgeInsets.all(10), child: Text( "ACCEPTED REQUESTS", style: fontTextStyle( 10, Color(0XFF646566), FontWeight.w400), ), ), ...acceptedByUserOrders .map((order) => acceptedOrdersCard(order)) .toList(), ], // Group acceptedOrders if (acceptedOrders.isNotEmpty) ...[ // Active / New Orders if (acceptedOrders.any((o) => getOrderTimeOnly(o.acceptedTime) != "Expired")) ...[ Padding( padding: EdgeInsets.all(10), child: Text( "NEW REQUESTS", style: fontTextStyle( 10, Color(0XFF646566), FontWeight.w400), ), ), ...acceptedOrders .where((o) => getOrderTimeOnly(o.acceptedTime) != "Expired") .map((order) => orderCard(order)) .toList(), ], // Expired Orders if (acceptedOrders.any((o) => getOrderTimeOnly(o.acceptedTime) == "Expired")) ...[ Padding( padding: EdgeInsets.all(10), child: Text( "EXPIRED REQUESTS", style: fontTextStyle( 10, Color(0XFF646566), FontWeight.w400), ), ), ...acceptedOrders .where((o) => getOrderTimeOnly(o.acceptedTime) == "Expired") .map((order) => orderCard(order)) .toList(), ], ], //rejected orders] if (rejectedOrders.isNotEmpty) ...[ Padding( padding: EdgeInsets.all(10), child: Text( "REJECTED REQUESTS", style: fontTextStyle( 10, Color(0XFF646566), FontWeight.w400), ), ), ...rejectedOrders .map((order) => rejectedOrdersCard(order)) .toList(), ], ], ), ), SizedBox( height: MediaQuery.of(context).size.height * .010, ), ], ) : Center( child: Text( 'No Data Available', style: fontTextStyle(12, Color(0XFF000000), FontWeight.w500), ), ), ), ); } }