diff --git a/android/app/google-services.json b/android/app/google-services.json new file mode 100644 index 0000000..40ed628 --- /dev/null +++ b/android/app/google-services.json @@ -0,0 +1,29 @@ +{ + "project_info": { + "project_number": "242950171023", + "project_id": "cheminova-1fcf0", + "storage_bucket": "cheminova-1fcf0.appspot.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:242950171023:android:7fdc614b0429b52445c3fa", + "android_client_info": { + "package_name": "com.example.cheminova" + } + }, + "oauth_client": [], + "api_key": [ + { + "current_key": "AIzaSyDfgOZAwDgUnzQYnIHm8ObxrDtTutmAoAE" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/firebase.json b/firebase.json new file mode 100644 index 0000000..2023ce9 --- /dev/null +++ b/firebase.json @@ -0,0 +1 @@ +{"flutter":{"platforms":{"android":{"default":{"projectId":"cheminova-1fcf0","appId":"1:242950171023:android:7fdc614b0429b52445c3fa","fileOutput":"android/app/google-services.json"}},"dart":{"lib/firebase_options.dart":{"projectId":"cheminova-1fcf0","configurations":{"android":"1:242950171023:android:7fdc614b0429b52445c3fa","ios":"1:242950171023:ios:f4aba8c6c2d8f5ec45c3fa","macos":"1:242950171023:ios:f4aba8c6c2d8f5ec45c3fa"}}}}}} \ No newline at end of file diff --git a/lib/controller/cart_controller.dart b/lib/controller/cart_controller.dart index 26c0f78..0225567 100644 --- a/lib/controller/cart_controller.dart +++ b/lib/controller/cart_controller.dart @@ -3,13 +3,17 @@ import '../models/product_model.dart'; import '../models/product_model1.dart'; class CartController extends GetxController { + // Observable list to store products added to the cart var cartList = [].obs; + // Observable variable to track the total count of items in the cart var cartCount = 0.obs; - var subtotal = 0.0.obs; - var gstTotal = 0.0.obs; - var grandTotal = 0.0.obs; + // Observable variables to calculate price details + var subtotal = 0.0.obs; // The total price of items without tax + var gstTotal = 0.0.obs; // The total GST amount + var grandTotal = 0.0.obs;// The total amount including GST - // Track the selected products + + // Observable list to track selected products for price calculation var selectedProducts = [].obs; @override @@ -18,79 +22,97 @@ class CartController extends GetxController { // Initialize the cart list or other initializations if needed initializeSelections(); } - + // Function to add a product to the cart void addToCart(Product product) { + // Check if the product already exists in the cart var existingProduct = cartList.firstWhereOrNull((p) => p.id == product.id); if (existingProduct != null) { + // If the product exists, increase its quantity existingProduct.quantity++; } else { + // If it's a new product, add it to the cart cartList.add(product); } + // Update the cart count cartCount.value = cartList.length; + // Recalculate the total price updateTotalPrice(); } - + // Function to update the total price, subtotal, and GST total void updateTotalPrice() { double subTotal = 0.0; double gstTotalAmount = 0.0; - + // Calculate subtotal and GST for selected products only for (var product in selectedProducts) { subTotal += product.price * product.quantity; gstTotalAmount += (product.price * product.quantity * (product.gst / 100)); } - + // Update observable values subtotal.value = subTotal; gstTotal.value = gstTotalAmount; grandTotal.value = subtotal.value + gstTotal.value; } - + // Function to increase the quantity of a product in the cart void increaseQuantity(Product product) { final index = cartList.indexWhere((item) => item.id == product.id); if (index != -1) { + // Increment the quantity of the product cartList[index].quantity++; + // If the product is selected, update the total price if (selectedProducts.contains(cartList[index])) { updateTotalPrice(); } } } - + // Function to decrease the quantity of a product in the cart void decreaseQuantity(Product product) { final index = cartList.indexWhere((item) => item.id == product.id); if (index != -1 && cartList[index].quantity > 1) { + // Decrement the quantity of the product cartList[index].quantity--; + // If the product is selected, update the total price if (selectedProducts.contains(cartList[index])) { updateTotalPrice(); } } } - + // Function to remove a product from the cart void removeFromCart(Product product) { + // Remove the product from the cart list cartList.removeWhere((item) => item.id == product.id); + // Remove the product from the selected list if it's there selectedProducts.remove(product); + // Update the cart count and total price cartCount.value = cartList.length; updateTotalPrice(); } - + // Function to toggle the selection of a product void toggleProductSelection(Product product, bool isSelected) { if (isSelected) { + // Add the product to the selected list if it's not already selected if (!selectedProducts.contains(product)) { selectedProducts.add(product); } } else { + // Remove the product from the selected list selectedProducts.remove(product); } + // Update the total price after selection change updateTotalPrice(); } - + // Function to select or deselect all products void selectAllProducts(bool selectAll) { if (selectAll) { + // Select all products in the cart selectedProducts.assignAll(cartList); } else { + // Clear all selections selectedProducts.clear(); } + // Update the total price after selection change updateTotalPrice(); } - + // Function to initialize product selections; selects all by default void initializeSelections() { selectAllProducts(true); } diff --git a/lib/controller/get_order_placed_controller.dart b/lib/controller/get_order_placed_controller.dart index bed7dbc..9db11e9 100644 --- a/lib/controller/get_order_placed_controller.dart +++ b/lib/controller/get_order_placed_controller.dart @@ -9,12 +9,18 @@ import '../utils/log_service.dart'; import 'get_place_order_service.dart'; class GetPlacedOrderController extends GetxController { + // Service to fetch all placed orders final GetOrderPlacedService _getOrderPlacedService = GetOrderPlacedService(); + // Controller to manage order placement functionality final OrderPlacedController _orderPlacedController = Get.put(OrderPlacedController()); + // Service to fetch a single placed order final GetSingleOrderPlacedService _getSingleOrderPlacedService = GetSingleOrderPlacedService(); - var placedOrders = [].obs; - var products = [].obs; + // Observable list to store fetched placed orders + var placedOrders = [].obs; + // Observable list to track products related to placed orders + var products = [].obs; + // Observable to handle loading state var isLoading = false.obs; @override @@ -22,12 +28,13 @@ class GetPlacedOrderController extends GetxController { super.onInit(); getOrders(); // Fetch the orders immediately on initialization } - + // Function to fetch all placed orders Future getOrders() async { - + // Call the service to fetch placed orders final fetchedOrders = await _getOrderPlacedService.getPlacedOrders(); if (fetchedOrders != null && fetchedOrders.isNotEmpty) { + // Add fetched orders to the observable list placedOrders.addAll(fetchedOrders); //logger.w("Fetched orders: $fetchedOrders"); @@ -36,10 +43,11 @@ class GetPlacedOrderController extends GetxController { } } - + // Function to search and fetch a single placed order by ID Future searchOrder() async { try { isLoading.value = true; + // Fetch a single order based on the first order's ID in the list final order = await _getSingleOrderPlacedService.getSinglePlacedOrder(placedOrders[0].id); if (order != null) { placedOrders.clear(); // Clear existing orders if needed @@ -54,10 +62,11 @@ class GetPlacedOrderController extends GetxController { } } - // Optional: Reset the pagination if needed + // Optional function to reset pagination and fetch fresh data void resetPagination() { + // Reset pagination in the service _getOrderPlacedService.resetPagination(); placedOrders.clear(); // Clear existing data - getOrders(); // Fetch fresh data + getOrders(); // Fetch fresh orders after resetting } } diff --git a/lib/controller/get_place_order_service.dart b/lib/controller/get_place_order_service.dart index 5c10096..41ca887 100644 --- a/lib/controller/get_place_order_service.dart +++ b/lib/controller/get_place_order_service.dart @@ -1,4 +1,5 @@ import 'package:cheminova/models/place_order_list_model.dart'; +import 'package:cheminova/utils/api_urls.dart'; import '../models/oder_place_model.dart'; import '../utils/common_api_service.dart'; import '../utils/show_snackbar.dart'; @@ -9,24 +10,28 @@ class GetOrderPlacedService { final List _allOrders = []; // To store all fetched orders bool _hasMoreOrders = true; // To check if there are more orders to fetch + // Function to fetch placed orders from the server Future?> getPlacedOrders() async { try { + // Continue fetching as long as there are more orders available while (_hasMoreOrders) { // Construct the API URL with pagination parameters - String url = "/api/get-placed-order-pd?page=$_currentPage"; - + String url = "${ApiUrls.getPlacedOrderUrl}?page=$_currentPage"; + // Call the common API service to fetch orders final response = await commonApiService>( method: "GET", url: url, fromJson: (json) { + // Parse the JSON response if it contains the 'plcaedOrders' key if (json['plcaedOrders'] != null) { + // Convert the JSON list to a list of PlacedOrderList objects final List orders = (json['plcaedOrders'] as List) .map((orderJson) => PlacedOrderList.fromJson(orderJson as Map)) .toList(); - + // Check if the fetched orders list is not empty if (orders.isNotEmpty) { - _allOrders.addAll(orders); - _currentPage++; + _allOrders.addAll(orders); // Add the fetched orders to the main list + _currentPage++; // Increment the page number for the next fetch // _limit += orders.length; // Adjust limit based on the number of fetched orders } else { _hasMoreOrders = false; // Stop fetching if no more orders are returned @@ -39,20 +44,21 @@ class GetOrderPlacedService { } }, ); - + // Stop fetching if the response is null or empty if (response == null || response.isEmpty) { _hasMoreOrders = false; // Stop fetching if the response is empty } } - + // Return all fetched orders after completing the fetch process return _allOrders; } catch (e) { + // Show an error message in a snackbar if an exception occurs showSnackbar(e.toString()); return null; } } - // Optional: Reset the pagination and orders when needed + // Function to reset the pagination and clear the orders list void resetPagination() { _currentPage = 1; //_limit = 100; // Reset the limit to the initial value diff --git a/lib/controller/get_single_placed_order_service.dart b/lib/controller/get_single_placed_order_service.dart index 7f67814..92a7253 100644 --- a/lib/controller/get_single_placed_order_service.dart +++ b/lib/controller/get_single_placed_order_service.dart @@ -1,30 +1,35 @@ import 'package:cheminova/models/place_order_list_model.dart'; // Import your model +import 'package:cheminova/utils/api_urls.dart'; import '../utils/common_api_service.dart'; import '../utils/show_snackbar.dart'; class GetSingleOrderPlacedService { + // Function to fetch a single placed order by its ID Future getSinglePlacedOrder(String orderId) async { try { // Construct the API URL for the single placed order - String url = "/api/get-single-placed-order-pd/$orderId"; + String url = "${ApiUrls.getSinglePlacedOrderUrl}$orderId"; final response = await commonApiService( method: "GET", url: url, fromJson: (json) { + // Check if the JSON response contains the 'singleOrder' key if (json['singleOrder'] != null) { // Convert the JSON response to a PlacedOrderList model return PlacedOrderList.fromJson(json['singleOrder'] as Map); } else { + // Throw an exception if the order is not found in the response throw Exception("Order not found"); // Throw an exception if not found } }, ); - return response; + return response; // Return the fetched order if successful } catch (e) { + // Show an error message in a snackbar if an exception occurs showSnackbar(e.toString()); - return null; + return null; // Return null to indicate an error occurred } } } diff --git a/lib/controller/home_controller.dart b/lib/controller/home_controller.dart index bfe9375..d6dbb73 100644 --- a/lib/controller/home_controller.dart +++ b/lib/controller/home_controller.dart @@ -6,46 +6,41 @@ import 'package:shared_preferences/shared_preferences.dart'; import '../notification_service.dart'; class HomeController extends GetxController { + // Instance of HomeService to handle API requests final HomeService homeService = HomeService(); + // Instance of NotificationServices for handling notifications NotificationServices notificationServices = NotificationServices(); - UserModel? user; - // var userModel = UserModel( - // id: '', - // uniqueId: '', - // name: '', - // email: '', - // phone: '', - // role: '', - // sbu: '', - // createdAt: '', - // updatedAt: '', - // ).obs; // Observable for UserModel + UserModel? user; // Variable to store user details @override void onInit() { - getUser(); - super.onInit(); - notificationServices.requestNotificationPermission(); + // Called when the controller is initialized + getUser(); // Fetch user data + super.onInit(); // Call parent class's onInit method + notificationServices.requestNotificationPermission(); // Request permission for notifications notificationServices.getDeviceToken().then((value) { + // Retrieve the FCM device token print('Device Token: $value'); - fcmToken(); + fcmToken(); // Call the function to send the FCM token to the server }); } - +// Function to handle FCM token retrieval and sending it to the server Future fcmToken() async { + // Get SharedPreferences instance SharedPreferences prefs = await SharedPreferences.getInstance(); - String? token = prefs.getString('token'); - final fcmToken = await NotificationServices().getDeviceToken(); + String? token = prefs.getString('token'); // Retrieve the saved user token + final fcmToken = await NotificationServices().getDeviceToken(); // Get the FCM device token print('fcmToken: $fcmToken'); - homeService.fcmToken({"fcmToken": fcmToken}, token!); + homeService.fcmToken({"fcmToken": fcmToken}, token); // Send the FCM token to the server } - + // Function to fetch user details from the server Future getUser() async { SharedPreferences prefs = await SharedPreferences.getInstance(); String? token = prefs.getString('token'); - + // Create an instance of HomeService HomeService homeService = HomeService(); + // Fetch user details using the token user = await homeService.getUser(token: token); if (user != null) { @@ -57,59 +52,3 @@ class HomeController extends GetxController { } - - - - -// import 'package:cheminova/controller/home_service.dart'; -// import 'package:cheminova/models/user_model.dart'; -// import 'package:get/get.dart'; -// import 'package:shared_preferences/shared_preferences.dart'; -// -// import '../notification_service.dart'; -// -// class HomeController extends GetxController { -// final HomeService homeService = HomeService(); -// NotificationServices notificationServices = NotificationServices(); -// -// -// -// var userModel = UserModel(id: '', uniqueId: '', name: '', email: '', phone: '', role: '', sbu: '', createdAt: '', updatedAt: '' -// -// ).obs; // Observable for UserModel -// -// @override -// void onInit() { -// getUser(); -// super.onInit(); -// notificationServices.requestNotificationPermission(); -// notificationServices.getDeviceToken().then((value) { -// print('Device Token: $value'); -// fcmToken(); -// }); -// } -// -// Future fcmToken() async { -// SharedPreferences prefs = await SharedPreferences.getInstance(); -// String? token = prefs.getString('token'); -// final fcmToken = await NotificationServices().getDeviceToken(); -// print('fcmToken: $fcmToken'); -// homeService.fcmToken({"fcmToken": fcmToken}, token!); -// } -// -// Future getUser() async { -// SharedPreferences prefs = await SharedPreferences.getInstance(); -// -// String? token = prefs.getString('token'); -// -// userModel = (await homeService.getUser(token: token)) as dynamic; -// -// -// // if (userModel != null) { -// // if (userModel != null) {ddddd -// // userModel.value = userResponse as UserModel; // Update the userModel with API response -// // update(); // Notify GetX to rebuild widgets using GetBuilder/Obx -// // } -// } -// } -// diff --git a/lib/controller/home_service.dart b/lib/controller/home_service.dart index 06190d4..4b127e0 100644 --- a/lib/controller/home_service.dart +++ b/lib/controller/home_service.dart @@ -4,20 +4,24 @@ import 'package:cheminova/utils/common_api_service.dart'; import 'package:cheminova/utils/show_snackbar.dart'; class HomeService { + // Function to fetch user details from the API Future getUser({String? token}) async { try { + // Making a GET request to fetch user profile data final response = await commonApiService( method: "GET", url: ApiUrls.profileUrl, - additionalHeaders: { // Pass the token here + additionalHeaders: { // Pass the token here 'Authorization': 'Bearer $token', }, fromJson: (json) { + // Callback to parse the JSON response into a UserModel if (json['user'] != null) { // Parse the user data from the API response - return UserModel.fromJson(json['user']); + return UserModel.fromJson( + json['user']); // Convert JSON to UserModel } - return json as UserModel; + return json as UserModel; // Return the response as UserModel if no 'user' key found }, ); return response; @@ -28,21 +32,26 @@ class HomeService { } } - +// Function to send FCM token to the server Future?> fcmToken(Map data, String? token) async { try { final response = await commonApiService( + // Making a POST request to send the FCM token url: ApiUrls.fcmUrl, method: 'POST', body: data, + // Body data to be sent in the request fromJson: (json) => json as String, // Just return the string response - additionalHeaders: { // Pass the token here + additionalHeaders: { + // Pass the token here 'Authorization': 'Bearer $token', + // Bearer token for authenticated requests }, ); + if (response != null) { // Since the response is a string, wrap it in a Map to avoid type issues return { diff --git a/lib/controller/kyc_controller.dart b/lib/controller/kyc_controller.dart index a66758d..8450c51 100644 --- a/lib/controller/kyc_controller.dart +++ b/lib/controller/kyc_controller.dart @@ -1,9 +1,8 @@ import 'dart:convert'; - import 'package:flutter/material.dart'; import 'package:get/get.dart'; +import 'package:get_storage/get_storage.dart'; import 'package:shared_preferences/shared_preferences.dart'; - import '../models/kyc_model.dart'; import 'kyc_service.dart'; @@ -11,6 +10,12 @@ class KycController extends GetxController { var kycList = [].obs; // Using an observable list to store KYC data var isLoading = false.obs; + @override + void onInit() { + super.onInit(); + loadKycFromLocalStorage(); // Load KYC data from local storage when initialized + } + Future fetchKycData() async { try { SharedPreferences prefs = await SharedPreferences.getInstance(); @@ -23,6 +28,7 @@ class KycController extends GetxController { if (data != null && data.isNotEmpty) { // Parse the list of KYC objects kycList.value = KycModel.fromJsonList(data); // Convert to List + saveKycToLocalStorage(); // Save the fetched KYC data to local storage } else { print("No KYC data found or API response is empty."); } @@ -36,10 +42,10 @@ class KycController extends GetxController { // Update KYC status locally and persist the changes Future updateKycStatus(KycModel kycModel, String status, String comment) async { final index = kycList.indexOf(kycModel); + if (index != -1) { kycList[index].status = status; // Update status locally saveKycToLocalStorage(); // Persist the changes locally - update(); // Notify listeners about the change // Show a success message after updating Get.snackbar( @@ -59,23 +65,19 @@ class KycController extends GetxController { prefs.setStringList('kycList', kycListJson); // Save the updated list locally } - // Load the KYC list from SharedPreferences + // Load KYC data from SharedPreferences Future loadKycFromLocalStorage() async { SharedPreferences prefs = await SharedPreferences.getInstance(); - List? storedKycList = prefs.getStringList('kycList'); + List? kycListJson = prefs.getStringList('kycList'); - if (storedKycList != null) { - // If local data is found, update the KYC list with the locally saved data - List localKycList = storedKycList.map((kycJson) => KycModel.fromJson(jsonDecode(kycJson))).toList(); + if (kycListJson != null) { + kycList.value = kycListJson.map((jsonStr) => KycModel.fromJson(jsonDecode(jsonStr))).toList(); + print("Loaded KYC data from local storage."); + + } else { + // If no data found, fetch from API + fetchKycData(); - // Merge local data with the API data (if any exists in kycList) - for (var localKyc in localKycList) { - int index = kycList.indexWhere((kyc) => kyc.id == localKyc.id); - if (index != -1) { - // Update the status with the locally saved status - kycList[index].status = localKyc.status; - } - } } } -} \ No newline at end of file +} diff --git a/lib/controller/kyc_service.dart b/lib/controller/kyc_service.dart index b352d87..ed2e6a9 100644 --- a/lib/controller/kyc_service.dart +++ b/lib/controller/kyc_service.dart @@ -1,21 +1,24 @@ - - +import 'package:cheminova/utils/api_urls.dart'; import 'package:dio/dio.dart'; class KycService { + + // Function to fetch KYC data from the API Future> getKycData(String token) async { try { + // Make a GET request to the KYC API endpoint with authorization token var response = await Dio().get( - 'https://api.cnapp.co.in/api/kyc/getAll', + ApiUrls.getKycUrl, + // 'https://api.cnapp.co.in/api/kyc/getAll', options: Options( headers: { 'Authorization': 'Bearer $token', }, ), ); - - if (response.statusCode == 200) { - print("response of /api/kyc/getAll : ${response.data}"); + // Check if the response status code indicates success + if (response.statusCode == 200) { + print("response of ApiUrls.getKycUrl: ${response.data}"); return response.data; // Return the data as a List } else { throw Exception("Failed to load KYC data"); @@ -28,39 +31,3 @@ class KycService { } - -// import 'dart:convert'; -// import 'package:cheminova/utils/api_urls.dart'; -// import '../models/kyc_model.dart'; -// import '../utils/common_api_service.dart'; -// -// class KycService { -// Future?> getKycData(String token) async { -// String url = ApiUrls.getKyc; // API endpoint for KYC data -// -// // Use the commonApiService for making the API request -// final response = await commonApiService>( -// method: "GET", -// url: url, -// additionalHeaders: { -// 'Authorization': 'Bearer $token', // Add the token in headers -// }, -// fromJson: (json) -// { -// if (json != null && json['data'] != null) { -// List dataList = json['data']; // Access 'data' array -// return dataList.map((item) => KycModel.fromJson(item)).toList(); -// } else { -// print('Invalid KYC response or data is null'); -// return []; -// } -// -// -// -// }, -// ); -// -// // Return the parsed KYC data list, or an empty list in case of failure -// return response; -// } -// } diff --git a/lib/controller/notification_api_service.dart b/lib/controller/notification_api_service.dart index 24f07d3..6802341 100644 --- a/lib/controller/notification_api_service.dart +++ b/lib/controller/notification_api_service.dart @@ -4,10 +4,12 @@ import 'package:cheminova/utils/api_urls.dart'; import '../utils/common_api_service.dart'; class NotificationApiService { + // Function to fetch notifications from the API Future?> getNotification(String token) async { try { + // Set the URL for fetching notifications String url =ApiUrls.getNotificationUrl; // Base URL to fetch product manuals - + // Make a GET request to the notification API final response = await commonApiService>( method: "GET", url: url, @@ -16,7 +18,7 @@ class NotificationApiService { }, fromJson: (json) { if (json['notifications'] != null) { - // Map the list of product manuals from the response + // If notifications are present in the response, map them to NotificationModel objects final List notification = (json['notifications'] as List) .map((manualJson) => NotificationModel.fromJson(manualJson as Map)) .toList(); diff --git a/lib/controller/place_order_controller.dart b/lib/controller/place_order_controller.dart index a2e56c1..e0a8e19 100644 --- a/lib/controller/place_order_controller.dart +++ b/lib/controller/place_order_controller.dart @@ -9,6 +9,7 @@ import '../models/oder_place_model.dart'; class OrderPlacedController extends GetxController { + // Observable variable to hold the details of the placed order var placedOrder1 = PlacedOrderModel( paymentMode: 'cheque', shipTo: '456, Park Street, Kolkata, West Bengal - 700016', @@ -23,13 +24,13 @@ class OrderPlacedController extends GetxController { var isLoading = false.obs; final OrderPlacedService _orderPlacedService = OrderPlacedService(); - +// Method to place an order Future placeOrder() async { SharedPreferences prefs = await SharedPreferences.getInstance(); String? token = prefs.getString('token'); isLoading.value = true; //try { - // Construct order details + // Construct order details from the observable variable PlacedOrderModel orderDetails = placedOrder1.value; print("Order Details: $orderDetails"); @@ -42,88 +43,4 @@ class OrderPlacedController extends GetxController { // } finally { // isLoading.value = false; // } - } - - - - - - - - -// import 'package:cheminova/controller/place_order_service.dart'; -// import 'package:cheminova/models/category_model.dart'; -// import 'package:get/get.dart'; -// import 'package:shared_preferences/shared_preferences.dart'; -// import '../models/oder_place_model.dart'; -// import 'cart_controller.dart'; -// -// -// class OrderPlacedController extends GetxController { -// final OrderPlacedService _orderPlacedService = OrderPlacedService(); -// final CartController _cartController = Get.find(); -// Rx placedOrder1 = Rx(null); -// RxBool isLoading = false.obs; -// -// // Method to place an order with provided details -// Future placeOrder() async { -// SharedPreferences prefs = await SharedPreferences.getInstance(); -// String? token = prefs.getString('token'); -// -// // Prepare order details -// final order = PlacedOrderModel( -// paymentMode: 'cheque', -// shipTo: '456, Park Street, Kolkata, West Bengal - 700016', -// billTo: '456, Park Street, Kolkata, West Bengal - 700016', -// subtotal: 4000, -// gstTotal: 18, -// grandTotal: 4720, -// orderItems: [ -// OrderItem( -// id: "66cc7869f02b935094127a27", -// sku: "BJD", -// name: "Zycor 60m.l", -// price: 4000, -// gst: 18, -// hsnCode: 200, -// description: "", -// productStatus: "Active", -// addedBy: "ChemiNova", -// image: [], -// createdAt: DateTime.parse("2024-08-26T12:43:21.103Z"), -// updatedAt: DateTime.parse("2024-08-26T12:43:21.103Z"), -// count: 1, category:Category(id: "66cc7868f02b935094127a21", categoryName: "Insectiside") , -// brand: Brand(id: "66cc77fbf02b9350941279f5", brandName: "Old"), v: 0, -// ), -// ], -// ); -// -// try { -// isLoading.value = true; -// PlacedOrderModel? result = await _orderPlacedService.placeOrder(order, token); -// if (result != null) { -// placedOrder1.value = result; -// Get.snackbar('Success', 'Order placed successfully.'); -// // _cartController.clearCart(); // Clear cart items after order -// } else { -// Get.snackbar('Error', 'Failed to place order.'); -// } -// } catch (e) { -// Get.snackbar('Error', e.toString()); -// } finally { -// isLoading.value = false; -// } -// } -// -// String getShippingAddress() { -// return placedOrder1.value?.shipTo ?? 'No shipping address'; -// } -// -// String getBillingAddress() { -// return placedOrder1.value?.billTo ?? 'No billing address'; -// } -// -// String getPaymentMode() { -// return placedOrder1.value?.paymentMode ?? 'No payment mode'; -// } -// } + } \ No newline at end of file diff --git a/lib/controller/place_order_service.dart b/lib/controller/place_order_service.dart index 79141cb..8019a15 100644 --- a/lib/controller/place_order_service.dart +++ b/lib/controller/place_order_service.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'dart:developer'; import 'package:cheminova/models/product_model.dart'; +import 'package:cheminova/utils/api_urls.dart'; import 'package:dio/dio.dart'; import '../models/oder_place_model.dart'; @@ -14,7 +15,7 @@ class OrderPlacedService { //try { // logger.w("orderjson ${jsonEncode(orderDetails.toJson())}"); final response = await dio.post( - 'https://api.cnapp.co.in/api/order-place', // Ensure this is your correct endpoint + '${ApiUrls.placedOrderUrl}', // Ensure this is your correct endpoint data: jsonEncode(orderDetails.toJson()), options: Options( headers: { diff --git a/lib/controller/product_controller.dart b/lib/controller/product_controller.dart index 071458b..c20cc17 100644 --- a/lib/controller/product_controller.dart +++ b/lib/controller/product_controller.dart @@ -4,6 +4,7 @@ import 'package:get/get.dart'; class ProductController extends GetxController { + // Instantiate the product service final ProductService productService = ProductService(); var products = [].obs; var categories = [].obs; // Holds the list of categories @@ -14,12 +15,14 @@ class ProductController extends GetxController { @override void onInit() { super.onInit(); + // Fetch categories when the controller initializes getCategory(); + // Fetch products when the controller initializes getUser(); } - +// Method to fetch products based on the selected category and current page Future getUser() async { - if (isLoading) return; + if (isLoading) return; // Prevent duplicate calls if already loading isLoading = true; try { final category = selectedCategory.value; // Get the selected category @@ -29,7 +32,7 @@ class ProductController extends GetxController { ); if (fetchedProducts != null) { - // Directly add the fetched products (which are of type List) to the list + // If products were fetched, add them to the observable list products.addAll(fetchedProducts); print("fetchedProducts ,$fetchedProducts"); } @@ -40,28 +43,29 @@ class ProductController extends GetxController { update(); } } - +// Method to fetch categories from the product service Future getCategory() async { try { final fetchedCategories = await productService.getCategory(); if (fetchedCategories != null) { + // If categories were fetched, map them to the observable list categories.assignAll(fetchedCategories.map((category) => category['categoryName'] as String)); - categories.insert(0, 'All'); // Add "All" option + categories.insert(0, 'All'); // Add "All" option as the first category } } catch (e) { print("Error fetching categories: $e"); } } - + // Method to set the selected category and fetch products void setCategory(String category) { selectedCategory.value = category == 'All' ? null : category; _currentPage = 1; - products.clear(); - getUser(); + products.clear(); // Clear the existing products + getUser(); // Fetch products based on the new category } - + // Method to load more products when reaching the end of the list void loadMoreProducts() { _currentPage++; - getUser(); + getUser(); // Fetch products for the next page } } diff --git a/lib/controller/product_mannual_service.dart b/lib/controller/product_mannual_service.dart index 3580a4a..84c80ac 100644 --- a/lib/controller/product_mannual_service.dart +++ b/lib/controller/product_mannual_service.dart @@ -6,6 +6,7 @@ import '../models/product_mannual_model.dart'; import '../utils/common_api_service.dart'; // Replace with your actual common API service import class ProductMannualService { + // Method to fetch product manuals using an authorization token Future?> getProductManuals(String token) async { try { String url = ApiUrls.getProductManualUrl; // Base URL to fetch product manuals @@ -18,11 +19,11 @@ class ProductMannualService { }, fromJson: (json) { if (json['productManuals'] != null) { - // Map the list of product manuals from the response + // If the productManuals key is present, map the response to a list of ProductManualModel objects final List productManuals = (json['productManuals'] as List) .map((manualJson) => ProductManualModel.fromJson(manualJson as Map)) .toList(); - return productManuals; + return productManuals; // Return the list of product manuals } else { return []; } diff --git a/lib/controller/product_service.dart b/lib/controller/product_service.dart index c0734d7..29ffb7f 100644 --- a/lib/controller/product_service.dart +++ b/lib/controller/product_service.dart @@ -5,20 +5,23 @@ import '../utils/common_api_service.dart'; import '../utils/show_snackbar.dart'; class ProductService { + // Method to fetch products based on the page number and optional category Future?> getProduct(int page, {String? category}) async { try { String url; + // Determine the URL based on the presence of a category filter if (category != null && category.isNotEmpty) { - url = "ApiUrls.getProductUrl?page=$page&category=$category"; + url = "${ApiUrls.getCategoryUrl}?page=$page&category=$category"; } else { - url = "/api/product/getAll/user?page=$page"; // URL without category filter + url = "${ApiUrls.getallProductUrl}?page=$page"; // URL without category filter } - + // Make the API call using the common API service final response = await commonApiService>( method: "GET", url: url, fromJson: (json) { if (json['products'] != null) { + // If the 'products' key exists, map it to a list of Product objects final List products = (json['products'] as List) .map((productJson) => Product.fromJson(productJson as Map)) .toList(); @@ -36,9 +39,10 @@ class ProductService { } } - + // Method to fetch product categories Future>?> getCategory() async { try { + // Make the API call to fetch categories final response = await commonApiService>>( method: "GET", url: ApiUrls.getCategoryUrl, @@ -47,9 +51,9 @@ class ProductService { final List> category = (json['categories'] as List) .map((productJson) => productJson as Map) .toList(); - return category; + return category; // Return the list of categories } else { - return []; + return []; // Return an empty list if no categories are found } }, ); diff --git a/lib/firebase_options.dart b/lib/firebase_options.dart new file mode 100644 index 0000000..a87afd5 --- /dev/null +++ b/lib/firebase_options.dart @@ -0,0 +1,75 @@ +// File generated by FlutterFire CLI. +// ignore_for_file: type=lint +import 'package:firebase_core/firebase_core.dart' show FirebaseOptions; +import 'package:flutter/foundation.dart' + show defaultTargetPlatform, kIsWeb, TargetPlatform; + +/// Default [FirebaseOptions] for use with your Firebase apps. +/// +/// Example: +/// ```dart +/// import 'firebase_options.dart'; +/// // ... +/// await Firebase.initializeApp( +/// options: DefaultFirebaseOptions.currentPlatform, +/// ); +/// ``` +class DefaultFirebaseOptions { + static FirebaseOptions get currentPlatform { + if (kIsWeb) { + throw UnsupportedError( + 'DefaultFirebaseOptions have not been configured for web - ' + 'you can reconfigure this by running the FlutterFire CLI again.', + ); + } + switch (defaultTargetPlatform) { + case TargetPlatform.android: + return android; + case TargetPlatform.iOS: + return ios; + case TargetPlatform.macOS: + return macos; + case TargetPlatform.windows: + throw UnsupportedError( + 'DefaultFirebaseOptions have not been configured for windows - ' + 'you can reconfigure this by running the FlutterFire CLI again.', + ); + case TargetPlatform.linux: + throw UnsupportedError( + 'DefaultFirebaseOptions have not been configured for linux - ' + 'you can reconfigure this by running the FlutterFire CLI again.', + ); + default: + throw UnsupportedError( + 'DefaultFirebaseOptions are not supported for this platform.', + ); + } + } + + static const FirebaseOptions android = FirebaseOptions( + apiKey: 'AIzaSyDfgOZAwDgUnzQYnIHm8ObxrDtTutmAoAE', + appId: '1:242950171023:android:7fdc614b0429b52445c3fa', + messagingSenderId: '242950171023', + projectId: 'cheminova-1fcf0', + storageBucket: 'cheminova-1fcf0.appspot.com', + ); + + static const FirebaseOptions ios = FirebaseOptions( + apiKey: 'AIzaSyCukVtk1vpdHcO1ayiPMz1wLQGfRGzEXxk', + appId: '1:242950171023:ios:f4aba8c6c2d8f5ec45c3fa', + messagingSenderId: '242950171023', + projectId: 'cheminova-1fcf0', + storageBucket: 'cheminova-1fcf0.appspot.com', + iosBundleId: 'com.example.cheminova', + ); + + static const FirebaseOptions macos = FirebaseOptions( + apiKey: 'AIzaSyCukVtk1vpdHcO1ayiPMz1wLQGfRGzEXxk', + appId: '1:242950171023:ios:f4aba8c6c2d8f5ec45c3fa', + messagingSenderId: '242950171023', + projectId: 'cheminova-1fcf0', + storageBucket: 'cheminova-1fcf0.appspot.com', + iosBundleId: 'com.example.cheminova', + ); + +} \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index c15bce6..a1ed218 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -10,13 +10,13 @@ var box; void main()async{ WidgetsFlutterBinding.ensureInitialized(); + // Ensure that Flutter's binding is initialized before running the app, necessary for async operations before runApp - - + // Initialize Firebase with the current platform's configuration await Firebase.initializeApp( options: DefaultFirebaseOptions.currentPlatform, ); - await Hive.initFlutter(); + await Hive.initFlutter(); // Initialize Hive for Flutter await Hive.openBox('cartBox'); runApp(const MyApp()); } @@ -26,6 +26,7 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { + // Use GetMaterialApp for navigation and state management with GetX return const GetMaterialApp( debugShowCheckedModeBanner: false, home: SplashScreen(), diff --git a/lib/models/added_by_model.dart b/lib/models/added_by_model.dart index dedcb72..ef36fe4 100644 --- a/lib/models/added_by_model.dart +++ b/lib/models/added_by_model.dart @@ -1,23 +1,23 @@ -class AddedBy { - String id; - String name; - - AddedBy({ - required this.id, - required this.name, - }); - - factory AddedBy.fromJson(Map json) => AddedBy( - id: json["_id"], - name: json["name"], - ); - - Map toJson() => { - "_id": id, - "name": name, - }; - @override - String toString() { - return 'AddedBy(id: $id, brandName: $AddedBy,)'; - } -} \ No newline at end of file +// class AddedBy { +// String id; +// String name; +// +// AddedBy({ +// required this.id, +// required this.name, +// }); +// +// factory AddedBy.fromJson(Map json) => AddedBy( +// id: json["_id"], +// name: json["name"], +// ); +// +// Map toJson() => { +// "_id": id, +// "name": name, +// }; +// @override +// String toString() { +// return 'AddedBy(id: $id, brandName: $AddedBy,)'; +// } +// } \ No newline at end of file diff --git a/lib/models/cart_item_model.dart b/lib/models/cart_item_model.dart index 2f392fe..665f19f 100644 --- a/lib/models/cart_item_model.dart +++ b/lib/models/cart_item_model.dart @@ -1,27 +1,27 @@ -// lib/models/cart_item.dart -import 'package:cheminova/models/product_model1.dart'; - -class CartItem { - final Product product; - int quantity; - - CartItem({ - required this.product, - this.quantity = 1, - }); - - // Method to increase quantity - void increaseQuantity() { - quantity++; - } - - // Method to decrease quantity - void decreaseQuantity() { - if (quantity > 1) { - quantity--; - } - } - - // Method to get total price of this item - int get totalPrice => product.price * quantity; -} +// // lib/models/cart_item.dart +// import 'package:cheminova/models/product_model1.dart'; +// +// class CartItem { +// final Product product; +// int quantity; +// +// CartItem({ +// required this.product, +// this.quantity = 1, +// }); +// +// // Method to increase quantity +// void increaseQuantity() { +// quantity++; +// } +// +// // Method to decrease quantity +// void decreaseQuantity() { +// if (quantity > 1) { +// quantity--; +// } +// } +// +// // Method to get total price of this item +// int get totalPrice => product.price * quantity; +// } diff --git a/lib/screens/authentication/change_password_screen.dart b/lib/screens/authentication/change_password_screen.dart index 7a534e4..bcc9efd 100644 --- a/lib/screens/authentication/change_password_screen.dart +++ b/lib/screens/authentication/change_password_screen.dart @@ -16,43 +16,47 @@ class ChangePasswordScreen extends StatefulWidget { } class _ChangePasswordScreenState extends State { + // Initialize the AuthController using GetX dependency injection final authController = Get.put(AuthController()); void dispose() { + // Dispose of the text controllers when the screen is closed to free up resources authController.currentpassController.dispose(); authController.newpassController.dispose(); authController.confirmpassController.dispose(); super.dispose(); } + // Function to validate user input and initiate password change void validateAndChangePassword() async { String oldPassword = authController.currentpassController.text.trim(); String newPassword = authController.newpassController.text.trim(); String confirmPassword = authController.confirmpassController.text.trim(); - + // Check if any of the fields are empty if (newPassword.isEmpty || confirmPassword.isEmpty || oldPassword.isEmpty) { showSnackbar('All fields are required'); return; } - + // Check if the new password meets the minimum length requirement if (newPassword.length < 8) { showSnackbar('Password must be at least 8 characters long'); return; } + // Check if the new password contains at least one special character if (!RegExp(r'[!@#$%^&*(),.?":{}|<>]').hasMatch(newPassword)) { showSnackbar('Password must contain at least one special character'); return; } - + // Check if new password and confirm password fields match if (newPassword != confirmPassword) { showSnackbar('New Password and Confirm Password do not match'); return; } - + // Call the changePassword method from AuthController authController.changePassword(); } @@ -107,6 +111,7 @@ class _ChangePasswordScreenState extends State { height: Get.height * 0.7, ), ), + // Main content area with a scrollable card Center( child: SingleChildScrollView( child: Card( @@ -120,7 +125,7 @@ class _ChangePasswordScreenState extends State { padding: const EdgeInsets.all(16.0), child: Column( children: [ - + // Title for the Change Password screen Container( padding: const EdgeInsets.only(bottom: 10), alignment: Alignment.centerLeft, @@ -134,6 +139,7 @@ class _ChangePasswordScreenState extends State { ), ), ), + // Input field for current password InputField( hintText: "Current Password", labelText: "Current Password", @@ -143,6 +149,7 @@ class _ChangePasswordScreenState extends State { ), const SizedBox(height: 15), + // Input field for new password InputField( hintText: "New Password", labelText: "New Password", @@ -151,6 +158,7 @@ class _ChangePasswordScreenState extends State { keyboardType: TextInputType.text, ), const SizedBox(height: 15), + // Input field for confirm password InputField( hintText: "Confirm Password", labelText: "Confirm Password", diff --git a/lib/screens/authentication/controller/auth_controller.dart b/lib/screens/authentication/controller/auth_controller.dart index ab473ab..edae0e2 100644 --- a/lib/screens/authentication/controller/auth_controller.dart +++ b/lib/screens/authentication/controller/auth_controller.dart @@ -9,14 +9,14 @@ import 'package:get/get.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../../../notification_service.dart'; -import '../../../utils/api_client.dart'; + import '../../../utils/api_urls.dart'; import '../../../utils/secure__storage_service.dart'; class AuthController extends GetxController { final authService = AuthService(); - final _apiClient = ApiClient(); + final _storageService = SecureStorageService(); TextEditingController emailController = TextEditingController(); @@ -31,10 +31,13 @@ class AuthController extends GetxController { @override void onInit(){ super.onInit(); + // Request notification permissions on initialization NotificationServices().requestNotificationPermission(); } + // Function to handle user login Future login() async { isLoading.value = true; + // Call the login service with email and password final response = await authService.login({ 'email': emailController.text, 'password': passwordController.text, @@ -98,7 +101,7 @@ class AuthController extends GetxController { // } - + // Function to handle forgotten password Future forgotpass() async{ isLoading.value = true; final response = await authService.forgotPassword( @@ -112,7 +115,7 @@ Future forgotpass() async{ showSnackbar("Email sent successfully"); } } - + // Function to handle password change Future changePassword() async { isLoading.value = true; diff --git a/lib/screens/authentication/controller/auth_service.dart b/lib/screens/authentication/controller/auth_service.dart index 64cc3b8..85c3e43 100644 --- a/lib/screens/authentication/controller/auth_service.dart +++ b/lib/screens/authentication/controller/auth_service.dart @@ -2,12 +2,13 @@ import 'package:cheminova/utils/api_urls.dart'; import 'package:cheminova/utils/common_api_service.dart'; import 'package:cheminova/utils/show_snackbar.dart'; -import '../../../utils/api_client.dart'; class AuthService { + // Function to handle user login Future?> login(Map data) async { try { + // Making a POST request to the login URL using the common API service final response = await commonApiService>( url: ApiUrls.loginUrl, method: 'POST', @@ -20,10 +21,10 @@ class AuthService { } return null; } - - + // Function to handle forgot password functionality // Function to handle password change functionality Future?> forgotPassword(Map data) async { try { + // Making a POST request to the forgot password URL using the common API service final response = await commonApiService>( url: ApiUrls.forgetPasswordUrl, method: 'POST', @@ -38,8 +39,10 @@ class AuthService { } + // Function to handle password change functionality Future?> changePassword(Map data, {required String token}) async { try { + // Making a PUT request to the change password URL using the common API service final response = await commonApiService>( url: ApiUrls.changePasswordUrl, method: 'PUT', diff --git a/lib/screens/authentication/forget_password_screen.dart b/lib/screens/authentication/forget_password_screen.dart index 6c18570..9882fc0 100644 --- a/lib/screens/authentication/forget_password_screen.dart +++ b/lib/screens/authentication/forget_password_screen.dart @@ -15,6 +15,7 @@ class ForgetPasswordScreen extends StatefulWidget { } class _ForgetPasswordScreenState extends State { + // Controllers for handling user input and managing state final userNameController = TextEditingController(); final passwordController = TextEditingController(); final authController = Get.put(AuthController()); @@ -60,6 +61,7 @@ class _ForgetPasswordScreenState extends State { height: Get.height * 0.7, ), ), + // Main content of the screen Center( child: SingleChildScrollView( child: Card( @@ -94,6 +96,7 @@ class _ForgetPasswordScreenState extends State { ), ), ), + // Instructional text for the user Container( padding: const EdgeInsets.only(bottom: 10), alignment: Alignment.centerLeft, @@ -107,6 +110,7 @@ class _ForgetPasswordScreenState extends State { ), ), ), + // Input field for the user to enter their email InputField( hintText: "Email", labelText: "Email", @@ -115,7 +119,7 @@ class _ForgetPasswordScreenState extends State { ), const SizedBox(height: 30), GestureDetector( - onTap: () => Get.back(), + onTap: () => Get.back(), // Navigate back to login screen child: Text( 'Back to Login', style: GoogleFonts.getFont( @@ -129,7 +133,7 @@ class _ForgetPasswordScreenState extends State { ), const SizedBox(height: 30), CustomButton(text: "Send", - + // Trigger forgot password function onPressed: () => authController.forgotpass(), isLoading: authController.isLoading.value, diff --git a/lib/screens/authentication/login_screen.dart b/lib/screens/authentication/login_screen.dart index 546d577..6cd2a78 100644 --- a/lib/screens/authentication/login_screen.dart +++ b/lib/screens/authentication/login_screen.dart @@ -16,9 +16,13 @@ class LoginScreen extends StatefulWidget { } class _LoginScreenState extends State { + // Global key for the form to validate user inputs final formKey = GlobalKey(); + // Controller for handling authentication logic final authController = Get.put(AuthController()); + // Email validation pattern final String emailPattern = r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$'; + // Password validation pattern (at least 6 characters) final String passwordPattern = r'^.{6,}$'; // At least 6 characters @override @@ -43,6 +47,7 @@ class _LoginScreenState extends State { height: Get.height * 0.7, ), ), + // Main content of the login screen wrapped in a scroll view SingleChildScrollView( child: Form( key: formKey, @@ -131,6 +136,7 @@ class _LoginScreenState extends State { ), ), ), + // Email input field with validation CommonTextFormField( controller: authController.emailController, keyboardType: TextInputType.emailAddress, @@ -147,6 +153,7 @@ class _LoginScreenState extends State { label: "Email", ), const SizedBox(height: 15), + // Password input field with validation CommonTextFormField( controller: authController.passwordController, validator: (value) { @@ -164,6 +171,7 @@ class _LoginScreenState extends State { label: "Password", ), const SizedBox(height: 30), + // Navigation to the forgot password screen GestureDetector( onTap: () => Get.to(() => const ForgetPasswordScreen()), diff --git a/lib/screens/authentication/profile_screen.dart b/lib/screens/authentication/profile_screen.dart index 8fc3f70..b9af1ef 100644 --- a/lib/screens/authentication/profile_screen.dart +++ b/lib/screens/authentication/profile_screen.dart @@ -9,11 +9,7 @@ import '../../widgets/comman_background.dart'; import '../../widgets/common_appbar.dart'; class ProfileScreen extends StatefulWidget { - // String? name; - // final String uniqueId; - // final String email; - // final String mobileNumber; - // final String designation; + const ProfileScreen({ Key? key, @@ -25,10 +21,11 @@ class ProfileScreen extends StatefulWidget { } class _ProfileScreenState extends State { - + // Initialize the HomeController using GetX final homecontroller = Get.put(HomeController()); @override Widget build(BuildContext context) { + // Accessing the user details from the HomeController final user = homecontroller!.user; return Stack( children: [ @@ -44,6 +41,7 @@ class _ProfileScreenState extends State { actions: [ IconButton( onPressed: () { + // Navigates back to the previous screen Navigator.pop(context); }, icon: SvgPicture.asset( @@ -53,6 +51,7 @@ class _ProfileScreenState extends State { ), ], ), + // Main content of the profile screen body: SingleChildScrollView( child: Column( children: [ @@ -70,6 +69,7 @@ class _ProfileScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ const SizedBox(height: 20), + // Displaying individual profile items _buildProfileItem('Name', user!.name), _buildProfileItem('ID', user.uniqueId), _buildProfileItem('Email ID', user.email), diff --git a/lib/screens/home_screen.dart b/lib/screens/home_screen.dart index 97d5f73..70ab880 100644 --- a/lib/screens/home_screen.dart +++ b/lib/screens/home_screen.dart @@ -54,7 +54,7 @@ class _HomeScreenState extends State { actions: [ GestureDetector( onTap: () { - // Action for notification icon tap + // Navigate to NotificationScreen when the notification icon is tapped Get.to(() => NotificationScreen()); }, child: Padding( @@ -95,7 +95,7 @@ class _HomeScreenState extends State { HomeCard( title: 'Order Tracking', onTap: () => Get.to( - () => const OrderTrackingScreen(), + () => const OrderTrackingScreen(), ), ), ], @@ -107,13 +107,13 @@ class _HomeScreenState extends State { HomeCard( title: 'Order Management', onTap: () => Get.to( - () => OrderManagementScreen(), + () => OrderManagementScreen(), ), ), HomeCard( title: 'Shipping Management', onTap: () => Get.to( - () => const ShippingManagementScreen(), + () => const ShippingManagementScreen(), ), ), ], @@ -125,13 +125,13 @@ class _HomeScreenState extends State { HomeCard( title: 'Inventory Management', onTap: () => Get.to( - () => const InventoryManagementScreen(), + () => const InventoryManagementScreen(), ), ), HomeCard( title: 'Reporting & Analytics', onTap: () => Get.to( - () => const ReportingAnalyticsScreen(), + () => const ReportingAnalyticsScreen(), ), ), @@ -144,13 +144,13 @@ class _HomeScreenState extends State { HomeCard( title: 'Order Data Export', onTap: () => Get.to( - () => const OrderHistoryReportScreen(), + () => const OrderHistoryReportScreen(), ), ), HomeCard( title: 'Retail Distributors Onboarding', onTap: () => Get.to( - () => const RetailDistributerOnBoardingScreen(), + () => const RetailDistributerOnBoardingScreen(), ), ), ], diff --git a/lib/screens/kyc/kyc_retailer_details_screen.dart b/lib/screens/kyc/kyc_retailer_details_screen.dart index 998aa9d..a5b12d2 100644 --- a/lib/screens/kyc/kyc_retailer_details_screen.dart +++ b/lib/screens/kyc/kyc_retailer_details_screen.dart @@ -1,4 +1,4 @@ -import 'package:cheminova/screens/retail/kyc_verification_screen.dart'; + import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'package:get/get.dart'; @@ -26,47 +26,95 @@ class _KycRetailerDetailScreenState void _approveKyc() { if (widget.kycModel!.status == "approved") { - Get.snackbar("Error", "The KYC has already been approved.", snackPosition: SnackPosition.BOTTOM, backgroundColor: Colors.red, colorText: Colors.white); + Get.snackbar( + "Error", + "The KYC has already been approved.", + snackPosition: SnackPosition.BOTTOM, + backgroundColor: Colors.red, + colorText: Colors.white, + ); } else { - _kycController.updateKycStatus(widget.kycModel!, "approved",""); - Get.snackbar("Success", "KYC approved successfully.", snackPosition: SnackPosition.BOTTOM, backgroundColor: Colors.green, colorText: Colors.white); - Get.back(); // Go back after approval + // Update the status in the model before calling the controller method + widget.kycModel!.status = "approved"; + _kycController.updateKycStatus(widget.kycModel!, "approved", ""); + setState(() { + + }); + + Get.snackbar( + "Success", + "KYC approved successfully.", + snackPosition: SnackPosition.BOTTOM, + backgroundColor: Colors.green, + colorText: Colors.white, + ); + + // Pass the updated model back to the previous screen + Get.back(result: widget.kycModel); } } void _rejectKyc() { if (widget.kycModel!.status == "reject") { - Get.snackbar("Error", "The KYC has already been rejected.", snackPosition: SnackPosition.BOTTOM, backgroundColor: Colors.red, colorText: Colors.white); + Get.snackbar( + "Error", + "The KYC has already been rejected.", + snackPosition: SnackPosition.BOTTOM, + backgroundColor: Colors.red, + colorText: Colors.white, + ); } else { // Show dialog to enter a comment Get.dialog( AlertDialog( - title: Text("Reject KYC"), + title: const Text("Reject KYC"), content: TextField( - controller: commentController, // TextEditingController for comment - decoration: InputDecoration(hintText: "Enter rejection comment"), + controller: commentController, + decoration: const InputDecoration(hintText: "Enter rejection comment"), ), actions: [ TextButton( onPressed: () { Get.back(); // Close dialog without action }, - child: Text("Cancel"), + child: const Text("Cancel"), ), TextButton( onPressed: () { String comment = commentController.text; if (comment.isNotEmpty) { - // Call reject method with comment + // Update the status in the model before calling the controller method + widget.kycModel!.status = "reject"; + + // Append the comment to the notes list + widget.kycModel!.notes ??= []; // Initialize if null + widget.kycModel!.notes!.add(comment); + _kycController.updateKycStatus(widget.kycModel!, "reject", comment); - Get.snackbar("Success", "KYC rejected with comment: $comment", snackPosition: SnackPosition.BOTTOM, backgroundColor: Colors.green, colorText: Colors.white); + setState(() {}); + + Get.snackbar( + "Success", + "KYC rejected with comment: $comment", + snackPosition: SnackPosition.BOTTOM, + backgroundColor: Colors.green, + colorText: Colors.white, + ); + + // Pass the updated model back to the previous screen Get.back(); // Close the dialog - Get.back(); // Go back to the previous screen + Get.back(result: widget.kycModel); // Pass the result back } else { - Get.snackbar("Error", "Comment is required", snackPosition: SnackPosition.BOTTOM, backgroundColor: Colors.red, colorText: Colors.white); + Get.snackbar( + "Error", + "Comment is required", + snackPosition: SnackPosition.BOTTOM, + backgroundColor: Colors.red, + colorText: Colors.white, + ); } }, - child: Text("Reject"), + child: const Text("Reject"), ), ], ), @@ -78,6 +126,8 @@ class _KycRetailerDetailScreenState + + @override Widget build(BuildContext context) { return Scaffold( @@ -270,7 +320,7 @@ class _KycRetailerDetailScreenState child: Padding( padding: const EdgeInsets.all(12), child: Text( - "Comment:", + "Comment:${widget.kycModel!.notes}", style: GoogleFonts.roboto( fontSize: Get.width * 0.04, fontWeight: FontWeight.w700, diff --git a/lib/screens/kyc/kyc_retailer_info_screen.dart b/lib/screens/kyc/kyc_retailer_info_screen.dart index 9d76262..f7e11dc 100644 --- a/lib/screens/kyc/kyc_retailer_info_screen.dart +++ b/lib/screens/kyc/kyc_retailer_info_screen.dart @@ -32,16 +32,19 @@ class _KycRetailerInfoScreenState extends State { @override void initState() { super.initState(); + _kycController.loadKycFromLocalStorage(); getKycData(); } Future _onRefresh() async { - await getKycData(); + // await getKycData(); + //navigateToKycDetail(_kycController.kycList as KycModel); await Future.delayed(Duration(seconds: 1)); } Future getKycData() async { await _kycController.fetchKycData(); + print("kyc successfully"); } @@ -56,6 +59,25 @@ class _KycRetailerInfoScreenState extends State { return formattedDate; } + + + + Future navigateToKycDetail(KycModel kycModel) async { + var result = await Get.to(() => KycRetailerDetailScreen(kycModel: kycModel)); + + if (result != null) { + // Update the list or filter based on the result + KycModel updatedKycModel = result; + setState(() { + // Find and update the KYC in your list + int index = _kycController.kycList.indexWhere((kyc) => kyc.status == updatedKycModel.status); + if (index != -1) { + _kycController.kycList[index] = updatedKycModel; + _kycController.saveKycToLocalStorage(); // Persist updates + } + }); + } + } @override Widget build(BuildContext context) { return Scaffold( @@ -177,11 +199,7 @@ class _KycRetailerInfoScreenState extends State { List filteredOrders = selectedStatus == "All" ? _kycController.kycList - : _kycController.kycList - .where((order) => - order.status == - selectedStatus) - .toList(); + : _kycController.kycList.where((kyc) => kyc.status == selectedStatus).toList(); return ListView.builder( padding: EdgeInsets.zero, @@ -189,6 +207,7 @@ class _KycRetailerInfoScreenState extends State { itemCount: filteredOrders.length, itemBuilder: (context, index) { final order = filteredOrders[index]; + final kyc = _kycController.kycList[index]; return Padding( padding: const EdgeInsets.symmetric( vertical: 8), @@ -302,12 +321,12 @@ class _KycRetailerInfoScreenState extends State { padding: const EdgeInsets.all(8.0), child: ElevatedButton( - onPressed: () => Get.to(() => - KycRetailerDetailScreen( - kycModel: - _kycController - .kycList[ - index])), + onPressed: () => navigateToKycDetail(kyc), // KycRetailerDetailScreen( + // kycModel: + // _kycController + // .kycList[ + // index]) + style: ElevatedButton.styleFrom( foregroundColor: @@ -349,279 +368,3 @@ class _KycRetailerInfoScreenState extends State { ); } } - - - - - - -// import 'package:cheminova/controller/kyc_controller.dart'; -// import 'package:cheminova/models/kyc_model.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/cart_controller.dart'; -// import 'kyc_retailer_details_screen.dart'; -// -// -// class KycRetailerInfoScreen extends StatefulWidget { -// -// KycModel? kycModel; -// KycRetailerInfoScreen({super.key, this.kycModel}); -// -// @override -// State createState() => _KycRetailerInfoScreenState(); -// } -// -// class _KycRetailerInfoScreenState extends State { -// final _searchController = TextEditingController(); -// final List _filterList = ["Order Status", "Date Range"]; -// -// final KycController _kycController = Get.put(KycController()); -// final CartController _cartController = Get.put(CartController()); -// final GlobalKey _refreshIndicatorKey = -// GlobalKey(); -// -// @override -// void initState() { -// super.initState(); -// getKycData(); -// } -// -// Future _onRefresh() async { -// await getKycData(); -// await Future.delayed(Duration(seconds: 1)); -// } -// -// Future getKycData() async { -// await _kycController.fetchKycData(); -// print("kyc successfully"); -// } -// -// 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; -// } -// -// @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("Kyc Management"), -// ), -// 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, -// mainAxisAlignment: MainAxisAlignment.start, -// 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: Chip( -// label: Text( -// _filterList[index], -// style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.w500), -// ), -// ), -// ), -// ), -// ), -// SizedBox( -// height: Get.height * 0.6, -// child: Obx(() { -// // // Use a set to keep track of unique order IDs -// // final Set uniqueOrderIds = {}; -// // final List uniqueOrders = []; -// // -// // for (var order in _kycController.kycList) { -// // if (uniqueOrderIds.add(order.id)) { -// // uniqueOrders.add(order); -// // } -// // } -// -// return ListView.builder( -// padding: EdgeInsets.zero, -// shrinkWrap: true, -// itemCount: _kycController.kycList.length, -// itemBuilder: (context, index) { -// final order = _kycController.kycList[index]; -// 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.id}") -// ], -// ), -// ), -// 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: [ -// -// Text( -// '${capitalizeFirstLetter(order!.tradeName.toString())}', // 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(() => KycRetailerDetailScreen( -// kycModel: _kycController.kycList[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/screens/order/checkout_screen.dart b/lib/screens/order/checkout_screen.dart index 4ecfe8f..b69a5b2 100644 --- a/lib/screens/order/checkout_screen.dart +++ b/lib/screens/order/checkout_screen.dart @@ -114,10 +114,6 @@ class _CheckoutScreenState extends State { }); } - // void _getOrder(){ - // final details = _getPlacedOrderController.getOrder(widget.productModel!.id); - // print("dffgfg,$details"); - // } void _onPlaceOrder() async { try { // Map the cart items (Product) to OrderItem objects diff --git a/lib/screens/order/order_confermation_screen.dart b/lib/screens/order/order_confermation_screen.dart index 538e137..92fa44b 100644 --- a/lib/screens/order/order_confermation_screen.dart +++ b/lib/screens/order/order_confermation_screen.dart @@ -14,9 +14,11 @@ import '../../models/oder_place_model.dart'; import '../../models/product_model1.dart'; class OrderConfermationScreen extends StatefulWidget { - Product? productModel; - PlacedOrderModel? placedOrder; - List? selectedProducts; + Product? productModel; // The selected product model + PlacedOrderModel? placedOrder; // The order details after placement + List? selectedProducts; // List of selected products for the order + + // Constructor to initialize the class with optional parameters OrderConfermationScreen({super.key,this.productModel,this.placedOrder,this.selectedProducts}); @override @@ -25,28 +27,15 @@ class OrderConfermationScreen extends StatefulWidget { } class _OrderConfermationScreenState extends State { - final CartController _cartController = Get.put(CartController()); + final CartController _cartController = Get.put(CartController()); // Instance of CartController + // Instance of OrderPlacedController final OrderPlacedController _placedController = Get.put(OrderPlacedController()); + // Instance of GetPlacedOrderController final GetPlacedOrderController _getPlacedOrderController = Get.put(GetPlacedOrderController()); - // final List _checkoutList = [ - // ProductModel( - // id: "1", - // image: 'assets/images/product.png', - // name: "Product 1", - // category: ProductCategory.food, - // description: 'Product 1 description', - // price: 100.00, - // ), - // ]; - // void _getOrder(){ - // final details = _getPlacedOrderController.getOrder(); - // showSnackbar("Get Placed Order Sucessfully"); - // print("dffgfg,$details"); - // } @override Widget build(BuildContext context) { - final orderItems = _placedController.placedOrder1; + final orderItems = _placedController.placedOrder1; // Fetching the placed order details return Scaffold( extendBodyBehindAppBar: true, appBar: AppBar( @@ -55,7 +44,7 @@ class _OrderConfermationScreenState extends State { leading: Builder( builder: (context) { return GestureDetector( - onTap: () => Scaffold.of(context).openDrawer(), + onTap: () => Scaffold.of(context).openDrawer(), // Open the drawer on tap child: Padding( padding: const EdgeInsets.all(16.0), child: SvgPicture.asset( @@ -67,7 +56,7 @@ class _OrderConfermationScreenState extends State { ), actions: [ GestureDetector( - onTap: () => Get.back(), + onTap: () => Get.back(), // Go back on tap child: Padding( padding: const EdgeInsets.all(8.0), child: SvgPicture.asset( @@ -92,7 +81,7 @@ class _OrderConfermationScreenState extends State { child: Column( children: [ SizedBox( - height: Get.height * 0.02, + height: Get.height * 0.02, // Spacing from the top ), Card( margin: const EdgeInsets.symmetric(horizontal: 18), @@ -208,7 +197,7 @@ class _OrderConfermationScreenState extends State { padding: const EdgeInsets.all(8.0), child: TextField( controller: TextEditingController( - text: widget.placedOrder!.shipTo, + text: widget.placedOrder!.shipTo, // Pre-filling the address ), decoration: InputDecoration( hintText: "Address : ${widget.placedOrder!.shipTo}", diff --git a/lib/screens/order_management/order_management_detail_screen.dart b/lib/screens/order_management/order_management_detail_screen.dart index c1729d7..aa691dd 100644 --- a/lib/screens/order_management/order_management_detail_screen.dart +++ b/lib/screens/order_management/order_management_detail_screen.dart @@ -16,8 +16,10 @@ import '../../models/product_model1.dart'; class OrderManagementDetailScreen extends StatefulWidget { //final Product? productModel; + // PlacedOrderList and PlacedOrderModel are optional parameters passed to this screen PlacedOrderList? placedOrderList; PlacedOrderModel? placedOrderModel; + // Constructor for initializing the screen with placed order details OrderManagementDetailScreen({super.key,this.placedOrderList,this.placedOrderModel}); @override @@ -28,8 +30,10 @@ class OrderManagementDetailScreen extends StatefulWidget { class _OrderManagementDetailScreenState extends State { + // Controllers for managing cart and placed orders final CartController _cartController = Get.put(CartController()); final GetPlacedOrderController _getPlacedOrderController = Get.put(GetPlacedOrderController()); + // Function to format date from the API to a more readable format String formatDate(String apiDate) { DateTime parsedDate = DateTime.parse(apiDate); @@ -38,15 +42,16 @@ class _OrderManagementDetailScreenState 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(); } - + // 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); @@ -54,7 +59,7 @@ Future adduni()async { } final order = uniqueOrders[0]; - // Combine product names into a single string + // Combine product names, categories, and quantities into strings final productNames = order.orderItem .map((item) => (item.name)) .join(', '); @@ -125,6 +130,7 @@ Future adduni()async { child: Column( mainAxisSize: MainAxisSize.min, children: [ + Card( child: Column( children: [ @@ -263,6 +269,7 @@ Future adduni()async { ), ), const SizedBox(height: 8), + // Card for displaying shipping information Card( child: Column( children: [ @@ -301,19 +308,7 @@ Future adduni()async { ), ), ), - // SizedBox( - // width: Get.width, - // child: Padding( - // padding: const EdgeInsets.all(8.0), - // child: Text( - // "Contact: +91 9123456789", - // style: GoogleFonts.roboto( - // fontSize: Get.width * 0.04, - // fontWeight: FontWeight.w400, - // ), - // ), - // ), - // ), + ], ), ), @@ -343,31 +338,7 @@ Future adduni()async { ), ), SizedBox(height: Get.height * 0.04), - // SizedBox( - // width: Get.width * 0.9, - // height: Get.height * 0.06, - // child: ElevatedButton( - // onPressed: () => Get.to( - // () => OrderFullfilmentScreen( - // placedOrderList:widget.placedOrderList , - // ), - // ), - // style: ElevatedButton.styleFrom( - // foregroundColor: Colors.white, - // backgroundColor: const Color(0xFF00784C), - // shape: RoundedRectangleBorder( - // borderRadius: BorderRadius.circular(10), - // ), - // ), - // child: Text( - // "Fulfill Order", - // style: GoogleFonts.roboto( - // fontSize: Get.width * 0.04, - // fontWeight: FontWeight.w600, - // ), - // ), - // ), - // ), + ], ), ), diff --git a/lib/screens/order_management/order_management_screen.dart b/lib/screens/order_management/order_management_screen.dart index 69fb4b3..e4778b3 100644 --- a/lib/screens/order_management/order_management_screen.dart +++ b/lib/screens/order_management/order_management_screen.dart @@ -33,24 +33,24 @@ class _OrderManagementScreenState extends State { @override void initState() { super.initState(); - getOrder1(); + getOrder1(); // Fetch orders when the screen initializes } Future _onRefresh() async { await getOrder1(); await Future.delayed(Duration(seconds: 1)); } - + // Fetches orders from the API Future getOrder1() async { await _getPlacedOrderController.getOrders(); print("Order fetched successfully"); } - + // Capitalizes the first letter of the string String capitalizeFirstLetter(String text) { if (text.isEmpty) return text; return text[0].toUpperCase() + text.substring(1).toLowerCase(); } - + // Formats the date received from the API String formatDate(String apiDate) { DateTime parsedDate = DateTime.parse(apiDate); String formattedDate = DateFormat('dd-MMM-yyyy').format(parsedDate); @@ -146,13 +146,13 @@ class _OrderManagementScreenState extends State { // Use a set to keep track of unique order IDs final Set uniqueOrderIds = {}; final List uniqueOrders = []; - + // Loop through the fetched orders to filter unique orders for (var order in _getPlacedOrderController.placedOrders) { if (uniqueOrderIds.add(order.id)) { uniqueOrders.add(order); } } - + // Displaying unique orders in a ListView return ListView.builder( padding: EdgeInsets.zero, shrinkWrap: true, @@ -240,7 +240,7 @@ class _OrderManagementScreenState extends State { padding: const EdgeInsets.all(8.0), child: ElevatedButton( onPressed: () => Get.to(() => OrderManagementDetailScreen( - placedOrderList: uniqueOrders[index])), + placedOrderList: uniqueOrders[index])), // Navigate to detail screen style: ElevatedButton.styleFrom( foregroundColor: Colors.white, backgroundColor: const Color(0xFF004791), @@ -275,252 +275,3 @@ class _OrderManagementScreenState extends State { } } - - - - - - - - - -// import 'package:cheminova/controller/get_place_order_service.dart'; -// import 'package:cheminova/controller/place_order_controller.dart'; -// import 'package:cheminova/models/place_order_list_model.dart'; -// import 'package:cheminova/screens/order_management/order_management_detail_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 '../../controller/cart_controller.dart'; -// import '../../controller/get_order_placed_controller.dart'; -// import '../../models/product_model1.dart'; -// import '../../models/oder_place_model.dart'; -// import '../../utils/show_snackbar.dart'; // Ensure this import is correct -// -// class OrderManagementScreen extends StatefulWidget { -// final Product? productModel; -// PlacedOrderList? placeOrder; -// OrderManagementScreen({super.key, this.productModel, this.placeOrder}); -// -// @override -// State createState() => _OrderManagementScreenState(); -// } -// -// class _OrderManagementScreenState extends State { -// final _searchController = TextEditingController(); -// final List _filterList = ["Order Status", "Date Range"]; -// -// final GetPlacedOrderController _getPlacedOrderController = Get.put(GetPlacedOrderController()); -// final CartController _cartController = Get.put(CartController()); -// -// @override -// void initState() { -// super.initState(); -// getOrder1(); -// } -// -// Future getOrder1() async { -// await _getPlacedOrderController.getOrders(); -// print("Order fetched successfully"); -// } -// -// 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 hh:mm:ss a').format(parsedDate); -// return formattedDate; -// } -// -// @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("Order Management"), -// ), -// drawer: const 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: Column( -// mainAxisSize: MainAxisSize.min, -// mainAxisAlignment: MainAxisAlignment.start, -// 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: Chip( -// label: Text( -// _filterList[index], -// style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.w500), -// ), -// ), -// ), -// ), -// ), -// SizedBox( -// height: Get.height * 0.6, -// child: Obx(() { -// return ListView.builder( -// padding: EdgeInsets.zero, -// shrinkWrap: true, -// itemCount: _getPlacedOrderController.placedOrders.length, -// itemBuilder: (context, index) { -// final order = _getPlacedOrderController.placedOrders[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.spaceBetween, -// children: [ -// Text("Order ID: ", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.bold)), -// Text("${order.id}") -// ], -// ), -// ), -// Padding( -// padding: const EdgeInsets.fromLTRB(16, 8, 8, 0), -// child: Row( -// mainAxisAlignment: MainAxisAlignment.spaceBetween, -// children: [ -// Text("Product Names: ", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.bold)), -// Expanded( -// child: Text(productNames, -// style: GoogleFonts.roboto( -// fontSize: 14, -// )), -// ), -// ], -// ), -// ), -// Padding( -// padding: const EdgeInsets.fromLTRB(16, 8, 8, 0), -// child: Row( -// mainAxisAlignment: MainAxisAlignment.spaceBetween, -// 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.spaceBetween, -// 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(() => OrderManagementDetailScreen( -// placedOrderList: _getPlacedOrderController.placedOrders[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/screens/product/cart_screen.dart b/lib/screens/product/cart_screen.dart index 26c2b5d..078026b 100644 --- a/lib/screens/product/cart_screen.dart +++ b/lib/screens/product/cart_screen.dart @@ -40,7 +40,7 @@ class _CartScreenState extends State { void _toggleSelectAll(bool? value) { setState(() { _selectAll = value ?? false; - _cartController.selectAllProducts(_selectAll); + _cartController.selectAllProducts(_selectAll); // Select or deselect all products }); } @@ -148,7 +148,7 @@ class _CartScreenState extends State { onChanged: _toggleSelectAll, ), Text( - "Select All", + "Select All", // Label for the select all checkbox style: GoogleFonts.roboto( fontSize: 16, fontWeight: FontWeight.w500, @@ -166,7 +166,7 @@ class _CartScreenState extends State { children: [ Checkbox( value: _cartController.selectedProducts.contains( - _cartController.cartList[index]), + _cartController.cartList[index]), // Checkbox for individual product selection onChanged: (value) { _cartController.toggleProductSelection( _cartController.cartList[index], @@ -244,7 +244,7 @@ class _CartScreenState extends State { height: Get.height * 0.06, child: ElevatedButton( onPressed: () => Get.to(() => CheckoutScreen( - selectedProducts: _cartController.selectedProducts, + selectedProducts: _cartController.selectedProducts, // Pass selected products to checkout )), style: ElevatedButton.styleFrom( foregroundColor: Colors.white, diff --git a/lib/screens/product/pdf_screen.dart b/lib/screens/product/pdf_screen.dart index 09f988b..4db0118 100644 --- a/lib/screens/product/pdf_screen.dart +++ b/lib/screens/product/pdf_screen.dart @@ -3,22 +3,23 @@ import 'package:cheminova/models/product_mannual_model.dart'; import 'package:flutter/material.dart'; import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart'; - +// The ViewPdfScreen widget to display a PDF document class ViewPdfScreen extends StatefulWidget { final ProductManualModel productManualModel; + // Constructor for ViewPdfScreen, requires a ProductManualModel const ViewPdfScreen({super.key, required this.productManualModel}); @override State createState() => _ViewPdfScreenState(); } - +// State class for ViewPdfScreen class _ViewPdfScreenState extends State { @override Widget build(BuildContext context) { return Scaffold( body: SafeArea( child: SfPdfViewer.network( - widget.productManualModel.productManual.url, + widget.productManualModel.productManual.url, // Fetch the PDF URL from the model ), ), ); diff --git a/lib/screens/product/product_catalog_screen.dart b/lib/screens/product/product_catalog_screen.dart index 4f3a217..de25b61 100644 --- a/lib/screens/product/product_catalog_screen.dart +++ b/lib/screens/product/product_catalog_screen.dart @@ -18,14 +18,14 @@ class ProductCatalogScreen extends StatefulWidget { } class _ProductCatalogScreenState extends State { - final ProductService _productService = ProductService(); + final ProductService _productService = ProductService(); // Service for fetching products final ScrollController _scrollController = ScrollController(); - final CartController cartController = Get.put(CartController()); + final CartController cartController = Get.put(CartController()); // Cart controller for managing cart state - List _products = []; // Use ProductModel here + List _products = []; // List to hold fetched products List> _categories = []; - int _currentPage = 1; + int _currentPage = 1; // Current page for pagination bool _isLoading = false; bool _hasMoreData = true; @@ -36,9 +36,10 @@ class _ProductCatalogScreenState extends State { @override void initState() { super.initState(); - _fetchCategories(); - _fetchProducts(); + _fetchCategories(); // Fetch categories on initialization + _fetchProducts(); // Fetch initial products _scrollController.addListener(() { + // Listener to fetch more products when scrolling to the bottom if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent && !_isLoading && @@ -47,25 +48,26 @@ class _ProductCatalogScreenState extends State { } }); } - + // Function to fetch products based on current filters and pagination Future _fetchProducts() async { setState(() { _isLoading = true; }); + // Set the category based on the selected category; use null for 'All' final category = _selectedCategory == 'All' ? null : _selectedCategory; - + // Fetch products from the service final products = await _productService.getProduct( _currentPage, category: category); setState(() { if (products != null) { - _products.addAll(products); // Assuming products is a List + _products.addAll(products); // Add fetched products to the list _hasMoreData = products.isNotEmpty; } _isLoading = false; }); } - + // Function to fetch categories from the service Future _fetchCategories() async { final categories = await _productService.getCategory(); if (categories != null) { @@ -76,7 +78,7 @@ class _ProductCatalogScreenState extends State { }); } } - +// Function to handle category change void _onCategoryChanged(String? newCategory) { if (newCategory != null) { setState(() { @@ -84,34 +86,34 @@ class _ProductCatalogScreenState extends State { _products.clear(); _currentPage = 1; }); - _fetchProducts(); + _fetchProducts(); // Fetch products for the new category } } - + // Function to fetch more products for pagination Future _fetchMoreProducts() async { if (!_isLoading && _hasMoreData) { setState(() { _isLoading = true; _currentPage++; }); - await _fetchProducts(); + await _fetchProducts(); // Fetch more products } } - + // Function to clear all filters void _clearFilters() { setState(() { _selectedCategory = null; _selectedPriceRange = null; _selectedAvailability = null; - _products.clear(); + _products.clear(); // Clear existing products _currentPage = 1; }); - _fetchProducts(); + _fetchProducts(); // Fetch products without filters } @override void dispose() { - _scrollController.dispose(); + _scrollController.dispose(); // Dispose of the scroll controller super.dispose(); } @@ -263,7 +265,7 @@ class _ProductCatalogScreenState extends State { padding: const EdgeInsets.symmetric( vertical: 8), child: ProductCard( - productModel: _products[index], + productModel: _products[index], // Product card for each product // Use ProductModel here ), ); @@ -282,7 +284,7 @@ class _ProductCatalogScreenState extends State { ), ); } - +// Function to build filter dropdowns Widget _buildFilterDropdown(int index) { switch (index) { case 0: diff --git a/lib/screens/product/product_detail_screen.dart b/lib/screens/product/product_detail_screen.dart index 623cd42..290eb96 100644 --- a/lib/screens/product/product_detail_screen.dart +++ b/lib/screens/product/product_detail_screen.dart @@ -23,7 +23,8 @@ class ProductDetailScreen extends StatefulWidget { } class _ProductDetailScreenState extends State { - final CartController _cartController = Get.put(CartController()); + final CartController _cartController = Get.put(CartController());// Initialize CartController + // 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(); @@ -114,6 +115,7 @@ class _ProductDetailScreenState extends State { ), ), ), + // Displaying product name Padding( padding: const EdgeInsets.symmetric(horizontal: 8), child: Row( @@ -131,6 +133,7 @@ class _ProductDetailScreenState extends State { ], ), ), + // Displaying product price Padding( padding: const EdgeInsets.symmetric(horizontal: 8), child: Row( @@ -148,6 +151,7 @@ class _ProductDetailScreenState extends State { ], ), ), + // Displaying product category Padding( padding: const EdgeInsets.symmetric(horizontal: 8), child: Row( @@ -166,6 +170,7 @@ class _ProductDetailScreenState extends State { ), ), const SizedBox(height: 8), + // Displaying product description Padding( padding: const EdgeInsets.symmetric(horizontal: 8), child: Row( @@ -187,13 +192,14 @@ class _ProductDetailScreenState extends State { ), ), SizedBox(height: Get.height * 0.04), + // Add to Cart button SizedBox( width: Get.width * 0.9, height: Get.height * 0.06, child: ElevatedButton( onPressed: () { // Pass the product data to the CartScreen - _cartController.addToCart(widget.productModel!); + _cartController.addToCart(widget.productModel!); // Add product to cart showSnackbar("Product successfully added to your cart"); }, style: ElevatedButton.styleFrom( diff --git a/lib/screens/product/product_mannual.dart b/lib/screens/product/product_mannual.dart index 3d81da9..d9e59c2 100644 --- a/lib/screens/product/product_mannual.dart +++ b/lib/screens/product/product_mannual.dart @@ -14,12 +14,14 @@ class ProductsManualScreen extends StatefulWidget { } class _ProductsManualScreenState extends State { + // Initialize the ProductManualController using GetX for managing state final ProductManualController _productManualController = Get.put(ProductManualController()); @override void initState() { super.initState(); - _productManualController.fetchProductManuals(); // Fetch product manual list from API + // Fetch product manual list from API when the screen initializes + _productManualController.fetchProductManuals(); } @override @@ -83,17 +85,17 @@ class _ProductsManualScreenState extends State { ); } - // Build the card content + // Method to build the main card content with the list of product manuals Widget _buildCardContent() { return Obx(() { if (_productManualController.isLoading.value) { return const CircularProgressIndicator(); // Loading state } - + // Check if the product manual list is empty if (_productManualController.productManualList.isEmpty) { return const Text("No product manuals available"); // Empty state } - + // Display the card with a list of product manual buttons return Card( margin: const EdgeInsets.symmetric(horizontal: 24), shape: RoundedRectangleBorder( @@ -104,7 +106,7 @@ class _ProductsManualScreenState extends State { child: Padding( padding: const EdgeInsets.all(16.0), child: Column( - children: _buildProductButtons(), + children: _buildProductButtons(), // Dynamically build buttons from API data ), ), ); @@ -116,18 +118,18 @@ class _ProductsManualScreenState extends State { return _productManualController.productManualList.map((productManual) { return CustomButton( text: productManual.title ?? "No Title", // Dynamically fetch product name - onPressed: () => _navigateToPdfScreen(productManual), + onPressed: () => _navigateToPdfScreen(productManual), // Navigate to PDF screen on button press ); }).toList(); } - // Method to handle navigation to PDF screen + // Method to handle navigation to the PDF screen with the selected product manual void _navigateToPdfScreen(ProductManualModel productManual) { Navigator.push( context, MaterialPageRoute( builder: (context) => ViewPdfScreen( - productManualModel: productManual, + productManualModel: productManual, // Pass the selected product manual data to the PDF screen ), ), ); diff --git a/lib/utils/api_client.dart b/lib/utils/api_client.dart deleted file mode 100644 index e62166e..0000000 --- a/lib/utils/api_client.dart +++ /dev/null @@ -1,60 +0,0 @@ - -import 'package:cheminova/utils/secure__storage_service.dart'; -import 'package:dio/dio.dart'; -import 'package:pretty_dio_logger/pretty_dio_logger.dart'; - -import 'api_urls.dart'; - - -class ApiClient { - final Dio _dio; - final SecureStorageService _storageService = SecureStorageService(); - - ApiClient({String? baseUrl}) - : _dio = Dio(BaseOptions( - baseUrl: baseUrl ?? ApiUrls.baseUrl, - connectTimeout: const Duration(seconds: 120), - receiveTimeout: const Duration(seconds: 120))) { - _dio.interceptors - .add(LogInterceptor(responseBody: true, requestBody: true)); - _dio.interceptors - .add(InterceptorsWrapper(onRequest: (options, handler) async { - String? token = await _storageService.read(key: 'access_token'); - if (token != null) { - options.headers['Authorization'] = 'Bearer $token'; - } - _dio.interceptors - .add(LogInterceptor(responseBody: true, requestBody: true)); - _dio.interceptors.add(PrettyDioLogger( - requestHeader: true, - requestBody: true, - responseBody: true, - responseHeader: false, - error: true, - compact: true, - maxWidth: 90, - )); - return handler.next(options); - }, onResponse: (response, handler) { - return handler.next(response); - }, onError: (DioException e, handler) { - return handler.next(e); - })); - } - - Future get(String path, {Map? queryParameters}) { - return _dio.get(path, queryParameters: queryParameters); - } - - Future post(String path, {dynamic data}) { - return _dio.post(path, data: data); - } - - Future put(String path, {Map? data}) { - return _dio.put(path, data: data); - } - - Future delete(String path, {Map? data}) { - return _dio.delete(path, data: data); - } -} diff --git a/lib/utils/api_urls.dart b/lib/utils/api_urls.dart index ee535fd..338a6a3 100644 --- a/lib/utils/api_urls.dart +++ b/lib/utils/api_urls.dart @@ -1,18 +1,40 @@ class ApiUrls { // static const String baseUrl = 'https://cheminova-api-2.onrender.com/api/'; + + //============================== Base Url =========================================// static const String baseUrl = 'https://api.cnapp.co.in'; + + //============================== Login =========================================// + static const String loginUrl = '/api/v1/user/login/'; - static const String profileUrl = '/api/v1/user/details'; static const String forgetPasswordUrl = '/api/v1/user/password/forgot'; static const String changePasswordUrl = '/api/v1/user/password/update'; static const String fcmUrl = '/api/v1/user/fcm-token'; + + + //============================== User Details ==============================// + static const String profileUrl = '/api/v1/user/details'; + + + //============================== Product Details ==============================// + static const String getCategoryUrl = '/api/category/getCategories'; - static const String getProductUrl = '/api/category/getCategories'; - static const String getProductManualUrl = '/api/productmanual/getall'; - static const String getKycUrl = '/api/kyc/getAll'; - static const String getNotificationUrl = '/api/get-notification-pd'; + // static const String getProductUrl = '/api/category/getCategories'; + static const String getallProductUrl = '/api/product/getAll/user'; + +//============================== Placed Order Details ==============================// + static const String getPlacedOrderUrl ='/api/get-placed-order-pd'; static const String getSinglePlacedOrderUrl ='/api/get-single-placed-order-pd'; static const String placedOrderUrl ='${baseUrl}/api/order-place'; + //============================== Product Manual ==============================// + static const String getProductManualUrl = '/api/productmanual/getall'; + + + //============================== Notification Details ==============================// + static const String getNotificationUrl = '/api/get-notification-pd'; + +//============================== Kyc Details ==============================// + static const String getKycUrl = '${baseUrl}/api/kyc/getAll'; } diff --git a/lib/utils/common_api_service.dart b/lib/utils/common_api_service.dart index 4e3e923..31ce75f 100644 --- a/lib/utils/common_api_service.dart +++ b/lib/utils/common_api_service.dart @@ -1,20 +1,22 @@ import 'dart:io'; +import 'package:cheminova/utils/api_urls.dart'; import 'package:cheminova/utils/constants.dart'; import 'package:cheminova/utils/show_snackbar.dart'; import 'package:dio/dio.dart'; import 'package:shared_preferences/shared_preferences.dart'; - +// Generic API service function that handles API requests with optional file uploads Future commonApiService({ required String url, required String method, - Map body = const {}, - File? imageFile, + Map body = const {}, // Request body + File? imageFile, // Optional image file for upload bool isformData = true, - Map? additionalHeaders, - required BodyType Function(Map) fromJson, + Map? additionalHeaders, // Additional headers for the request + required BodyType Function(Map) fromJson,// Function to parse the response data }) async { try { + // Initialize Dio for making HTTP requests Dio dio = Dio(); final Response response; @@ -23,22 +25,23 @@ Future commonApiService({ // Fetch the token from SharedPreferences SharedPreferences prefs = await SharedPreferences.getInstance(); String? token = prefs.getString('token'); - +// Setting default headers, including Content-Type and Authorization if token is present Map headers = { 'Content-Type': isformData ? 'multipart/form-data' : 'application/json', }; - + // Adding the token to the headers if available if (token != null) { headers['Authorization'] = 'Bearer $token'; } - + // Adding any additional headers provided in the request if (additionalHeaders != null) { headers.addAll(additionalHeaders); } + // Setting options with the headers Options options = Options(headers: headers); - + // Preparing form data for requests, especially if files are involved FormData formData = FormData.fromMap(body); - + // Adding the image file to the form data if present if (imageFile != null) { String fileName = imageFile.path.split('/').last; formData.files.add(MapEntry( @@ -46,25 +49,26 @@ Future commonApiService({ await MultipartFile.fromFile(imageFile.path, filename: fileName), )); } - + // Handling different HTTP methods based on the provided method parameter if (method == "POST") { - response = await dio.post("$baseUrl$url", + response = await dio.post("${ApiUrls.baseUrl}$url", data: isformData ? formData : body, options: options); } else if (method == "PUT") { - response = await dio.put("$baseUrl$url", + response = await dio.put("${ApiUrls.baseUrl}$url", data: isformData ? formData : body, options: options); } else if (method == "DELETE") { - response = await dio.delete("$baseUrl$url", options: options); + response = await dio.delete("${ApiUrls.baseUrl}$url", options: options); } else if (method == "PATCH") { - response = await dio.patch("$baseUrl$url", + response = await dio.patch("${ApiUrls.baseUrl}$url", data: isformData ? formData : body, options: options); } else { - response = await dio.get("$baseUrl$url", options: options); + // Default to GET method if no specific method is matched + response = await dio.get("${ApiUrls.baseUrl}$url", options: options); } print("response of $url : $response"); - + // Special handling for login endpoint to store token in SharedPreferences if (url == "/api/v1/user/login/" && response.data['token'] != null) { prefs.setString('token', response.data['token']); @@ -73,14 +77,14 @@ Future commonApiService({ // if (url == "/api/territorymanager/my-profile") { // return fromJson(response.data['myData']); // } - + // Returning parsed response data using the fromJson function provided return fromJson(response.data); } on DioException catch (e) { print("dio exception $url ${e.response?.data}}"); print("dio exception details: ${e.message} ${e.response?.statusCode}"); String errorMessage = "An error occurred"; - + // Extracting error message from the response if available if (e.response?.data is Map) { errorMessage = e.response?.data['message'] ?? errorMessage; } else if (e.response?.data is String) { @@ -91,5 +95,6 @@ Future commonApiService({ } catch (e) { print("exception $url $e"); } + // Returning null in case of any exception return null; } diff --git a/lib/utils/constants.dart b/lib/utils/constants.dart index 2f1ac98..98c48ca 100644 --- a/lib/utils/constants.dart +++ b/lib/utils/constants.dart @@ -1,3 +1,3 @@ //String baseUrl = "https://cheminova-api-2.onrender.com"; -String baseUrl = "https://api.cnapp.co.in"; \ No newline at end of file +//String baseUrl = "https://api.cnapp.co.in"; \ No newline at end of file diff --git a/lib/widgets/common_elevated_button.dart b/lib/widgets/common_elevated_button.dart index d8777b0..60ac4e3 100644 --- a/lib/widgets/common_elevated_button.dart +++ b/lib/widgets/common_elevated_button.dart @@ -1,46 +1,46 @@ -import 'package:flutter/material.dart'; - -class CommonElevatedButton extends StatelessWidget { - final String text; - final void Function()? onPressed; - final double? height; - final double? width; - final double? borderRadius; - final Color? backgroundColor; - final bool isLoading; - - const CommonElevatedButton( - {super.key, - required this.text, - this.onPressed, - this.borderRadius, - this.backgroundColor, - this.height, - this.width, - this.isLoading = false}); - - @override - Widget build(BuildContext context) { - return SizedBox( - height: height ?? kToolbarHeight - 25, - width: width ?? 200, - child: ElevatedButton( - onPressed: isLoading ? null : onPressed, - style: ElevatedButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(borderRadius ?? 6)), - backgroundColor: backgroundColor ?? const Color(0xff1E1E1E), - side: const BorderSide(color: Colors.transparent)), - child: Center( - child: isLoading - ? const CircularProgressIndicator( - backgroundColor: Colors.white, - valueColor: AlwaysStoppedAnimation(Colors.black)) - : Text(text, - style: const TextStyle( - fontSize: 15, - color: Colors.white, - fontWeight: FontWeight.w400, - fontFamily: 'Anek'))))); - } -} +// import 'package:flutter/material.dart'; +// +// class CommonElevatedButton extends StatelessWidget { +// final String text; +// final void Function()? onPressed; +// final double? height; +// final double? width; +// final double? borderRadius; +// final Color? backgroundColor; +// final bool isLoading; +// +// const CommonElevatedButton( +// {super.key, +// required this.text, +// this.onPressed, +// this.borderRadius, +// this.backgroundColor, +// this.height, +// this.width, +// this.isLoading = false}); +// +// @override +// Widget build(BuildContext context) { +// return SizedBox( +// height: height ?? kToolbarHeight - 25, +// width: width ?? 200, +// child: ElevatedButton( +// onPressed: isLoading ? null : onPressed, +// style: ElevatedButton.styleFrom( +// shape: RoundedRectangleBorder( +// borderRadius: BorderRadius.circular(borderRadius ?? 6)), +// backgroundColor: backgroundColor ?? const Color(0xff1E1E1E), +// side: const BorderSide(color: Colors.transparent)), +// child: Center( +// child: isLoading +// ? const CircularProgressIndicator( +// backgroundColor: Colors.white, +// valueColor: AlwaysStoppedAnimation(Colors.black)) +// : Text(text, +// style: const TextStyle( +// fontSize: 15, +// color: Colors.white, +// fontWeight: FontWeight.w400, +// fontFamily: 'Anek'))))); +// } +// } diff --git a/lib/widgets/home_card.dart b/lib/widgets/home_card.dart index 7d6ea66..3359993 100644 --- a/lib/widgets/home_card.dart +++ b/lib/widgets/home_card.dart @@ -5,8 +5,8 @@ import 'package:google_fonts/google_fonts.dart'; class HomeCard extends StatelessWidget { final String title; - final VoidCallback onTap; - + final VoidCallback onTap; // Function to execute when the card is tapped + // Constructor to initialize the card with title and onTap action const HomeCard({ super.key, required this.title, @@ -16,7 +16,7 @@ class HomeCard extends StatelessWidget { @override Widget build(BuildContext context) { return GestureDetector( - onTap: onTap, + onTap: onTap, // Handling tap event on the card child: Container( margin: const EdgeInsets.fromLTRB(0, 0, 20, 0), child: ClipRect( diff --git a/lib/widgets/my_drawer.dart b/lib/widgets/my_drawer.dart index 9ad4389..b3e2505 100644 --- a/lib/widgets/my_drawer.dart +++ b/lib/widgets/my_drawer.dart @@ -17,16 +17,17 @@ class MyDrawer extends StatefulWidget { } class _MyDrawerState extends State { - final homecontroller = Get.put(HomeController()); + final homecontroller = Get.put(HomeController()); // Initialize HomeController @override Widget build(BuildContext context) { - final user = homecontroller.user; + final user = homecontroller.user; // Get the current user from HomeController return Drawer( child: ListView( padding: EdgeInsets.zero, children: [ SizedBox( height: 150, + // Drawer header displaying user information child: DrawerHeader( decoration: const BoxDecoration( color: Colors.black87, @@ -53,6 +54,7 @@ class _MyDrawerState extends State { ), ), ), + // Navigation tile for Home ListTile( leading: const Icon(Icons.home), title: const Text('Home'), @@ -60,10 +62,11 @@ class _MyDrawerState extends State { Navigator.pushAndRemoveUntil( context, MaterialPageRoute(builder: (context) => const HomeScreen()), - (route) => false, + (route) => false, // Remove all previous routes ); }, ), + // Navigation tile for Profile ListTile( leading: const Icon(Icons.account_circle), title: const Text('Profile'), @@ -74,6 +77,7 @@ class _MyDrawerState extends State { ); }, ), + // Navigation tile for Change Password ListTile( leading: const Icon(Icons.settings), title: const Text('Change Password'), @@ -84,6 +88,7 @@ class _MyDrawerState extends State { ); }, ), + // Navigation tile for Logout ListTile( leading: const Icon(Icons.exit_to_app), title: const Text('Logout'), @@ -96,7 +101,7 @@ class _MyDrawerState extends State { ); } } - +// Function to display logout confirmation dialog Future logoutBox(BuildContext context) { Size size = MediaQuery.of(context).size; return showDialog( diff --git a/lib/widgets/product_card.dart b/lib/widgets/product_card.dart index 6a58ac5..9de1fda 100644 --- a/lib/widgets/product_card.dart +++ b/lib/widgets/product_card.dart @@ -50,12 +50,13 @@ class _ProductCardState extends State { final CartController _cartController = Get.put(CartController()); bool showQuantity = widget.isInCart || widget.isCheckout || widget.isConfirmation; bool isProductInCart = _cartController.cartList.any((p) => p.id == widget.productModel!.id); - +// Get the current quantity of the product, either from the cart or the default value int currentQuantity = isProductInCart ? _cartController.cartList.firstWhere((p) => p.id == widget.productModel!.id).quantity : widget.productModel!.quantity; return GestureDetector( + // Navigate to the ProductDetailScreen on tap unless the product is in cart or checkout onTap: () => widget.isInCart || widget.isCheckout ? null : Get.to(() => ProductDetailScreen(productModel: widget.productModel)), @@ -84,6 +85,7 @@ class _ProductCardState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ + // Display the product name with the first letter capitalized Text( capitalizeFirstLetter(widget.productModel!.name), style: GoogleFonts.roboto( @@ -91,6 +93,7 @@ class _ProductCardState extends State { fontWeight: FontWeight.w500, ), ), + // Display the category name of the product Text( capitalizeFirstLetter(widget.productModel!.category!.categoryName), style: GoogleFonts.roboto( @@ -98,6 +101,7 @@ class _ProductCardState extends State { fontWeight: FontWeight.w400, ), ), + // Display the price of the product Text( "₹ ${widget.productModel!.price.toString()}", style: GoogleFonts.roboto( @@ -113,6 +117,7 @@ class _ProductCardState extends State { fontWeight: FontWeight.w700, ), ), + // Display quantity adjustment buttons and remove button if the product is in cart if (!widget.isCheckout) widget.isInCart ? Row(