From 3f4c0bced9559266334af8fb85534660f4ad4982 Mon Sep 17 00:00:00 2001 From: saritabirare Date: Sun, 13 Oct 2024 19:52:03 +0530 Subject: [PATCH] 1) rd Order circle updated code --- lib/controller/get_cancle_service.dart | 39 + lib/controller/get_delivered_controller.dart | 23 + lib/controller/get_delivered_service.dart | 39 + lib/controller/get_dispatch_controller.dart | 75 ++ lib/controller/get_dispatch_service.dart | 104 ++ lib/controller/get_pending_service.dart | 39 + lib/controller/get_rd_cancle_controller.dart | 28 + lib/controller/get_rd_pending_controller.dart | 24 + .../get_single_invoice_Service.dart | 33 + .../get_single_invoice_controller.dart | 38 + lib/controller/rd_get_order_controller.dart | 42 +- lib/controller/rd_get_order_service.dart | 61 - lib/controller/rd_get_single_service.dart | 73 ++ .../rd_processing_invoice_controller.dart | 57 + .../rd_processing_invoice_service.dart | 41 + lib/controller/rd_processing_service.dart | 50 +- .../rd_single_order_controller.dart | 52 + lib/models/get_delivered_model.dart | 150 +++ lib/models/get_dispatch_model.dart | 191 +++ lib/models/get_invoice_model.dart | 243 ++++ lib/models/get_rd_cancelled_model.dart | 190 +++ lib/models/get_rd_pennding_model.dart | 179 +++ lib/models/rd_processing_invoice_model.dart | 191 +++ lib/models/single_get_order_model.dart | 264 +++++ .../rd orders/partial_pending_dialog.dart | 461 ++++++++ .../partial_processing_dialog_screen.dart | 404 +++++-- .../rd_cancelled_details_screen.dart | 830 +++++++++++++ .../rd orders/rd_cancelled_screen.dart | 350 ++++++ .../rd_delivered_details_screen.dart | 742 ++++++++++++ .../rd orders/rd_delivered_screen.dart | 369 ++++++ .../rd_dispatched_details_screen.dart | 838 +++++++++++++ .../rd orders/rd_dispatched_scree.dart | 376 ++++++ .../rd orders/rd_order_details_screen.dart | 883 ++++++++++++-- lib/screens/rd orders/rd_order_screen.dart | 65 +- lib/screens/rd orders/rd_pending_deatils.dart | 1035 +++++++++++++++++ lib/screens/rd orders/rd_pending_screen.dart | 304 +++++ .../rd orders/rd_processing_details.dart | 703 +++++++++++ .../rd orders/rd_processing_screen.dart | 298 +++++ lib/utils/api_urls.dart | 8 + 39 files changed, 9640 insertions(+), 252 deletions(-) create mode 100644 lib/controller/get_cancle_service.dart create mode 100644 lib/controller/get_delivered_controller.dart create mode 100644 lib/controller/get_delivered_service.dart create mode 100644 lib/controller/get_dispatch_controller.dart create mode 100644 lib/controller/get_dispatch_service.dart create mode 100644 lib/controller/get_pending_service.dart create mode 100644 lib/controller/get_rd_cancle_controller.dart create mode 100644 lib/controller/get_rd_pending_controller.dart create mode 100644 lib/controller/get_single_invoice_Service.dart create mode 100644 lib/controller/get_single_invoice_controller.dart create mode 100644 lib/controller/rd_get_single_service.dart create mode 100644 lib/controller/rd_processing_invoice_controller.dart create mode 100644 lib/controller/rd_processing_invoice_service.dart create mode 100644 lib/controller/rd_single_order_controller.dart create mode 100644 lib/models/get_delivered_model.dart create mode 100644 lib/models/get_dispatch_model.dart create mode 100644 lib/models/get_invoice_model.dart create mode 100644 lib/models/get_rd_cancelled_model.dart create mode 100644 lib/models/get_rd_pennding_model.dart create mode 100644 lib/models/rd_processing_invoice_model.dart create mode 100644 lib/models/single_get_order_model.dart create mode 100644 lib/screens/rd orders/partial_pending_dialog.dart create mode 100644 lib/screens/rd orders/rd_cancelled_details_screen.dart create mode 100644 lib/screens/rd orders/rd_cancelled_screen.dart create mode 100644 lib/screens/rd orders/rd_delivered_details_screen.dart create mode 100644 lib/screens/rd orders/rd_delivered_screen.dart create mode 100644 lib/screens/rd orders/rd_dispatched_details_screen.dart create mode 100644 lib/screens/rd orders/rd_dispatched_scree.dart create mode 100644 lib/screens/rd orders/rd_pending_deatils.dart create mode 100644 lib/screens/rd orders/rd_pending_screen.dart create mode 100644 lib/screens/rd orders/rd_processing_details.dart create mode 100644 lib/screens/rd orders/rd_processing_screen.dart diff --git a/lib/controller/get_cancle_service.dart b/lib/controller/get_cancle_service.dart new file mode 100644 index 0000000..08f7e04 --- /dev/null +++ b/lib/controller/get_cancle_service.dart @@ -0,0 +1,39 @@ +import 'package:cheminova/models/get_rd_cancelled_model.dart'; + +import '../models/rd_get_order_model.dart'; +import '../utils/api_urls.dart'; +import '../utils/common_api_service.dart'; + +class GetCancleService { + Future?> getRDCancleProduct(String token) async { + try { + String url = ApiUrls.getrdCancleOrderUrl; // Base URL to fetch product manuals + + final response = await commonApiService>( + method: "GET", + url: url, + additionalHeaders: { // Pass the token here + 'Authorization': 'Bearer $token', + }, + fromJson: (json) { + if (json['plcaedOrders'] != null) { + // If the productManuals key is present, map the response to a list of ProductManualModel objects + final List productManuals = (json['plcaedOrders'] as List) + .map((manualJson) => GetRdCancelledModel.fromJson(manualJson)) + .toList(); + return productManuals; // Return the list of product manuals + } else { + return []; + } + }, + ); + return response; + } catch (e) { + + print("fkfgghgh ,${e.toString()}"); + //print(e.toString()); + return null; + } + } + +} \ No newline at end of file diff --git a/lib/controller/get_delivered_controller.dart b/lib/controller/get_delivered_controller.dart new file mode 100644 index 0000000..5ff463c --- /dev/null +++ b/lib/controller/get_delivered_controller.dart @@ -0,0 +1,23 @@ +import 'package:cheminova/controller/get_delivered_service.dart'; +import 'package:cheminova/models/get_delivered_model.dart'; +import 'package:get/get.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +class GetDeliveredController extends GetxController{ + var isLoading = true.obs; // Tracks the loading state + var productProcessingRDList = [].obs; // List of products + // Fetch the products from the API + Future getRDDeliveredInvoiceProduct() async { + try { + SharedPreferences prefs = await SharedPreferences.getInstance(); + String? token = prefs.getString('token'); + isLoading(true); // Start loading + final response = await GetDeliveredService().getRDDeliveredProduct(token!); // Fetch products from API + if (response != null) { + productProcessingRDList.assignAll(response); // Assign products to the observable list + } + } finally { + isLoading(false); // End loading + } + } +} \ No newline at end of file diff --git a/lib/controller/get_delivered_service.dart b/lib/controller/get_delivered_service.dart new file mode 100644 index 0000000..39cfc82 --- /dev/null +++ b/lib/controller/get_delivered_service.dart @@ -0,0 +1,39 @@ +import 'package:cheminova/models/get_delivered_model.dart'; + +import '../utils/api_urls.dart'; +import '../utils/common_api_service.dart'; + +class GetDeliveredService { + + + Future?> getRDDeliveredProduct(String token) async { + try { + String url = ApiUrls.getRdDliveredOrdergUrl; // Base URL to fetch product manuals + + final response = await commonApiService>( + method: "GET", + url: url, + additionalHeaders: { // Pass the token here + 'Authorization': 'Bearer $token', + }, + fromJson: (json) { + if (json['invoices'] != null) { + // If the productManuals key is present, map the response to a list of ProductManualModel objects + final List productManuals = (json['invoices'] as List) + .map((manualJson) => GetDeliveredModel.fromJson(manualJson)) + .toList(); + return productManuals; // Return the list of product manuals + } else { + return []; + } + }, + ); + return response; + } catch (e) { + + print("fkfgghgh ,${e.toString()}"); + //print(e.toString()); + return null; + } + } +} \ No newline at end of file diff --git a/lib/controller/get_dispatch_controller.dart b/lib/controller/get_dispatch_controller.dart new file mode 100644 index 0000000..4d6de68 --- /dev/null +++ b/lib/controller/get_dispatch_controller.dart @@ -0,0 +1,75 @@ +import 'package:cheminova/controller/get_dispatch_service.dart'; +import 'package:cheminova/models/get_dispatch_model.dart'; +import 'package:get/get.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +class GetDispatchController extends GetxController{ + var isLoading = true.obs; // Tracks the loading state + var productProcessingRDList = [].obs; // Li + // Fetch the products from the API + Future getRDDispatchInvoiceProduct() async { + try { + SharedPreferences prefs = await SharedPreferences.getInstance(); + String? token = prefs.getString('token'); + isLoading(true); // Start loading + final response = await GetDispatchService().getRDDispatchedProduct(token!); // Fetch products from API + if (response != null) { + productProcessingRDList.assignAll(response); // Assign products to the observable list + } + } finally { + isLoading(false); // End loading + } + } + + + Future RDProcessingToDispatchProduct(String orderId, String courierName,String couriertrackingId) async { + try { + SharedPreferences prefs = await SharedPreferences.getInstance(); + String? token = prefs.getString('token'); // Get the token + + if (token == null || token.isEmpty) { + throw Exception("Token is missing. Please login again."); + } + + isLoading(true); // Show loading indicator + + // Call the service function and pass the token, orderId, and reason + await GetDispatchService().RDProcessingToDispatchOrder(token, orderId, courierName,couriertrackingId); + + // Optionally refresh the data or show success message + print("Order Dispatched process complete."); + } catch (e) { + print("Error: $e"); + } finally { + isLoading(false); // Hide loading indicator + } + } + + + + + + Future RDDispatchToDeliveredProduct(String orderId) async { + try { + SharedPreferences prefs = await SharedPreferences.getInstance(); + String? token = prefs.getString('token'); // Get the token + + if (token == null || token.isEmpty) { + throw Exception("Token is missing. Please login again."); + } + + isLoading(true); // Show loading indicator + + // Call the service function and pass the token, orderId, and reason + await GetDispatchService().RDDispatchToDeliveredOrder(token, orderId,); + + // Optionally refresh the data or show success message + print("Order Delivered process complete."); + } catch (e) { + print("Error: $e"); + } finally { + isLoading(false); // Hide loading indicator + } + } + +} \ No newline at end of file diff --git a/lib/controller/get_dispatch_service.dart b/lib/controller/get_dispatch_service.dart new file mode 100644 index 0000000..16ff4d8 --- /dev/null +++ b/lib/controller/get_dispatch_service.dart @@ -0,0 +1,104 @@ +import 'package:cheminova/models/get_dispatch_model.dart'; +import 'package:dio/dio.dart'; + +import '../utils/api_urls.dart'; +import '../utils/common_api_service.dart'; + +class GetDispatchService{ + + Future?> getRDDispatchedProduct(String token) async { + try { + String url = ApiUrls.getRdDispatchedOrdergUrl; // Base URL to fetch product manuals + + final response = await commonApiService>( + method: "GET", + url: url, + additionalHeaders: { // Pass the token here + 'Authorization': 'Bearer $token', + }, + fromJson: (json) { + if (json['invoices'] != null) { + // If the productManuals key is present, map the response to a list of ProductManualModel objects + final List productManuals = (json['invoices'] as List) + .map((manualJson) => GetDispatchModel.fromJson(manualJson)) + .toList(); + return productManuals; // Return the list of product manuals + } else { + return []; + } + }, + ); + return response; + } catch (e) { + + print("fkfgghgh ,${e.toString()}"); + //print(e.toString()); + return null; + } + } + + + Future RDProcessingToDispatchOrder(String token, String orderId, String courierName,String couriertrackingId) async { + try { + // Correct API URL with orderId passed in the URL + final String url = 'https://api.cnapp.co.in/api/pd-invoice/dispatched/$orderId'; + + // Make the PUT request + final response = await Dio().put( + url, // Use the correct URL here + data: { + "courierName": courierName, + "couriertrackingId":couriertrackingId, + // Send the cancellation reason as JSON + }, + options: Options( + headers: { + 'Authorization': 'Bearer $token', // Pass the token in the Authorization header + 'Content-Type': 'application/json', // Set content-type to application/json + }, + ), + ); + + // Check the response status + if (response.statusCode == 200) { + print("Order Dispatched successfully"); + } else { + throw Exception('Failed to Dispatched the order'); + } + } catch (e) { + // Handle error + print('Error Dispatched the order: $e'); + } + } + + + Future RDDispatchToDeliveredOrder(String token, String orderId,) async { + try { + // Correct API URL with orderId passed in the URL + final String url = 'https://api.cnapp.co.in/api/pd-invoice/delivered/$orderId'; + + // Make the PUT request + final response = await Dio().put( + url, // Use the correct URL here + + options: Options( + headers: { + 'Authorization': 'Bearer $token', // Pass the token in the Authorization header + 'Content-Type': 'application/json', // Set content-type to application/json + }, + ), + ); + + // Check the response status + if (response.statusCode == 200) { + print("Order cancelled successfully"); + } else { + throw Exception('Failed to cancel the order'); + } + } catch (e) { + // Handle error + print('Error cancelling the order: $e'); + } + } + +} \ No newline at end of file diff --git a/lib/controller/get_pending_service.dart b/lib/controller/get_pending_service.dart new file mode 100644 index 0000000..b1d1600 --- /dev/null +++ b/lib/controller/get_pending_service.dart @@ -0,0 +1,39 @@ +import 'package:cheminova/models/get_rd_pennding_model.dart'; + +import '../utils/api_urls.dart'; +import '../utils/common_api_service.dart'; + +class GetPendingService{ + + Future?> getRDPendingProduct(String token) async { + try { + String url = ApiUrls.getRdPendingOrdergUrl; // Base URL to fetch product manuals + + final response = await commonApiService>( + method: "GET", + url: url, + additionalHeaders: { // Pass the token here + 'Authorization': 'Bearer $token', + }, + fromJson: (json) { + if (json['plcaedOrders'] != null) { + // If the productManuals key is present, map the response to a list of ProductManualModel objects + final List productManuals = (json['plcaedOrders'] as List) + .map((manualJson) => GetRdPendingModel.fromJson(manualJson)) + .toList(); + return productManuals; // Return the list of product manuals + } else { + return []; + } + }, + ); + return response; + } catch (e) { + + print("fkfgghgh ,${e.toString()}"); + //print(e.toString()); + return null; + } + } + +} \ No newline at end of file diff --git a/lib/controller/get_rd_cancle_controller.dart b/lib/controller/get_rd_cancle_controller.dart new file mode 100644 index 0000000..4d3e014 --- /dev/null +++ b/lib/controller/get_rd_cancle_controller.dart @@ -0,0 +1,28 @@ +import 'package:cheminova/controller/rd_get_order_service.dart'; +import 'package:cheminova/controller/rd_get_single_service.dart'; +import 'package:cheminova/models/get_rd_cancelled_model.dart'; +import 'package:cheminova/models/rd_get_order_model.dart'; +import 'package:cheminova/models/single_get_order_model.dart'; +import 'package:get/get.dart'; +import 'package:get/get_state_manager/src/simple/get_controllers.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +import 'get_cancle_service.dart'; + +class GetRDCancleController extends GetxController { + var isLoading = true.obs; // Tracks the loading state + var productRDList = [].obs; + Future getRDCancleProduct() async { + try { + SharedPreferences prefs = await SharedPreferences.getInstance(); + String? token = prefs.getString('token'); + //isLoading(true); // Start loading + final response = await GetCancleService().getRDCancleProduct(token!); // Fetch products from API + if (response != null) { + productRDList.assignAll(response); // Assign products to the observable list + } + } finally { + isLoading(false); // End loading + } + } +} \ No newline at end of file diff --git a/lib/controller/get_rd_pending_controller.dart b/lib/controller/get_rd_pending_controller.dart new file mode 100644 index 0000000..a2ef9a9 --- /dev/null +++ b/lib/controller/get_rd_pending_controller.dart @@ -0,0 +1,24 @@ +import 'package:cheminova/controller/get_pending_service.dart'; +import 'package:cheminova/models/get_rd_pennding_model.dart'; +import 'package:get/get.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +class GetRdPendingController extends GetxController{ + var isLoading = true.obs; // Tracks the loading state + var productRDList = [].obs; // List of products + Future getRDPendingProduct() async { + + try { + SharedPreferences prefs = await SharedPreferences.getInstance(); + String? token = prefs.getString('token'); + isLoading(true); // Start loading + final response = await GetPendingService().getRDPendingProduct(token!); // Fetch products from API + if (response != null) { + productRDList.assignAll(response); // Assign products to the observable list + } + } finally { + isLoading(false); // End loading + } + } + +} \ No newline at end of file diff --git a/lib/controller/get_single_invoice_Service.dart b/lib/controller/get_single_invoice_Service.dart new file mode 100644 index 0000000..fa2530b --- /dev/null +++ b/lib/controller/get_single_invoice_Service.dart @@ -0,0 +1,33 @@ +import 'package:dio/dio.dart'; + +import '../models/get_invoice_model.dart'; +import '../utils/api_urls.dart'; +import '../utils/common_api_service.dart'; + +class GetSingleInvoiceService{ + final Dio _dio = Dio(); + + Future fetchInvoice(String token, String invoiceId) async { + final url = 'https://api.cnapp.co.in/api/pd-get-invoices/$invoiceId'; + + try { + final response = await _dio.get( + url, + options: Options( + headers: { + 'Authorization': 'Bearer $token', + }, + ) + ); + + if (response.statusCode == 200) { + return GetInvoiceModel.fromJson(response.data); + } else { + throw Exception('Failed to load invoice'); + } + } catch (e) { + print(e); // Handle error here + return null; + } + } +} \ No newline at end of file diff --git a/lib/controller/get_single_invoice_controller.dart b/lib/controller/get_single_invoice_controller.dart new file mode 100644 index 0000000..69f696e --- /dev/null +++ b/lib/controller/get_single_invoice_controller.dart @@ -0,0 +1,38 @@ +import 'package:cheminova/models/get_invoice_model.dart'; +import 'package:get/get.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +import 'get_single_invoice_Service.dart'; + +class GetSingleInvoiceController extends GetxController { +// Import your Invoice model file + + // Observable for holding the fetched invoice + var invoice = [].obs; + var isLoading = true.obs; // Observable for loading state + var errorMessage = ''.obs; // Observable for error message + + @override + void onInit() { + super.onInit(); + + // Call fetchInvoice with a specific ID + } + + Future fetchInvoice(String invoiceId) async { + isLoading.value = true; // Set loading state to true + try { + SharedPreferences prefs = await SharedPreferences.getInstance(); + String? token = prefs.getString('token'); + invoice.value = (await GetSingleInvoiceService().fetchInvoice(token!,invoiceId)) + as List; + if (invoice.value == null) { + errorMessage.value = 'Invoice not found'; + } + } catch (e) { + errorMessage.value = e.toString(); // Set the error message + } finally { + isLoading.value = false; // Set loading state to false + } + } +} diff --git a/lib/controller/rd_get_order_controller.dart b/lib/controller/rd_get_order_controller.dart index 2fe1bd3..a6f502a 100644 --- a/lib/controller/rd_get_order_controller.dart +++ b/lib/controller/rd_get_order_controller.dart @@ -1,5 +1,6 @@ import 'package:cheminova/controller/product_mannual_service.dart'; import 'package:cheminova/controller/rd_get_order_service.dart'; +import 'package:cheminova/controller/rd_get_single_service.dart'; import 'package:cheminova/models/rd_get_order_model.dart'; import 'package:get/get.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -33,34 +34,23 @@ class GetProductRDController extends GetxController { - Future getRDPendingProduct() async { - try { - SharedPreferences prefs = await SharedPreferences.getInstance(); - String? token = prefs.getString('token'); - isLoading(true); // Start loading - final response = await GetProductRDService().getRDPendingProduct(token!); // Fetch products from API - if (response != null) { - productRDList.assignAll(response); // Assign products to the observable list - } - } finally { - isLoading(false); // End loading - } - } + // Future fetchRDSingleProduct() async { + // try { + // SharedPreferences prefs = await SharedPreferences.getInstance(); + // String? token = prefs.getString('token'); + // isLoading(true); // Start loading + // final response = await GetSingleProductService().getSingleOrder(productRDList[0].id,token!); // Fetch products from API + // if (response != null) { + // // productRDList.assignAll(response); // Assign products to the observable list + // } + // } finally { + // isLoading(false); // End loading + // } + // } + // + - Future getRDCancleProduct() async { - try { - SharedPreferences prefs = await SharedPreferences.getInstance(); - String? token = prefs.getString('token'); - isLoading(true); // Start loading - final response = await GetProductRDService().getRDCancleProduct(token!); // Fetch products from API - if (response != null) { - productRDList.assignAll(response); // Assign products to the observable list - } - } finally { - isLoading(false); // End loading - } - } } diff --git a/lib/controller/rd_get_order_service.dart b/lib/controller/rd_get_order_service.dart index e73095e..0861305 100644 --- a/lib/controller/rd_get_order_service.dart +++ b/lib/controller/rd_get_order_service.dart @@ -40,68 +40,7 @@ class GetProductRDService { - Future?> getRDPendingProduct(String token) async { - try { - String url = ApiUrls.getRdPendingOrdergUrl; // Base URL to fetch product manuals - final response = await commonApiService>( - method: "GET", - url: url, - additionalHeaders: { // Pass the token here - 'Authorization': 'Bearer $token', - }, - fromJson: (json) { - if (json['plcaedOrders'] != null) { - // If the productManuals key is present, map the response to a list of ProductManualModel objects - final List productManuals = (json['plcaedOrders'] as List) - .map((manualJson) => PlacedOrdersResponse.fromJson(manualJson)) - .toList(); - return productManuals; // Return the list of product manuals - } else { - return []; - } - }, - ); - return response; - } catch (e) { - - print("fkfgghgh ,${e.toString()}"); - //print(e.toString()); - return null; - } - } - - - Future?> getRDCancleProduct(String token) async { - try { - String url = ApiUrls.getrdCancleOrderUrl; // Base URL to fetch product manuals - - final response = await commonApiService>( - method: "GET", - url: url, - additionalHeaders: { // Pass the token here - 'Authorization': 'Bearer $token', - }, - fromJson: (json) { - if (json['plcaedOrders'] != null) { - // If the productManuals key is present, map the response to a list of ProductManualModel objects - final List productManuals = (json['plcaedOrders'] as List) - .map((manualJson) => PlacedOrdersResponse.fromJson(manualJson)) - .toList(); - return productManuals; // Return the list of product manuals - } else { - return []; - } - }, - ); - return response; - } catch (e) { - - print("fkfgghgh ,${e.toString()}"); - //print(e.toString()); - return null; - } - } diff --git a/lib/controller/rd_get_single_service.dart b/lib/controller/rd_get_single_service.dart new file mode 100644 index 0000000..7158a88 --- /dev/null +++ b/lib/controller/rd_get_single_service.dart @@ -0,0 +1,73 @@ +import 'dart:convert'; + +import 'package:cheminova/models/single_get_order_model.dart'; +import 'package:dio/dio.dart'; + +import '../models/rd_get_order_model.dart'; +import '../utils/api_urls.dart'; +import '../utils/common_api_service.dart'; +import '../utils/show_snackbar.dart'; + +class GetSingleProductService{ + // Future getSingleOrder(String token,String orderId) async { + // try { + // // Ensure the base URL and orderId are concatenated properly + // String url = "/api/pd-get-single-place-order/$orderId"; + // + // final response = await commonApiService( + // method: "GET", + // url: url, + // additionalHeaders: { + // 'Authorization': 'Bearer $token', // Correctly pass the token as 'Bearer ' + // }, + // fromJson: (json) { + // // Check if the JSON response contains the 'singleOrder' key + // if (json['singleOrder'] != null) { + // // Convert the JSON response to a SingleGetOrderModel + // return SingleGetOrderModel.fromJson(json['singleOrder'] as Map); + // } else { + // // Handle the case when the order is not found + // throw Exception("Order not found in response."); + // } + // }, + // ); + // + // return response; // Return the fetched order if successful + // } catch (e) { + // // Show a snackbar with the error message + // showSnackbar(e.toString()); + // return null; // Return null to indicate an error occurred + // } + // } + + + + +Future GetsingleOrder(String token,String orderId) async { + try { + final response = await Dio().get( + 'https://api.cnapp.co.in/api/pd-get-single-place-order/$orderId', + + options: Options( + headers: { + 'Authorization': 'Bearer $token', + }, + ), + ); + + + if (response.statusCode == 200) { + final data = response.data['singleOrder']; + jsonDecode(data); + return SingleGetOrderModel.fromJson(data); + } else { + print('Failed to load order'); + return null; + } + } catch (e) { + print('Error: $e'); + return null; + } + } + +} \ No newline at end of file diff --git a/lib/controller/rd_processing_invoice_controller.dart b/lib/controller/rd_processing_invoice_controller.dart new file mode 100644 index 0000000..657418b --- /dev/null +++ b/lib/controller/rd_processing_invoice_controller.dart @@ -0,0 +1,57 @@ +import 'package:cheminova/controller/product_mannual_service.dart'; +import 'package:cheminova/controller/rd_get_order_service.dart'; +import 'package:cheminova/controller/rd_processing_invoice_service.dart'; +import 'package:cheminova/models/rd_get_order_model.dart'; +import 'package:cheminova/models/rd_processing_invoice_model.dart'; +import 'package:get/get.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import '../models/product_mannual_model.dart'; // Your model import +// Your service import + +class GetRDProcessingInvoiceController extends GetxController { + var isLoading = true.obs; // Tracks the loading state + var productProcessingRDList = [].obs; // List of products + var productDispatchRDList = [].obs; + var productDeliveredRDList = [].obs; + @override + void onInit() { + getRDProcessingInvoiceProduct(); + super.onInit(); + } + + // Fetch the products from the API + // Fetch the products from the API + Future getRDProcessingInvoiceProduct() async { + try { + SharedPreferences prefs = await SharedPreferences.getInstance(); + String? token = prefs.getString('token'); + + // Check if the token is null + if (token == null) { + // Handle the case where the token is not available + print("Error: Token is null. Please login again."); + return; // Optionally, you can navigate the user to the login screen + } + + isLoading(true); // Start loading + + // Fetch products from API + final response = await RdProcessingInvoiceService().getRDProcessingProduct(token); + + // Check if response is not null and assign it to the observable list + if (response != null) { + productProcessingRDList.assignAll(response); // Assign products to the observable list + } else { + // Optionally handle the case where the response is null + print("No products found or response is null."); + } + } catch (e) { + // Handle any exceptions that occur during the fetch + print("An error occurred while fetching products: ${e.toString()}"); + } finally { + isLoading(false); // End loading regardless of success or failure + } + } + +} + diff --git a/lib/controller/rd_processing_invoice_service.dart b/lib/controller/rd_processing_invoice_service.dart new file mode 100644 index 0000000..d9aa2b1 --- /dev/null +++ b/lib/controller/rd_processing_invoice_service.dart @@ -0,0 +1,41 @@ +import 'package:cheminova/models/rd_processing_invoice_model.dart'; + +import '../utils/api_urls.dart'; +import '../utils/common_api_service.dart'; + +class RdProcessingInvoiceService{ + + Future?> getRDProcessingProduct(String token) async { + try { + String url = ApiUrls.getRdProcessingInvoiceOrdergUrl; // Base URL to fetch product manuals + + final response = await commonApiService>( + method: "GET", + url: url, + additionalHeaders: { // Pass the token here + 'Authorization': 'Bearer $token', + }, + fromJson: (json) { + // Check if the 'invoices' key is present and is a list + if (json['invoices'] != null && json['invoices'] is List) { + // Map the response to a list of InvoiceResponseModel objects + final List productManuals = (json['invoices'] as List) + .map((manualJson) => InvoiceResponseModel.fromJson(manualJson)) + .toList(); + return productManuals; // Return the list of product manuals + } else { + // If 'invoices' is null or not a list, return an empty list or handle it as needed + return []; + } + }, + ); + + return response; + } catch (e) { + print("Error: ${e.toString()}"); + return null; + } + } + + +} \ No newline at end of file diff --git a/lib/controller/rd_processing_service.dart b/lib/controller/rd_processing_service.dart index 275c47c..39d1e32 100644 --- a/lib/controller/rd_processing_service.dart +++ b/lib/controller/rd_processing_service.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'package:cheminova/models/rd_placed_order_model.dart'; import 'package:cheminova/utils/api_urls.dart'; +import 'package:cheminova/utils/show_snackbar.dart'; import 'package:flutter/material.dart'; import 'package:dio/dio.dart'; import '../models/rd_order_item_model.dart'; @@ -10,11 +11,13 @@ import '../models/rd_order_item_model.dart'; class RDOrderPlacedService { final Dio _dio = Dio(); // Create Dio instance - Future placRDeOrder(PlacedOrdersProcessing orderDetails, String token) async { + Future placRDeOrder(PlacedOrdersProcessing orderDetails, + String token) async { //try { // logger.w("orderjson ${jsonEncode(orderDetails.toJson())}"); final response = await _dio.post( - 'https://api.cnapp.co.in/api/pd-process-order', // Ensure this is your correct endpoint + 'https://api.cnapp.co.in/api/pd-process-order', + // Ensure this is your correct endpoint data: jsonEncode(orderDetails.toJson()), options: Options( headers: { @@ -25,16 +28,41 @@ class RDOrderPlacedService { ); //logger.w("Status code,${response.statusCode}"); if (response.statusCode != 200) { - throw Exception('Failed to RD place order'); } + } -// on DioException catch (e) { -// print("DioException: ${e.message}"); -// throw Exception('Failed to place order: ${e.message}'); -// } -// catch (e) { -// print("General Exception: ${e.toString()}"); -// throw Exception('Failed to place order: ${e.toString()}'); -// } + + Future RDOrderCancel(String token, String orderId, String reason) async { + try { + // Correct API URL with orderId passed in the URL + final String url = 'https://api.cnapp.co.in/api/pd-cancel-order/$orderId'; + + // Make the PUT request + final response = await _dio.put( + url, // Use the correct URL here + data: { + "cancellationReason": reason, // Send the cancellation reason as JSON + }, + options: Options( + headers: { + 'Authorization': 'Bearer $token', // Pass the token in the Authorization header + 'Content-Type': 'application/json', // Set content-type to application/json + }, + ), + ); + + // Check the response status + if (response.statusCode == 200) { + print("Order cancelled successfully"); + } else { + throw Exception('Failed to cancel the order'); + } + } catch (e) { + // Handle error + print('Error cancelling the order: $e'); + } + } + } + diff --git a/lib/controller/rd_single_order_controller.dart b/lib/controller/rd_single_order_controller.dart new file mode 100644 index 0000000..041d3a2 --- /dev/null +++ b/lib/controller/rd_single_order_controller.dart @@ -0,0 +1,52 @@ +import 'dart:convert'; +import 'package:cheminova/controller/rd_get_single_service.dart'; +import 'package:cheminova/models/single_get_order_model.dart'; +import 'package:get/get.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import '../utils/show_snackbar.dart'; + +class RdSingleOrderController extends GetxController { + var isLoading = true.obs; // Tracks the loading state + var productRDOrderSingleList = [].obs; // List of products + + Future fetchRDSingleOrderProduct(String id) async { + try { + SharedPreferences prefs = await SharedPreferences.getInstance(); + String? token = prefs.getString('token'); + + // Check if the token exists before proceeding + if (token == null || token.isEmpty) { + print("Token is missing"); + throw Exception("Token is missing"); + } + + print("Login token: $token"); + isLoading(true); // Start loading + + // Check if the list has any elements + if (productRDOrderSingleList.isEmpty) { + print("No orders found."); + showSnackbar("No orders found."); + return; // Early exit if no orders are available + } + + // Fetch the product using the API call, passing the token + final response = await GetSingleProductService().GetsingleOrder(token, id); + + if (response != null) { + // Assign the fetched products to the observable list (uncomment this if needed) + // productRDOrderSingleList.assignAll(response); + print("Fetched order details: $response"); + } else { + print("Response is null"); + showSnackbar("Response is null"); + } + } catch (e) { + // Print the error for debugging + print("Error: $e"); + showSnackbar("Error: $e"); + } finally { + isLoading(false); // End loading + } + } +} diff --git a/lib/models/get_delivered_model.dart b/lib/models/get_delivered_model.dart new file mode 100644 index 0000000..1f5781f --- /dev/null +++ b/lib/models/get_delivered_model.dart @@ -0,0 +1,150 @@ +// class GetDeliveredModel { +// int totalCount; +// int currentPage; +// int totalPages; +// List invoices; +// +// GetDeliveredModel({ +// required this.totalCount, +// required this.currentPage, +// required this.totalPages, +// required this.invoices, +// }); +// +// factory GetDeliveredModel.fromJson(Map json) { +// return GetDeliveredModel( +// totalCount: json['totalCount'], +// currentPage: json['currentPage'], +// totalPages: json['totalPages'], +// invoices: List.from( +// json['invoices'].map((invoice) => Invoice.fromJson(invoice)), +// ), +// ); +// } +// } + +class GetDeliveredModel { + CourierStatusTimeline courierStatusTimeline; + String id; + String invoiceId; + OrderId orderId; + List items; + int subtotal; + double gstTotal; + double invoiceAmount; + String courierStatus; + int v; + String courierName; + String courierTrackingId; + + GetDeliveredModel({ + required this.courierStatusTimeline, + required this.id, + required this.invoiceId, + required this.orderId, + required this.items, + required this.subtotal, + required this.gstTotal, + required this.invoiceAmount, + required this.courierStatus, + required this.v, + required this.courierName, + required this.courierTrackingId, + }); + + factory GetDeliveredModel.fromJson(Map json) { + return GetDeliveredModel( + courierStatusTimeline: CourierStatusTimeline.fromJson( + json['courierstatus_timeline']), + id: json['_id'], + invoiceId: json['invoiceId'], + orderId: OrderId.fromJson(json['orderId']), + items: List.from(json['items'].map((item) => Item.fromJson(item))), + subtotal: json['subtotal'], + gstTotal: json['gstTotal'].toDouble(), + invoiceAmount: json['invoiceAmount'].toDouble(), + courierStatus: json['courierStatus'], + v: json['__v'], + courierName: json['courier_name'], + courierTrackingId: json['courier_tracking_id'], + ); + } +} + +class CourierStatusTimeline { + String processing; + String dispatched; + String delivered; + + CourierStatusTimeline({ + required this.processing, + required this.dispatched, + required this.delivered, + }); + + factory CourierStatusTimeline.fromJson(Map json) { + return CourierStatusTimeline( + processing: json['processing'], + dispatched: json['dispatched'], + delivered: json['delivered'], + ); + } +} + +class OrderId { + String id; + String uniqueId; + + OrderId({ + required this.id, + required this.uniqueId, + }); + + factory OrderId.fromJson(Map json) { + return OrderId( + id: json['_id'], + uniqueId: json['uniqueId'], + ); + } +} + +class Item { + String productId; + String sku; + String name; + String categoryName; + String brandName; + int price; + int gst; + int hsnCode; + int processQuantity; + String id; + + Item({ + required this.productId, + required this.sku, + required this.name, + required this.categoryName, + required this.brandName, + required this.price, + required this.gst, + required this.hsnCode, + required this.processQuantity, + required this.id, + }); + + factory Item.fromJson(Map json) { + return Item( + productId: json['productId'], + sku: json['SKU'], + name: json['name'], + categoryName: json['categoryName'], + brandName: json['brandName'], + price: json['price'], + gst: json['GST'], + hsnCode: json['HSN_Code'], + processQuantity: json['processquantity'], + id: json['_id'], + ); + } +} diff --git a/lib/models/get_dispatch_model.dart b/lib/models/get_dispatch_model.dart new file mode 100644 index 0000000..9a96518 --- /dev/null +++ b/lib/models/get_dispatch_model.dart @@ -0,0 +1,191 @@ +// class GetDispatchModel { +// int totalCount; +// int currentPage; +// int totalPages; +// List invoices; +// +// GetDispatchModel({ +// required this.totalCount, +// required this.currentPage, +// required this.totalPages, +// required this.invoices, +// }); +// +// factory GetDispatchModel.fromJson(Map json) { +// return GetDispatchModel( +// totalCount: json['totalCount']??0, +// currentPage: json['currentPage']??1, +// totalPages: json['totalPages']??1, +// invoices: List.from(json['invoices'].map((x) => Invoice.fromJson(x))), +// ); +// } +// +// Map toJson() { +// return { +// 'totalCount': totalCount, +// 'currentPage': currentPage, +// 'totalPages': totalPages, +// 'invoices': invoices.map((x) => x.toJson()).toList(), +// }; +// } +// } + +class GetDispatchModel { + String id; + String invoiceId; + OrderId orderId; + List items; + double subtotal; + double gstTotal; + double invoiceAmount; + String courierStatus; + CourierStatusTimeline courierstatusTimeline; + String courierName; + String courierTrackingId; + + GetDispatchModel({ + required this.id, + required this.invoiceId, + required this.orderId, + required this.items, + required this.subtotal, + required this.gstTotal, + required this.invoiceAmount, + required this.courierStatus, + required this.courierstatusTimeline, + required this.courierName, + required this.courierTrackingId, + }); + + factory GetDispatchModel.fromJson(Map json) { + return GetDispatchModel( + id: json['_id'], + invoiceId: json['invoiceId'], + orderId: OrderId.fromJson(json['orderId']), + items: List.from(json['items'].map((x) => Item.fromJson(x))), + subtotal: json['subtotal'].toDouble(), + gstTotal: json['gstTotal'].toDouble(), + invoiceAmount: json['invoiceAmount'].toDouble(), + courierStatus: json['courierStatus'], + courierstatusTimeline: CourierStatusTimeline.fromJson(json['courierstatus_timeline']), + courierName: json['courier_name'], + courierTrackingId: json['courier_tracking_id'], + ); + } + + Map toJson() { + return { + '_id': id, + 'invoiceId': invoiceId, + 'orderId': orderId.toJson(), + 'items': items.map((x) => x.toJson()).toList(), + 'subtotal': subtotal, + 'gstTotal': gstTotal, + 'invoiceAmount': invoiceAmount, + 'courierStatus': courierStatus, + 'courierstatus_timeline': courierstatusTimeline.toJson(), + 'courier_name': courierName, + 'courier_tracking_id': courierTrackingId, + }; + } +} + +class OrderId { + String id; + String uniqueId; + + OrderId({ + required this.id, + required this.uniqueId, + }); + + factory OrderId.fromJson(Map json) { + return OrderId( + id: json['_id'], + uniqueId: json['uniqueId'], + ); + } + + Map toJson() { + return { + '_id': id, + 'uniqueId': uniqueId, + }; + } +} + +class Item { + String productId; + String SKU; + String name; + String categoryName; + String brandName; + double price; + int GST; + int HSNCode; + int processquantity; + + Item({ + required this.productId, + required this.SKU, + required this.name, + required this.categoryName, + required this.brandName, + required this.price, + required this.GST, + required this.HSNCode, + required this.processquantity, + }); + + factory Item.fromJson(Map json) { + return Item( + productId: json['productId'], + SKU: json['SKU'], + name: json['name'], + categoryName: json['categoryName'], + brandName: json['brandName'], + price: json['price'].toDouble(), + GST: json['GST'], + HSNCode: json['HSN_Code'], + processquantity: json['processquantity'], + ); + } + + Map toJson() { + return { + 'productId': productId, + 'SKU': SKU, + 'name': name, + 'categoryName': categoryName, + 'brandName': brandName, + 'price': price, + 'GST': GST, + 'HSN_Code': HSNCode, + 'processquantity': processquantity, + }; + } +} + +class CourierStatusTimeline { + String processing; + String dispatched; + + CourierStatusTimeline({ + required this.processing, + required this.dispatched, + }); + + factory CourierStatusTimeline.fromJson(Map json) { + return CourierStatusTimeline( + processing: json['processing'], + dispatched: json['dispatched'], + ); + } + + Map toJson() { + return { + 'processing': processing, + 'dispatched': dispatched, + }; + } +} diff --git a/lib/models/get_invoice_model.dart b/lib/models/get_invoice_model.dart new file mode 100644 index 0000000..3bb1c8a --- /dev/null +++ b/lib/models/get_invoice_model.dart @@ -0,0 +1,243 @@ +class GetInvoiceModel { + CourierStatusTimeline courierStatusTimeline; + String id; + String invoiceId; + OrderId orderId; + List items; + int subtotal; + double gstTotal; + double invoiceAmount; + String courierStatus; + int v; + + GetInvoiceModel({ + required this.courierStatusTimeline, + required this.id, + required this.invoiceId, + required this.orderId, + required this.items, + required this.subtotal, + required this.gstTotal, + required this.invoiceAmount, + required this.courierStatus, + required this.v, + }); + + factory GetInvoiceModel.fromJson(Map json) { + return GetInvoiceModel( + courierStatusTimeline: CourierStatusTimeline.fromJson( + json['courierstatus_timeline']), + id: json['_id'], + invoiceId: json['invoiceId'], + orderId: OrderId.fromJson(json['orderId']), + items: List.from(json['items'].map((item) => Item.fromJson(item))), + subtotal: json['subtotal'], + gstTotal: json['gstTotal'].toDouble(), + invoiceAmount: json['invoiceAmount'].toDouble(), + courierStatus: json['courierStatus'], + v: json['__v'], + ); + } +} + +class CourierStatusTimeline { + String processing; + + CourierStatusTimeline({ + required this.processing, + }); + + factory CourierStatusTimeline.fromJson(Map json) { + return CourierStatusTimeline( + processing: json['processing'], + ); + } +} + +class OrderId { + String id; + String paymentMode; + String shipTo; + String billTo; + List orderItems; + int subtotal; + double gstTotal; + double grandTotal; + String status; + List invoices; + AddedBy addedBy; + String pd; + bool isCancelled; + bool isDelivered; + String deliveredDate; + String statusUpdatedAt; + String uniqueId; + String createdAt; + String updatedAt; + int v; + + OrderId({ + required this.id, + required this.paymentMode, + required this.shipTo, + required this.billTo, + required this.orderItems, + required this.subtotal, + required this.gstTotal, + required this.grandTotal, + required this.status, + required this.invoices, + required this.addedBy, + required this.pd, + required this.isCancelled, + required this.isDelivered, + required this.deliveredDate, + required this.statusUpdatedAt, + required this.uniqueId, + required this.createdAt, + required this.updatedAt, + required this.v, + }); + + factory OrderId.fromJson(Map json) { + return OrderId( + id: json['_id'], + paymentMode: json['paymentMode'], + shipTo: json['shipTo'], + billTo: json['billTo'], + orderItems: List.from(json['orderItem'].map((item) => OrderItem.fromJson(item))), + subtotal: json['subtotal'], + gstTotal: json['gstTotal'].toDouble(), + grandTotal: json['grandTotal'].toDouble(), + status: json['status'], + invoices: List.from(json['invoices']), + addedBy: AddedBy.fromJson(json['addedBy']), + pd: json['pd'], + isCancelled: json['iscancelled'], + isDelivered: json['isDelivered'], + deliveredDate: json['DeliveredDate'] ?? '', + statusUpdatedAt: json['statusUpdatedAt'], + uniqueId: json['uniqueId'], + createdAt: json['createdAt'], + updatedAt: json['updatedAt'], + v: json['__v'], + ); + } +} + +class OrderItem { + String productId; + String sku; + String name; + String categoryName; + String brandName; + int price; + int gst; + int hsnCode; + String description; + List image; + int quantity; + int remainingQuantity; + String id; + + OrderItem({ + required this.productId, + required this.sku, + required this.name, + required this.categoryName, + required this.brandName, + required this.price, + required this.gst, + required this.hsnCode, + required this.description, + required this.image, + required this.quantity, + required this.remainingQuantity, + required this.id, + }); + + factory OrderItem.fromJson(Map json) { + return OrderItem( + productId: json['productId'], + sku: json['SKU'], + name: json['name'], + categoryName: json['categoryName'], + brandName: json['brandName'], + price: json['price'], + gst: json['GST'], + hsnCode: json['HSN_Code'], + description: json['description'] ?? '', + image: List.from(json['image']), + quantity: json['quantity'], + remainingQuantity: json['remainingQuantity'], + id: json['_id'], + ); + } +} + +class Item { + String productId; + String sku; + String name; + String categoryName; + String brandName; + int price; + int gst; + int hsnCode; + int processQuantity; + String id; + + Item({ + required this.productId, + required this.sku, + required this.name, + required this.categoryName, + required this.brandName, + required this.price, + required this.gst, + required this.hsnCode, + required this.processQuantity, + required this.id, + }); + + factory Item.fromJson(Map json) { + return Item( + productId: json['productId'], + sku: json['SKU'], + name: json['name'], + categoryName: json['categoryName'], + brandName: json['brandName'], + price: json['price'], + gst: json['GST'], + hsnCode: json['HSN_Code'], + processQuantity: json['processquantity'], + id: json['_id'], + ); + } +} + +class AddedBy { + String id; + String name; + String email; + String mobileNumber; + dynamic fcmToken; + + AddedBy({ + required this.id, + required this.name, + required this.email, + required this.mobileNumber, + this.fcmToken, + }); + + factory AddedBy.fromJson(Map json) { + return AddedBy( + id: json['_id'], + name: json['name'], + email: json['email'], + mobileNumber: json['mobile_number'], + fcmToken: json['fcm_token'], + ); + } +} diff --git a/lib/models/get_rd_cancelled_model.dart b/lib/models/get_rd_cancelled_model.dart new file mode 100644 index 0000000..eb89d49 --- /dev/null +++ b/lib/models/get_rd_cancelled_model.dart @@ -0,0 +1,190 @@ +class GetRdCancelledModel { + final String id; + final String paymentMode; + final String shipTo; + final String billTo; + final List orderItems; + final double subtotal; + final double gstTotal; + final double grandTotal; + final String status; + final List invoices; + final String addedBy; + final String pd; + final bool isCancelled; + final bool isDelivered; + final String deliveredDate; + final String statusUpdatedAt; + final String uniqueId; + final String createdAt; + final String updatedAt; + final int version; + final String orderCancelledReason; + + GetRdCancelledModel({ + required this.id, + required this.paymentMode, + required this.shipTo, + required this.billTo, + required this.orderItems, + required this.subtotal, + required this.gstTotal, + required this.grandTotal, + required this.status, + required this.invoices, + required this.addedBy, + required this.pd, + required this.isCancelled, + required this.isDelivered, + required this.deliveredDate, + required this.statusUpdatedAt, + required this.uniqueId, + required this.createdAt, + required this.updatedAt, + required this.version, + required this.orderCancelledReason, + }); + + factory GetRdCancelledModel.fromJson(Map json) { + return GetRdCancelledModel( + id: json['_id'], + paymentMode: json['paymentMode'], + shipTo: json['shipTo'], + billTo: json['billTo'], + orderItems: (json['orderItem'] as List) + .map((item) => OrderItem.fromJson(item)) + .toList(), + subtotal: json['subtotal'].toDouble(), + gstTotal: json['gstTotal'].toDouble(), + grandTotal: json['grandTotal'].toDouble(), + status: json['status'], + invoices: List.from(json['invoices']), + addedBy: json['addedBy'], + pd: json['pd'], + isCancelled: json['iscancelled'], + isDelivered: json['isDelivered'], + deliveredDate: json['DeliveredDate'] ?? '', + statusUpdatedAt: json['statusUpdatedAt'], + uniqueId: json['uniqueId'], + createdAt: json['createdAt'], + updatedAt: json['updatedAt'], + version: json['__v'], + orderCancelledReason: json['order_Cancelled_Reason'], + ); + } + + Map toJson() { + return { + '_id': id, + 'paymentMode': paymentMode, + 'shipTo': shipTo, + 'billTo': billTo, + 'orderItem': orderItems.map((item) => item.toJson()).toList(), + 'subtotal': subtotal, + 'gstTotal': gstTotal, + 'grandTotal': grandTotal, + 'status': status, + 'invoices': invoices, + 'addedBy': addedBy, + 'pd': pd, + 'iscancelled': isCancelled, + 'isDelivered': isDelivered, + 'DeliveredDate': deliveredDate, + 'statusUpdatedAt': statusUpdatedAt, + 'uniqueId': uniqueId, + 'createdAt': createdAt, + 'updatedAt': updatedAt, + '__v': version, + 'order_Cancelled_Reason': orderCancelledReason, + }; + } + + @override + String toString() { + return 'PlacedOrder(id: $id, paymentMode: $paymentMode, shipTo: $shipTo, ' + 'billTo: $billTo, orderItems: $orderItems, subtotal: $subtotal, ' + 'gstTotal: $gstTotal, grandTotal: $grandTotal, status: $status, ' + 'invoices: $invoices, addedBy: $addedBy, pd: $pd, isCancelled: $isCancelled, ' + 'isDelivered: $isDelivered, deliveredDate: $deliveredDate, ' + 'statusUpdatedAt: $statusUpdatedAt, uniqueId: $uniqueId, ' + 'createdAt: $createdAt, updatedAt: $updatedAt, version: $version, ' + 'orderCancelledReason: $orderCancelledReason)'; + } +} + +class OrderItem { + final String productId; + final String sku; + final String name; + final String categoryName; + final String brandName; + final double price; + final double gst; + final int hsnCode; + final String description; + final List images; + final int quantity; + final int remainingQuantity; + final String id; + + OrderItem({ + required this.productId, + required this.sku, + required this.name, + required this.categoryName, + required this.brandName, + required this.price, + required this.gst, + required this.hsnCode, + required this.description, + required this.images, + required this.quantity, + required this.remainingQuantity, + required this.id, + }); + + factory OrderItem.fromJson(Map json) { + return OrderItem( + productId: json['productId'], + sku: json['SKU'], + name: json['name'], + categoryName: json['categoryName'], + brandName: json['brandName'], + price: json['price'].toDouble(), + gst: json['GST'].toDouble(), + hsnCode: json['HSN_Code'], + description: json['description'] ?? '', + images: List.from(json['image']), + quantity: json['quantity'], + remainingQuantity: json['remainingQuantity'], + id: json['_id'], + ); + } + + Map toJson() { + return { + 'productId': productId, + 'SKU': sku, + 'name': name, + 'categoryName': categoryName, + 'brandName': brandName, + 'price': price, + 'GST': gst, + 'HSN_Code': hsnCode, + 'description': description, + 'image': images, + 'quantity': quantity, + 'remainingQuantity': remainingQuantity, + '_id': id, + }; + } + + @override + String toString() { + return 'OrderItem(productId: $productId, sku: $sku, name: $name, ' + 'categoryName: $categoryName, brandName: $brandName, price: $price, ' + 'gst: $gst, hsnCode: $hsnCode, description: $description, ' + 'images: $images, quantity: $quantity, remainingQuantity: $remainingQuantity, ' + 'id: $id)'; + } +} diff --git a/lib/models/get_rd_pennding_model.dart b/lib/models/get_rd_pennding_model.dart new file mode 100644 index 0000000..c6bf1de --- /dev/null +++ b/lib/models/get_rd_pennding_model.dart @@ -0,0 +1,179 @@ +import 'package:cheminova/models/rd_order_item_model.dart'; + +class GetRdPendingModel { + String id; + String paymentMode; + String shipTo; + String billTo; + List orderItem; + double subtotal; + double gstTotal; + double grandTotal; + String status; + List invoices; + String addedBy; + String pd; + bool isCancelled; + bool isDelivered; + String deliveredDate; + String statusUpdatedAt; + String uniqueId; + String createdAt; + String updatedAt; + + GetRdPendingModel({ + required this.id, + required this.paymentMode, + required this.shipTo, + required this.billTo, + required this.orderItem, + required this.subtotal, + required this.gstTotal, + required this.grandTotal, + required this.status, + required this.invoices, + required this.addedBy, + required this.pd, + required this.isCancelled, + required this.isDelivered, + required this.deliveredDate, + required this.statusUpdatedAt, + required this.uniqueId, + required this.createdAt, + required this.updatedAt, + }); + + factory GetRdPendingModel.fromJson(Map json) { + return GetRdPendingModel( + id: json['_id'], + paymentMode: json['paymentMode'], + shipTo: json['shipTo'], + billTo: json['billTo'], + orderItem: (json['orderItem'] as List) + .map((item) => RDOrderItem.fromJson(item)) + .toList(), + subtotal: json['subtotal'].toDouble(), + gstTotal: json['gstTotal'].toDouble(), + grandTotal: json['grandTotal'].toDouble(), + status: json['status'], + invoices: List.from(json['invoices']), + addedBy: json['addedBy'], + pd: json['pd'], + isCancelled: json['iscancelled'], + isDelivered: json['isDelivered'], + deliveredDate: json['DeliveredDate'], + statusUpdatedAt: json['statusUpdatedAt'], + uniqueId: json['uniqueId'], + createdAt: json['createdAt'], + updatedAt: json['updatedAt'], + ); + } + + Map toJson() { + return { + '_id': id, + 'paymentMode': paymentMode, + 'shipTo': shipTo, + 'billTo': billTo, + 'orderItem': orderItem.map((item) => item.toJson()).toList(), + 'subtotal': subtotal, + 'gstTotal': gstTotal, + 'grandTotal': grandTotal, + 'status': status, + 'invoices': invoices, + 'addedBy': addedBy, + 'pd': pd, + 'iscancelled': isCancelled, + 'isDelivered': isDelivered, + 'DeliveredDate': deliveredDate, + 'statusUpdatedAt': statusUpdatedAt, + 'uniqueId': uniqueId, + 'createdAt': createdAt, + 'updatedAt': updatedAt, + }; + } + + @override + String toString() { + return 'Order{id: $id, paymentMode: $paymentMode, shipTo: $shipTo, billTo: $billTo, ' + 'orderItem: $orderItem, subtotal: $subtotal, gstTotal: $gstTotal, grandTotal: $grandTotal, ' + 'status: $status, invoices: $invoices, addedBy: $addedBy, pd: $pd, isCancelled: $isCancelled, ' + 'isDelivered: $isDelivered, deliveredDate: $deliveredDate, statusUpdatedAt: $statusUpdatedAt, ' + 'uniqueId: $uniqueId, createdAt: $createdAt, updatedAt: $updatedAt}'; + } +} +// +// class PendingOrderItem { +// String productId; +// String sku; +// String name; +// String categoryName; +// String brandName; +// double price; +// double gst; +// int hsnCode; +// String description; +// List image; +// int quantity; +// int remainingQuantity; +// String id; +// +// PendingOrderItem({ +// required this.productId, +// required this.sku, +// required this.name, +// required this.categoryName, +// required this.brandName, +// required this.price, +// required this.gst, +// required this.hsnCode, +// required this.description, +// required this.image, +// required this.quantity, +// required this.remainingQuantity, +// required this.id, +// }); +// +// factory PendingOrderItem.fromJson(Map json) { +// return PendingOrderItem( +// productId: json['productId'], +// sku: json['SKU'], +// name: json['name'], +// categoryName: json['categoryName'], +// brandName: json['brandName'], +// price: json['price'].toDouble(), +// gst: json['GST'].toDouble(), +// hsnCode: json['HSN_Code'], +// description: json['description'], +// image: List.from(json['image']), +// quantity: json['quantity'], +// remainingQuantity: json['remainingQuantity'], +// id: json['_id'], +// ); +// } +// +// Map toJson() { +// return { +// 'productId': productId, +// 'SKU': sku, +// 'name': name, +// 'categoryName': categoryName, +// 'brandName': brandName, +// 'price': price, +// 'GST': gst, +// 'HSN_Code': hsnCode, +// 'description': description, +// 'image': image, +// 'quantity': quantity, +// 'remainingQuantity': remainingQuantity, +// '_id': id, +// }; +// } +// +// @override +// String toString() { +// return 'OrderItem{productId: $productId, sku: $sku, name: $name, categoryName: $categoryName, ' +// 'brandName: $brandName, price: $price, gst: $gst, hsnCode: $hsnCode, description: $description, ' +// 'image: $image, quantity: $quantity, remainingQuantity: $remainingQuantity, id: $id}'; +// } +// } diff --git a/lib/models/rd_processing_invoice_model.dart b/lib/models/rd_processing_invoice_model.dart new file mode 100644 index 0000000..92fe7bc --- /dev/null +++ b/lib/models/rd_processing_invoice_model.dart @@ -0,0 +1,191 @@ +import 'dart:convert'; +// +// class InvoiceResponseModel { +// final int totalCount; +// final int currentPage; +// final int totalPages; +// final List invoices; +// +// InvoiceResponseModel({ +// required this.totalCount, +// required this.currentPage, +// required this.totalPages, +// required this.invoices, +// }); +// +// factory InvoiceResponseModel.fromJson(Map json) { +// return InvoiceResponseModel( +// totalCount: json['totalCount'] ?? 0, +// currentPage: json['currentPage'] ?? 1, +// totalPages: json['totalPages'] ?? 1, +// invoices: json['invoices'] != null +// ? List.from(json['invoices'].map((x) => Invoice.fromJson(x))) +// : [], // Handle the case where 'invoices' is null +// ); +// } +// +// Map toJson() { +// return { +// 'totalCount': totalCount, +// 'currentPage': currentPage, +// 'totalPages': totalPages, +// 'invoices': invoices.map((invoice) => invoice.toJson()).toList(), +// }; +// } +// +// @override +// String toString() { +// return 'InvoiceResponse(totalCount: $totalCount, currentPage: $currentPage, totalPages: $totalPages, invoices: $invoices)'; +// } +// } + + +class InvoiceResponseModel { + final String id; + final String invoiceId; + final Order orderId; + final List items; + final double subtotal; + final double gstTotal; + final double invoiceAmount; + final String courierStatus; + final Map courierStatusTimeline; + + InvoiceResponseModel({ + required this.id, + required this.invoiceId, + required this.orderId, + required this.items, + required this.subtotal, + required this.gstTotal, + required this.invoiceAmount, + required this.courierStatus, + required this.courierStatusTimeline, + }); + + factory InvoiceResponseModel.fromJson(Map json) { + return InvoiceResponseModel( + id: json['_id'], + invoiceId: json['invoiceId'], + orderId: Order.fromJson(json['orderId']), + items: json['items'] != null + ? List.from(json['items'].map((item) => Item.fromJson(item))) + : [], // Provide an empty list if 'items' is null + subtotal: json['subtotal'].toDouble(), + gstTotal: json['gstTotal'].toDouble(), + invoiceAmount: json['invoiceAmount'].toDouble(), + courierStatus: json['courierStatus'], + courierStatusTimeline: Map.from(json['courierstatus_timeline'] ?? {}), + //Provide an empty map if 'courierstatus_timeline' is null + ); + } + + Map toJson() { + return { + '_id': id, + 'invoiceId': invoiceId, + 'orderId': orderId.toJson(), + 'items': items.map((item) => item.toJson()).toList(), + 'subtotal': subtotal, + 'gstTotal': gstTotal, + 'invoiceAmount': invoiceAmount, + 'courierStatus': courierStatus, + 'courierstatus_timeline': courierStatusTimeline, + }; + } + + @override + String toString() { + return 'Invoice(id: $id, invoiceId: $invoiceId, orderId: $orderId, items: $items, subtotal: $subtotal, gstTotal: $gstTotal, invoiceAmount: $invoiceAmount, courierStatus: $courierStatus)'; + } +} + +class Order { + final String id; + final String uniqueId; + + Order({ + required this.id, + required this.uniqueId, + }); + + factory Order.fromJson(Map json) { + return Order( + id: json['_id'], + uniqueId: json['uniqueId'], + ); + } + + Map toJson() { + return { + '_id': id, + 'uniqueId': uniqueId, + }; + } + + @override + String toString() { + return 'Order(id: $id, uniqueId: $uniqueId)'; + } +} + +class Item { + final String productId; + final String sku; + final String name; + final String categoryName; + final String brandName; + final double price; + final double gst; + final int hsnCode; + final int processQuantity; + final String id; + + Item({ + required this.productId, + required this.sku, + required this.name, + required this.categoryName, + required this.brandName, + required this.price, + required this.gst, + required this.hsnCode, + required this.processQuantity, + required this.id, + }); + + factory Item.fromJson(Map json) { + return Item( + productId: json['productId'], + sku: json['SKU'], + name: json['name'], + categoryName: json['categoryName'], + brandName: json['brandName'], + price: json['price'].toDouble(), + gst: json['GST'].toDouble(), + hsnCode: json['HSN_Code'], + processQuantity: json['processquantity'], + id: json['_id'], + ); + } + + Map toJson() { + return { + 'productId': productId, + 'SKU': sku, + 'name': name, + 'categoryName': categoryName, + 'brandName': brandName, + 'price': price, + 'GST': gst, + 'HSN_Code': hsnCode, + 'processquantity': processQuantity, + '_id': id, + }; + } + + @override + String toString() { + return 'Item(productId: $productId, sku: $sku, name: $name, categoryName: $categoryName, brandName: $brandName, price: $price, gst: $gst, hsnCode: $hsnCode, processQuantity: $processQuantity)'; + } +} diff --git a/lib/models/single_get_order_model.dart b/lib/models/single_get_order_model.dart new file mode 100644 index 0000000..e29ade4 --- /dev/null +++ b/lib/models/single_get_order_model.dart @@ -0,0 +1,264 @@ +class SingleGetOrderModel { + final String id; + final String paymentMode; + final String shipTo; + final String billTo; + final List orderItem; + final double subtotal; + final double gstTotal; + final double grandTotal; + final String status; + final List invoices; + final AddedBy addedBy; + final String pd; + final bool isCancelled; + final bool isDelivered; + final String deliveredDate; + final DateTime statusUpdatedAt; + final String uniqueId; + final DateTime createdAt; + final DateTime updatedAt; + + SingleGetOrderModel({ + required this.id, + required this.paymentMode, + required this.shipTo, + required this.billTo, + required this.orderItem, + required this.subtotal, + required this.gstTotal, + required this.grandTotal, + required this.status, + required this.invoices, + required this.addedBy, + required this.pd, + required this.isCancelled, + required this.isDelivered, + required this.deliveredDate, + required this.statusUpdatedAt, + required this.uniqueId, + required this.createdAt, + required this.updatedAt, + }); + + factory SingleGetOrderModel.fromJson(Map json) { + return SingleGetOrderModel( + id: json['_id'] ?? '', + paymentMode: json['paymentMode'] ?? '', + shipTo: json['shipTo'] ?? '', + billTo: json['billTo'] ?? '', + orderItem: (json['orderItem'] as List?) + ?.map((item) => OrderItem.fromJson(item)) + .toList() ?? + [], + subtotal: (json['subtotal'] as num?)?.toDouble() ?? 0.0, + gstTotal: (json['gstTotal'] as num?)?.toDouble() ?? 0.0, + grandTotal: (json['grandTotal'] as num?)?.toDouble() ?? 0.0, + status: json['status'] ?? '', + invoices: json['invoices'] ?? [], + addedBy: AddedBy.fromJson(json['addedBy'] ?? {}), + pd: json['pd'] ?? '', + isCancelled: json['iscancelled'] ?? false, + isDelivered: json['isDelivered'] ?? false, + deliveredDate: json['DeliveredDate'] ?? '', + statusUpdatedAt: DateTime.parse(json['statusUpdatedAt'] ?? DateTime.now().toString()), + uniqueId: json['uniqueId'] ?? '', + createdAt: DateTime.parse(json['createdAt'] ?? DateTime.now().toString()), + updatedAt: DateTime.parse(json['updatedAt'] ?? DateTime.now().toString()), + ); + } + + Map toJson() { + return { + '_id': id, + 'paymentMode': paymentMode, + 'shipTo': shipTo, + 'billTo': billTo, + 'orderItem': orderItem.map((item) => item.toJson()).toList(), + 'subtotal': subtotal, + 'gstTotal': gstTotal, + 'grandTotal': grandTotal, + 'status': status, + 'invoices': invoices, + 'addedBy': addedBy.toJson(), + 'pd': pd, + 'iscancelled': isCancelled, + 'isDelivered': isDelivered, + 'DeliveredDate': deliveredDate, + 'statusUpdatedAt': statusUpdatedAt.toIso8601String(), + 'uniqueId': uniqueId, + 'createdAt': createdAt.toIso8601String(), + 'updatedAt': updatedAt.toIso8601String(), + }; + } + + @override + String toString() { + return 'SingleOrder(id: $id, paymentMode: $paymentMode, shipTo: $shipTo, billTo: $billTo, ' + 'orderItem: $orderItem, subtotal: $subtotal, gstTotal: $gstTotal, grandTotal: $grandTotal, ' + 'status: $status, invoices: $invoices, addedBy: $addedBy, pd: $pd, ' + 'isCancelled: $isCancelled, isDelivered: $isDelivered, deliveredDate: $deliveredDate, ' + 'statusUpdatedAt: $statusUpdatedAt, uniqueId: $uniqueId, createdAt: $createdAt, updatedAt: $updatedAt)'; + } +} + +class OrderItem { + final String productId; + final String sku; + final String name; + final String categoryName; + final String brandName; + final double price; + final double gst; + final String hsnCode; + final String description; + final List image; + final int quantity; + final int remainingQuantity; + final String id; + + OrderItem({ + required this.productId, + required this.sku, + required this.name, + required this.categoryName, + required this.brandName, + required this.price, + required this.gst, + required this.hsnCode, + required this.description, + required this.image, + required this.quantity, + required this.remainingQuantity, + required this.id, + }); + + factory OrderItem.fromJson(Map json) { + return OrderItem( + productId: json['productId'] ?? '', + sku: json['SKU'] ?? '', + name: json['name'] ?? '', + categoryName: json['categoryName'] ?? '', + brandName: json['brandName'] ?? '', + price: (json['price'] as num?)?.toDouble() ?? 0.0, + gst: (json['GST'] as num?)?.toDouble() ?? 0.0, + hsnCode: json['HSN_Code'] ?? '', + description: json['description'] ?? '', + image: json['image'] ?? [], + quantity: json['quantity'] ?? 0, + remainingQuantity: json['remainingQuantity'] ?? 0, + id: json['_id'] ?? '', + ); + } + + Map toJson() { + return { + 'productId': productId, + 'SKU': sku, + 'name': name, + 'categoryName': categoryName, + 'brandName': brandName, + 'price': price, + 'GST': gst, + 'HSN_Code': hsnCode, + 'description': description, + 'image': image, + 'quantity': quantity, + 'remainingQuantity': remainingQuantity, + '_id': id, + }; + } + + @override + String toString() { + return 'OrderItem(productId: $productId, SKU: $sku, name: $name, categoryName: $categoryName, ' + 'brandName: $brandName, price: $price, GST: $gst, HSN_Code: $hsnCode, ' + 'description: $description, image: $image, quantity: $quantity, ' + 'remainingQuantity: $remainingQuantity, id: $id)'; + } +} + +class AddedBy { + final String id; + final String designation; + final String name; + final String email; + final String mobileNumber; + final String principalDistributor; + final String addedBy; + final String userType; + final String kyc; + final String? fcmToken; + final DateTime createdAt; + final DateTime updatedAt; + final String mappedSC; + final String uniqueId; + final String mappedTM; + + AddedBy({ + required this.id, + required this.designation, + required this.name, + required this.email, + required this.mobileNumber, + required this.principalDistributor, + required this.addedBy, + required this.userType, + required this.kyc, + this.fcmToken, + required this.createdAt, + required this.updatedAt, + required this.mappedSC, + required this.uniqueId, + required this.mappedTM, + }); + + factory AddedBy.fromJson(Map json) { + return AddedBy( + id: json['_id'] ?? '', + designation: json['designation'] ?? '', + name: json['name'] ?? '', + email: json['email'] ?? '', + mobileNumber: json['mobile_number'] ?? '', + principalDistributor: json['principal_distributer'] ?? '', + addedBy: json['addedBy'] ?? '', + userType: json['userType'] ?? '', + kyc: json['kyc'] ?? '', + fcmToken: json['fcm_token'], + createdAt: DateTime.parse(json['createdAt'] ?? DateTime.now().toString()), + updatedAt: DateTime.parse(json['updatedAt'] ?? DateTime.now().toString()), + mappedSC: json['mappedSC'] ?? '', + uniqueId: json['uniqueId'] ?? '', + mappedTM: json['mappedTM'] ?? '', + ); + } + + Map toJson() { + return { + '_id': id, + 'designation': designation, + 'name': name, + 'email': email, + 'mobile_number': mobileNumber, + 'principal_distributer': principalDistributor, + 'addedBy': addedBy, + 'userType': userType, + 'kyc': kyc, + 'fcm_token': fcmToken, + 'createdAt': createdAt.toIso8601String(), + 'updatedAt': updatedAt.toIso8601String(), + 'mappedSC': mappedSC, + 'uniqueId': uniqueId, + 'mappedTM': mappedTM, + }; + } + + @override + String toString() { + return 'AddedBy(id: $id, designation: $designation, name: $name, email: $email, ' + 'mobileNumber: $mobileNumber, principalDistributor: $principalDistributor, ' + 'addedBy: $addedBy, userType: $userType, kyc: $kyc, fcmToken: $fcmToken, ' + 'createdAt: $createdAt, updatedAt: $updatedAt, mappedSC: $mappedSC, ' + 'uniqueId: $uniqueId, mappedTM: $mappedTM)'; + } +} diff --git a/lib/screens/rd orders/partial_pending_dialog.dart b/lib/screens/rd orders/partial_pending_dialog.dart new file mode 100644 index 0000000..0733e0a --- /dev/null +++ b/lib/screens/rd orders/partial_pending_dialog.dart @@ -0,0 +1,461 @@ + +import 'package:cheminova/models/rd_get_order_model.dart'; +import 'package:cheminova/models/rd_order_item_model.dart'; +import 'package:cheminova/models/rd_placed_order_model.dart'; +import 'package:cheminova/screens/order/checkout_screen.dart'; +import 'package:cheminova/widgets/my_drawer.dart'; +import 'package:cheminova/widgets/product_card.dart'; +import 'package:cheminova/widgets/product_card1.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:get/get.dart'; +import 'package:google_fonts/google_fonts.dart'; + +import '../../controller/cart_controller.dart'; +import '../../controller/rd_processing_order_controller.dart'; +import '../../models/get_rd_pennding_model.dart'; +import '../../models/oder_place_model.dart'; +import '../../models/product_model1.dart'; +import '../../utils/show_snackbar.dart'; + +class PartialPendingDialogScreen extends StatefulWidget { + // PlacedOrdersResponse? productModel; + GetRdPendingModel? productpendingModel; + PartialPendingDialogScreen({super.key, this.productpendingModel}); + + @override + State createState() => _PartialPendingDialogScreenState(); +} + +class _PartialPendingDialogScreenState extends State { + final RDOrderPlacedController controller = Get.put(RDOrderPlacedController()); + bool _selectAll = true; // Default to true to select all products + List processingItems = []; + List pendingItems = []; + @override + void initState() { + super.initState(); + _separateProcessingAndPendingItems(); + } + void _separateProcessingAndPendingItems() { + for (var item in widget.productpendingModel!.orderItem) { + if (item.remainingQuantity! > 0) { + // If remainingQuantity > 0, it is available for processing + processingItems.add(item ); + } else { + // If remainingQuantity == 0, it should go into pending + pendingItems.add(item); + } + } + } + void _showPartialOrderDialog() { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text("Confirm Partial Order"), + content: const Text("Do you want to place a partial order for the available items?"), + actions: [ + TextButton( + onPressed: () async { + Map orderItemMap = {}; + + // Process only available items (processingItems) + for (var item in processingItems) { + var productId = item.productId; + if (orderItemMap.containsKey(productId)) { + var existingItem = orderItemMap[productId]!; + existingItem.quantity = (existingItem.quantity ?? 0) + (item.quantity ?? 0); + } else { + orderItemMap[productId] = RDOrderItem( + productId: productId, + sku: item.sku, + name: item.name, + categoryName: item.categoryName, + brandName: item.brandName, + price: item.price, + gst: item.gst, + hsnCode: item.hsnCode, + description: item.description, + image: [], + quantity: item.quantity ?? 0, + remainingQuantity: item.remainingQuantity ?? 0, + processquantity: item.processquantity ?? 0, + ); + } + } + + List orderItems = orderItemMap.values.toList(); + controller.placedOrder1.value = PlacedOrdersProcessing( + orderId: widget.productpendingModel!.id, + invoiceItems: orderItems, + ); + + await controller.placeRDOrder(); + showSnackbar("Partial order processed successfully."); + + Future.delayed(const Duration(seconds: 1), () { + Navigator.of(context).pop(); + }); + + setState(() {}); + }, + child: const Text("Confirm"), + ), + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: const Text("Cancel"), + ), + ], + ); + }, + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + extendBodyBehindAppBar: true, + appBar: AppBar( + backgroundColor: Colors.transparent, + elevation: 0, + leading: Builder( + builder: (context) { + return GestureDetector( + onTap: () => Scaffold.of(context).openDrawer(), + child: Padding( + padding: const EdgeInsets.all(16.0), + child: SvgPicture.asset( + 'assets/svg/menu.svg', + ), + ), + ); + }, + ), + actions: [ + GestureDetector( + onTap: () => Get.back(), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: SvgPicture.asset( + 'assets/svg/back_arrow.svg', + ), + ), + ), + ], + title: const Center( + child: Text( + "Modify Product Availability", + ), + ), + ), + drawer: MyDrawer(), + body: Stack( + fit: StackFit.expand, + children: [ + Image.asset( + 'assets/images/image_1.png', + fit: BoxFit.cover, + ), + SafeArea( + child: Column( + children: [ + SizedBox(height: Get.height * 0.02), + Card( + margin: const EdgeInsets.symmetric(horizontal: 18), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(19), + side: const BorderSide(color: Color(0xFFFDFDFD)), + ), + color: const Color(0xFFB4D1E5).withOpacity(0.9), + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + height: Get.height * 0.6, + child: ListView.builder( + padding: EdgeInsets.zero, + itemCount: processingItems.length, + itemBuilder: (context, index) { + final orderItem = processingItems[index]; + return ProductCard1(productModel: orderItem); + }, + ), + + ), + const SizedBox(height: 10), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Subtotal ", + style: GoogleFonts.roboto( + fontSize: 15, + color: Colors.black, + fontWeight: FontWeight.bold, + ), + ), + Text("₹ ${widget.productpendingModel!.subtotal ?? 0}"), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "GST ", + style: GoogleFonts.roboto( + fontSize: 15, + color: Colors.black, + fontWeight: FontWeight.bold, + ), + ), + Text("₹ ${widget.productpendingModel!.gstTotal ?? 0}"), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Total Amount ", + style: GoogleFonts.roboto( + fontSize: 15, + color: Colors.black, + fontWeight: FontWeight.bold, + ), + ), + Text("₹ ${widget.productpendingModel!.grandTotal ?? 0}"), + ], + ), + ], + ), + ), + ), + SizedBox(height: Get.height * 0.020), + SizedBox( + width: Get.width * 0.9, + height: Get.height * 0.06, + child: ElevatedButton( + onPressed: _showPartialOrderDialog, // Show dialog when pressed + style: ElevatedButton.styleFrom( + foregroundColor: Colors.white, + backgroundColor: const Color(0xFF00784C), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + ), + child: Text( + "Submit", + style: GoogleFonts.roboto( + fontSize: 16, + fontWeight: FontWeight.w600, + ), + ), + ), + ), + ], + ), + ), + ], + ), + ); + } +} + + + + + + + + + + +// +// +// class PartialProcessingDialogScreen extends StatefulWidget { +// final PlacedOrdersResponse? productModel; +// +// PartialProcessingDialogScreen({super.key, this.productModel}); +// +// @override +// State createState() => _PartialProcessingDialogScreenState(); +// } +// +// class _PartialProcessingDialogScreenState extends State { +// final RDOrderPlacedController controller = Get.put(RDOrderPlacedController()); +// +// // Add lists for processing and pending items +// List processingItems = []; +// List pendingItems = []; +// +// @override +// void initState() { +// super.initState(); +// // Separate processing and pending items based on availability +// _separateProcessingAndPendingItems(); +// } +// +// void _separateProcessingAndPendingItems() { +// for (var item in widget.productModel!.orderItem) { +// if (item.remainingQuantity > 0) { +// // If remainingQuantity > 0, it is available for processing +// processingItems.add(item); +// } else { +// // If remainingQuantity == 0, it should go into pending +// pendingItems.add(item); +// } +// } +// } +// +// void _showPartialOrderDialog() { +// showDialog( +// context: context, +// builder: (BuildContext context) { +// return AlertDialog( +// title: const Text("Confirm Partial Order"), +// content: const Text("Do you want to place a partial order for the available items?"), +// actions: [ +// TextButton( +// onPressed: () async { +// Map orderItemMap = {}; +// +// // Process only available items (processingItems) +// for (var item in processingItems) { +// var productId = item.productId; +// if (orderItemMap.containsKey(productId)) { +// var existingItem = orderItemMap[productId]!; +// existingItem.quantity = (existingItem.quantity ?? 0) + (item.quantity ?? 0); +// } else { +// orderItemMap[productId] = RDOrderItem( +// productId: productId, +// sku: item.sku, +// name: item.name, +// categoryName: item.categoryName, +// brandName: item.brandName, +// price: item.price, +// gst: item.gst, +// hsnCode: item.hsnCode, +// description: item.description, +// image: [], +// quantity: item.quantity ?? 0, +// remainingQuantity: item.remainingQuantity ?? 0, +// processquantity: item.processquantity ?? 0, +// ); +// } +// } +// +// List orderItems = orderItemMap.values.toList(); +// controller.placedOrder1.value = PlacedOrdersProcessing( +// orderId: widget.productModel!.id, +// invoiceItems: orderItems, +// ); +// +// await controller.placeRDOrder(); +// showSnackbar("Partial order processed successfully."); +// +// Future.delayed(const Duration(seconds: 1), () { +// Navigator.of(context).pop(); +// }); +// +// setState(() {}); +// }, +// child: const Text("Confirm"), +// ), +// TextButton( +// onPressed: () { +// Navigator.of(context).pop(); +// }, +// child: const Text("Cancel"), +// ), +// ], +// ); +// }, +// ); +// } +// +// @override +// Widget build(BuildContext context) { +// return Scaffold( +// appBar: AppBar( +// title: const Text("Modify Product Availability"), +// ), +// body: SafeArea( +// child: Column( +// children: [ +// Expanded( +// child: ListView( +// children: [ +// const SizedBox(height: 20), +// Card( +// margin: const EdgeInsets.symmetric(horizontal: 18), +// shape: RoundedRectangleBorder( +// borderRadius: BorderRadius.circular(19), +// side: const BorderSide(color: Color(0xFFFDFDFD)), +// ), +// color: const Color(0xFFB4D1E5).withOpacity(0.9), +// child: Padding( +// padding: const EdgeInsets.all(12.0), +// child: Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// const Text( +// "Processing Products", +// style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), +// ), +// SizedBox( +// height: Get.height * 0.3, +// child: ListView.builder( +// itemCount: processingItems.length, +// itemBuilder: (context, index) { +// final orderItem = processingItems[index]; +// return ProductCard1(productModel: orderItem); +// }, +// ), +// ), +// const SizedBox(height: 10), +// const Text( +// "Pending Products", +// style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), +// ), +// SizedBox( +// height: Get.height * 0.3, +// child: ListView.builder( +// itemCount: pendingItems.length, +// itemBuilder: (context, index) { +// final orderItem = pendingItems[index]; +// return ProductCard1(productModel: orderItem); +// }, +// ), +// ), +// ], +// ), +// ), +// ), +// ], +// ), +// ), +// SizedBox( +// width: Get.width * 0.9, +// height: Get.height * 0.06, +// child: ElevatedButton( +// onPressed: _showPartialOrderDialog, +// style: ElevatedButton.styleFrom( +// foregroundColor: Colors.white, +// backgroundColor: const Color(0xFF00784C), +// shape: RoundedRectangleBorder( +// borderRadius: BorderRadius.circular(10), +// ), +// ), +// child: const Text("Submit"), +// ), +// ), +// ], +// ), +// ), +// ); +// } +// } diff --git a/lib/screens/rd orders/partial_processing_dialog_screen.dart b/lib/screens/rd orders/partial_processing_dialog_screen.dart index 657f9e4..371ac51 100644 --- a/lib/screens/rd orders/partial_processing_dialog_screen.dart +++ b/lib/screens/rd orders/partial_processing_dialog_screen.dart @@ -1,9 +1,9 @@ -import 'package:cheminova/controller/get_order_placed_controller.dart'; -import 'package:cheminova/controller/rd_get_order_controller.dart'; + import 'package:cheminova/models/rd_get_order_model.dart'; import 'package:cheminova/models/rd_order_item_model.dart'; import 'package:cheminova/models/rd_placed_order_model.dart'; import 'package:cheminova/screens/order/checkout_screen.dart'; +import 'package:cheminova/screens/rd%20orders/rd_pending_screen.dart'; import 'package:cheminova/widgets/my_drawer.dart'; import 'package:cheminova/widgets/product_card.dart'; import 'package:cheminova/widgets/product_card1.dart'; @@ -14,12 +14,271 @@ import 'package:google_fonts/google_fonts.dart'; import '../../controller/cart_controller.dart'; import '../../controller/rd_processing_order_controller.dart'; +import '../../models/get_rd_pennding_model.dart'; import '../../models/oder_place_model.dart'; import '../../models/product_model1.dart'; import '../../utils/show_snackbar.dart'; +// +// class PartialProcessingDialogScreen extends StatefulWidget { +// PlacedOrdersResponse? productModel; +// GetRdPendingModel? productpendingModel; +// PartialProcessingDialogScreen({super.key, this.productModel}); +// +// @override +// State createState() => _PartialProcessingDialogScreenState(); +// } +// +// class _PartialProcessingDialogScreenState extends State { +// final RDOrderPlacedController controller = Get.put(RDOrderPlacedController()); +// bool _selectAll = true; // Default to true to select all products +// List processingItems = []; +// List pendingItems = []; +// @override +// void initState() { +// super.initState(); +// _separateProcessingAndPendingItems(); +// } +// void _separateProcessingAndPendingItems() { +// for (var item in widget.productModel!.orderItem) { +// if (item.remainingQuantity! > 0) { +// // If remainingQuantity > 0, it is available for processing +// processingItems.add(item); +// } else { +// // If remainingQuantity == 0, it should go into pending +// pendingItems.add(item); +// } +// } +// } +// void _showPartialOrderDialog() { +// showDialog( +// context: context, +// builder: (BuildContext context) { +// return AlertDialog( +// title: const Text("Confirm Partial Order"), +// content: const Text("Do you want to place a partial order for the available items?"), +// actions: [ +// TextButton( +// onPressed: () async { +// Map orderItemMap = {}; +// +// // Process only available items (processingItems) +// for (var item in processingItems) { +// var productId = item.productId; +// if (orderItemMap.containsKey(productId)) { +// var existingItem = orderItemMap[productId]!; +// existingItem.quantity = (existingItem.quantity ?? 0) + (item.quantity ?? 0); +// } else { +// orderItemMap[productId] = RDOrderItem( +// productId: productId, +// sku: item.sku, +// name: item.name, +// categoryName: item.categoryName, +// brandName: item.brandName, +// price: item.price, +// gst: item.gst, +// hsnCode: item.hsnCode, +// description: item.description, +// image: [], +// quantity: item.quantity ?? 0, +// remainingQuantity: item.remainingQuantity ?? 0, +// processquantity: item.processquantity ?? 0, +// ); +// } +// } +// +// List orderItems = orderItemMap.values.toList(); +// controller.placedOrder1.value = PlacedOrdersProcessing( +// orderId: widget.productModel!.id, +// invoiceItems: orderItems, +// ); +// +// await controller.placeRDOrder(); +// showSnackbar("Partial order processed successfully."); +// +// Future.delayed(const Duration(seconds: 1), () { +// Navigator.of(context).pop(); +// }); +// +// setState(() {}); +// }, +// child: const Text("Confirm"), +// ), +// TextButton( +// onPressed: () { +// Navigator.of(context).pop(); +// }, +// child: const Text("Cancel"), +// ), +// ], +// ); +// }, +// ); +// } +// +// @override +// Widget build(BuildContext context) { +// return Scaffold( +// extendBodyBehindAppBar: true, +// appBar: AppBar( +// backgroundColor: Colors.transparent, +// elevation: 0, +// leading: Builder( +// builder: (context) { +// return GestureDetector( +// onTap: () => Scaffold.of(context).openDrawer(), +// child: Padding( +// padding: const EdgeInsets.all(16.0), +// child: SvgPicture.asset( +// 'assets/svg/menu.svg', +// ), +// ), +// ); +// }, +// ), +// actions: [ +// GestureDetector( +// onTap: () => Get.back(), +// child: Padding( +// padding: const EdgeInsets.all(8.0), +// child: SvgPicture.asset( +// 'assets/svg/back_arrow.svg', +// ), +// ), +// ), +// ], +// title: const Center( +// child: Text( +// "Modify Product Availability", +// ), +// ), +// ), +// drawer: MyDrawer(), +// body: Stack( +// fit: StackFit.expand, +// children: [ +// Image.asset( +// 'assets/images/image_1.png', +// fit: BoxFit.cover, +// ), +// SafeArea( +// child: Column( +// children: [ +// SizedBox(height: Get.height * 0.02), +// Card( +// margin: const EdgeInsets.symmetric(horizontal: 18), +// shape: RoundedRectangleBorder( +// borderRadius: BorderRadius.circular(19), +// side: const BorderSide(color: Color(0xFFFDFDFD)), +// ), +// color: const Color(0xFFB4D1E5).withOpacity(0.9), +// child: Padding( +// padding: const EdgeInsets.all(12.0), +// child: Column( +// mainAxisSize: MainAxisSize.min, +// children: [ +// SizedBox( +// height: Get.height * 0.6, +// child: ListView.builder( +// padding: EdgeInsets.zero, +// itemCount: processingItems.length, +// itemBuilder: (context, index) { +// final orderItem = processingItems[index]; +// return ProductCard1(productModel: orderItem); +// }, +// ), +// +// ), +// const SizedBox(height: 10), +// Row( +// mainAxisAlignment: MainAxisAlignment.spaceBetween, +// children: [ +// Text( +// "Subtotal ", +// style: GoogleFonts.roboto( +// fontSize: 15, +// color: Colors.black, +// fontWeight: FontWeight.bold, +// ), +// ), +// Text("₹ ${widget.productModel!.subtotal ?? 0}"), +// ], +// ), +// Row( +// mainAxisAlignment: MainAxisAlignment.spaceBetween, +// children: [ +// Text( +// "GST ", +// style: GoogleFonts.roboto( +// fontSize: 15, +// color: Colors.black, +// fontWeight: FontWeight.bold, +// ), +// ), +// Text("₹ ${widget.productModel!.gstTotal ?? 0}"), +// ], +// ), +// Row( +// mainAxisAlignment: MainAxisAlignment.spaceBetween, +// children: [ +// Text( +// "Total Amount ", +// style: GoogleFonts.roboto( +// fontSize: 15, +// color: Colors.black, +// fontWeight: FontWeight.bold, +// ), +// ), +// Text("₹ ${widget.productModel!.grandTotal ?? 0}"), +// ], +// ), +// ], +// ), +// ), +// ), +// SizedBox(height: Get.height * 0.020), +// SizedBox( +// width: Get.width * 0.9, +// height: Get.height * 0.06, +// child: ElevatedButton( +// onPressed: _showPartialOrderDialog, // Show dialog when pressed +// style: ElevatedButton.styleFrom( +// foregroundColor: Colors.white, +// backgroundColor: const Color(0xFF00784C), +// shape: RoundedRectangleBorder( +// borderRadius: BorderRadius.circular(10), +// ), +// ), +// child: Text( +// "Submit", +// style: GoogleFonts.roboto( +// fontSize: 16, +// fontWeight: FontWeight.w600, +// ), +// ), +// ), +// ), +// ], +// ), +// ), +// ], +// ), +// ); +// } +// } +// + + + + + + + + + + class PartialProcessingDialogScreen extends StatefulWidget { - PlacedOrdersResponse? productModel; + final PlacedOrdersResponse? productModel; PartialProcessingDialogScreen({super.key, this.productModel}); @@ -29,11 +288,28 @@ class PartialProcessingDialogScreen extends StatefulWidget { class _PartialProcessingDialogScreenState extends State { final RDOrderPlacedController controller = Get.put(RDOrderPlacedController()); - bool _selectAll = true; // Default to true to select all products + + // Add lists for processing and pending items + List processingItems = []; + List pendingItems = []; @override void initState() { super.initState(); + // Separate processing and pending items based on availability + _separateProcessingAndPendingItems(); + } + + void _separateProcessingAndPendingItems() { + for (var item in widget.productModel!.orderItem) { + if (item.remainingQuantity! > 0) { + // If remainingQuantity > 0, it is available for processing + processingItems.add(item); + } else { + // If remainingQuantity == 0, it should go into pending + pendingItems.add(item); + } + } } void _showPartialOrderDialog() { @@ -41,24 +317,20 @@ class _PartialProcessingDialogScreenState extends State orderItemMap = {}; - // Populate the map with items and their quantities - for (var item in widget.productModel!.orderItem) { - var productId = item.productId; // Adjust if needed - + // Process only available items (processingItems) + for (var item in processingItems) { + var productId = item.productId; if (orderItemMap.containsKey(productId)) { - // If the product already exists, aggregate the quantity var existingItem = orderItemMap[productId]!; existingItem.quantity = (existingItem.quantity ?? 0) + (item.quantity ?? 0); } else { - // If it's a new product, add it to the map orderItemMap[productId] = RDOrderItem( productId: productId, sku: item.sku, @@ -69,7 +341,7 @@ class _PartialProcessingDialogScreenState extends State orderItems = orderItemMap.values.toList(); - controller.placedOrder1.value = PlacedOrdersProcessing( orderId: widget.productModel!.id, invoiceItems: orderItems, ); - // Debugging: Print the JSON payload - print(controller.placedOrder1.value.toJson()); - await controller.placeRDOrder(); - // Show confirmation snackbar - showSnackbar( "Partial Order processed and invoice created successfully"); + showSnackbar("Partial order processed successfully."); + Navigator.of(context).pop(); + // Future.delayed(const Duration(seconds: 1), () { + // Get.to(RdOrderPendingScreen()); + // //Navigator.of(context).pop(); + // }); - Future.delayed(const Duration(seconds: 1), () { - Get.back(); // Close the dialog - }); - - setState(() {}); // Refresh the UI + //setState(() {}); }, - child: Text("Confirm"), + child: const Text("Confirm"), ), TextButton( onPressed: () { - Get.back(); // Close the dialog + //Get.back(); + Navigator.of(context).pop(); }, - child: Text("Cancel"), + child: const Text("Cancel"), ), ], ); @@ -115,8 +383,8 @@ class _PartialProcessingDialogScreenState extends State Get.back(), child: Padding( @@ -157,42 +425,40 @@ class _PartialProcessingDialogScreenState extends State createState() => + _RdCancelledDetailScreenState(); +} + + +class _RdCancelledDetailScreenState + extends State { + // Controllers for managing cart and placed orders + final CartController _cartController = Get.put(CartController()); + final GetPlacedOrderController _getPlacedOrderController = Get.put(GetPlacedOrderController()); + final GetRDCancleController _getRDCancleController = Get.put(GetRDCancleController()); + final List statusOptions = [ + "new", + "pending", + "processing", + "dispatched", + "cancelled", + "delivered", + ]; + String selectedStatus = "All"; + String _groupValue = "cheque"; + // Function to format date from the API to a more readable format + + + String formatDate(String apiDate) { + // Parse the API date string into a DateTime object + DateTime parsedDate = DateTime.parse(apiDate).toLocal(); // Convert to local time + + // Format the date and time according to your specified format + String formattedDate = DateFormat('EEE MMM dd yyyy').format(parsedDate); + + return formattedDate; // Return the formatted date string + } + + // Function to capitalize the first letter of a string + String capitalizeFirstLetter(String text) { + if (text.isEmpty) return text; + return text[0].toUpperCase() + text.substring(1).toLowerCase(); + } + + + void _onPaymentModeChanged(String? value) { + setState(() { + _groupValue = value!; + }); + _saveSelectedPaymentMode(); + } + + + void _saveSelectedPaymentMode() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + await prefs.setString('selectedPaymentMode', _groupValue); + } + + void _loadSelectedPaymentMode() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + setState(() { + _groupValue = prefs.getString('selectedPaymentMode') ?? 'cheque'; + }); + } + // Function to collect unique order IDs and corresponding order details + // Future adduni()async { + // final Set uniqueOrderIds = {}; + // final List uniqueOrders = []; + // // Loop through placed orders and add unique orders to the list + // for (var order in _getPlacedOrderController.placedOrders) { + // if (uniqueOrderIds.add(order.uniqueId)) { + // uniqueOrders.add(order); + // } + // } + // final order = uniqueOrders[0]; + // + // // Combine product names, categories, and quantities into strings + // final productNames = order.orderItem + // .map((item) => (item.name)) + // .join(', '); + // final categotyName = order.orderItem + // .map((item) => (item.categoryName)) + // .join(', '); + // final quantity = order.orderItem + // .map((item) => (item.quantity)) + // .join(', '); + // } + @override + void initState() { + // TODO: implement initState + super.initState(); + selectedStatus= widget.placedOrderList?.status ?? 'new'; + } + + @override + Widget build(BuildContext context) { + return Scaffold( + extendBodyBehindAppBar: true, + appBar: AppBar( + backgroundColor: Colors.transparent, + elevation: 0, + leading: GestureDetector( + onTap: () {}, + child: Padding( + padding: const EdgeInsets.all(16.0), + child: SvgPicture.asset( + 'assets/svg/menu.svg', + ), + ), + ), + actions: [ + GestureDetector( + onTap: () => Get.back(), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: SvgPicture.asset( + 'assets/svg/back_arrow.svg', + ), + ), + ), + ], + title: const Text( + "RD Cancelled Order Detail", + ), + ), + body: Stack( + fit: StackFit.expand, + children: [ + Image.asset( + 'assets/images/image_1.png', + fit: BoxFit.cover, + ), + SafeArea( + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + SizedBox( + height: Get.height * 0.02, + ), + Card( + margin: const EdgeInsets.symmetric(horizontal: 18), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(19), + side: const BorderSide(color: Color(0xFFFDFDFD)), + ), + color: const Color(0xFFB4D1E5).withOpacity(0.9), + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Card( + child: Column( + children: [ + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Text( + "Invoices", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.05, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Invoice ID:", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text(widget.placedOrderList!.uniqueId), + // Text(widget.placedOrderList!.uniqueId), + ], + ), + ), + ), + SizedBox( + width: Get.width, + child: Padding( + padding: const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Items: ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + SizedBox(height: 10), // Add spacing between the title and the list of items + Column( + children: widget.placedOrderList!.orderItems.map((item) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 4.0), // Add some spacing between items + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Text( + "${item.name.toString()} (${item.sku.toString()})", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.03, + ), + overflow: TextOverflow.ellipsis, // Handle long text + ), + ), + Text("x ${item.remainingQuantity.toString()}"), + ], + ), + ); + }).toList(), + ), + ], + ), + ), + ), + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Sub Total : ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text("₹ ${widget.placedOrderList!.subtotal}"), + ], + ), + ), + ), + + // SizedBox( + // width: Get.width, + // child: Padding( + // padding: + // const EdgeInsets.fromLTRB(8, 8, 8, 0), + // child: Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // children: [ + // Text( + // "Gst %: ", + // style: GoogleFonts.roboto( + // fontSize: Get.width * 0.04, + // fontWeight: FontWeight.bold, + // ), + // ), + // Text(" ${widget.placedOrderList!.orderItem[0].gst}%"), + // ], + // ), + // ), + // ), + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "GST : ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text("₹ ${widget.placedOrderList!.gstTotal}"), + ], + ), + ), + ), + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Invoice Amount: ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text("₹ ${widget.placedOrderList!.grandTotal}"), + ], + ), + ), + ), + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Courier Status : ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + ElevatedButton( + onPressed: (){}, + // Get.to(() => + // RdOrderDetailScreen( + // placedOrderList: uniqueOrders[index])), // Navigate to detail screen + style: ElevatedButton.styleFrom( + foregroundColor: Colors.white, + backgroundColor: Colors.orange, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10)), + ), + child: Text(widget.placedOrderList!.status, style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.w400)), + ), + //Text("₹ ${widget.placedOrderList!.gstTotal}"), + ], + ), + ), + ), + ], + ), + ), + + + Card( + child: SizedBox( + height: Get.height * 0.35, // Adjust the height as per your requirement + child: Padding( + padding: EdgeInsets.all(Get.width * 0.02), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Add title here + Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), // Adjust padding if needed + child: Text( + "Order Summary", // Title text + style: GoogleFonts.roboto( + fontSize: Get.width * 0.05, // Adjust font size as needed + fontWeight: FontWeight.bold, + ), + ), + ), + Expanded( + child: ListView.builder( + padding: EdgeInsets.zero, + itemCount: widget.placedOrderList?.orderItems.length ?? 0, + itemBuilder: (context, index) { + final orderItem = widget.placedOrderList!.orderItems[index]; + return orderItem != null + ? Card( + margin: const EdgeInsets.symmetric(vertical: 5.0), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + children: [ + Image.asset( + "assets/images/product.png", + height: 50, + width: 50, + fit: BoxFit.cover, + ), + const SizedBox(width: 10), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text( + capitalizeFirstLetter(orderItem.name), + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text( + "Quantity: ${orderItem.quantity}", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.03, + ), + ), + Text("Price: ${orderItem.price}"), + Text("Subtotal: ${widget.placedOrderList!.subtotal}"), + Text("Gst: ${orderItem.gst}%"), + Text("GST Total: ${widget.placedOrderList!.gstTotal}"), + Text("Total Amount: ${widget.placedOrderList!.grandTotal}"), + ], + ), + ), + ], + ), + ), + ) + : const SizedBox.shrink(); + }, + ), + ), + ], + ), + ), + ), + ), + + const SizedBox(height: 8), + Card( + child: SizedBox( + height: Get.height * 0.35, // Adjust the height as per your requirement + child: Padding( + padding: EdgeInsets.all(Get.width * 0.02), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Add title here + Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), // Adjust padding if needed + child: Text( + "Order Itmes to processed", // Title text + style: GoogleFonts.roboto( + fontSize: Get.width * 0.05, // Adjust font size as needed + fontWeight: FontWeight.bold, + ), + ), + ), + Expanded( + child: ListView.builder( + padding: EdgeInsets.zero, + itemCount: widget.placedOrderList?.orderItems.length ?? 0, + itemBuilder: (context, index) { + final orderItem = widget.placedOrderList!.orderItems[index]; + return orderItem != null + ? Card( + margin: const EdgeInsets.symmetric(vertical: 5.0), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + children: [ + Image.asset( + "assets/images/product.png", + height: 50, + width: 50, + fit: BoxFit.cover, + ), + const SizedBox(width: 10), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text( + capitalizeFirstLetter(orderItem.name), + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text( + "Quantity: ${orderItem.remainingQuantity}", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.03, + ), + ), + Text("Price: ${orderItem.price}"), + Text("Subtotal: ${widget.placedOrderList!.subtotal}"), + Text("Gst: ${orderItem.gst}%"), + Text("GST Total: ${widget.placedOrderList!.gstTotal}"), + Text("Total Amount: ${widget.placedOrderList!.grandTotal}"), + ], + ), + ), + ], + ), + ), + ) + : const SizedBox.shrink(); + }, + ), + ), + ], + ), + ), + ), + ), + + const SizedBox(height: 8), + SizedBox( + height: Get.height* 0.19, + child: Card( + child: Column( + children: [ + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Text( + "Customer Details", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.05, + fontWeight: FontWeight.w500, + ), + ), + ), + ), + SizedBox( + width: Get.width, + //height: Get.height*0.09, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + children: [ + Text( + "Name: ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text("${"VAIBHAV"}",maxLines: 4, + overflow:TextOverflow.ellipsis,) + , ], + ) + ), + ), + SizedBox( + width: Get.width, + // height: Get.height*0.09, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + children: [ + Text( + "Email: ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text("${"vaibhav.gurjar20001@gmail.com"}",maxLines: 4, + overflow:TextOverflow.ellipsis,) + , ], + ) + ), + ), + SizedBox( + width: Get.width, + // height: Get.height*0.09, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + children: [ + Text( + "Mobile Number: ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text("${"7779797976"}",maxLines: 4, + overflow:TextOverflow.ellipsis,) + , ], + ) + ), + ) + + ], + ), + ), + ), + const SizedBox(height: 8), + Card( + child: Column( + children: [ + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Text( + "Billing Information", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.05, + fontWeight: FontWeight.w500, + ), + ), + ), + ), + SizedBox( + width: Get.width, + height: Get.height*0.06, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Wrap( + crossAxisAlignment: WrapCrossAlignment.start, + children: [ + Text( + "Address: ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text("${widget.placedOrderList!.billTo}",maxLines: 4, + overflow:TextOverflow.ellipsis,) + ], + ), + ), + ), + + ], + ), + ), + const SizedBox(height: 8), + // Card for displaying shipping information + Card( + child: Column( + children: [ + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Text( + "Shipping Information", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.05, + fontWeight: FontWeight.w500, + ), + ), + ), + ), + SizedBox( + width: Get.width, + height: Get.height*0.06, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Wrap( + crossAxisAlignment: WrapCrossAlignment.start, + children: [ + Text( + "Address: ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text("${widget.placedOrderList!.shipTo}",maxLines: 4, + overflow:TextOverflow.ellipsis,) + ], + ), + ), + ), + + ], + ), + ), + const SizedBox(height: 8), + Card( + child: Column( + children: [ + SizedBox( + width: Get.width, + height: Get.height*0.05, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + children: [ + Text( + "Payment Mode : ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.w500, + ), + ), + Text(capitalizeFirstLetter(widget.placedOrderList!.paymentMode)), + // Text("${widget.placedOrderList!.paymentMode}",maxLines: 4, + // overflow:TextOverflow.ellipsis,) + ], + ), + ), + ), + + + ], + ), + ), + const SizedBox(height: 8), + Card( + child: Column( + children: [ + SizedBox( + width: Get.width, + height: Get.height*0.05, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + children: [ + Text( + "Order Status :", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.w500, + ), + ), + SizedBox(width: Get.width*0.01,), + //Text(capitalizeFirstLetter(widget.placedOrderList!.status)), + Text("${widget.placedOrderList!.status}",maxLines: 4, + overflow:TextOverflow.ellipsis,) + ], + ), + ), + ), + + + ], + ), + ), + const SizedBox(height: 8), + SizedBox( + height: Get.height * 0.05, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Text( + "CancelledReason: ", + style: TextStyle(fontWeight: FontWeight.bold), + ), + SizedBox(width: 10), // Space between label and dropdown + Text("${widget.placedOrderList!.orderCancelledReason}",maxLines: 4, + overflow:TextOverflow.ellipsis,) + ], + ), + ), + SizedBox( + width: Get.width * 0.4, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: ElevatedButton( + onPressed: (){}, + // Get.to(() => + // RdOrderDetailScreen( + // placedOrderList: uniqueOrders[index])), // Navigate to detail screen + style: ElevatedButton.styleFrom( + foregroundColor: Colors.white, + backgroundColor: const Color(0xFF004791), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10)), + ), + child: Text("Update Status", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.w400)), + ), + ), + ) + + ], + ), + ), + ), + SizedBox(height: Get.height * 0.04), + + ], + ), + ), + ), + ], + ), + ); + } +} diff --git a/lib/screens/rd orders/rd_cancelled_screen.dart b/lib/screens/rd orders/rd_cancelled_screen.dart new file mode 100644 index 0000000..399e12f --- /dev/null +++ b/lib/screens/rd orders/rd_cancelled_screen.dart @@ -0,0 +1,350 @@ + +import 'package:cheminova/controller/rd_get_order_controller.dart'; +import 'package:cheminova/models/get_rd_cancelled_model.dart'; +import 'package:cheminova/models/rd_get_order_model.dart'; +import 'package:cheminova/models/single_get_order_model.dart'; +import 'package:cheminova/screens/rd%20orders/rd_cancelled_details_screen.dart'; +import 'package:cheminova/screens/rd%20orders/rd_dispatched_details_screen.dart'; +import 'package:cheminova/screens/rd%20orders/rd_order_details_screen.dart'; +import 'package:cheminova/screens/rd%20orders/rd_pending_deatils.dart'; +import 'package:cheminova/screens/rd%20orders/rd_processing_details.dart'; +import 'package:cheminova/widgets/input_field.dart'; +import 'package:cheminova/widgets/my_drawer.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:get/get.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:intl/intl.dart'; + +import '../../controller/get_rd_cancle_controller.dart'; +import '../order_management/order_management_detail_screen.dart'; + +class RdCancelledScreen extends StatefulWidget { + final PlacedOrdersResponse? getrdProduct; + + RdCancelledScreen({super.key, this.getrdProduct}); + + @override + State createState() => _RdCancelledScreenState(); +} + +class _RdCancelledScreenState extends State { + final _searchController = TextEditingController(); + final List _filterList = [ "new", + "pending", + "processing", + "dispatched", + "cancelled", + "delivered",]; + int _selectedIndex = 0; + final GetRDCancleController _getRdProductController = Get.put(GetRDCancleController()); + final GlobalKey _refreshIndicatorKey = GlobalKey(); + + @override + void initState() { + super.initState(); + getOrder1(); + } + + Future _onRefresh() async { + await getOrder1(); + await Future.delayed(Duration(seconds: 1)); + } + + Future getOrder1() async { + await _getRdProductController.getRDCancleProduct(); + if (_getRdProductController.productRDList.isEmpty) { + print("No orders found."); + } else { + print("Orders fetched successfully"); + } + } + + String capitalizeFirstLetter(String text) { + if (text.isEmpty) return text; + return text[0].toUpperCase() + text.substring(1).toLowerCase(); + } + + String formatDate(String apiDate) { + // Parse the API date string into a DateTime object + DateTime parsedDate = DateTime.parse(apiDate).toLocal(); // Convert to local time + + // Format the date and time according to your specified format + String formattedDate = DateFormat('EEE MMM dd yyyy').format(parsedDate); + + return formattedDate; // Return the formatted date string + } + + @override + Widget build(BuildContext context) { + return Scaffold( + extendBodyBehindAppBar: true, + appBar: AppBar( + centerTitle: true, + backgroundColor: Colors.transparent, + elevation: 0, + leading: Builder( + builder: (context) { + return GestureDetector( + onTap: () => Scaffold.of(context).openDrawer(), + child: Padding( + padding: const EdgeInsets.all(16.0), + child: SvgPicture.asset('assets/svg/menu.svg'), + ), + ); + }, + ), + actions: [ + GestureDetector( + onTap: () => Get.back(), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: SvgPicture.asset('assets/svg/back_arrow.svg'), + ), + ), + ], + title: const Text("RD Cancelled Order"), + ), + drawer: MyDrawer(), + body: Stack( + fit: StackFit.expand, + children: [ + Image.asset('assets/images/image_1.png', fit: BoxFit.cover), + SafeArea( + child: SingleChildScrollView( + child: Padding( + padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), + child: RefreshIndicator( + key: _refreshIndicatorKey, + onRefresh: _onRefresh, + color: Colors.black, + backgroundColor: Colors.white, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + InputField( + hintText: "Search Order", + labelText: "Search Order", + controller: _searchController, + ), + SizedBox(height: Get.height * 0.035), + Card( + margin: const EdgeInsets.symmetric(horizontal: 18), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(19), + side: const BorderSide(color: Color(0xFFFDFDFD)), + ), + color: const Color(0xFFB4D1E5).withOpacity(0.9), + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + // SizedBox( + // height: Get.height * 0.05, + // child: ListView.builder( + // shrinkWrap: true, + // scrollDirection: Axis.horizontal, + // itemCount: _filterList.length, + // itemBuilder: (context, index) => Padding( + // padding: const EdgeInsets.symmetric(horizontal: 4), + // child: GestureDetector( + // onTap: () { + // setState(() { + // _selectedIndex = index; // Update selected index + // }); + // // Navigate to different screens based on selected tab + // switch (_filterList[index]) { + // case "new": + // // Get.to(YourScreen1()); // Navigate to "new" orders screen + // break; + // case "pending": + // // Get.to(YourScreen2()); // Navigate to "pending" orders screen + // break; + // case "processing": + // // Get.to(YourScreen3()); // Navigate to "processing" orders screen + // break; + // // Add more cases for other statuses + // case "dispatched": + // // Get.to(YourScreen4()); // Navigate to dispatched orders + // break; + // case "cancelled": + // // Get.to(YourScreen5()); // Navigate to cancelled orders + // break; + // case "delivered": + // //Get.to(YourScreen6()); // Navigate to delivered orders + // break; + // default: + // // Get.to(YourScreen1()); // Default screen + // } + // }, + // child: Chip( + // label: Text(capitalizeFirstLetter( _filterList[index]) + // , + // style: GoogleFonts.roboto( + // fontSize: 14, + // fontWeight: FontWeight.w500, + // color: _selectedIndex == index ? Colors.white : Colors.black, // Change color when selected + // ), + // ), + // backgroundColor: _selectedIndex == index ? Colors.blue : Colors.grey[300], // Change color when selected + // ), + // ), + // ), + // ), + // ), + SizedBox( + height: Get.height * 0.6, + child: Obx(() { + // if (_getRdProductController.productRDList.isEmpty) { + // return Center( + // child: Text( + // 'No Orders Found', + // style: GoogleFonts.roboto(fontSize: 14), + // ), + // ); + // } + + final Set uniqueOrderIds = {}; + final List uniqueOrders = []; + + for (var order in _getRdProductController.productRDList) { + if (uniqueOrderIds.add(order.id)) { + uniqueOrders.add(order); + } + } + + if (uniqueOrders.isEmpty) { + return Center( + child: Text( + 'No Orders Found', + style: GoogleFonts.roboto(fontSize: 14), + ), + ); + } + + return ListView.builder( + padding: EdgeInsets.zero, + shrinkWrap: true, + itemCount: uniqueOrders.length, + itemBuilder: (context, index) { + final order = uniqueOrders[index]; + + // Combine product names into a single string + final productNames = order.orderItems + .map((item) => capitalizeFirstLetter(item.name)) + .join(', '); + + return Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Card( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.fromLTRB(16, 8, 8, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("Order ID: ", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.bold)), + Text("${order.uniqueId}") + ], + ), + ), + Padding( + padding: const EdgeInsets.fromLTRB(16, 8, 8, 0), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, // Aligns the Column to the top of the Text + children: [ + Text( + "Product Names: ", + style: GoogleFonts.roboto( + fontSize: 14, + fontWeight: FontWeight.bold, + ), + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, // Aligns text to the right within the Column + children: [ + const SizedBox(height: 4), // Adds a small space between the label and the product names + for (int i = 0; i < productNames.split(",").length; i++) + Text( + '${i + 1}. ${productNames.split(",")[i].trim()}', // Adds index and trims whitespace + textAlign: TextAlign.left, // Aligns text to the right + style: GoogleFonts.roboto( + fontSize: 14, + ), + ), + ], + ), + ), + ], + ), + ), + + + Padding( + padding: const EdgeInsets.fromLTRB(16, 8, 8, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("Order Date: ", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.bold)), + Text(formatDate("${order.createdAt}")) + ], + ), + ), + Padding( + padding: const EdgeInsets.fromLTRB(16, 8, 8, 8), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("Status: ", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.bold)), + Text(capitalizeFirstLetter("${order.status}")) + + ], + ), + ), + SizedBox( + width: Get.width * 0.4, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: ElevatedButton( + onPressed: ()=> + Get.to(() => + RdCancelledDetailScreen( + placedOrderList: uniqueOrders[index])), // Navigate to detail screen + style: ElevatedButton.styleFrom( + foregroundColor: Colors.white, + backgroundColor: const Color(0xFF004791), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10)), + ), + child: Text("View Details", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.w400)), + ), + ), + ) + ], + ), + ), + ); + }, + ); + }), + ) + ], + ), + ), + ), + ], + ), + ), + ), + ), + ), + ], + ), + ); + } +} + diff --git a/lib/screens/rd orders/rd_delivered_details_screen.dart b/lib/screens/rd orders/rd_delivered_details_screen.dart new file mode 100644 index 0000000..96d044d --- /dev/null +++ b/lib/screens/rd orders/rd_delivered_details_screen.dart @@ -0,0 +1,742 @@ +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:cheminova/controller/get_order_placed_controller.dart'; +import 'package:cheminova/models/get_delivered_model.dart'; +import 'package:cheminova/models/oder_place_model.dart'; +import 'package:cheminova/models/order_item_model.dart'; +import 'package:cheminova/models/place_order_list_model.dart'; +import 'package:cheminova/models/rd_get_order_model.dart'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:get/get.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:intl/intl.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +import '../../controller/cart_controller.dart'; +import '../../controller/get_delivered_controller.dart'; +import '../../models/product_model1.dart'; + +class RdDeliveredDetailsScreen extends StatefulWidget { + //final Product? productModel; + // PlacedOrderList and PlacedOrderModel are optional parameters passed to this screen + GetDeliveredModel? placedOrderList; +// PlacedOrderModel? placedOrderModel; + // Constructor for initializing the screen with placed order details + RdDeliveredDetailsScreen({super.key,this.placedOrderList}); + + @override + State createState() => + _RdDeliveredDetailsScreenState(); +} + + +class _RdDeliveredDetailsScreenState + extends State { + // Controllers for managing cart and placed orders + final CartController _cartController = Get.put(CartController()); + final GetDeliveredController _getPlacedOrderController = Get.put(GetDeliveredController()); + final List statusOptions = [ + "new", + "pending", + "processing", + "dispatched", + "cancelled", + "delivered", + ]; + String selectedStatus = "All"; + String _groupValue = "cheque"; + // Function to format date from the API to a more readable format + List _statusList = ["dispatched", "delivered"]; + + String formatDate(String apiDate) { + // Parse the API date string into a DateTime object + DateTime parsedDate = DateTime.parse(apiDate).toLocal(); // Convert to local time + + // Format the date and time according to your specified format + String formattedDate = DateFormat('EEE MMM dd yyyy').format(parsedDate); + + return formattedDate; // Return the formatted date string + } + + // Function to capitalize the first letter of a string + String capitalizeFirstLetter(String text) { + if (text.isEmpty) return text; + return text[0].toUpperCase() + text.substring(1).toLowerCase(); + } + + + void _onPaymentModeChanged(String? value) { + setState(() { + _groupValue = value!; + }); + _saveSelectedPaymentMode(); + } + + + void _saveSelectedPaymentMode() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + await prefs.setString('selectedPaymentMode', _groupValue); + } + + void _loadSelectedPaymentMode() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + setState(() { + _groupValue = prefs.getString('selectedPaymentMode') ?? 'cheque'; + }); + } + // Function to collect unique order IDs and corresponding order details + Future adduni()async { + final Set uniqueOrderIds = {}; + final List uniqueOrders = []; + // Loop through placed orders and add unique orders to the list + for (var order in _getPlacedOrderController.productProcessingRDList) { + if (uniqueOrderIds.add(order.orderId.uniqueId)) { + uniqueOrders.add(order); + } + } + final order = uniqueOrders[0]; + + // Combine product names, categories, and quantities into strings + final productNames = order.items + .map((item) => (item.name)) + .join(', '); + final categotyName = order.items + .map((item) => (item.categoryName)) + .join(', '); + final quantity = order.items + .map((item) => (item.processQuantity)) + .join(', '); + } + @override + void initState() { + // TODO: implement initState + super.initState(); + selectedStatus= widget.placedOrderList?.courierStatus ?? 'new'; + } + + + + + + @override + Widget build(BuildContext context) { + return Scaffold( + extendBodyBehindAppBar: true, + appBar: AppBar( + backgroundColor: Colors.transparent, + elevation: 0, + leading: GestureDetector( + onTap: () {}, + child: Padding( + padding: const EdgeInsets.all(16.0), + child: SvgPicture.asset( + 'assets/svg/menu.svg', + ), + ), + ), + actions: [ + GestureDetector( + onTap: () => Get.back(), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: SvgPicture.asset( + 'assets/svg/back_arrow.svg', + ), + ), + ), + ], + title: const Text( + "RD Delivered Order Details", + ), + ), + body: Stack( + fit: StackFit.expand, + children: [ + Image.asset( + 'assets/images/image_1.png', + fit: BoxFit.cover, + ), + SafeArea( + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + SizedBox( + height: Get.height * 0.02, + ), + Card( + margin: const EdgeInsets.symmetric(horizontal: 18), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(19), + side: const BorderSide(color: Color(0xFFFDFDFD)), + ), + color: const Color(0xFFB4D1E5).withOpacity(0.9), + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + + Card( + child: Column( + children: [ + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Text( + "Invoices", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.05, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Invoice ID:", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text(widget.placedOrderList!.invoiceId), + // Text(widget.placedOrderList!.uniqueId), + ], + ), + ), + ), + SizedBox( + width: Get.width, + child: Padding( + padding: const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Items: ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + SizedBox(height: 10), // Add spacing between the title and the list of items + Column( + children: widget.placedOrderList!.items.map((item) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 4.0), // Add some spacing between items + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Text( + "${item.name.toString()} (${item.sku.toString()})", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.03, + ), + overflow: TextOverflow.ellipsis, // Handle long text + ), + ), + Text("x ${item.processQuantity.toString()}"), + ], + ), + ); + }).toList(), + ), + ], + ), + ), + ), + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Sub Total : ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text("₹ ${widget.placedOrderList!.subtotal}"), + ], + ), + ), + ), + + + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "GST : ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text("₹ ${widget.placedOrderList!.gstTotal}"), + ], + ), + ), + ), + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Invoice Amount: ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text("₹ ${widget.placedOrderList!.invoiceAmount}"), + ], + ), + ), + ), + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Courier Status : ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + ElevatedButton( + onPressed: (){}, + // Get.to(() => + // RdOrderDetailScreen( + // placedOrderList: uniqueOrders[index])), // Navigate to detail screen + style: ElevatedButton.styleFrom( + foregroundColor: Colors.white, + backgroundColor: Colors.orange, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10)), + ), + child: Text(widget.placedOrderList!.courierStatus, style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.w400)), + ), + //Text("₹ ${widget.placedOrderList!.gstTotal}"), + ], + ), + ), + ), + ], + ), + ), + const SizedBox(height: 8), + // Card( + // child: SizedBox( + // height: Get.height * 0.22, + // child: Padding( + // padding: EdgeInsets.all(Get.width * 0.02), + // child: ListView.builder( + // padding: EdgeInsets.zero, + // itemCount: widget.placedOrderList?.items.length ?? 0, + // itemBuilder: (context, index) { + // final orderItem = widget.placedOrderList!.items[index]; + // return orderItem != null + // ? Card( + // margin: const EdgeInsets.symmetric(vertical: 5.0), + // shape: RoundedRectangleBorder( + // borderRadius: BorderRadius.circular(10), + // ), + // child: Padding( + // padding: const EdgeInsets.all(8.0), + // child: Row( + // children: [ + // Image.asset( + // "assets/images/product.png", // Add the image URL here + // height: 50, + // width: 50, + // fit: BoxFit.cover, + // ), + // const SizedBox(width: 10), + // Expanded( + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.end, + // children: [ + // Text( + // capitalizeFirstLetter(orderItem.name), + // style: GoogleFonts.roboto( + // fontSize: Get.width * 0.04, + // fontWeight: FontWeight.bold, + // ), + // ), + // Text( + // "Quantity: ${orderItem.processQuantity}", + // style: GoogleFonts.roboto( + // fontSize: Get.width * 0.03, + // ), + // ), + // ], + // ), + // ), + // ], + // ), + // ), + // ) + // : const SizedBox.shrink(); + // }, + // ), + // ), + // ), + // ), + const SizedBox(height: 8), + SizedBox( + height: Get.height* 0.19, + child: Card( + child: Column( + children: [ + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Text( + "Customer Details", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.05, + fontWeight: FontWeight.w500, + ), + ), + ), + ), + SizedBox( + width: Get.width, + //height: Get.height*0.09, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + children: [ + Text( + "Name: ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text("${"VAIBHAV"}",maxLines: 4, + overflow:TextOverflow.ellipsis,) + , ], + ) + ), + ), + SizedBox( + width: Get.width, + // height: Get.height*0.09, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + children: [ + Text( + "Email: ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text("${"vaibhav.gurjar20001@gmail.com"}",maxLines: 4, + overflow:TextOverflow.ellipsis,) + , ], + ) + ), + ), + SizedBox( + width: Get.width, + // height: Get.height*0.09, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + children: [ + Text( + "Mobile Number: ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text("${"7779797976"}",maxLines: 4, + overflow:TextOverflow.ellipsis,) + , ], + ) + ), + ) + + ], + ), + ), + ), + const SizedBox(height: 8), + Card( + child: Column( + children: [ + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Text( + "Billing Information", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.05, + fontWeight: FontWeight.w500, + ), + ), + ), + ), + SizedBox( + width: Get.width, + height: Get.height*0.06, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Wrap( + crossAxisAlignment: WrapCrossAlignment.start, + children: [ + Text( + "Address: ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text("${"456, Park Street, Kolkata, West Bengal - 700016"}",maxLines: 4, + overflow:TextOverflow.ellipsis,) + ], + ), + ), + ), + + ], + ), + ), + const SizedBox(height: 8), + // Card for displaying shipping information + Card( + child: Column( + children: [ + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Text( + "Shipping Information", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.05, + fontWeight: FontWeight.w500, + ), + ), + ), + ), + SizedBox( + width: Get.width, + height: Get.height*0.06, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Wrap( + crossAxisAlignment: WrapCrossAlignment.start, + children: [ + Text( + "Address: ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text("${"456, Park Street, Kolkata, West Bengal - 700016"}",maxLines: 4, + overflow:TextOverflow.ellipsis,) + ], + ), + ), + ), + + ], + ), + ), + const SizedBox(height: 8), + Card( + child: Column( + children: [ + SizedBox( + width: Get.width, + height: Get.height*0.05, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + children: [ + Text( + "Payment Mode : ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.w500, + ), + ), + Text(capitalizeFirstLetter("online-transfer")), + // Text("${widget.placedOrderList!.paymentMode}",maxLines: 4, + // overflow:TextOverflow.ellipsis,) + ], + ), + ), + ), + + + ], + ), + ), + const SizedBox(height: 8), + Card( + child: Column( + children: [ + SizedBox( + width: Get.width, + height: Get.height*0.05, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + children: [ + Text( + "Order Status :", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.w500, + ), + ), + SizedBox(width: Get.width*0.01,), + //Text(capitalizeFirstLetter(widget.placedOrderList!.status)), + Text("${"Delivered"}",maxLines: 4, + overflow:TextOverflow.ellipsis,) + ], + ), + ), + ), + + + ], + ), + ), + const SizedBox(height: 8), + // SizedBox( + // height: Get.height * 0.05, + // child: Row( + // crossAxisAlignment: CrossAxisAlignment.center, + // children: [ + // const Text( + // "Status: ", + // style: TextStyle(fontWeight: FontWeight.bold), + // ), + // SizedBox(width: 10), // Space between label and dropdown + // Expanded( + // child: DropdownButtonFormField( + // value: selectedStatus, + // decoration: InputDecoration( + // filled: true, + // fillColor: Colors.white, // White background + // contentPadding: EdgeInsets.symmetric( + // vertical: 10, horizontal: 12), + // border: OutlineInputBorder( + // borderRadius: BorderRadius.circular(10), + // borderSide: BorderSide( + // color: Colors.grey, + // width: 1, + // ), + // ), + // ), + // items: [ + // "new", + // "pending", + // "processing", + // "dispatched", + // "cancelled", + // "delivered", + // ].map((String status) { + // return DropdownMenuItem( + // value: status, + // child: Text(capitalizeFirstLetter(status)), + // ); + // }).toList(), + // onChanged: (newValue) { + // setState(() { + // selectedStatus = newValue!; + // }); + // }, + // ), + // ), + // ], + // ), + // ), + // SizedBox( + // width: Get.width * 0.4, + // child: Padding( + // padding: const EdgeInsets.all(8.0), + // child: ElevatedButton( + // onPressed: (){}, + // // Get.to(() => + // // RdOrderDetailScreen( + // // placedOrderList: uniqueOrders[index])), // Navigate to detail screen + // style: ElevatedButton.styleFrom( + // foregroundColor: Colors.white, + // backgroundColor: const Color(0xFF004791), + // shape: RoundedRectangleBorder( + // borderRadius: BorderRadius.circular(10)), + // ), + // child: Text("Update Status", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.w400)), + // ), + // ), + // ) + + ], + ), + ), + ), + SizedBox(height: Get.height * 0.04), + + ], + ), + ), + ), + ], + ), + ); + } +} diff --git a/lib/screens/rd orders/rd_delivered_screen.dart b/lib/screens/rd orders/rd_delivered_screen.dart new file mode 100644 index 0000000..627153e --- /dev/null +++ b/lib/screens/rd orders/rd_delivered_screen.dart @@ -0,0 +1,369 @@ + +import 'package:cheminova/controller/get_delivered_controller.dart'; +import 'package:cheminova/controller/rd_get_order_controller.dart'; +import 'package:cheminova/models/get_delivered_model.dart'; +import 'package:cheminova/models/rd_get_order_model.dart'; +import 'package:cheminova/screens/rd%20orders/rd_cancelled_details_screen.dart'; +import 'package:cheminova/screens/rd%20orders/rd_delivered_details_screen.dart'; +import 'package:cheminova/screens/rd%20orders/rd_dispatched_details_screen.dart'; +import 'package:cheminova/screens/rd%20orders/rd_order_details_screen.dart'; +import 'package:cheminova/screens/rd%20orders/rd_pending_deatils.dart'; +import 'package:cheminova/screens/rd%20orders/rd_processing_details.dart'; +import 'package:cheminova/widgets/input_field.dart'; +import 'package:cheminova/widgets/my_drawer.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:get/get.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:intl/intl.dart'; + +import '../order_management/order_management_detail_screen.dart'; + +class RdDeliveredScreen extends StatefulWidget { + final GetDeliveredModel? getrdProduct; + + RdDeliveredScreen({super.key, this.getrdProduct}); + + @override + State createState() => _RdDeliveredScreenState(); +} + +class _RdDeliveredScreenState extends State { + final _searchController = TextEditingController(); + final List _filterList = [ "new", + "pending", + "processing", + "dispatched", + "cancelled", + "delivered",]; + int _selectedIndex = 0; + final GetDeliveredController _getRdProductController = Get.put(GetDeliveredController()); + final GlobalKey _refreshIndicatorKey = GlobalKey(); + + @override + void initState() { + super.initState(); + getOrder1(); + } + + Future _onRefresh() async { + await getOrder1(); + await Future.delayed(Duration(seconds: 1)); + } + + Future getOrder1() async { + await _getRdProductController.getRDDeliveredInvoiceProduct(); + if (_getRdProductController.productProcessingRDList.isEmpty) { + print("No orders found."); + } else { + print("Orders fetched successfully"); + } + } + + String capitalizeFirstLetter(String text) { + if (text.isEmpty) return text; + return text[0].toUpperCase() + text.substring(1).toLowerCase(); + } + + String formatDate(String apiDate) { + // Parse the API date string into a DateTime object + DateTime parsedDate = DateTime.parse(apiDate).toLocal(); // Convert to local time + + // Format the date and time according to your specified format + String formattedDate = DateFormat('EEE MMM dd yyyy').format(parsedDate); + + return formattedDate; // Return the formatted date string + } + + @override + Widget build(BuildContext context) { + return Scaffold( + extendBodyBehindAppBar: true, + appBar: AppBar( + centerTitle: true, + backgroundColor: Colors.transparent, + elevation: 0, + leading: Builder( + builder: (context) { + return GestureDetector( + onTap: () => Scaffold.of(context).openDrawer(), + child: Padding( + padding: const EdgeInsets.all(16.0), + child: SvgPicture.asset('assets/svg/menu.svg'), + ), + ); + }, + ), + actions: [ + GestureDetector( + onTap: () => Get.back(), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: SvgPicture.asset('assets/svg/back_arrow.svg'), + ), + ), + ], + title: const Text("RD Delivered Order"), + ), + drawer: MyDrawer(), + body: Stack( + fit: StackFit.expand, + children: [ + Image.asset('assets/images/image_1.png', fit: BoxFit.cover), + SafeArea( + child: SingleChildScrollView( + child: Padding( + padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), + child: RefreshIndicator( + key: _refreshIndicatorKey, + onRefresh: _onRefresh, + color: Colors.black, + backgroundColor: Colors.white, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + InputField( + hintText: "Search Order", + labelText: "Search Order", + controller: _searchController, + ), + SizedBox(height: Get.height * 0.035), + Card( + margin: const EdgeInsets.symmetric(horizontal: 18), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(19), + side: const BorderSide(color: Color(0xFFFDFDFD)), + ), + color: const Color(0xFFB4D1E5).withOpacity(0.9), + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + // SizedBox( + // height: Get.height * 0.05, + // child: ListView.builder( + // shrinkWrap: true, + // scrollDirection: Axis.horizontal, + // itemCount: _filterList.length, + // itemBuilder: (context, index) => Padding( + // padding: const EdgeInsets.symmetric(horizontal: 4), + // child: GestureDetector( + // onTap: () { + // setState(() { + // _selectedIndex = index; // Update selected index + // }); + // // Navigate to different screens based on selected tab + // switch (_filterList[index]) { + // case "new": + // // Get.to(YourScreen1()); // Navigate to "new" orders screen + // break; + // case "pending": + // // Get.to(YourScreen2()); // Navigate to "pending" orders screen + // break; + // case "processing": + // // Get.to(YourScreen3()); // Navigate to "processing" orders screen + // break; + // // Add more cases for other statuses + // case "dispatched": + // // Get.to(YourScreen4()); // Navigate to dispatched orders + // break; + // case "cancelled": + // // Get.to(YourScreen5()); // Navigate to cancelled orders + // break; + // case "delivered": + // //Get.to(YourScreen6()); // Navigate to delivered orders + // break; + // default: + // // Get.to(YourScreen1()); // Default screen + // } + // }, + // child: Chip( + // label: Text(capitalizeFirstLetter( _filterList[index]) + // , + // style: GoogleFonts.roboto( + // fontSize: 14, + // fontWeight: FontWeight.w500, + // color: _selectedIndex == index ? Colors.white : Colors.black, // Change color when selected + // ), + // ), + // backgroundColor: _selectedIndex == index ? Colors.blue : Colors.grey[300], // Change color when selected + // ), + // ), + // ), + // ), + // ), + SizedBox( + height: Get.height * 0.6, + child: Obx(() { + // if (_getRdProductController.productRDList.isEmpty) { + // return Center( + // child: Text( + // 'No Orders Found', + // style: GoogleFonts.roboto(fontSize: 14), + // ), + // ); + // } + + final Set uniqueOrderIds = {}; + final List uniqueOrders = []; + + for (var order in _getRdProductController.productProcessingRDList) { + if (uniqueOrderIds.add(order.id)) { + uniqueOrders.add(order); + } + } + + if (uniqueOrders.isEmpty) { + return Center( + child: Text( + 'No Orders Found', + style: GoogleFonts.roboto(fontSize: 14), + ), + ); + } + + return ListView.builder( + padding: EdgeInsets.zero, + shrinkWrap: true, + itemCount: uniqueOrders.length, + itemBuilder: (context, index) { + final order = uniqueOrders[index]; + + // Combine product names into a single string + final productNames = order.items + .map((item) => capitalizeFirstLetter(item.name)) + .join(', '); + + return Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Card( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.fromLTRB(16, 8, 8, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("Order ID: ", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.bold)), + Text("${order.orderId.uniqueId}") + ], + ), + ), + Padding( + padding: const EdgeInsets.fromLTRB(16, 8, 8, 0), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Invoice ID: ", + style: GoogleFonts.roboto( + fontSize: 14, + fontWeight: FontWeight.bold, + ), + ), + Text(order.invoiceId), + + ], + ), + ), + + Padding( + padding: const EdgeInsets.fromLTRB(16, 8, 8, 0), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Delivered Date: ", + style: GoogleFonts.roboto( + fontSize: 14, + fontWeight: FontWeight.bold, + ), + ), + Text( + _getRdProductController.productProcessingRDList[0]!.courierStatusTimeline !=null + ? formatDate( _getRdProductController.productProcessingRDList[0].courierStatusTimeline.delivered) + : 'N/A', // If the map is empty or null, display 'N/A' + style: GoogleFonts.roboto( + fontSize: 14, + ), + ), + + ], + ), + ), + Padding( + padding: const EdgeInsets.fromLTRB(16, 8, 8, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("Items: ", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.bold)), + Text("${order.items.length}"), + ], + ), + ), + Padding( + padding: const EdgeInsets.fromLTRB(16, 8, 8, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("Invoice Value: ", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.bold)), + Text("${order.invoiceAmount}"), + ], + ), + ), + Padding( + padding: const EdgeInsets.fromLTRB(16, 8, 8, 8), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("Status: ", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.bold)), + Text(capitalizeFirstLetter("${order.courierStatus}")) + + ], + ), + ), + SizedBox( + width: Get.width * 0.4, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: ElevatedButton( + onPressed: ()=> + Get.to(() => + RdDeliveredDetailsScreen( + placedOrderList: uniqueOrders[index])), // Navigate to detail screen + style: ElevatedButton.styleFrom( + foregroundColor: Colors.white, + backgroundColor: const Color(0xFF004791), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10)), + ), + child: Text("View Details", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.w400)), + ), + ), + ) + ], + ), + ), + ); + }, + ); + }), + ) + ], + ), + ), + ), + ], + ), + ), + ), + ), + ), + ], + ), + ); + } +} + diff --git a/lib/screens/rd orders/rd_dispatched_details_screen.dart b/lib/screens/rd orders/rd_dispatched_details_screen.dart new file mode 100644 index 0000000..936dfe0 --- /dev/null +++ b/lib/screens/rd orders/rd_dispatched_details_screen.dart @@ -0,0 +1,838 @@ +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:cheminova/controller/get_dispatch_controller.dart'; +import 'package:cheminova/controller/get_order_placed_controller.dart'; +import 'package:cheminova/models/get_dispatch_model.dart'; +import 'package:cheminova/models/oder_place_model.dart'; +import 'package:cheminova/models/order_item_model.dart'; +import 'package:cheminova/models/place_order_list_model.dart'; +import 'package:cheminova/models/rd_get_order_model.dart'; +import 'package:cheminova/utils/show_snackbar.dart'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:get/get.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:intl/intl.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +import '../../controller/cart_controller.dart'; +import '../../models/product_model1.dart'; + +class RdDispatchedDetailsDetailScreen extends StatefulWidget { + //final Product? productModel; + // PlacedOrderList and PlacedOrderModel are optional parameters passed to this screen + GetDispatchModel? placedOrderList; + PlacedOrderModel? placedOrderModel; + // Constructor for initializing the screen with placed order details + RdDispatchedDetailsDetailScreen({super.key,this.placedOrderList,this.placedOrderModel}); + + @override + State createState() => + _RdDispatchedDetailsDetailScreenState(); +} + + +class _RdDispatchedDetailsDetailScreenState + extends State { + // Controllers for managing cart and placed orders + final CartController _cartController = Get.put(CartController()); + final GetDispatchController _getPlacedOrderController = Get.put(GetDispatchController()); + final GetDispatchController _getDispatchController = Get.put(GetDispatchController()); + final List statusOptions = [ + "new", + "pending", + "processing", + "dispatched", + "cancelled", + "delivered", + ]; + String selectedStatus = "dispatched"; + String _groupValue = "cheque"; + // Function to format date from the API to a more readable format + + List _statusList = ["dispatched", "delivered"]; + String formatDate(String apiDate) { + // Parse the API date string into a DateTime object + DateTime parsedDate = DateTime.parse(apiDate).toLocal(); // Convert to local time + + // Format the date and time according to your specified format + String formattedDate = DateFormat('EEE MMM dd yyyy').format(parsedDate); + + return formattedDate; // Return the formatted date string + } + + // Function to capitalize the first letter of a string + String capitalizeFirstLetter(String text) { + if (text.isEmpty) return text; + return text[0].toUpperCase() + text.substring(1).toLowerCase(); + } + + + void _onPaymentModeChanged(String? value) { + setState(() { + _groupValue = value!; + }); + _saveSelectedPaymentMode(); + } + + + void _saveSelectedPaymentMode() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + await prefs.setString('selectedPaymentMode', _groupValue); + } + + void _loadSelectedPaymentMode() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + setState(() { + _groupValue = prefs.getString('selectedPaymentMode') ?? 'cheque'; + }); + } + // Function to collect unique order IDs and corresponding order details + Future adduni()async { + final Set uniqueOrderIds = {}; + final List uniqueOrders = []; + // Loop through placed orders and add unique orders to the list + for (var order in _getPlacedOrderController.productProcessingRDList) { + if (uniqueOrderIds.add(order.orderId.uniqueId)) { + uniqueOrders.add(order); + } + } + final order = uniqueOrders[0]; + + // Combine product names, categories, and quantities into strings + final productNames = order.items + .map((item) => (item.name)) + .join(', '); + final categotyName =order.items + .map((item) => (item.categoryName)) + .join(', '); + final quantity = order.items + .map((item) => (item.processquantity)) + .join(', '); + } + @override + void initState() { + // TODO: implement initState + super.initState(); + selectedStatus= widget.placedOrderList?.courierStatus ?? 'new'; + _getPlacedOrderController.getRDDispatchInvoiceProduct(); + } + + + void showConfirmDeliveryDialog(BuildContext context) { + final TextEditingController _deliveryDetailsController = TextEditingController(); + DateTime? selectedDate; // Variable to hold the selected delivery date + + showDialog( + context: context, + builder: (context) { + return StatefulBuilder( + builder: (context, setState) { // Use StatefulBuilder to update the dialog state + return AlertDialog( + title: Text('Confirm Delivery'), + content: Column( + mainAxisSize: MainAxisSize.min, // Shrink to fit the content + children: [ + SizedBox(height: 20), // Space between text field and date picker + Text( + selectedDate == null + ? 'Select Delivery Date *' + : 'Delivery Date: ${selectedDate!.toLocal().toString().split(' ')[0]}', // Show selected date + style: TextStyle(fontSize: 16), + ), + SizedBox(height: 10), // Space + ElevatedButton( + onPressed: () async { + // Show date picker + DateTime? pickedDate = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime.now(), // Prevent past dates + lastDate: DateTime(2101), + ); + if (pickedDate != null) { + // Update the selected date and refresh the UI + setState(() { + selectedDate = pickedDate; + }); + } + }, + child: Text('Select Date'), + ), + ], + ), + actions: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(); // Close the dialog + }, + child: Text('Cancel'), + ), + TextButton( + onPressed: () async { + if (selectedDate != null) { + // Handle the confirmation logic + String deliveryDetails = _deliveryDetailsController.text; + + // Check if the selected status is "delivered" + if (selectedStatus == "delivered") { + // Call your API method here + await _getDispatchController.RDDispatchToDeliveredProduct(widget.placedOrderList!.id); + showSnackbar("Order Status updated Order Delivered"); + } else { + // Show a message if the status is not "Delivered" + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('Cannot confirm delivery: Status is not Delivered.')), + ); + } + } else { + // Show a message if the date is not selected + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('Please select a delivery date.')), + ); + } + Navigator.of(context).pop(); // Close the dialog after submission + }, + child: Text('Confirm'), + ), + ], + ); + }, + ); + }, + ); + } + + // + // void showConfirmDeliveryDialog() { + // final TextEditingController _deliveryDetailsController = TextEditingController(); + // DateTime? selectedDate; // Variable to hold the selected delivery date + // + // showDialog( + // context: context, + // builder: (context) { + // return AlertDialog( + // title: Text('Confirm Delivery'), + // content: Column( + // mainAxisSize: MainAxisSize.min, // Shrink to fit the content + // children: [ + // SizedBox(height: 20), // Space between text field and date picker + // Text(selectedDate == null + // ? 'Select Delivery Date *' + // : 'Delivery Date: ${selectedDate!.toLocal()}'.split(' ')[0]), // Show selected date + // SizedBox(height: 10), // Space + // ElevatedButton( + // onPressed: () async { + // // Show date picker + // DateTime? pickedDate = await showDatePicker( + // context: context, + // initialDate: DateTime.now(), + // firstDate: DateTime.now(), // Prevent past dates + // lastDate: DateTime(2101), + // ); + // if (pickedDate != null && pickedDate != selectedDate) { + // selectedDate = pickedDate; // Update the selected date + // } + // }, + // child: Text('Select Date'), + // ), + // ], + // ), + // actions: [ + // TextButton( + // onPressed: () { + // Navigator.of(context).pop(); // Close the dialog + // }, + // child: Text('Cancel'), + // ), + // TextButton( + // onPressed: () async { + // if (selectedDate != null) { + // // Handle the confirmation logic + // String deliveryDetails = _deliveryDetailsController.text; + // + // // Check if the selected status is "Delivered" + // if (selectedStatus == "delivered") { + // // Call your API method here + // await _getDispatchController.RDDispatchToDeliveredProduct(widget.placedOrderList!.id); + // } else { + // // Show a message if the status is not "Delivered" + // ScaffoldMessenger.of(context).showSnackBar( + // SnackBar(content: Text('Cannot confirm delivery: Status is not Delivered.')), + // ); + // } + // } else { + // // Show a message if the date is not selected + // ScaffoldMessenger.of(context).showSnackBar( + // SnackBar(content: Text('Please select a delivery date.')), + // ); + // } + // Navigator.of(context).pop(); // Close the dialog after submission + // }, + // child: Text('Confirm'), + // ), + // ], + // ); + // }, + // ); + // } + + @override + Widget build(BuildContext context) { + return Scaffold( + extendBodyBehindAppBar: true, + appBar: AppBar( + backgroundColor: Colors.transparent, + elevation: 0, + leading: GestureDetector( + onTap: () {}, + child: Padding( + padding: const EdgeInsets.all(16.0), + child: SvgPicture.asset( + 'assets/svg/menu.svg', + ), + ), + ), + actions: [ + GestureDetector( + onTap: () => Get.back(), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: SvgPicture.asset( + 'assets/svg/back_arrow.svg', + ), + ), + ), + ], + title: const Text( + "RD Dispatched Order Details", + ), + ), + body: Stack( + fit: StackFit.expand, + children: [ + Image.asset( + 'assets/images/image_1.png', + fit: BoxFit.cover, + ), + SafeArea( + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + SizedBox( + height: Get.height * 0.02, + ), + Card( + margin: const EdgeInsets.symmetric(horizontal: 18), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(19), + side: const BorderSide(color: Color(0xFFFDFDFD)), + ), + color: const Color(0xFFB4D1E5).withOpacity(0.9), + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Card( + child: Column( + children: [ + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Text( + "Invoices", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.05, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Invoice ID:", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text(widget.placedOrderList!.invoiceId), + // Text(widget.placedOrderList!.uniqueId), + ], + ), + ), + ), + SizedBox( + width: Get.width, + child: Padding( + padding: const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Items: ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + SizedBox(height: 10), // Add spacing between the title and the list of items + Column( + children: widget.placedOrderList!.items.map((item) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 4.0), // Add some spacing between items + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Text( + "${item.name.toString()} (${item.SKU.toString()})", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.03, + ), + overflow: TextOverflow.ellipsis, // Handle long text + ), + ), + Text("x ${item.processquantity.toString()}"), + ], + ), + ); + }).toList(), + ), + ], + ), + ), + ), + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Sub Total : ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text("₹ ${widget.placedOrderList!.subtotal}"), + ], + ), + ), + ), + + + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "GST : ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text("₹ ${widget.placedOrderList!.gstTotal}"), + ], + ), + ), + ), + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Invoice Amount: ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text("₹ ${widget.placedOrderList!.invoiceAmount}"), + ], + ), + ), + ), + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Courier Status : ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + ElevatedButton( + onPressed: (){}, + // Get.to(() => + // RdOrderDetailScreen( + // placedOrderList: uniqueOrders[index])), // Navigate to detail screen + style: ElevatedButton.styleFrom( + foregroundColor: Colors.white, + backgroundColor: Colors.orange, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10)), + ), + child: Text(widget.placedOrderList!.courierStatus, style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.w400)), + ), + //Text("₹ ${widget.placedOrderList!.gstTotal}"), + ], + ), + ), + ), + ], + ), + ), + + + const SizedBox(height: 8), + SizedBox( + height: Get.height* 0.19, + child: Card( + child: Column( + children: [ + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Text( + "Customer Details", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.05, + fontWeight: FontWeight.w500, + ), + ), + ), + ), + SizedBox( + width: Get.width, + //height: Get.height*0.09, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + children: [ + Text( + "Name: ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text("${"VAIBHAV"}",maxLines: 4, + overflow:TextOverflow.ellipsis,) + , ], + ) + ), + ), + SizedBox( + width: Get.width, + // height: Get.height*0.09, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + children: [ + Text( + "Email: ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text("${"vaibhav.gurjar20001@gmail.com"}",maxLines: 4, + overflow:TextOverflow.ellipsis,) + , ], + ) + ), + ), + SizedBox( + width: Get.width, + // height: Get.height*0.09, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + children: [ + Text( + "Mobile Number: ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text("${"7779797976"}",maxLines: 4, + overflow:TextOverflow.ellipsis,) + , ], + ) + ), + ) + + ], + ), + ), + ), + const SizedBox(height: 8), + Card( + child: Column( + children: [ + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Text( + "Billing Information", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.05, + fontWeight: FontWeight.w500, + ), + ), + ), + ), + SizedBox( + width: Get.width, + height: Get.height*0.06, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Wrap( + crossAxisAlignment: WrapCrossAlignment.start, + children: [ + Text( + "Address: ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text("${"456, Park Street, Kolkata, West Bengal - 700016"}",maxLines: 4, + overflow:TextOverflow.ellipsis,) + ], + ), + ), + ), + + ], + ), + ), + const SizedBox(height: 8), + // Card for displaying shipping information + Card( + child: Column( + children: [ + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Text( + "Shipping Information", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.05, + fontWeight: FontWeight.w500, + ), + ), + ), + ), + SizedBox( + width: Get.width, + height: Get.height*0.06, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Wrap( + crossAxisAlignment: WrapCrossAlignment.start, + children: [ + Text( + "Address: ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text("${"456, Park Street, Kolkata, West Bengal - 700016"}",maxLines: 4, + overflow:TextOverflow.ellipsis,) + ], + ), + ), + ), + + ], + ), + ), + const SizedBox(height: 8), + Card( + child: Column( + children: [ + SizedBox( + width: Get.width, + height: Get.height*0.05, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + children: [ + Text( + "Payment Mode : ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.w500, + ), + ), + Text(capitalizeFirstLetter("Cheque")), + // Text("${widget.placedOrderList!.paymentMode}",maxLines: 4, + // overflow:TextOverflow.ellipsis,) + ], + ), + ), + ), + + + ], + ), + ), + const SizedBox(height: 8), + Card( + child: Column( + children: [ + SizedBox( + width: Get.width, + height: Get.height*0.05, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + children: [ + Text( + "Order Status :", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.w500, + ), + ), + SizedBox(width: Get.width*0.01,), + //Text(capitalizeFirstLetter(widget.placedOrderList!.status)), + Text("${"Dispatched"}",maxLines: 4, + overflow:TextOverflow.ellipsis,) + ], + ), + ), + ), + + + ], + ), + ), + const SizedBox(height: 8), + SizedBox( + height: Get.height * 0.05, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Text( + "Status: ", + style: TextStyle(fontWeight: FontWeight.bold), + ), + SizedBox(width: 10), // Space between label and dropdown + Expanded( + child: DropdownButtonFormField( + value: selectedStatus, + decoration: InputDecoration( + filled: true, + fillColor: Colors.white, // White background + contentPadding: EdgeInsets.symmetric( + vertical: 10, horizontal: 12), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: BorderSide( + color: Colors.grey, + width: 1, + ), + ), + ), + items: _statusList.map((String status){ + return DropdownMenuItem( + value: status, + child: Text(capitalizeFirstLetter(status)), + ); + }).toList(), + onChanged: (newValue) { + setState(() { + selectedStatus = newValue!; + }); + }, + ), + ), + ], + ), + ), + SizedBox( + width: Get.width * 0.4, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: ElevatedButton( + onPressed: (){ + showConfirmDeliveryDialog(context); + }, + // Get.to(() => + // RdOrderDetailScreen( + // placedOrderList: uniqueOrders[index])), // Navigate to detail screen + style: ElevatedButton.styleFrom( + foregroundColor: Colors.white, + backgroundColor: const Color(0xFF004791), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10)), + ), + child: Text("Update Status", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.w400)), + ), + ), + ) + + ], + ), + ), + ), + SizedBox(height: Get.height * 0.04), + + ], + ), + ), + ), + ], + ), + ); + } +} diff --git a/lib/screens/rd orders/rd_dispatched_scree.dart b/lib/screens/rd orders/rd_dispatched_scree.dart new file mode 100644 index 0000000..9cf5b45 --- /dev/null +++ b/lib/screens/rd orders/rd_dispatched_scree.dart @@ -0,0 +1,376 @@ + +import 'package:cheminova/controller/rd_get_order_controller.dart'; +import 'package:cheminova/models/get_dispatch_model.dart'; +import 'package:cheminova/models/rd_get_order_model.dart'; +import 'package:cheminova/screens/rd%20orders/rd_dispatched_details_screen.dart'; +import 'package:cheminova/screens/rd%20orders/rd_order_details_screen.dart'; +import 'package:cheminova/screens/rd%20orders/rd_pending_deatils.dart'; +import 'package:cheminova/screens/rd%20orders/rd_processing_details.dart'; +import 'package:cheminova/widgets/input_field.dart'; +import 'package:cheminova/widgets/my_drawer.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:get/get.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:intl/intl.dart'; + +import '../../controller/get_dispatch_controller.dart'; +import '../order_management/order_management_detail_screen.dart'; + +class RdDispatchedScreen extends StatefulWidget { + final GetDispatchModel? getrdProduct; + + RdDispatchedScreen({super.key, this.getrdProduct}); + + @override + State createState() => _RdDispatchedScreenState(); +} + +class _RdDispatchedScreenState extends State { + final _searchController = TextEditingController(); + final List _filterList = [ "new", + "pending", + "processing", + "dispatched", + "cancelled", + "delivered",]; + int _selectedIndex = 0; + final GetDispatchController _getRdProductController = Get.put(GetDispatchController()); + final GlobalKey _refreshIndicatorKey = GlobalKey(); + + @override + void initState() { + super.initState(); + getOrder1(); + } + + Future _onRefresh() async { + await getOrder1(); + await Future.delayed(Duration(seconds: 1)); + } + + Future getOrder1() async { + await _getRdProductController.getRDDispatchInvoiceProduct(); + if (_getRdProductController.productProcessingRDList.isEmpty) { + print("No orders found."); + } else { + print("Orders fetched successfully"); + } + } + + String capitalizeFirstLetter(String text) { + if (text.isEmpty) return text; + return text[0].toUpperCase() + text.substring(1).toLowerCase(); + } + + String formatDate(String apiDate) { + // Parse the API date string into a DateTime object + DateTime parsedDate = DateTime.parse(apiDate).toLocal(); // Convert to local time + + // Format the date and time according to your specified format + String formattedDate = DateFormat('EEE MMM dd yyyy').format(parsedDate); + + return formattedDate; // Return the formatted date string + } + + // String formatDate(String apiDate) { + // // Parse the API date string into a DateTime object + // DateTime parsedDate = DateTime.parse(apiDate).toLocal(); // Convert to local time + // + // // Format the date and time according to your specified format + // String formattedDate = DateFormat('EEE MMM dd yyyy, hh:mm a').format(parsedDate); + // + // return formattedDate; // Return the formatted date string + // } + @override + Widget build(BuildContext context) { + return Scaffold( + extendBodyBehindAppBar: true, + appBar: AppBar( + centerTitle: true, + backgroundColor: Colors.transparent, + elevation: 0, + leading: Builder( + builder: (context) { + return GestureDetector( + onTap: () => Scaffold.of(context).openDrawer(), + child: Padding( + padding: const EdgeInsets.all(16.0), + child: SvgPicture.asset('assets/svg/menu.svg'), + ), + ); + }, + ), + actions: [ + GestureDetector( + onTap: () => Get.back(), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: SvgPicture.asset('assets/svg/back_arrow.svg'), + ), + ), + ], + title: const Text("RD Dispatched Order"), + ), + drawer: MyDrawer(), + body: Stack( + fit: StackFit.expand, + children: [ + Image.asset('assets/images/image_1.png', fit: BoxFit.cover), + SafeArea( + child: SingleChildScrollView( + child: Padding( + padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), + child: RefreshIndicator( + key: _refreshIndicatorKey, + onRefresh: _onRefresh, + color: Colors.black, + backgroundColor: Colors.white, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + InputField( + hintText: "Search Order", + labelText: "Search Order", + controller: _searchController, + ), + SizedBox(height: Get.height * 0.035), + Card( + margin: const EdgeInsets.symmetric(horizontal: 18), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(19), + side: const BorderSide(color: Color(0xFFFDFDFD)), + ), + color: const Color(0xFFB4D1E5).withOpacity(0.9), + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + // SizedBox( + // height: Get.height * 0.05, + // child: ListView.builder( + // shrinkWrap: true, + // scrollDirection: Axis.horizontal, + // itemCount: _filterList.length, + // itemBuilder: (context, index) => Padding( + // padding: const EdgeInsets.symmetric(horizontal: 4), + // child: GestureDetector( + // onTap: () { + // setState(() { + // _selectedIndex = index; // Update selected index + // }); + // // Navigate to different screens based on selected tab + // switch (_filterList[index]) { + // case "new": + // // Get.to(YourScreen1()); // Navigate to "new" orders screen + // break; + // case "pending": + // // Get.to(YourScreen2()); // Navigate to "pending" orders screen + // break; + // case "processing": + // // Get.to(YourScreen3()); // Navigate to "processing" orders screen + // break; + // // Add more cases for other statuses + // case "dispatched": + // // Get.to(YourScreen4()); // Navigate to dispatched orders + // break; + // case "cancelled": + // // Get.to(YourScreen5()); // Navigate to cancelled orders + // break; + // case "delivered": + // //Get.to(YourScreen6()); // Navigate to delivered orders + // break; + // default: + // // Get.to(YourScreen1()); // Default screen + // } + // }, + // child: Chip( + // label: Text(capitalizeFirstLetter( _filterList[index]) + // , + // style: GoogleFonts.roboto( + // fontSize: 14, + // fontWeight: FontWeight.w500, + // color: _selectedIndex == index ? Colors.white : Colors.black, // Change color when selected + // ), + // ), + // backgroundColor: _selectedIndex == index ? Colors.blue : Colors.grey[300], // Change color when selected + // ), + // ), + // ), + // ), + // ), + SizedBox( + height: Get.height * 0.6, + child: Obx(() { + // if (_getRdProductController.productRDList.isEmpty) { + // return Center( + // child: Text( + // 'No Orders Found', + // style: GoogleFonts.roboto(fontSize: 14), + // ), + // ); + // } + + final Set uniqueOrderIds = {}; + final List uniqueOrders = []; + + for (var order in _getRdProductController.productProcessingRDList) { + if (uniqueOrderIds.add(order.id)) { + uniqueOrders.add(order); + } + } + + if (uniqueOrders.isEmpty) { + return Center( + child: Text( + 'No Orders Found', + style: GoogleFonts.roboto(fontSize: 14), + ), + ); + } + + return ListView.builder( + padding: EdgeInsets.zero, + shrinkWrap: true, + itemCount: uniqueOrders.length, + itemBuilder: (context, index) { + final order = uniqueOrders[index]; + + // Combine product names into a single string + final productNames = order.items + .map((item) => capitalizeFirstLetter(item.name)) + .join(', '); + + return Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Card( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.fromLTRB(16, 8, 8, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("Order ID: ", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.bold)), + Text("${order.orderId.uniqueId}") + ], + ), + ), + Padding( + padding: const EdgeInsets.fromLTRB(16, 8, 8, 0), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Invoice ID: ", + style: GoogleFonts.roboto( + fontSize: 14, + fontWeight: FontWeight.bold, + ), + ), + Text(order.invoiceId), + + ], + ), + ), + + Padding( + padding: const EdgeInsets.fromLTRB(16, 8, 8, 0), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Dispatched Date: ", + style: GoogleFonts.roboto( + fontSize: 14, + fontWeight: FontWeight.bold, + ), + ), + Text( + _getRdProductController.productProcessingRDList[0].courierstatusTimeline !=null + ? formatDate( _getRdProductController.productProcessingRDList[0].courierstatusTimeline.dispatched) + : 'N/A', // If the map is empty or null, display 'N/A' + style: GoogleFonts.roboto( + fontSize: 14, + ), + ), + + ], + ), + ), + Padding( + padding: const EdgeInsets.fromLTRB(16, 8, 8, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("Items: ", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.bold)), + Text("${order.items.length}"), + ], + ), + ), + Padding( + padding: const EdgeInsets.fromLTRB(16, 8, 8, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("Invoice Value: ", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.bold)), + Text("${order.invoiceAmount}"), + ], + ), + ), + Padding( + padding: const EdgeInsets.fromLTRB(16, 8, 8, 8), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("Status: ", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.bold)), + Text(capitalizeFirstLetter("${order.courierStatus}")) + + ], + ), + ), + SizedBox( + width: Get.width * 0.4, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: ElevatedButton( + onPressed: ()=> + Get.to(() => + RdDispatchedDetailsDetailScreen( + placedOrderList: uniqueOrders[index])), // Navigate to detail screen + style: ElevatedButton.styleFrom( + foregroundColor: Colors.white, + backgroundColor: const Color(0xFF004791), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10)), + ), + child: Text("View Details", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.w400)), + ), + ), + ) + ], + ), + ), + ); + }, + ); + }), + ) + ], + ), + ), + ), + ], + ), + ), + ), + ), + ), + ], + ), + ); + } +} + diff --git a/lib/screens/rd orders/rd_order_details_screen.dart b/lib/screens/rd orders/rd_order_details_screen.dart index 605a9fd..1ba3105 100644 --- a/lib/screens/rd orders/rd_order_details_screen.dart +++ b/lib/screens/rd orders/rd_order_details_screen.dart @@ -76,13 +76,15 @@ class _RdOrderDetailScreenState } String formatDate(String apiDate) { + // Parse the API date string into a DateTime object + DateTime parsedDate = DateTime.parse(apiDate).toLocal(); // Convert to local time - DateTime parsedDate = DateTime.parse(apiDate); + // Format the date and time according to your specified format + String formattedDate = DateFormat('EEE MMM dd yyyy').format(parsedDate); - String formattedDate = DateFormat('dd-MMM-yyyy').format(parsedDate); - - return formattedDate; + return formattedDate; // Return the formatted date string } + // Function to capitalize the first letter of a string String capitalizeFirstLetter(String text) { if (text.isEmpty) return text; @@ -132,14 +134,13 @@ class _RdOrderDetailScreenState .map((item) => (item.quantity)) .join(', '); } -@override + @override void initState() { // TODO: implement initState super.initState(); - selectedStatus= widget.placedOrderList?.status ?? 'new'; + selectedStatus= widget.placedOrderList?.status ?? 'new'; // controller.fetchOrderItems(widget.placedOrderList!.id); } - void _showConfirmationDialog() { String dialogTitle; String dialogContent; @@ -204,12 +205,12 @@ class _RdOrderDetailScreenState // Update the status in your UI or backend to reflect the cancelled state setState(() { - // Update the status in the local model/UI + // Update the status in the local model/UI }); // Close the dialog after a short delay Future.delayed(Duration(seconds: 1), () { - Get.back(); // Close the dialog + Navigator.of(context).pop(); // Close the dialog }); return; // Exit here to prevent further processing @@ -217,9 +218,11 @@ class _RdOrderDetailScreenState if (selectedStatus == "partial processing") { Get.to(() => PartialProcessingDialogScreen(productModel: widget.placedOrderList)); + return; } + // Create a map to track products by their IDs and aggregate quantities Map orderItemMap = {}; @@ -229,8 +232,10 @@ class _RdOrderDetailScreenState if (orderItemMap.containsKey(productId)) { // If the product already exists, aggregate the quantity - var existingItem = orderItemMap[productId]!; // Get the existing item + var existingItem = orderItemMap[productId]!; existingItem.quantity = (existingItem.quantity ?? 0) + (item.orderItem[0].quantity ?? 0); + existingItem.remainingQuantity = (existingItem.remainingQuantity ?? 0) + (item.orderItem[0].remainingQuantity ?? 0); + existingItem.processquantity = (existingItem.processquantity ?? 0) + (item.orderItem[0].processquantity ?? 0); } else { // If it's a new product, add it to the map orderItemMap[productId] = RDOrderItem( @@ -240,13 +245,13 @@ class _RdOrderDetailScreenState categoryName: item.orderItem[0].categoryName, brandName: item.orderItem[0].brandName, price: item.orderItem[0].price, - gst: item.orderItem[0].gst, + gst: item.orderItem[0].gst.toInt(), hsnCode: item.orderItem[0].hsnCode, description: item.orderItem[0].description, image: [], // Handle images appropriately - quantity: item.orderItem[0].quantity??0, - remainingQuantity: item.orderItem[0].remainingQuantity??0, - processquantity: item.orderItem[0].processquantity??0, + quantity: item.orderItem[0].quantity ?? 0, + remainingQuantity: item.orderItem[0].remainingQuantity ?? 0, + processquantity: item.orderItem[0].processquantity ?? 0, ); } } @@ -261,23 +266,24 @@ class _RdOrderDetailScreenState ); // Debugging: Print the JSON payload - print(controller.placedOrder1.value.toJson()); + print("Sending order payload: ${controller.placedOrder1.value.toJson()}"); + // Place the order and catch any errors await controller.placeRDOrder(); showSnackbar("Order processed and invoice created successfully"); + Navigator.of(context).pop(); + // Close the dialog after a short delay - Future.delayed(Duration(seconds: 1), () { - Get.back(); // Close the dialog - }); + // Close the dialog - setState(() {}); // Refresh the UI +// Refresh the UI// Refresh the UI }, child: Text("Confirm"), ), TextButton( onPressed: () { - Get.back(); // Close the dialog + Navigator.of(context).pop(); // Close the dialog }, child: Text("Cancel"), ), @@ -290,6 +296,7 @@ class _RdOrderDetailScreenState + @override Widget build(BuildContext context) { return Scaffold( @@ -349,7 +356,7 @@ class _RdOrderDetailScreenState child: Column( mainAxisSize: MainAxisSize.min, children: [ - + Card( child: Column( children: [ @@ -514,7 +521,7 @@ class _RdOrderDetailScreenState ), _buildInfoRow("Address", widget.placedOrderList!.shipTo, Get.width * 0.04) - + ], ), ), @@ -537,7 +544,7 @@ class _RdOrderDetailScreenState fontWeight: FontWeight.w500, ), ), - Text(capitalizeFirstLetter(widget.placedOrderList!.paymentMode)), + Text(capitalizeFirstLetter(widget.placedOrderList!.paymentMode)), // Text("${widget.placedOrderList!.paymentMode}",maxLines: 4, // overflow:TextOverflow.ellipsis,) ], @@ -582,48 +589,48 @@ class _RdOrderDetailScreenState ), ), const SizedBox(height: 8), - SizedBox( - height: Get.height * 0.05, - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Text( - "Status: ", - style: TextStyle(fontWeight: FontWeight.bold), - ), - SizedBox(width: 10), // Space between label and dropdown - Expanded( - child: DropdownButtonFormField( - value: selectedStatus, - decoration: InputDecoration( - filled: true, - fillColor: Colors.white, // White background - contentPadding: EdgeInsets.symmetric( - vertical: 10, horizontal: 12), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(10), - borderSide: BorderSide( - color: Colors.grey, - width: 1, + SizedBox( + height: Get.height * 0.05, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Text( + "Status: ", + style: TextStyle(fontWeight: FontWeight.bold), + ), + SizedBox(width: 10), // Space between label and dropdown + Expanded( + child: DropdownButtonFormField( + value: selectedStatus, + decoration: InputDecoration( + filled: true, + fillColor: Colors.white, // White background + contentPadding: EdgeInsets.symmetric( + vertical: 10, horizontal: 12), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: BorderSide( + color: Colors.grey, + width: 1, + ), + ), + ), + items: _statusList.map((String status) { + return DropdownMenuItem( + value: status, + child: Text(capitalizeFirstLetter(status)), + ); + }).toList(), + onChanged: (newValue) { + setState(() { + selectedStatus = newValue!; + }); + }, + ), + ), + ], ), ), - ), - items: _statusList.map((String status) { - return DropdownMenuItem( - value: status, - child: Text(capitalizeFirstLetter(status)), - ); - }).toList(), - onChanged: (newValue) { - setState(() { - selectedStatus = newValue!; - }); - }, - ), - ), - ], - ), - ), if (selectedStatus == "processing" || selectedStatus == "partial processing" || selectedStatus == "cancelled") @@ -636,26 +643,26 @@ class _RdOrderDetailScreenState // Show confirmation dialog _showConfirmationDialog(); }, - // Get.to(() => - // RdOrderDetailScreen( - // placedOrderList: uniqueOrders[index])), // Navigate to detail screen - style: ElevatedButton.styleFrom( - foregroundColor: Colors.white, - backgroundColor: const Color(0xFF004791), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10)), + // Get.to(() => + // RdOrderDetailScreen( + // placedOrderList: uniqueOrders[index])), // Navigate to detail screen + style: ElevatedButton.styleFrom( + foregroundColor: Colors.white, + backgroundColor: const Color(0xFF004791), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10)), + ), + child: Text("Update Status", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.w400)), ), - child: Text("Update Status", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.w400)), ), - ), - ) + ) ], ), ), ), SizedBox(height: Get.height * 0.04), - + ], ), ), @@ -714,3 +721,729 @@ Widget _buildInfoRow(String label, String value, double fontSize) { ); } + + + + + +// import 'package:auto_size_text/auto_size_text.dart'; +// import 'package:cheminova/controller/get_order_placed_controller.dart'; +// import 'package:cheminova/controller/rd_get_order_controller.dart'; +// import 'package:cheminova/models/oder_place_model.dart'; +// import 'package:cheminova/models/order_item_model.dart'; +// import 'package:cheminova/models/place_order_list_model.dart'; +// import 'package:cheminova/models/rd_get_order_model.dart'; +// import 'package:cheminova/models/rd_order_item_model.dart'; +// import 'package:cheminova/models/rd_placed_order_model.dart'; +// import 'package:cheminova/screens/rd%20orders/partial_processing_dialog_screen.dart'; +// +// import 'package:flutter/cupertino.dart'; +// import 'package:flutter/material.dart'; +// import 'package:flutter_svg/svg.dart'; +// import 'package:get/get.dart'; +// import 'package:google_fonts/google_fonts.dart'; +// import 'package:intl/intl.dart'; +// import 'package:shared_preferences/shared_preferences.dart'; +// +// import '../../controller/cart_controller.dart'; +// import '../../controller/rd_processing_order_controller.dart'; +// import '../../models/product_model1.dart'; +// import '../../utils/show_snackbar.dart'; +// +// class RdOrderDetailScreen extends StatefulWidget { +// //final Product? productModel; +// // PlacedOrderList and PlacedOrderModel are optional parameters passed to this screen +// PlacedOrdersResponse? placedOrderList; +// // PlacedOrderModel? placedOrderModel; +// // Constructor for initializing the screen with placed order details +// RdOrderDetailScreen({super.key,this.placedOrderList}); +// +// @override +// State createState() => +// _RdOrderDetailScreenState(); +// } +// +// +// class _RdOrderDetailScreenState +// extends State { +// // Controllers for managing cart and placed orders +// +// final GetProductRDController _getPlacedOrderController = Get.put(GetProductRDController()); +// final RDOrderPlacedController controller = Get.put(RDOrderPlacedController()); +// String? orderId; +// final List statusOptions = [ +// "new", +// "pending", +// "processing", +// "dispatched", +// "cancelled", +// "delivered", +// ]; +// +// +// List _statusList = ["new", "processing", "partial processing", "cancelled"]; // Default status list +// +// // Define different status lists for different categories +// final Map> statusLists = { +// "new": ["new", "processing", "partial processing", "cancelled"], +// "pending": ["pending", "processing", "dispatched", "cancelled"], +// "dispatched": ["dispatched", "delivered", "returned", "cancelled"], +// "delivered": ["delivered", "returned", "cancelled"], +// }; +// String selectedStatus = "new"; +// String _groupValue = "cheque"; +// // Function to format date from the API to a more readable format +// +// +// // This function updates the dropdown list dynamically based on category selection +// void updateStatusList(String category) { +// setState(() { +// _statusList = statusLists[category]!; // Update status list based on the selected category +// selectedStatus = _statusList.first; // Set the default selection to the first item +// }); +// } +// +// String formatDate(String apiDate) { +// +// DateTime parsedDate = DateTime.parse(apiDate); +// +// String formattedDate = DateFormat('dd-MMM-yyyy').format(parsedDate); +// +// return formattedDate; +// } +// // Function to capitalize the first letter of a string +// String capitalizeFirstLetter(String text) { +// if (text.isEmpty) return text; +// return text[0].toUpperCase() + text.substring(1).toLowerCase(); +// } +// +// +// void _onPaymentModeChanged(String? value) { +// setState(() { +// _groupValue = value!; +// }); +// _saveSelectedPaymentMode(); +// } +// +// +// void _saveSelectedPaymentMode() async { +// SharedPreferences prefs = await SharedPreferences.getInstance(); +// await prefs.setString('selectedPaymentMode', _groupValue); +// } +// +// void _loadSelectedPaymentMode() async { +// SharedPreferences prefs = await SharedPreferences.getInstance(); +// setState(() { +// _groupValue = prefs.getString('selectedPaymentMode') ?? 'cheque'; +// }); +// } +// // Function to collect unique order IDs and corresponding order details +// Future adduni()async { +// final Set uniqueOrderIds = {}; +// final List uniqueOrders = []; +// // Loop through placed orders and add unique orders to the list +// for (var order in _getPlacedOrderController.productRDList) { +// if (uniqueOrderIds.add(order.uniqueId)) { +// uniqueOrders.add(order); +// } +// } +// final order = uniqueOrders[0]; +// +// // Combine product names, categories, and quantities into strings +// final productNames = order.orderItem +// .map((item) => (item.name)) +// .join(', '); +// final categotyName = order.orderItem +// .map((item) => (item.categoryName)) +// .join(', '); +// final quantity = order.orderItem +// .map((item) => (item.quantity)) +// .join(', '); +// } +// @override +// void initState() { +// // TODO: implement initState +// super.initState(); +// selectedStatus= widget.placedOrderList?.status ?? 'new'; +// // controller.fetchOrderItems(widget.placedOrderList!.id); +// } +// +// void _showConfirmationDialog() { +// String dialogTitle; +// String dialogContent; +// TextEditingController reasonController = TextEditingController(); +// +// // Set dialog title and content based on selected status +// switch (selectedStatus) { +// case "processing": +// dialogTitle = "Update Order Status"; +// dialogContent = "Are you sure you want to update the status to processing?"; +// break; +// case "partial processing": +// dialogTitle = "Update to Partial Processing"; +// dialogContent = "Are you sure you want to update the status to 'Partial Processing'?"; +// break; +// case "cancelled": +// dialogTitle = "Cancellation Reason"; +// dialogContent = "Please provide a reason for cancelling the order:"; +// break; +// default: +// dialogTitle = "Update Order Status"; +// dialogContent = "Are you sure you want to update the status to '$selectedStatus'?"; +// break; +// } +// +// showDialog( +// context: context, +// builder: (context) { +// return AlertDialog( +// title: Text(dialogTitle), +// content: selectedStatus == "cancelled" +// ? Column( +// mainAxisSize: MainAxisSize.min, +// children: [ +// Text(dialogContent), +// SizedBox(height: 10), +// TextField( +// controller: reasonController, +// decoration: InputDecoration( +// labelText: 'Cancellation Reason', +// border: OutlineInputBorder(), +// ), +// ), +// ], +// ) +// : Text(dialogContent), +// actions: [ +// TextButton( +// onPressed: () async { +// if (selectedStatus == "cancelled") { +// // Ensure the reason is provided for cancellation +// if (reasonController.text.isEmpty) { +// showSnackbar("Please provide a reason for cancelling the order."); +// return; // Exit early if reason is empty +// } +// +// // Proceed with cancellation +// await controller.CancleRDProduct(widget.placedOrderList!.id, reasonController.text); +// +// // Notify user about successful cancellation +// showSnackbar("Order cancelled successfully"); +// +// // Update the status in your UI or backend to reflect the cancelled state +// setState(() { +// // Update the status in the local model/UI +// }); +// +// // Close the dialog after a short delay +// Future.delayed(Duration(seconds: 1), () { +// Get.back(); // Close the dialog +// }); +// +// return; // Exit here to prevent further processing +// } +// +// if (selectedStatus == "partial processing") { +// Get.to(() => PartialProcessingDialogScreen(productModel: widget.placedOrderList)); +// return; +// } +// +// // Create a map to track products by their IDs and aggregate quantities +// Map orderItemMap = {}; +// +// // Populate the map with items and their quantities +// for (var item in _getPlacedOrderController.productRDList) { +// var productId = item.orderItem[0].productId; +// +// if (orderItemMap.containsKey(productId)) { +// // If the product already exists, aggregate the quantity +// var existingItem = orderItemMap[productId]!; // Get the existing item +// existingItem.quantity = (existingItem.quantity ?? 0) + (item.orderItem[0].quantity ?? 0); +// } else { +// // If it's a new product, add it to the map +// orderItemMap[productId] = RDOrderItem( +// productId: productId, +// sku: item.orderItem[0].sku, +// name: item.orderItem[0].name, +// categoryName: item.orderItem[0].categoryName, +// brandName: item.orderItem[0].brandName, +// price: item.orderItem[0].price, +// gst: item.orderItem[0].gst, +// hsnCode: item.orderItem[0].hsnCode, +// description: item.orderItem[0].description, +// image: [], // Handle images appropriately +// quantity: item.orderItem[0].quantity??0, +// remainingQuantity: item.orderItem[0].remainingQuantity??0, +// processquantity: item.orderItem[0].processquantity??0, +// ); +// } +// } +// +// // Convert the map to a list +// List orderItems = orderItemMap.values.toList(); +// +// // Ensure the placed order contains the correct orderId and items +// controller.placedOrder1.value = PlacedOrdersProcessing( +// orderId: widget.placedOrderList!.id, +// invoiceItems: orderItems, +// ); +// +// // Debugging: Print the JSON payload +// print(controller.placedOrder1.value.toJson()); +// +// await controller.placeRDOrder(); +// +// showSnackbar("Order processed and invoice created successfully"); +// +// Future.delayed(Duration(seconds: 1), () { +// Get.back(); // Close the dialog +// }); +// +// setState(() {}); // Refresh the UI +// }, +// child: Text("Confirm"), +// ), +// TextButton( +// onPressed: () { +// Get.back(); // Close the dialog +// }, +// child: Text("Cancel"), +// ), +// ], +// ); +// }, +// ); +// } +// +// +// +// +// @override +// Widget build(BuildContext context) { +// return Scaffold( +// extendBodyBehindAppBar: true, +// appBar: AppBar( +// backgroundColor: Colors.transparent, +// elevation: 0, +// leading: GestureDetector( +// onTap: () {}, +// child: Padding( +// padding: const EdgeInsets.all(16.0), +// child: SvgPicture.asset( +// 'assets/svg/menu.svg', +// ), +// ), +// ), +// actions: [ +// GestureDetector( +// onTap: () => Get.back(), +// child: Padding( +// padding: const EdgeInsets.all(8.0), +// child: SvgPicture.asset( +// 'assets/svg/back_arrow.svg', +// ), +// ), +// ), +// ], +// title: const Text( +// "Order Detail", +// ), +// ), +// body: Stack( +// fit: StackFit.expand, +// children: [ +// Image.asset( +// 'assets/images/image_1.png', +// fit: BoxFit.cover, +// ), +// SafeArea( +// child: SingleChildScrollView( +// child: Column( +// mainAxisSize: MainAxisSize.min, +// mainAxisAlignment: MainAxisAlignment.start, +// children: [ +// SizedBox( +// height: Get.height * 0.02, +// ), +// Card( +// margin: const EdgeInsets.symmetric(horizontal: 18), +// shape: RoundedRectangleBorder( +// borderRadius: BorderRadius.circular(19), +// side: const BorderSide(color: Color(0xFFFDFDFD)), +// ), +// color: const Color(0xFFB4D1E5).withOpacity(0.9), +// child: Padding( +// padding: const EdgeInsets.all(12.0), +// child: Column( +// mainAxisSize: MainAxisSize.min, +// children: [ +// +// Card( +// child: Column( +// children: [ +// SizedBox( +// width: Get.width, +// child: Padding( +// padding: +// const EdgeInsets.fromLTRB(8, 8, 8, 0), +// child: Text( +// "Order Summary", +// style: GoogleFonts.roboto( +// fontSize: Get.width * 0.05, +// fontWeight: FontWeight.bold, +// ), +// ), +// ), +// ), +// _buildRow("Order ID:", widget.placedOrderList!.uniqueId, Get.width * 0.04), +// _buildRow("Order Date:", formatDate("${widget.placedOrderList!.createdAt}"), Get.width * 0.04), +// _buildRow("Total Items:", "${widget.placedOrderList!.orderItem.length}", Get.width * 0.04), +// _buildRow("Sub Total:", "₹ ${widget.placedOrderList!.subtotal}", Get.width * 0.04), +// _buildRow("GST:", "₹ ${widget.placedOrderList!.gstTotal}", Get.width * 0.04), +// _buildRow("Total Amount:", "₹ ${widget.placedOrderList!.grandTotal}", Get.width * 0.04), +// +// +// ], +// ), +// ), +// const SizedBox(height: 8), +// Card( +// child: SizedBox( +// height: Get.height * 0.22, +// child: Padding( +// padding: EdgeInsets.all(Get.width * 0.02), +// child: ListView.builder( +// padding: EdgeInsets.zero, +// itemCount: widget.placedOrderList?.orderItem.length ?? 0, +// itemBuilder: (context, index) { +// final orderItem = widget.placedOrderList!.orderItem[index]; +// return orderItem != null +// ? Card( +// margin: const EdgeInsets.symmetric(vertical: 5.0), +// shape: RoundedRectangleBorder( +// borderRadius: BorderRadius.circular(10), +// ), +// child: Padding( +// padding: const EdgeInsets.all(8.0), +// child: Row( +// children: [ +// Image.asset( +// "assets/images/product.png", // Add the image URL here +// height: 50, +// width: 50, +// fit: BoxFit.cover, +// ), +// const SizedBox(width: 10), +// Expanded( +// child: Column( +// crossAxisAlignment: CrossAxisAlignment.end, +// children: [ +// Text( +// capitalizeFirstLetter(orderItem.name), +// style: GoogleFonts.roboto( +// fontSize: Get.width * 0.04, +// fontWeight: FontWeight.bold, +// ), +// ), +// Text( +// "Quantity: ${orderItem.quantity}", +// style: GoogleFonts.roboto( +// fontSize: Get.width * 0.03, +// ), +// ), +// Text("Price: ${orderItem.price}"), +// Text("Subtotal : ${widget.placedOrderList!.subtotal}"), +// Text("Gst : ${orderItem.gst}%"), +// Text("GST : ${widget.placedOrderList!.gstTotal}"), +// Text("Total Amount : ${widget.placedOrderList!.grandTotal}"), +// ], +// ), +// ), +// ], +// ), +// ), +// ) +// : const SizedBox.shrink(); +// }, +// ), +// ), +// ), +// ), +// const SizedBox(height: 8), +// SizedBox( +// height: Get.height* 0.19, +// child: Card( +// child: Column( +// children: [ +// SizedBox( +// width: Get.width, +// child: Padding( +// padding: +// const EdgeInsets.fromLTRB(8, 8, 8, 0), +// child: Text( +// "Customer Details", +// style: GoogleFonts.roboto( +// fontSize: Get.width * 0.05, +// fontWeight: FontWeight.w500, +// ), +// ), +// ), +// ), +// _buildRow("Name:", "VAIBHAV", Get.width * 0.04), +// _buildRow("Email:", "vaibhav.gurjar20001@gmail.com", Get.width * 0.04), +// _buildRow("Mobile Number:", "7779797976", Get.width * 0.04), +// +// +// ], +// ), +// ), +// ), +// const SizedBox(height: 8), +// Card( +// child: Column( +// children: [ +// SizedBox( +// width: Get.width, +// child: Padding( +// padding: +// const EdgeInsets.fromLTRB(8, 8, 8, 0), +// child: Text( +// "Billing Information", +// style: GoogleFonts.roboto( +// fontSize: Get.width * 0.05, +// fontWeight: FontWeight.w500, +// ), +// ), +// ), +// ), +// _buildInfoRow("Address", widget.placedOrderList!.billTo, Get.width * 0.04) +// +// ], +// ), +// ), +// const SizedBox(height: 8), +// // Card for displaying shipping information +// Card( +// child: Column( +// children: [ +// SizedBox( +// width: Get.width, +// child: Padding( +// padding: +// const EdgeInsets.fromLTRB(8, 8, 8, 0), +// child: Text( +// "Shipping Information", +// style: GoogleFonts.roboto( +// fontSize: Get.width * 0.05, +// fontWeight: FontWeight.w500, +// ), +// ), +// ), +// ), +// _buildInfoRow("Address", widget.placedOrderList!.shipTo, Get.width * 0.04) +// +// +// ], +// ), +// ), +// const SizedBox(height: 8), +// Card( +// child: Column( +// children: [ +// SizedBox( +// width: Get.width, +// height: Get.height*0.05, +// child: Padding( +// padding: +// const EdgeInsets.fromLTRB(8, 8, 8, 0), +// child: Row( +// children: [ +// Text( +// "Payment Mode : ", +// style: GoogleFonts.roboto( +// fontSize: Get.width * 0.04, +// fontWeight: FontWeight.w500, +// ), +// ), +// Text(capitalizeFirstLetter(widget.placedOrderList!.paymentMode)), +// // Text("${widget.placedOrderList!.paymentMode}",maxLines: 4, +// // overflow:TextOverflow.ellipsis,) +// ], +// ), +// ), +// ), +// +// +// ], +// ), +// ), +// const SizedBox(height: 8), +// Card( +// child: Column( +// children: [ +// SizedBox( +// width: Get.width, +// height: Get.height*0.05, +// child: Padding( +// padding: +// const EdgeInsets.fromLTRB(8, 8, 8, 0), +// child: Row( +// children: [ +// Text( +// "Order Status :", +// style: GoogleFonts.roboto( +// fontSize: Get.width * 0.04, +// fontWeight: FontWeight.w500, +// ), +// ), +// SizedBox(width: Get.width*0.01,), +// Text(capitalizeFirstLetter(selectedStatus)), +// // Text("${widget.placedOrderList!.status}",maxLines: 4, +// // overflow:TextOverflow.ellipsis,) +// ], +// ), +// ), +// ), +// +// +// ], +// ), +// ), +// const SizedBox(height: 8), +// SizedBox( +// height: Get.height * 0.05, +// child: Row( +// crossAxisAlignment: CrossAxisAlignment.center, +// children: [ +// const Text( +// "Status: ", +// style: TextStyle(fontWeight: FontWeight.bold), +// ), +// SizedBox(width: 10), // Space between label and dropdown +// Expanded( +// child: DropdownButtonFormField( +// value: selectedStatus, +// decoration: InputDecoration( +// filled: true, +// fillColor: Colors.white, // White background +// contentPadding: EdgeInsets.symmetric( +// vertical: 10, horizontal: 12), +// border: OutlineInputBorder( +// borderRadius: BorderRadius.circular(10), +// borderSide: BorderSide( +// color: Colors.grey, +// width: 1, +// ), +// ), +// ), +// items: _statusList.map((String status) { +// return DropdownMenuItem( +// value: status, +// child: Text(capitalizeFirstLetter(status)), +// ); +// }).toList(), +// onChanged: (newValue) { +// setState(() { +// selectedStatus = newValue!; +// }); +// }, +// ), +// ), +// ], +// ), +// ), +// if (selectedStatus == "processing" || +// selectedStatus == "partial processing" || +// selectedStatus == "cancelled") +// SizedBox( +// width: Get.width * 0.4, +// child: Padding( +// padding: const EdgeInsets.all(8.0), +// child: ElevatedButton( +// onPressed: () { +// // Show confirmation dialog +// _showConfirmationDialog(); +// }, +// // Get.to(() => +// // RdOrderDetailScreen( +// // placedOrderList: uniqueOrders[index])), // Navigate to detail screen +// style: ElevatedButton.styleFrom( +// foregroundColor: Colors.white, +// backgroundColor: const Color(0xFF004791), +// shape: RoundedRectangleBorder( +// borderRadius: BorderRadius.circular(10)), +// ), +// child: Text("Update Status", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.w400)), +// ), +// ), +// ) +// +// ], +// ), +// ), +// ), +// SizedBox(height: Get.height * 0.04), +// +// ], +// ), +// ), +// ), +// ], +// ), +// ); +// } +// } +// Widget _buildRow(String label, String value, double fontSize) { +// return SizedBox( +// width: Get.width, +// child: Padding( +// padding: const EdgeInsets.fromLTRB(8, 8, 8, 0), +// child: Row( +// mainAxisAlignment: MainAxisAlignment.spaceBetween, +// children: [ +// Text( +// label, +// style: GoogleFonts.roboto( +// fontSize: fontSize, +// fontWeight: FontWeight.bold, +// ), +// ), +// Text(value), +// ], +// ), +// ), +// ); +// } +// +// Widget _buildInfoRow(String label, String value, double fontSize) { +// return SizedBox( +// width: Get.width, +// child: Padding( +// padding: const EdgeInsets.fromLTRB(8, 8, 8, 0), +// child: Row( +// children: [ +// Text( +// "$label ", +// style: GoogleFonts.roboto( +// fontSize: fontSize, +// fontWeight: FontWeight.bold, +// ), +// ), +// Expanded( +// child: Text( +// value, +// maxLines: 4, +// overflow: TextOverflow.ellipsis, +// ), +// ), +// ], +// ), +// ), +// ); +// +// } +// +// +// +// +// diff --git a/lib/screens/rd orders/rd_order_screen.dart b/lib/screens/rd orders/rd_order_screen.dart index 31d393a..e8a81e1 100644 --- a/lib/screens/rd orders/rd_order_screen.dart +++ b/lib/screens/rd orders/rd_order_screen.dart @@ -15,12 +15,15 @@ import 'package:get/get.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:intl/intl.dart'; +import '../../controller/rd_single_order_controller.dart'; +import '../../models/single_get_order_model.dart'; import '../order_management/order_management_detail_screen.dart'; class RdOrderScreen extends StatefulWidget { final PlacedOrdersResponse? getrdProduct; + SingleGetOrderModel? getSingleProduct; - RdOrderScreen({super.key, this.getrdProduct}); + RdOrderScreen({super.key, this.getrdProduct,this.getSingleProduct}); @override State createState() => _RdOrderScreenState(); @@ -36,12 +39,15 @@ class _RdOrderScreenState extends State { "delivered",]; int _selectedIndex = 0; final GetProductRDController _getRdProductController = Get.put(GetProductRDController()); + final RdSingleOrderController _getrdSingleOrderController = Get.put(RdSingleOrderController()); final GlobalKey _refreshIndicatorKey = GlobalKey(); @override void initState() { super.initState(); getOrder1(); + // getOrder3(_getrdSingleOrderController.productRDOrderSingleList[0].id); + } Future _onRefresh() async { @@ -54,21 +60,41 @@ class _RdOrderScreenState extends State { if (_getRdProductController.productRDList.isEmpty) { print("No orders found."); } else { - print("Orders fetched successfully"); + print(" New Orders fetched successfully"); + } + + } + + Future getOrder3(String orderId) async { + if (orderId != null && orderId.isNotEmpty) { + await _getrdSingleOrderController.fetchRDSingleOrderProduct(orderId); + if (_getrdSingleOrderController.productRDOrderSingleList.isEmpty) { + print("No orders found."); + } else { + print("Single Order fetched successfully."); + } + } else { + print("Order ID is invalid."); } } + String capitalizeFirstLetter(String text) { if (text.isEmpty) return text; return text[0].toUpperCase() + text.substring(1).toLowerCase(); } String formatDate(String apiDate) { - DateTime parsedDate = DateTime.parse(apiDate); - String formattedDate = DateFormat('dd-MMM-yyyy').format(parsedDate); - return formattedDate; + // Parse the API date string into a DateTime object + DateTime parsedDate = DateTime.parse(apiDate).toLocal(); // Convert to local time + + // Format the date and time according to your specified format + String formattedDate = DateFormat('EEE MMM dd yyyy').format(parsedDate); + + return formattedDate; // Return the formatted date string } + @override Widget build(BuildContext context) { return Scaffold( @@ -156,7 +182,7 @@ class _RdOrderScreenState extends State { Get.to(RdOrderPendingScreen()); // Navigate to "pending" orders screen break; case "processing": - Get.to(RdOrderProcessingScreen()); // Navigate to "processing" orders screen + Get.to(RdOrderProcessingScreen()); // Navigate to "processing" orders screen break; // Add more cases for other statuses case "dispatched": @@ -277,7 +303,16 @@ class _RdOrderScreenState extends State { ), ), - + Padding( + padding: const EdgeInsets.fromLTRB(16, 8, 8, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("Order Value: ", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.bold)), + Text("${order.grandTotal}") + ], + ), + ), Padding( padding: const EdgeInsets.fromLTRB(16, 8, 8, 0), child: Row( @@ -303,10 +338,18 @@ class _RdOrderScreenState extends State { child: Padding( padding: const EdgeInsets.all(8.0), child: ElevatedButton( - onPressed: ()=> - Get.to(() => - RdOrderDetailScreen( - placedOrderList: uniqueOrders[index])), // Navigate to detail screen + onPressed: (){ + Get.to(() => RdOrderDetailScreen( + placedOrderList: _getRdProductController.productRDList[index])); + // getOrder3(_getRdProductController.productRDList[index].id).then((_) { + // // Navigate to the details screen only if the single order data is fetched + // + // }); + }, + // => + // Get.to(() => + // RdOrderDetailScreen( + // placedOrderList: _getRdProductController.productRDList[index])), // Navigate to detail screen style: ElevatedButton.styleFrom( foregroundColor: Colors.white, backgroundColor: const Color(0xFF004791), diff --git a/lib/screens/rd orders/rd_pending_deatils.dart b/lib/screens/rd orders/rd_pending_deatils.dart new file mode 100644 index 0000000..77186cf --- /dev/null +++ b/lib/screens/rd orders/rd_pending_deatils.dart @@ -0,0 +1,1035 @@ +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:cheminova/controller/get_order_placed_controller.dart'; +import 'package:cheminova/controller/get_rd_pending_controller.dart'; +import 'package:cheminova/controller/rd_get_order_controller.dart'; +import 'package:cheminova/models/get_rd_pennding_model.dart'; +import 'package:cheminova/models/oder_place_model.dart'; +import 'package:cheminova/models/order_item_model.dart'; +import 'package:cheminova/models/place_order_list_model.dart'; +import 'package:cheminova/models/rd_get_order_model.dart'; +import 'package:cheminova/screens/rd%20orders/partial_pending_dialog.dart'; +import 'package:cheminova/screens/rd%20orders/partial_processing_dialog_screen.dart'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:get/get.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:intl/intl.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +import '../../controller/cart_controller.dart'; +import '../../controller/rd_processing_order_controller.dart'; +import '../../models/product_model1.dart'; +import '../../models/rd_order_item_model.dart'; +import '../../models/rd_placed_order_model.dart'; +import '../../utils/show_snackbar.dart'; + +class RdOrderPendingScreenDetailScreen extends StatefulWidget { + //final Product? productModel; + // PlacedOrderList and PlacedOrderModel are optional parameters passed to this screen + GetRdPendingModel? placedOrderList; + +// PlacedOrderModel? placedOrderModel; + // Constructor for initializing the screen with placed order details + RdOrderPendingScreenDetailScreen({super.key,this.placedOrderList}); + + @override + State createState() => + _RdOrderPendingScreenDetailScreenState(); +} + + +class _RdOrderPendingScreenDetailScreenState + extends State { + // Controllers for managing cart and placed orders + final CartController _cartController = Get.put(CartController()); + final GetRdPendingController _getPlacedOrderController = Get.put(GetRdPendingController()); + final GetProductRDController _getPlacedOrderController1 = Get.put(GetProductRDController()); + final RDOrderPlacedController controller = Get.put(RDOrderPlacedController()); + + final List statusOptions = [ + "new", + "pending", + "processing", + "dispatched", + "cancelled", + "delivered", + ]; + String selectedStatus = "pending"; + String _groupValue = "cheque"; + // Function to format date from the API to a more readable format + + List _statusList = ["pending", "processing", "partial processing", "cancelled"]; + String formatDate(String apiDate) { + // Parse the API date string into a DateTime object + DateTime parsedDate = DateTime.parse(apiDate).toLocal(); // Convert to local time + + // Format the date and time according to your specified format + String formattedDate = DateFormat('EEE MMM dd yyyy').format(parsedDate); + + return formattedDate; // Return the formatted date string + } + + // Function to capitalize the first letter of a string + String capitalizeFirstLetter(String text) { + if (text.isEmpty) return text; + return text[0].toUpperCase() + text.substring(1).toLowerCase(); + } + + + void _onPaymentModeChanged(String? value) { + setState(() { + _groupValue = value!; + }); + _saveSelectedPaymentMode(); + } + + + void _saveSelectedPaymentMode() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + await prefs.setString('selectedPaymentMode', _groupValue); + } + + void _loadSelectedPaymentMode() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + setState(() { + _groupValue = prefs.getString('selectedPaymentMode') ?? 'cheque'; + }); + } + // Function to collect unique order IDs and corresponding order details + Future adduni()async { + final Set uniqueOrderIds = {}; + final List uniqueOrders = []; + // Loop through placed orders and add unique orders to the list + for (var order in _getPlacedOrderController.productRDList) { + if (uniqueOrderIds.add(order.uniqueId)) { + uniqueOrders.add(order); + } + } + final order = uniqueOrders[0]; + + // Combine product names, categories, and quantities into strings + final productNames = order.orderItem + .map((item) => (item.name)) + .join(', '); + final categotyName = order.orderItem + .map((item) => (item.categoryName)) + .join(', '); + final quantity = order.orderItem + .map((item) => (item.quantity)) + .join(', '); + } + @override + void initState() { + // TODO: implement initState + super.initState(); + selectedStatus= widget.placedOrderList?.status ?? 'new'; + } + + + + void _showConfirmationDialog() { + String dialogTitle; + String dialogContent; + TextEditingController reasonController = TextEditingController(); + + // Set dialog title and content based on selected status + switch (selectedStatus) { + case "processing": + dialogTitle = "Update Order Status"; + dialogContent = "Are you sure you want to update the status to processing?"; + break; + case "partial processing": + dialogTitle = "Update to Partial Processing"; + dialogContent = "Are you sure you want to update the status to 'Partial Processing'?"; + break; + case "cancelled": + dialogTitle = "Cancellation Reason"; + dialogContent = "Please provide a reason for cancelling the order:"; + break; + default: + dialogTitle = "Update Order Status"; + dialogContent = "Are you sure you want to update the status to '$selectedStatus'?"; + break; + } + + showDialog( + context: context, + builder: (context) { + return AlertDialog( + title: Text(dialogTitle), + content: selectedStatus == "cancelled" + ? Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text(dialogContent), + SizedBox(height: 10), + TextField( + controller: reasonController, + decoration: InputDecoration( + labelText: 'Cancellation Reason', + border: OutlineInputBorder(), + ), + ), + ], + ) + : Text(dialogContent), + actions: [ + TextButton( + onPressed: () async { + { + if (selectedStatus == "cancelled") { + // Ensure the reason is provided for cancellation + if (reasonController.text.isEmpty) { + showSnackbar("Please provide a reason for cancelling the order."); + return; // Exit early if reason is empty + } + + // Proceed with cancellation + await controller.CancleRDProduct(widget.placedOrderList!.id, reasonController.text); + + // Notify user about successful cancellation + showSnackbar("Order cancelled successfully"); + + // Update the status in your UI or backend to reflect the cancelled state + setState(() {}); + + // Close the dialog after a short delay + Future.delayed(Duration(seconds: 1), () { + Navigator.of(context).pop(); // Close the dialog + }); + + return; // Exit here to prevent further processing + } + + if (selectedStatus == "partial processing") { + Get.to(() => PartialPendingDialogScreen(productpendingModel: widget.placedOrderList)); + return; + } + + // Create a map to track products by their IDs and aggregate quantities + Map orderItemMap = {}; + + // Populate the map with items and their quantities + for (var item in _getPlacedOrderController1.productRDList) { + var productId = item.orderItem[0].productId; + + if (orderItemMap.containsKey(productId)) { + // If the product already exists, aggregate the quantity + var existingItem = orderItemMap[productId]!; + existingItem.quantity = (existingItem.quantity ?? 0) + (item.orderItem[0].quantity ?? 0); + existingItem.remainingQuantity = (existingItem.remainingQuantity ?? 0) + (item.orderItem[0].remainingQuantity ?? 0); + existingItem.processquantity = (existingItem.processquantity ?? 0) + (item.orderItem[0].processquantity ?? 0); + } else { + // If it's a new product, add it to the map + orderItemMap[productId] = RDOrderItem( + productId: productId, + sku: item.orderItem[0].sku, + name: item.orderItem[0].name, + categoryName: item.orderItem[0].categoryName, + brandName: item.orderItem[0].brandName, + price: item.orderItem[0].price, + gst: item.orderItem[0].gst.toInt(), + hsnCode: item.orderItem[0].hsnCode, + description: item.orderItem[0].description, + image: [], // Handle images appropriately + quantity: item.orderItem[0].quantity ?? 0, + remainingQuantity: item.orderItem[0].remainingQuantity ?? 0, + processquantity: item.orderItem[0].processquantity ?? 0, + ); + } + } + + // Convert the map to a list + List orderItems = orderItemMap.values.toList(); + + // Ensure the placed order contains the correct orderId and items + controller.placedOrder1.value = PlacedOrdersProcessing( + orderId: widget.placedOrderList!.id, + invoiceItems: orderItems, + ); + + // Debugging: Print the JSON payload + print("Sending order payload: ${controller.placedOrder1.value.toJson()}"); + + // Place the order and catch any errors + await controller.placeRDOrder(); + + showSnackbar("Order processed and invoice created successfully"); + + + Navigator.of(context).pop(); + // Close the dialog after a short delay + + // Close the dialog + + + // Refresh the UI + + } + // catch (e) { + // print("Error placing order: $e"); + // showSnackbar("Failed to place the order. Please try again."); + // } + }, + child: Text("Confirm"), + ), + TextButton( + onPressed: () { + Navigator.of(context).pop(); // Close the dialog + }, + child: Text("Cancel"), + ), + ], + ); + }, + ); + } + + + @override + Widget build(BuildContext context) { + int remainingQuantity = (widget.placedOrderList!.orderItem[0].quantity)! -(widget.placedOrderList!.orderItem[0].remainingQuantity!.toInt()); + return Scaffold( + extendBodyBehindAppBar: true, + appBar: AppBar( + backgroundColor: Colors.transparent, + elevation: 0, + leading: GestureDetector( + onTap: () {}, + child: Padding( + padding: const EdgeInsets.all(16.0), + child: SvgPicture.asset( + 'assets/svg/menu.svg', + ), + ), + ), + actions: [ + GestureDetector( + onTap: () => Get.back(), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: SvgPicture.asset( + 'assets/svg/back_arrow.svg', + ), + ), + ), + ], + title: const Text( + "RDPending Order Details", + ), + ), + body: Stack( + fit: StackFit.expand, + children: [ + Image.asset( + 'assets/images/image_1.png', + fit: BoxFit.cover, + ), + SafeArea( + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + SizedBox( + height: Get.height * 0.02, + ), + Card( + margin: const EdgeInsets.symmetric(horizontal: 18), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(19), + side: const BorderSide(color: Color(0xFFFDFDFD)), + ), + color: const Color(0xFFB4D1E5).withOpacity(0.9), + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + + Card( + child: Column( + children: [ + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Text( + "Invoices", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.05, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Invoice ID:", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text(widget.placedOrderList!.uniqueId), + // Text(widget.placedOrderList!.uniqueId), + ], + ), + ), + ), + SizedBox( + width: Get.width, + child: Padding( + padding: const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + + Text( + "Items: ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + SizedBox(height: 10), // Add spacing between the title and the list of items + Column( + children: widget.placedOrderList!.orderItem.map((item) { + + return Padding( + padding: const EdgeInsets.symmetric(vertical: 4.0), // Add some spacing between items + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Text( + "${item.name.toString()} (${item.sku.toString()})", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.03, + ), + overflow: TextOverflow.ellipsis, // Handle long text + ), + ), + Text("x ${remainingQuantity.toString()}"), + ], + ), + ); + }).toList(), + ), + ], + ), + ), + ), + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Sub Total : ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text("₹ ${widget.placedOrderList!.subtotal}"), + ], + ), + ), + ), + + // SizedBox( + // width: Get.width, + // child: Padding( + // padding: + // const EdgeInsets.fromLTRB(8, 8, 8, 0), + // child: Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // children: [ + // Text( + // "Gst %: ", + // style: GoogleFonts.roboto( + // fontSize: Get.width * 0.04, + // fontWeight: FontWeight.bold, + // ), + // ), + // Text(" ${widget.placedOrderList!.orderItem[0].gst}%"), + // ], + // ), + // ), + // ), + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "GST : ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text("₹ ${widget.placedOrderList!.gstTotal}"), + ], + ), + ), + ), + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Invoice Amount: ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text("₹ ${widget.placedOrderList!.grandTotal}"), + ], + ), + ), + ), + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Courier Status : ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + ElevatedButton( + onPressed: (){}, + // Get.to(() => + // RdOrderDetailScreen( + // placedOrderList: uniqueOrders[index])), // Navigate to detail screen + style: ElevatedButton.styleFrom( + foregroundColor: Colors.white, + backgroundColor: Colors.orange, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10)), + ), + child: Text(widget.placedOrderList!.status, style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.w400)), + ), + //Text("₹ ${widget.placedOrderList!.gstTotal}"), + ], + ), + ), + ), + ], + ), + ), + const SizedBox(height: 8), + + const SizedBox(height: 8), + + Card( + child: SizedBox( + height: Get.height * 0.35, // Adjust the height as per your requirement + child: Padding( + padding: EdgeInsets.all(Get.width * 0.02), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Add title here + Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), // Adjust padding if needed + child: Text( + "Order Summary", // Title text + style: GoogleFonts.roboto( + fontSize: Get.width * 0.05, // Adjust font size as needed + fontWeight: FontWeight.bold, + ), + ), + ), + Expanded( + child: ListView.builder( + padding: EdgeInsets.zero, + itemCount: widget.placedOrderList?.orderItem.length ?? 0, + itemBuilder: (context, index) { + final orderItem = widget.placedOrderList!.orderItem[index]; + return orderItem != null + ? Card( + margin: const EdgeInsets.symmetric(vertical: 5.0), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + children: [ + Image.asset( + "assets/images/product.png", + height: 50, + width: 50, + fit: BoxFit.cover, + ), + const SizedBox(width: 10), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text( + capitalizeFirstLetter(orderItem.name), + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text( + "Quantity: ${orderItem.quantity}", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.03, + ), + ), + Text("Price: ${orderItem.price}"), + Text("Subtotal: ${widget.placedOrderList!.subtotal}"), + Text("Gst: ${orderItem.gst}%"), + Text("GST Total: ${widget.placedOrderList!.gstTotal}"), + Text("Total Amount: ${widget.placedOrderList!.grandTotal}"), + ], + ), + ), + ], + ), + ), + ) + : const SizedBox.shrink(); + }, + ), + ), + ], + ), + ), + ), + ), + + const SizedBox(height: 8), + Card( + child: SizedBox( + height: Get.height * 0.35, // Adjust the height as per your requirement + child: Padding( + padding: EdgeInsets.all(Get.width * 0.02), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Add title here + Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), // Adjust padding if needed + child: Text( + "Order Itmes to processed", // Title text + style: GoogleFonts.roboto( + fontSize: Get.width * 0.05, // Adjust font size as needed + fontWeight: FontWeight.bold, + ), + ), + ), + Expanded( + child: ListView.builder( + padding: EdgeInsets.zero, + itemCount: widget.placedOrderList?.orderItem.length ?? 0, + itemBuilder: (context, index) { + final orderItem = widget.placedOrderList!.orderItem[index]; + return orderItem != null + ? Card( + margin: const EdgeInsets.symmetric(vertical: 5.0), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + children: [ + Image.asset( + "assets/images/product.png", + height: 50, + width: 50, + fit: BoxFit.cover, + ), + const SizedBox(width: 10), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text( + capitalizeFirstLetter(orderItem.name), + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text( + "Quantity: ${orderItem.remainingQuantity}", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.03, + ), + ), + Text("Price: ${orderItem.price}"), + Text("Subtotal: ${widget.placedOrderList!.subtotal}"), + Text("Gst: ${orderItem.gst}%"), + Text("GST Total: ${widget.placedOrderList!.gstTotal}"), + Text("Total Amount: ${widget.placedOrderList!.grandTotal}"), + ], + ), + ), + ], + ), + ), + ) + : const SizedBox.shrink(); + }, + ), + ), + ], + ), + ), + ), + ), + const SizedBox(height: 8), + SizedBox( + height: Get.height* 0.19, + child: Card( + child: Column( + children: [ + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Text( + "Customer Details", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.05, + fontWeight: FontWeight.w500, + ), + ), + ), + ), + SizedBox( + width: Get.width, + //height: Get.height*0.09, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + children: [ + Text( + "Name: ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text("${"VAIBHAV"}",maxLines: 4, + overflow:TextOverflow.ellipsis,) + , ], + ) + ), + ), + SizedBox( + width: Get.width, + // height: Get.height*0.09, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + children: [ + Text( + "Email: ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text("${"vaibhav.gurjar20001@gmail.com"}",maxLines: 4, + overflow:TextOverflow.ellipsis,) + , ], + ) + ), + ), + SizedBox( + width: Get.width, + // height: Get.height*0.09, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + children: [ + Text( + "Mobile Number: ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text("${"7779797976"}",maxLines: 4, + overflow:TextOverflow.ellipsis,) + , ], + ) + ), + ) + + ], + ), + ), + ), + const SizedBox(height: 8), + Card( + child: Column( + children: [ + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Text( + "Billing Information", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.05, + fontWeight: FontWeight.w500, + ), + ), + ), + ), + SizedBox( + width: Get.width, + height: Get.height*0.06, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Wrap( + crossAxisAlignment: WrapCrossAlignment.start, + children: [ + Text( + "Address: ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text("${widget.placedOrderList!.billTo}",maxLines: 4, + overflow:TextOverflow.ellipsis,) + ], + ), + ), + ), + + ], + ), + ), + const SizedBox(height: 8), + // Card for displaying shipping information + Card( + child: Column( + children: [ + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Text( + "Shipping Information", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.05, + fontWeight: FontWeight.w500, + ), + ), + ), + ), + SizedBox( + width: Get.width, + height: Get.height*0.06, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Wrap( + crossAxisAlignment: WrapCrossAlignment.start, + children: [ + Text( + "Address: ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text("${widget.placedOrderList!.shipTo}",maxLines: 4, + overflow:TextOverflow.ellipsis,) + ], + ), + ), + ), + + ], + ), + ), + const SizedBox(height: 8), + Card( + child: Column( + children: [ + SizedBox( + width: Get.width, + height: Get.height*0.05, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + children: [ + Text( + "Payment Mode : ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.w500, + ), + ), + Text(capitalizeFirstLetter(widget.placedOrderList!.paymentMode)), + // Text("${widget.placedOrderList!.paymentMode}",maxLines: 4, + // overflow:TextOverflow.ellipsis,) + ], + ), + ), + ), + + + ], + ), + ), + const SizedBox(height: 8), + Card( + child: Column( + children: [ + SizedBox( + width: Get.width, + height: Get.height*0.05, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + children: [ + Text( + "Order Status :", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.w500, + ), + ), + SizedBox(width: Get.width*0.01,), + //Text(capitalizeFirstLetter(widget.placedOrderList!.status)), + Text("${widget.placedOrderList!.status}",maxLines: 4, + overflow:TextOverflow.ellipsis,) + ], + ), + ), + ), + + + ], + ), + ), + const SizedBox(height: 8), + SizedBox( + height: Get.height * 0.05, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Text( + "Status: ", + style: TextStyle(fontWeight: FontWeight.bold), + ), + SizedBox(width: 10), // Space between label and dropdown + Expanded( + child: DropdownButtonFormField( + value: selectedStatus, + decoration: InputDecoration( + filled: true, + fillColor: Colors.white, // White background + contentPadding: EdgeInsets.symmetric( + vertical: 10, horizontal: 12), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: BorderSide( + color: Colors.grey, + width: 1, + ), + ), + ), + items: _statusList.map((String status) { + return DropdownMenuItem( + value: status, + child: Text(capitalizeFirstLetter(status)), + ); + }).toList(), + onChanged: (newValue) { + setState(() { + selectedStatus = newValue!; + }); + }, + ), + ), + ], + ), + ), + SizedBox( + width: Get.width * 0.4, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: ElevatedButton( + onPressed: (){ + _showConfirmationDialog(); + }, + // Get.to(() => + // RdOrderDetailScreen( + // placedOrderList: uniqueOrders[index])), // Navigate to detail screen + style: ElevatedButton.styleFrom( + foregroundColor: Colors.white, + backgroundColor: const Color(0xFF004791), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10)), + ), + child: Text("Update Status", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.w400)), + ), + ), + ) + + ], + ), + ), + ), + SizedBox(height: Get.height * 0.04), + + ], + ), + ), + ), + ], + ), + ); + } +} diff --git a/lib/screens/rd orders/rd_pending_screen.dart b/lib/screens/rd orders/rd_pending_screen.dart new file mode 100644 index 0000000..a026fa4 --- /dev/null +++ b/lib/screens/rd orders/rd_pending_screen.dart @@ -0,0 +1,304 @@ + +import 'package:cheminova/controller/get_rd_pending_controller.dart'; +import 'package:cheminova/controller/rd_get_order_controller.dart'; +import 'package:cheminova/models/get_rd_pennding_model.dart'; +import 'package:cheminova/models/rd_get_order_model.dart'; +import 'package:cheminova/screens/rd%20orders/rd_order_details_screen.dart'; +import 'package:cheminova/screens/rd%20orders/rd_pending_deatils.dart'; +import 'package:cheminova/widgets/input_field.dart'; +import 'package:cheminova/widgets/my_drawer.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:get/get.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:intl/intl.dart'; + +import '../order_management/order_management_detail_screen.dart'; + +class RdOrderPendingScreen extends StatefulWidget { + final GetRdPendingModel? getrdProduct; + + RdOrderPendingScreen({super.key, this.getrdProduct}); + + @override + State createState() => _RdOrderPendingScreenState(); +} + +class _RdOrderPendingScreenState extends State { + final _searchController = TextEditingController(); + final List _filterList = [ "new", + "pending", + "processing", + "dispatched", + "cancelled", + "delivered",]; + int _selectedIndex = 0; + final GetRdPendingController _getRdProductController = Get.put(GetRdPendingController()); + final GlobalKey _refreshIndicatorKey = GlobalKey(); + + @override + void initState() { + super.initState(); + getOrder1(); + } + + Future _onRefresh() async { + await getOrder1(); + await Future.delayed(Duration(seconds: 1)); + + } + + Future getOrder1() async { + await _getRdProductController.getRDPendingProduct(); + if (_getRdProductController.productRDList.isEmpty) { + print("No orders found."); + } else { + print("Orders fetched successfully"); + } + } + + String capitalizeFirstLetter(String text) { + if (text.isEmpty) return text; + return text[0].toUpperCase() + text.substring(1).toLowerCase(); + } + + String formatDate(String apiDate) { + // Parse the API date string into a DateTime object + DateTime parsedDate = DateTime.parse(apiDate).toLocal(); // Convert to local time + + // Format the date and time according to your specified format + String formattedDate = DateFormat('EEE MMM dd yyyy').format(parsedDate); + + return formattedDate; // Return the formatted date string + } + @override + Widget build(BuildContext context) { + return Scaffold( + extendBodyBehindAppBar: true, + appBar: AppBar( + centerTitle: true, + backgroundColor: Colors.transparent, + elevation: 0, + leading: Builder( + builder: (context) { + return GestureDetector( + onTap: () => Scaffold.of(context).openDrawer(), + child: Padding( + padding: const EdgeInsets.all(16.0), + child: SvgPicture.asset('assets/svg/menu.svg'), + ), + ); + }, + ), + actions: [ + GestureDetector( + onTap: () => Get.back(), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: SvgPicture.asset('assets/svg/back_arrow.svg'), + ), + ), + ], + title: const Text("RD Pending Order"), + ), + drawer: MyDrawer(), + body: Stack( + fit: StackFit.expand, + children: [ + Image.asset('assets/images/image_1.png', fit: BoxFit.cover), + SafeArea( + child: SingleChildScrollView( + child: Padding( + padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), + child: RefreshIndicator( + key: _refreshIndicatorKey, + onRefresh: _onRefresh, + color: Colors.black, + backgroundColor: Colors.white, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + InputField( + hintText: "Search Order", + labelText: "Search Order", + controller: _searchController, + ), + SizedBox(height: Get.height * 0.035), + SizedBox(height: Get.height * 0.035), + Card( + margin: const EdgeInsets.symmetric(horizontal: 18), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(19), + side: const BorderSide(color: Color(0xFFFDFDFD)), + ), + color: const Color(0xFFB4D1E5).withOpacity(0.9), + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + + SizedBox( + height: Get.height * 0.6, + child: Obx(() { + if (_getRdProductController.productRDList.isEmpty) { + return Center( + child: Text( + 'No Orders Found', + style: GoogleFonts.roboto(fontSize: 14), + ), + ); + } + + final Set uniqueOrderIds = {}; + final List uniqueOrders = []; + + for (var order in _getRdProductController.productRDList) { + if (uniqueOrderIds.add(order.id)) { + uniqueOrders.add(order); + } + } + + if (uniqueOrders.isEmpty) { + return Center( + child: Text( + 'No Orders Found', + style: GoogleFonts.roboto(fontSize: 14), + ), + ); + } + + return ListView.builder( + padding: EdgeInsets.zero, + shrinkWrap: true, + itemCount: uniqueOrders.length, + itemBuilder: (context, index) { + final order = uniqueOrders[index]; + + // Combine product names into a single string + final productNames = order.orderItem + .map((item) => capitalizeFirstLetter(item.name)) + .join(', '); + + return Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Card( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.fromLTRB(16, 8, 8, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("Order ID: ", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.bold)), + Text("${order.uniqueId}") + ], + ), + ), + Padding( + padding: const EdgeInsets.fromLTRB(16, 8, 8, 0), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, // Aligns the Column to the top of the Text + children: [ + Text( + "Product Names: ", + style: GoogleFonts.roboto( + fontSize: 14, + fontWeight: FontWeight.bold, + ), + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, // Aligns text to the right within the Column + children: [ + const SizedBox(height: 4), // Adds a small space between the label and the product names + for (int i = 0; i < productNames.split(",").length; i++) + Text( + '${i + 1}. ${productNames.split(",")[i].trim()}', // Adds index and trims whitespace + textAlign: TextAlign.left, // Aligns text to the right + style: GoogleFonts.roboto( + fontSize: 14, + ), + ), + ], + ), + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.fromLTRB(16, 8, 8, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("Order Value: ", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.bold)), + Text("${order.grandTotal}") + ], + ), + ), + + Padding( + padding: const EdgeInsets.fromLTRB(16, 8, 8, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("Order Date: ", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.bold)), + Text(formatDate("${order.createdAt}")) + ], + ), + ), + Padding( + padding: const EdgeInsets.fromLTRB(16, 8, 8, 8), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("Status: ", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.bold)), + Text(capitalizeFirstLetter("${order.status}")) + + ], + ), + ), + SizedBox( + width: Get.width * 0.4, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: ElevatedButton( + onPressed: ()=> + Get.to(() => + RdOrderPendingScreenDetailScreen( + placedOrderList: uniqueOrders[index])), // Navigate to detail screen + style: ElevatedButton.styleFrom( + foregroundColor: Colors.white, + backgroundColor: const Color(0xFF004791), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10)), + ), + child: Text("View Details", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.w400)), + ), + ), + ) + ], + ), + ), + ); + }, + ); + }), + ) + ], + ), + ), + ), + ], + ), + ), + ), + ), + ), + ], + ), + ); + } +} + diff --git a/lib/screens/rd orders/rd_processing_details.dart b/lib/screens/rd orders/rd_processing_details.dart new file mode 100644 index 0000000..7dcab9b --- /dev/null +++ b/lib/screens/rd orders/rd_processing_details.dart @@ -0,0 +1,703 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:get/get.dart'; +import 'package:get/get_core/src/get_main.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:intl/intl.dart'; + +import '../../controller/get_dispatch_controller.dart'; +import '../../controller/get_single_invoice_controller.dart'; +import '../../controller/rd_get_order_controller.dart'; +import '../../controller/rd_processing_invoice_controller.dart'; +import '../../controller/rd_processing_order_controller.dart'; +import '../../models/get_invoice_model.dart'; +import '../../models/rd_processing_invoice_model.dart'; +import '../../utils/show_snackbar.dart'; +class RdOrderProcessingDetailScreen extends StatefulWidget { + InvoiceResponseModel? placedOrderList; + GetInvoiceModel? placeInvoiceList; + RdOrderProcessingDetailScreen({super.key ,this.placedOrderList,this.placeInvoiceList}); + + @override + State createState() => _RdOrderProcessingDetailScreenState(); +} + +class _RdOrderProcessingDetailScreenState extends State { + + + + final GetRDProcessingInvoiceController _getRdProductController = Get.put(GetRDProcessingInvoiceController()); + final GetSingleInvoiceController _getSingleInvoiceController = Get.put(GetSingleInvoiceController()); + final RDOrderPlacedController controller = Get.put(RDOrderPlacedController()); + final GetDispatchController _getDispatchController = Get.put(GetDispatchController()); + final List statusOptions = [ + "new", + "pending", + "processing", + "dispatched", + "cancelled", + "delivered", + ]; + String selectedStatus = "processing"; + String _groupValue = "cheque"; + // Function to format date from the API to a more readable format + + List _statusList = ["processing","dispatch"]; + // String formatDate(String apiDate) { + // // Parse the API date string into a DateTime object + // DateTime parsedDate = DateTime.parse(apiDate).toLocal(); // Convert to local time + // + // // Format the date and time according to your specified format + // String formattedDate = DateFormat('EEE MMM dd yyyy, hh:mm a').format(parsedDate); + // + // return formattedDate; // Return the formatted date string + // } + + // Function to capitalize the first letter of a string + String capitalizeFirstLetter(String text) { + if (text.isEmpty) return text; + return text[0].toUpperCase() + text.substring(1).toLowerCase(); + } + + + getOrder1(){ + _getSingleInvoiceController.fetchInvoice(widget.placedOrderList!.id); + print("dfdfdfg"''); + } + void _showDispatchDetailsDialog() { + // Only show the dialog if the selected status is "dispatch" + if (selectedStatus != "dispatch") { + // You can show a Snackbar or a simple AlertDialog if needed + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('Dispatch option is only available when the status is "dispatch".')), + ); + return; // Exit the function if the condition is not met + } + + final TextEditingController _courierNameController = TextEditingController(); + final TextEditingController _courierTrackingIdController = TextEditingController(); + + showDialog( + context: context, + builder: (context) { + return AlertDialog( + title: Text('Dispatch Details'), + content: Column( + mainAxisSize: MainAxisSize.min, // Shrink to fit the content + children: [ + TextField( + controller: _courierNameController, + decoration: InputDecoration( + labelText: 'Courier Name', + ), + ), + TextField( + controller: _courierTrackingIdController, + decoration: InputDecoration( + labelText: 'Courier Tracking ID', + ), + ), + ], + ), + actions: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(); // Close the dialog + }, + child: Text('Cancel'), + ), + TextButton( + onPressed: () { + String courierName = _courierNameController.text; + String courierTrackingId = _courierTrackingIdController.text; + + // Call the API to submit data + _getDispatchController.RDProcessingToDispatchProduct(widget.placedOrderList!.id, courierName, courierTrackingId); + showSnackbar("Order Status updated Order Dispatched"); + Navigator.of(context).pop(); // Close the dialog after submission + }, + child: Text('Submit'), + ), + ], + ); + }, + ); + } + + @override + void initState() { + // TODO: implement initState + super.initState(); + getOrder1(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + extendBodyBehindAppBar: true, + appBar: AppBar( + backgroundColor: Colors.transparent, + elevation: 0, + leading: GestureDetector( + onTap: () {}, + child: Padding( + padding: const EdgeInsets.all(16.0), + child: SvgPicture.asset( + 'assets/svg/menu.svg', + ), + ), + ), + actions: [ + GestureDetector( + onTap: () => Get.back(), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: SvgPicture.asset( + 'assets/svg/back_arrow.svg', + ), + ), + ), + ], + title: const Text( + "Processing Order Detail", + ), + ), + body: Stack( + fit: StackFit.expand, + children: [ + Image.asset( + 'assets/images/image_1.png', + fit: BoxFit.cover, + ), + SafeArea( + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + SizedBox( + height: Get.height * 0.02, + ), + Card( + margin: const EdgeInsets.symmetric(horizontal: 18), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(19), + side: const BorderSide(color: Color(0xFFFDFDFD)), + ), + color: const Color(0xFFB4D1E5).withOpacity(0.9), + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + + Card( + child: Column( + children: [ + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Text( + "Invoices", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.05, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Invoice ID:", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text(widget.placedOrderList!.invoiceId), + // Text(widget.placedOrderList!.uniqueId), + ], + ), + ), + ), + SizedBox( + width: Get.width, + child: Padding( + padding: const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Items: ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + SizedBox(height: 10), // Add spacing between the title and the list of items + Column( + children: widget.placedOrderList!.items.map((item) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 4.0), // Add some spacing between items + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Text( + "${item.name.toString()} (${item.sku.toString()})", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.03, + ), + overflow: TextOverflow.ellipsis, // Handle long text + ), + ), + Text("x ${item.processQuantity.toString()}"), + ], + ), + ); + }).toList(), + ), + ], + ), + ), + ), + + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Sub Total : ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text("₹ ${widget.placedOrderList!.subtotal}"), + ], + ), + ), + ), + + + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "GST : ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text("₹ ${widget.placedOrderList!.gstTotal}"), + ], + ), + ), + ), + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Invoice Amount: ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text("₹ ${widget.placedOrderList!.invoiceAmount}"), + ], + ), + ), + ), + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Courier Status : ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + ElevatedButton( + onPressed: (){}, + // Get.to(() => + // RdOrderDetailScreen( + // placedOrderList: uniqueOrders[index])), // Navigate to detail screen + style: ElevatedButton.styleFrom( + foregroundColor: Colors.white, + backgroundColor: Colors.orange, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10)), + ), + child: + Text(widget.placedOrderList!.courierStatus, style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.w400)), + ), + //Text("₹ ${widget.placedOrderList!.gstTotal}"), + ], + ), + ), + ), + ], + ), + ), + const SizedBox(height: 8), + + const SizedBox(height: 8), + + + + + const SizedBox(height: 8), + SizedBox( + height: Get.height* 0.19, + child: Card( + child: Column( + children: [ + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Text( + "Customer Details", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.05, + fontWeight: FontWeight.w500, + ), + ), + ), + ), + SizedBox( + width: Get.width, + //height: Get.height*0.09, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + children: [ + Text( + "Name: ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text("${"VAIBHAV"}",maxLines: 4, + overflow:TextOverflow.ellipsis,) + , ], + ) + ), + ), + SizedBox( + width: Get.width, + // height: Get.height*0.09, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + children: [ + Text( + "Email: ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text("${"vaibhav.gurjar20001@gmail.com"}",maxLines: 4, + overflow:TextOverflow.ellipsis,) + , ], + ) + ), + ), + SizedBox( + width: Get.width, + // height: Get.height*0.09, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + children: [ + Text( + "Mobile Number: ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text("${"7779797976"}",maxLines: 4, + overflow:TextOverflow.ellipsis,) + , ], + ) + ), + ) + + ], + ), + ), + ), + const SizedBox(height: 8), + Card( + child: Column( + children: [ + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Text( + "Billing Information", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.05, + fontWeight: FontWeight.w500, + ), + ), + ), + ), + SizedBox( + width: Get.width, + height: Get.height*0.06, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Wrap( + crossAxisAlignment: WrapCrossAlignment.start, + children: [ + Text( + "Address: ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text("${"456, Park Street, Kolkata, West Bengal - 700016"}",maxLines: 4, + overflow:TextOverflow.ellipsis,) + ], + ), + ), + ), + + ], + ), + ), + const SizedBox(height: 8), + // Card for displaying shipping information + Card( + child: Column( + children: [ + SizedBox( + width: Get.width, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Text( + "Shipping Information", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.05, + fontWeight: FontWeight.w500, + ), + ), + ), + ), + SizedBox( + width: Get.width, + height: Get.height*0.06, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Wrap( + crossAxisAlignment: WrapCrossAlignment.start, + children: [ + Text( + "Address: ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.bold, + ), + ), + Text("${"456, Park Street, Kolkata, West Bengal - 700016"}",maxLines: 4, + overflow:TextOverflow.ellipsis,) + ], + ), + ), + ), + + ], + ), + ), + const SizedBox(height: 8), + Card( + child: Column( + children: [ + SizedBox( + width: Get.width, + height: Get.height*0.05, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + children: [ + Text( + "Payment Mode : ", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.w500, + ), + ), + Text(capitalizeFirstLetter("online-transfer")), + // Text("${widget.placedOrderList!.paymentMode}",maxLines: 4, + // overflow:TextOverflow.ellipsis,) + ], + ), + ), + ), + + + ], + ), + ), + const SizedBox(height: 8), + Card( + child: Column( + children: [ + SizedBox( + width: Get.width, + height: Get.height*0.05, + child: Padding( + padding: + const EdgeInsets.fromLTRB(8, 8, 8, 0), + child: Row( + children: [ + Text( + "Order Status :", + style: GoogleFonts.roboto( + fontSize: Get.width * 0.04, + fontWeight: FontWeight.w500, + ), + ), + SizedBox(width: Get.width*0.01,), + //Text(capitalizeFirstLetter(widget.placedOrderList!.status)), + Text("${widget.placedOrderList!.courierStatus}",maxLines: 4, + overflow:TextOverflow.ellipsis,) + ], + ), + ), + ), + + + ], + ), + ), + const SizedBox(height: 8), + SizedBox( + height: Get.height * 0.05, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Text( + "Status: ", + style: TextStyle(fontWeight: FontWeight.bold), + ), + SizedBox(width: 10), // Space between label and dropdown + Expanded( + child: DropdownButtonFormField( + value: selectedStatus, + decoration: InputDecoration( + filled: true, + fillColor: Colors.white, // White background + contentPadding: EdgeInsets.symmetric( + vertical: 10, horizontal: 12), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: BorderSide( + color: Colors.grey, + width: 1, + ), + ), + ), + items: _statusList.map((String status) { + return DropdownMenuItem( + value: status, + child: Text(capitalizeFirstLetter(status)), + ); + }).toList(), + onChanged: (newValue) { + setState(() { + selectedStatus = newValue!; + }); + }, + ), + ), + ], + ), + ), + SizedBox( + width: Get.width * 0.4, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: ElevatedButton( + onPressed: (){ + //_getDispatchController.RDProcessingToDispatchProduct(widget.placedOrderList!.invoiceId, widget.placedOrderList!., couriertrackingId) + _showDispatchDetailsDialog(); + }, + // Get.to(() => + // RdOrderDetailScreen( + // placedOrderList: uniqueOrders[index])), // Navigate to detail screen + style: ElevatedButton.styleFrom( + foregroundColor: Colors.white, + backgroundColor: const Color(0xFF004791), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10)), + ), + child: Text("Update Status", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.w400)), + ), + ), + ) + + ], + ), + ), + ), + SizedBox(height: Get.height * 0.04), + + ], + ), + ), + ), + ], + ), + ); + } + +} + + diff --git a/lib/screens/rd orders/rd_processing_screen.dart b/lib/screens/rd orders/rd_processing_screen.dart new file mode 100644 index 0000000..905ad72 --- /dev/null +++ b/lib/screens/rd orders/rd_processing_screen.dart @@ -0,0 +1,298 @@ + +import 'package:cheminova/controller/rd_get_order_controller.dart'; +import 'package:cheminova/controller/rd_processing_invoice_controller.dart'; +import 'package:cheminova/models/rd_get_order_model.dart'; +import 'package:cheminova/models/rd_processing_invoice_model.dart'; +import 'package:cheminova/screens/rd%20orders/rd_cancelled_screen.dart'; +import 'package:cheminova/screens/rd%20orders/rd_delivered_screen.dart'; +import 'package:cheminova/screens/rd%20orders/rd_dispatched_scree.dart'; +import 'package:cheminova/screens/rd%20orders/rd_order_details_screen.dart'; +import 'package:cheminova/screens/rd%20orders/rd_order_screen.dart'; +import 'package:cheminova/screens/rd%20orders/rd_pending_screen.dart'; +import 'package:cheminova/screens/rd%20orders/rd_processing_details.dart'; +import 'package:cheminova/screens/rd%20orders/rd_processing_screen.dart'; +import 'package:cheminova/widgets/input_field.dart'; +import 'package:cheminova/widgets/my_drawer.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:get/get.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:intl/intl.dart'; + +import '../order_management/order_management_detail_screen.dart'; + +class RdOrderProcessingScreen extends StatefulWidget { + final InvoiceResponseModel? getrdProduct; + + RdOrderProcessingScreen({super.key, this.getrdProduct}); + + @override + State createState() => _RdOrderProcessingScreenState(); +} + +class _RdOrderProcessingScreenState extends State { + final _searchController = TextEditingController(); + final List _filterList = [ "new", + "pending", + "processing", + "dispatched", + "cancelled", + "delivered",]; + int _selectedIndex = 0; + final GetRDProcessingInvoiceController _getRdProductController = Get.put(GetRDProcessingInvoiceController()); + final GlobalKey _refreshIndicatorKey = GlobalKey(); + + @override + void initState() { + super.initState(); + getOrder1(); + } + + Future _onRefresh() async { + await getOrder1(); + //await Future.delayed(Duration(seconds: 1)); + } + + Future getOrder1() async { + await _getRdProductController.getRDProcessingInvoiceProduct(); + if (_getRdProductController.productProcessingRDList.isEmpty) { + print("No orders found."); + } else { + print("Orders fetched successfully"); + } + setState(() { + + }); + } + + String capitalizeFirstLetter(String text) { + if (text.isEmpty) return text; + return text[0].toUpperCase() + text.substring(1).toLowerCase(); + } + + String formatDate(String apiDate) { + // Parse the API date string into a DateTime object + DateTime parsedDate = DateTime.parse(apiDate).toLocal(); // Convert to local time + + // Format the date and time according to your specified format + String formattedDate = DateFormat('EEE MMM dd yyyy').format(parsedDate); + + return formattedDate; // Return the formatted date string + } + + @override + @override + Widget build(BuildContext context) { + return Scaffold( + extendBodyBehindAppBar: true, + appBar: AppBar( + centerTitle: true, + backgroundColor: Colors.transparent, + elevation: 0, + leading: Builder( + builder: (context) { + return GestureDetector( + onTap: () => Scaffold.of(context).openDrawer(), + child: Padding( + padding: const EdgeInsets.all(16.0), + child: SvgPicture.asset('assets/svg/menu.svg'), + ), + ); + }, + ), + actions: [ + GestureDetector( + onTap: () => Get.back(), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: SvgPicture.asset('assets/svg/back_arrow.svg'), + ), + ), + ], + title: const Text("RD Processing Order"), + ), + drawer: MyDrawer(), + body: Stack( + fit: StackFit.expand, + children: [ + Image.asset('assets/images/image_1.png', fit: BoxFit.cover), + SafeArea( + child: SingleChildScrollView( + child: Padding( + padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), + child: RefreshIndicator( + key: _refreshIndicatorKey, + onRefresh: _onRefresh, + color: Colors.black, + backgroundColor: Colors.white, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + InputField( + hintText: "Search Order", + labelText: "Search Order", + controller: _searchController, + ), + SizedBox(height: Get.height * 0.035), + Card( + margin: const EdgeInsets.symmetric(horizontal: 18), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(19), + side: const BorderSide(color: Color(0xFFFDFDFD)), + ), + color: const Color(0xFFB4D1E5).withOpacity(0.9), + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + + SizedBox( + height: Get.height * 0.6, + child: + + + ListView.builder( + padding: EdgeInsets.zero, + shrinkWrap: true, + itemCount:_getRdProductController.productProcessingRDList.length, + itemBuilder: (context, index) { + final order = _getRdProductController.productProcessingRDList[index]; + + // Combine product names into a single string + final productNames = order.items + .map((item) => capitalizeFirstLetter(item.name)) + .join(', '); + + return Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Card( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.fromLTRB(16, 8, 8, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("Order ID: ", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.bold)), + Text("${order.orderId.uniqueId}") + ], + ), + ), + Padding( + padding: const EdgeInsets.fromLTRB(16, 8, 8, 0), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Invoice ID: ", + style: GoogleFonts.roboto( + fontSize: 14, + fontWeight: FontWeight.bold, + ), + ), + Text(order.invoiceId), + + ], + ), + ), + + Padding( + padding: const EdgeInsets.fromLTRB(16, 8, 8, 0), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Processing Date: ", + style: GoogleFonts.roboto( + fontSize: 14, + fontWeight: FontWeight.bold, + ), + ), + // Text(formatDate(widget.getrdProduct!.courierStatusTimeline.processing)), + Text( + _getRdProductController.productProcessingRDList[0].courierStatusTimeline.isNotEmpty == true + ? formatDate( _getRdProductController.productProcessingRDList[0].courierStatusTimeline["processing"].toString()) + : 'N/A', // If the map is empty or null, display 'N/A' + style: GoogleFonts.roboto( + fontSize: 14, + ), + ), + ], + ), + ), + + Padding( + padding: const EdgeInsets.fromLTRB(16, 8, 8, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("Items: ", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.bold)), + Text("${order.items.length}"), + ], + ), + ), + Padding( + padding: const EdgeInsets.fromLTRB(16, 8, 8, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("Invoice Value: ", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.bold)), + Text("${order.invoiceAmount}"), + ], + ), + ), + Padding( + padding: const EdgeInsets.fromLTRB(16, 8, 8, 8), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("Status: ", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.bold)), + Text(capitalizeFirstLetter("${order.courierStatus}")) + ], + ), + ), + SizedBox( + width: Get.width * 0.4, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: ElevatedButton( + onPressed: () => + Get.to(() => RdOrderProcessingDetailScreen(placedOrderList: _getRdProductController.productProcessingRDList[index])), + style: ElevatedButton.styleFrom( + foregroundColor: Colors.white, + backgroundColor: const Color(0xFF004791), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + ), + child: Text("View Details", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.w400)), + ), + ), + ) + ], + ), + ), + ); + }, + ) + ), + + ], + ), + ), + ), + ], + ), + ), + ), + ), + )] + ), + ); + } +} + + + diff --git a/lib/utils/api_urls.dart b/lib/utils/api_urls.dart index 93c8052..ad96ade 100644 --- a/lib/utils/api_urls.dart +++ b/lib/utils/api_urls.dart @@ -62,10 +62,18 @@ class ApiUrls { //============================== RD dispatched Order Details ==============================// static const String getRdDispatchedOrdergUrl = '/api/pd-get-dispatched-invoices'; + //============================== RD Single Invoice Order Details ==============================// + static const String getRdSingleInvoicesOrdergUrl = '/api/pd-get-invoices'; //============================== RD delivered Order Details ==============================// static const String getRdDliveredOrdergUrl = '/api/pd-get-delivered-invoices'; +//============================== RD processing to dispatch Order Details ==============================// + static const String RdProcessingtoDispatchOrdergUrl = '/api/pd-invoice/dispatched'; + + +//============================== RD dispatched to Delivered Order Details ==============================// + static const String RdDispatchtoDeliveredOrdergUrl = '/api/pd-invoice/delivered'; }