1)All files comments added

This commit is contained in:
saritabirare 2024-09-27 17:17:26 +05:30
parent fadbad07bf
commit 545b43aef5
46 changed files with 676 additions and 1168 deletions

View File

@ -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"
}

1
firebase.json Normal file
View File

@ -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"}}}}}}

View File

@ -3,13 +3,17 @@ import '../models/product_model.dart';
import '../models/product_model1.dart'; import '../models/product_model1.dart';
class CartController extends GetxController { class CartController extends GetxController {
// Observable list to store products added to the cart
var cartList = <Product>[].obs; var cartList = <Product>[].obs;
// Observable variable to track the total count of items in the cart
var cartCount = 0.obs; var cartCount = 0.obs;
var subtotal = 0.0.obs; // Observable variables to calculate price details
var gstTotal = 0.0.obs; var subtotal = 0.0.obs; // The total price of items without tax
var grandTotal = 0.0.obs; 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 = <Product>[].obs; var selectedProducts = <Product>[].obs;
@override @override
@ -18,79 +22,97 @@ class CartController extends GetxController {
// Initialize the cart list or other initializations if needed // Initialize the cart list or other initializations if needed
initializeSelections(); initializeSelections();
} }
// Function to add a product to the cart
void addToCart(Product product) { void addToCart(Product product) {
// Check if the product already exists in the cart
var existingProduct = cartList.firstWhereOrNull((p) => p.id == product.id); var existingProduct = cartList.firstWhereOrNull((p) => p.id == product.id);
if (existingProduct != null) { if (existingProduct != null) {
// If the product exists, increase its quantity
existingProduct.quantity++; existingProduct.quantity++;
} else { } else {
// If it's a new product, add it to the cart
cartList.add(product); cartList.add(product);
} }
// Update the cart count
cartCount.value = cartList.length; cartCount.value = cartList.length;
// Recalculate the total price
updateTotalPrice(); updateTotalPrice();
} }
// Function to update the total price, subtotal, and GST total
void updateTotalPrice() { void updateTotalPrice() {
double subTotal = 0.0; double subTotal = 0.0;
double gstTotalAmount = 0.0; double gstTotalAmount = 0.0;
// Calculate subtotal and GST for selected products only
for (var product in selectedProducts) { for (var product in selectedProducts) {
subTotal += product.price * product.quantity; subTotal += product.price * product.quantity;
gstTotalAmount += (product.price * product.quantity * (product.gst / 100)); gstTotalAmount += (product.price * product.quantity * (product.gst / 100));
} }
// Update observable values
subtotal.value = subTotal; subtotal.value = subTotal;
gstTotal.value = gstTotalAmount; gstTotal.value = gstTotalAmount;
grandTotal.value = subtotal.value + gstTotal.value; grandTotal.value = subtotal.value + gstTotal.value;
} }
// Function to increase the quantity of a product in the cart
void increaseQuantity(Product product) { void increaseQuantity(Product product) {
final index = cartList.indexWhere((item) => item.id == product.id); final index = cartList.indexWhere((item) => item.id == product.id);
if (index != -1) { if (index != -1) {
// Increment the quantity of the product
cartList[index].quantity++; cartList[index].quantity++;
// If the product is selected, update the total price
if (selectedProducts.contains(cartList[index])) { if (selectedProducts.contains(cartList[index])) {
updateTotalPrice(); updateTotalPrice();
} }
} }
} }
// Function to decrease the quantity of a product in the cart
void decreaseQuantity(Product product) { void decreaseQuantity(Product product) {
final index = cartList.indexWhere((item) => item.id == product.id); final index = cartList.indexWhere((item) => item.id == product.id);
if (index != -1 && cartList[index].quantity > 1) { if (index != -1 && cartList[index].quantity > 1) {
// Decrement the quantity of the product
cartList[index].quantity--; cartList[index].quantity--;
// If the product is selected, update the total price
if (selectedProducts.contains(cartList[index])) { if (selectedProducts.contains(cartList[index])) {
updateTotalPrice(); updateTotalPrice();
} }
} }
} }
// Function to remove a product from the cart
void removeFromCart(Product product) { void removeFromCart(Product product) {
// Remove the product from the cart list
cartList.removeWhere((item) => item.id == product.id); cartList.removeWhere((item) => item.id == product.id);
// Remove the product from the selected list if it's there
selectedProducts.remove(product); selectedProducts.remove(product);
// Update the cart count and total price
cartCount.value = cartList.length; cartCount.value = cartList.length;
updateTotalPrice(); updateTotalPrice();
} }
// Function to toggle the selection of a product
void toggleProductSelection(Product product, bool isSelected) { void toggleProductSelection(Product product, bool isSelected) {
if (isSelected) { if (isSelected) {
// Add the product to the selected list if it's not already selected
if (!selectedProducts.contains(product)) { if (!selectedProducts.contains(product)) {
selectedProducts.add(product); selectedProducts.add(product);
} }
} else { } else {
// Remove the product from the selected list
selectedProducts.remove(product); selectedProducts.remove(product);
} }
// Update the total price after selection change
updateTotalPrice(); updateTotalPrice();
} }
// Function to select or deselect all products
void selectAllProducts(bool selectAll) { void selectAllProducts(bool selectAll) {
if (selectAll) { if (selectAll) {
// Select all products in the cart
selectedProducts.assignAll(cartList); selectedProducts.assignAll(cartList);
} else { } else {
// Clear all selections
selectedProducts.clear(); selectedProducts.clear();
} }
// Update the total price after selection change
updateTotalPrice(); updateTotalPrice();
} }
// Function to initialize product selections; selects all by default
void initializeSelections() { void initializeSelections() {
selectAllProducts(true); selectAllProducts(true);
} }

View File

@ -9,12 +9,18 @@ import '../utils/log_service.dart';
import 'get_place_order_service.dart'; import 'get_place_order_service.dart';
class GetPlacedOrderController extends GetxController { class GetPlacedOrderController extends GetxController {
// Service to fetch all placed orders
final GetOrderPlacedService _getOrderPlacedService = GetOrderPlacedService(); final GetOrderPlacedService _getOrderPlacedService = GetOrderPlacedService();
// Controller to manage order placement functionality
final OrderPlacedController _orderPlacedController = Get.put(OrderPlacedController()); final OrderPlacedController _orderPlacedController = Get.put(OrderPlacedController());
// Service to fetch a single placed order
final GetSingleOrderPlacedService _getSingleOrderPlacedService = GetSingleOrderPlacedService(); final GetSingleOrderPlacedService _getSingleOrderPlacedService = GetSingleOrderPlacedService();
var placedOrders = <PlacedOrderList>[].obs;
var products = <Product>[].obs;
// Observable list to store fetched placed orders
var placedOrders = <PlacedOrderList>[].obs;
// Observable list to track products related to placed orders
var products = <Product>[].obs;
// Observable to handle loading state
var isLoading = false.obs; var isLoading = false.obs;
@override @override
@ -22,12 +28,13 @@ class GetPlacedOrderController extends GetxController {
super.onInit(); super.onInit();
getOrders(); // Fetch the orders immediately on initialization getOrders(); // Fetch the orders immediately on initialization
} }
// Function to fetch all placed orders
Future<void> getOrders() async { Future<void> getOrders() async {
// Call the service to fetch placed orders
final fetchedOrders = await _getOrderPlacedService.getPlacedOrders(); final fetchedOrders = await _getOrderPlacedService.getPlacedOrders();
if (fetchedOrders != null && fetchedOrders.isNotEmpty) { if (fetchedOrders != null && fetchedOrders.isNotEmpty) {
// Add fetched orders to the observable list
placedOrders.addAll(fetchedOrders); placedOrders.addAll(fetchedOrders);
//logger.w("Fetched orders: $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<void> searchOrder() async { Future<void> searchOrder() async {
try { try {
isLoading.value = true; 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); final order = await _getSingleOrderPlacedService.getSinglePlacedOrder(placedOrders[0].id);
if (order != null) { if (order != null) {
placedOrders.clear(); // Clear existing orders if needed 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() { void resetPagination() {
// Reset pagination in the service
_getOrderPlacedService.resetPagination(); _getOrderPlacedService.resetPagination();
placedOrders.clear(); // Clear existing data placedOrders.clear(); // Clear existing data
getOrders(); // Fetch fresh data getOrders(); // Fetch fresh orders after resetting
} }
} }

View File

@ -1,4 +1,5 @@
import 'package:cheminova/models/place_order_list_model.dart'; import 'package:cheminova/models/place_order_list_model.dart';
import 'package:cheminova/utils/api_urls.dart';
import '../models/oder_place_model.dart'; import '../models/oder_place_model.dart';
import '../utils/common_api_service.dart'; import '../utils/common_api_service.dart';
import '../utils/show_snackbar.dart'; import '../utils/show_snackbar.dart';
@ -9,24 +10,28 @@ class GetOrderPlacedService {
final List<PlacedOrderList> _allOrders = []; // To store all fetched orders final List<PlacedOrderList> _allOrders = []; // To store all fetched orders
bool _hasMoreOrders = true; // To check if there are more orders to fetch bool _hasMoreOrders = true; // To check if there are more orders to fetch
// Function to fetch placed orders from the server
Future<List<PlacedOrderList>?> getPlacedOrders() async { Future<List<PlacedOrderList>?> getPlacedOrders() async {
try { try {
// Continue fetching as long as there are more orders available
while (_hasMoreOrders) { while (_hasMoreOrders) {
// Construct the API URL with pagination parameters // 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<List<PlacedOrderList>>( final response = await commonApiService<List<PlacedOrderList>>(
method: "GET", method: "GET",
url: url, url: url,
fromJson: (json) { fromJson: (json) {
// Parse the JSON response if it contains the 'plcaedOrders' key
if (json['plcaedOrders'] != null) { if (json['plcaedOrders'] != null) {
// Convert the JSON list to a list of PlacedOrderList objects
final List<PlacedOrderList> orders = (json['plcaedOrders'] as List) final List<PlacedOrderList> orders = (json['plcaedOrders'] as List)
.map((orderJson) => PlacedOrderList.fromJson(orderJson as Map<String, dynamic>)) .map((orderJson) => PlacedOrderList.fromJson(orderJson as Map<String, dynamic>))
.toList(); .toList();
// Check if the fetched orders list is not empty
if (orders.isNotEmpty) { if (orders.isNotEmpty) {
_allOrders.addAll(orders); _allOrders.addAll(orders); // Add the fetched orders to the main list
_currentPage++; _currentPage++; // Increment the page number for the next fetch
// _limit += orders.length; // Adjust limit based on the number of fetched orders // _limit += orders.length; // Adjust limit based on the number of fetched orders
} else { } else {
_hasMoreOrders = false; // Stop fetching if no more orders are returned _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) { if (response == null || response.isEmpty) {
_hasMoreOrders = false; // Stop fetching if the response is empty _hasMoreOrders = false; // Stop fetching if the response is empty
} }
} }
// Return all fetched orders after completing the fetch process
return _allOrders; return _allOrders;
} catch (e) { } catch (e) {
// Show an error message in a snackbar if an exception occurs
showSnackbar(e.toString()); showSnackbar(e.toString());
return null; return null;
} }
} }
// Optional: Reset the pagination and orders when needed // Function to reset the pagination and clear the orders list
void resetPagination() { void resetPagination() {
_currentPage = 1; _currentPage = 1;
//_limit = 100; // Reset the limit to the initial value //_limit = 100; // Reset the limit to the initial value

View File

@ -1,30 +1,35 @@
import 'package:cheminova/models/place_order_list_model.dart'; // Import your model 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/common_api_service.dart';
import '../utils/show_snackbar.dart'; import '../utils/show_snackbar.dart';
class GetSingleOrderPlacedService { class GetSingleOrderPlacedService {
// Function to fetch a single placed order by its ID
Future<PlacedOrderList?> getSinglePlacedOrder(String orderId) async { Future<PlacedOrderList?> getSinglePlacedOrder(String orderId) async {
try { try {
// Construct the API URL for the single placed order // 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<PlacedOrderList>( final response = await commonApiService<PlacedOrderList>(
method: "GET", method: "GET",
url: url, url: url,
fromJson: (json) { fromJson: (json) {
// Check if the JSON response contains the 'singleOrder' key
if (json['singleOrder'] != null) { if (json['singleOrder'] != null) {
// Convert the JSON response to a PlacedOrderList model // Convert the JSON response to a PlacedOrderList model
return PlacedOrderList.fromJson(json['singleOrder'] as Map<String, dynamic>); return PlacedOrderList.fromJson(json['singleOrder'] as Map<String, dynamic>);
} else { } else {
// Throw an exception if the order is not found in the response
throw Exception("Order not found"); // Throw an exception if not found throw Exception("Order not found"); // Throw an exception if not found
} }
}, },
); );
return response; return response; // Return the fetched order if successful
} catch (e) { } catch (e) {
// Show an error message in a snackbar if an exception occurs
showSnackbar(e.toString()); showSnackbar(e.toString());
return null; return null; // Return null to indicate an error occurred
} }
} }
} }

View File

@ -6,46 +6,41 @@ import 'package:shared_preferences/shared_preferences.dart';
import '../notification_service.dart'; import '../notification_service.dart';
class HomeController extends GetxController { class HomeController extends GetxController {
// Instance of HomeService to handle API requests
final HomeService homeService = HomeService(); final HomeService homeService = HomeService();
// Instance of NotificationServices for handling notifications
NotificationServices notificationServices = NotificationServices(); NotificationServices notificationServices = NotificationServices();
UserModel? user; UserModel? user; // Variable to store user details
// var userModel = UserModel(
// id: '',
// uniqueId: '',
// name: '',
// email: '',
// phone: '',
// role: '',
// sbu: '',
// createdAt: '',
// updatedAt: '',
// ).obs; // Observable for UserModel
@override @override
void onInit() { void onInit() {
getUser(); // Called when the controller is initialized
super.onInit(); getUser(); // Fetch user data
notificationServices.requestNotificationPermission(); super.onInit(); // Call parent class's onInit method
notificationServices.requestNotificationPermission(); // Request permission for notifications
notificationServices.getDeviceToken().then((value) { notificationServices.getDeviceToken().then((value) {
// Retrieve the FCM device token
print('Device Token: $value'); 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<void> fcmToken() async { Future<void> fcmToken() async {
// Get SharedPreferences instance
SharedPreferences prefs = await SharedPreferences.getInstance(); SharedPreferences prefs = await SharedPreferences.getInstance();
String? token = prefs.getString('token'); String? token = prefs.getString('token'); // Retrieve the saved user token
final fcmToken = await NotificationServices().getDeviceToken(); final fcmToken = await NotificationServices().getDeviceToken(); // Get the FCM device token
print('fcmToken: $fcmToken'); 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<void> getUser() async { Future<void> getUser() async {
SharedPreferences prefs = await SharedPreferences.getInstance(); SharedPreferences prefs = await SharedPreferences.getInstance();
String? token = prefs.getString('token'); String? token = prefs.getString('token');
// Create an instance of HomeService
HomeService homeService = HomeService(); HomeService homeService = HomeService();
// Fetch user details using the token
user = await homeService.getUser(token: token); user = await homeService.getUser(token: token);
if (user != null) { 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<void> 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<void> 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
// // }
// }
// }
//

View File

@ -4,20 +4,24 @@ import 'package:cheminova/utils/common_api_service.dart';
import 'package:cheminova/utils/show_snackbar.dart'; import 'package:cheminova/utils/show_snackbar.dart';
class HomeService { class HomeService {
// Function to fetch user details from the API
Future<UserModel?> getUser({String? token}) async { Future<UserModel?> getUser({String? token}) async {
try { try {
// Making a GET request to fetch user profile data
final response = await commonApiService<UserModel>( final response = await commonApiService<UserModel>(
method: "GET", method: "GET",
url: ApiUrls.profileUrl, url: ApiUrls.profileUrl,
additionalHeaders: { // Pass the token here additionalHeaders: { // Pass the token here
'Authorization': 'Bearer $token', 'Authorization': 'Bearer $token',
}, },
fromJson: (json) { fromJson: (json) {
// Callback to parse the JSON response into a UserModel
if (json['user'] != null) { if (json['user'] != null) {
// Parse the user data from the API response // 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; return response;
@ -28,21 +32,26 @@ class HomeService {
} }
} }
// Function to send FCM token to the server
Future<Map<String, dynamic>?> fcmToken(Map<String, dynamic> data, Future<Map<String, dynamic>?> fcmToken(Map<String, dynamic> data,
String? token) async { String? token) async {
try { try {
final response = await commonApiService<String>( final response = await commonApiService<String>(
// Making a POST request to send the FCM token
url: ApiUrls.fcmUrl, url: ApiUrls.fcmUrl,
method: 'POST', method: 'POST',
body: data, body: data,
// Body data to be sent in the request
fromJson: (json) => json as String, fromJson: (json) => json as String,
// Just return the string response // Just return the string response
additionalHeaders: { // Pass the token here additionalHeaders: {
// Pass the token here
'Authorization': 'Bearer $token', 'Authorization': 'Bearer $token',
// Bearer token for authenticated requests
}, },
); );
if (response != null) { if (response != null) {
// Since the response is a string, wrap it in a Map to avoid type issues // Since the response is a string, wrap it in a Map to avoid type issues
return { return {

View File

@ -1,9 +1,8 @@
import 'dart:convert'; import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import '../models/kyc_model.dart'; import '../models/kyc_model.dart';
import 'kyc_service.dart'; import 'kyc_service.dart';
@ -11,6 +10,12 @@ class KycController extends GetxController {
var kycList = <KycModel>[].obs; // Using an observable list to store KYC data var kycList = <KycModel>[].obs; // Using an observable list to store KYC data
var isLoading = false.obs; var isLoading = false.obs;
@override
void onInit() {
super.onInit();
loadKycFromLocalStorage(); // Load KYC data from local storage when initialized
}
Future<void> fetchKycData() async { Future<void> fetchKycData() async {
try { try {
SharedPreferences prefs = await SharedPreferences.getInstance(); SharedPreferences prefs = await SharedPreferences.getInstance();
@ -23,6 +28,7 @@ class KycController extends GetxController {
if (data != null && data.isNotEmpty) { if (data != null && data.isNotEmpty) {
// Parse the list of KYC objects // Parse the list of KYC objects
kycList.value = KycModel.fromJsonList(data); // Convert to List<KycModel> kycList.value = KycModel.fromJsonList(data); // Convert to List<KycModel>
saveKycToLocalStorage(); // Save the fetched KYC data to local storage
} else { } else {
print("No KYC data found or API response is empty."); 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 // Update KYC status locally and persist the changes
Future<void> updateKycStatus(KycModel kycModel, String status, String comment) async { Future<void> updateKycStatus(KycModel kycModel, String status, String comment) async {
final index = kycList.indexOf(kycModel); final index = kycList.indexOf(kycModel);
if (index != -1) { if (index != -1) {
kycList[index].status = status; // Update status locally kycList[index].status = status; // Update status locally
saveKycToLocalStorage(); // Persist the changes locally saveKycToLocalStorage(); // Persist the changes locally
update(); // Notify listeners about the change
// Show a success message after updating // Show a success message after updating
Get.snackbar( Get.snackbar(
@ -59,23 +65,19 @@ class KycController extends GetxController {
prefs.setStringList('kycList', kycListJson); // Save the updated list locally prefs.setStringList('kycList', kycListJson); // Save the updated list locally
} }
// Load the KYC list from SharedPreferences // Load KYC data from SharedPreferences
Future<void> loadKycFromLocalStorage() async { Future<void> loadKycFromLocalStorage() async {
SharedPreferences prefs = await SharedPreferences.getInstance(); SharedPreferences prefs = await SharedPreferences.getInstance();
List<String>? storedKycList = prefs.getStringList('kycList'); List<String>? kycListJson = prefs.getStringList('kycList');
if (storedKycList != null) { if (kycListJson != null) {
// If local data is found, update the KYC list with the locally saved data kycList.value = kycListJson.map((jsonStr) => KycModel.fromJson(jsonDecode(jsonStr))).toList();
List<KycModel> localKycList = storedKycList.map((kycJson) => KycModel.fromJson(jsonDecode(kycJson))).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;
}
}
} }
} }
} }

View File

@ -1,21 +1,24 @@
import 'package:cheminova/utils/api_urls.dart';
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
class KycService { class KycService {
// Function to fetch KYC data from the API
Future<List<dynamic>> getKycData(String token) async { Future<List<dynamic>> getKycData(String token) async {
try { try {
// Make a GET request to the KYC API endpoint with authorization token
var response = await Dio().get( 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( options: Options(
headers: { headers: {
'Authorization': 'Bearer $token', 'Authorization': 'Bearer $token',
}, },
), ),
); );
// Check if the response status code indicates success
if (response.statusCode == 200) { if (response.statusCode == 200) {
print("response of /api/kyc/getAll : ${response.data}"); print("response of ApiUrls.getKycUrl: ${response.data}");
return response.data; // Return the data as a List<dynamic> return response.data; // Return the data as a List<dynamic>
} else { } else {
throw Exception("Failed to load KYC data"); 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<List<KycModel>?> 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<List<KycModel>>(
// method: "GET",
// url: url,
// additionalHeaders: {
// 'Authorization': 'Bearer $token', // Add the token in headers
// },
// fromJson: (json)
// {
// if (json != null && json['data'] != null) {
// List<dynamic> 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;
// }
// }

View File

@ -4,10 +4,12 @@ import 'package:cheminova/utils/api_urls.dart';
import '../utils/common_api_service.dart'; import '../utils/common_api_service.dart';
class NotificationApiService { class NotificationApiService {
// Function to fetch notifications from the API
Future<List<NotificationModel>?> getNotification(String token) async { Future<List<NotificationModel>?> getNotification(String token) async {
try { try {
// Set the URL for fetching notifications
String url =ApiUrls.getNotificationUrl; // Base URL to fetch product manuals String url =ApiUrls.getNotificationUrl; // Base URL to fetch product manuals
// Make a GET request to the notification API
final response = await commonApiService<List<NotificationModel>>( final response = await commonApiService<List<NotificationModel>>(
method: "GET", method: "GET",
url: url, url: url,
@ -16,7 +18,7 @@ class NotificationApiService {
}, },
fromJson: (json) { fromJson: (json) {
if (json['notifications'] != null) { 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<NotificationModel> notification = (json['notifications'] as List) final List<NotificationModel> notification = (json['notifications'] as List)
.map((manualJson) => NotificationModel.fromJson(manualJson as Map<String, dynamic>)) .map((manualJson) => NotificationModel.fromJson(manualJson as Map<String, dynamic>))
.toList(); .toList();

View File

@ -9,6 +9,7 @@ import '../models/oder_place_model.dart';
class OrderPlacedController extends GetxController { class OrderPlacedController extends GetxController {
// Observable variable to hold the details of the placed order
var placedOrder1 = PlacedOrderModel( var placedOrder1 = PlacedOrderModel(
paymentMode: 'cheque', paymentMode: 'cheque',
shipTo: '456, Park Street, Kolkata, West Bengal - 700016', shipTo: '456, Park Street, Kolkata, West Bengal - 700016',
@ -23,13 +24,13 @@ class OrderPlacedController extends GetxController {
var isLoading = false.obs; var isLoading = false.obs;
final OrderPlacedService _orderPlacedService = OrderPlacedService(); final OrderPlacedService _orderPlacedService = OrderPlacedService();
// Method to place an order
Future<void> placeOrder() async { Future<void> placeOrder() async {
SharedPreferences prefs = await SharedPreferences.getInstance(); SharedPreferences prefs = await SharedPreferences.getInstance();
String? token = prefs.getString('token'); String? token = prefs.getString('token');
isLoading.value = true; isLoading.value = true;
//try { //try {
// Construct order details // Construct order details from the observable variable
PlacedOrderModel orderDetails = placedOrder1.value; PlacedOrderModel orderDetails = placedOrder1.value;
print("Order Details: $orderDetails"); print("Order Details: $orderDetails");
@ -42,88 +43,4 @@ class OrderPlacedController extends GetxController {
// } finally { // } finally {
// isLoading.value = false; // 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<PlacedOrderModel?> placedOrder1 = Rx<PlacedOrderModel?>(null);
// RxBool isLoading = false.obs;
//
// // Method to place an order with provided details
// Future<void> 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';
// }
// }

View File

@ -2,6 +2,7 @@ import 'dart:convert';
import 'dart:developer'; import 'dart:developer';
import 'package:cheminova/models/product_model.dart'; import 'package:cheminova/models/product_model.dart';
import 'package:cheminova/utils/api_urls.dart';
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import '../models/oder_place_model.dart'; import '../models/oder_place_model.dart';
@ -14,7 +15,7 @@ class OrderPlacedService {
//try { //try {
// logger.w("orderjson ${jsonEncode(orderDetails.toJson())}"); // logger.w("orderjson ${jsonEncode(orderDetails.toJson())}");
final response = await dio.post( 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()), data: jsonEncode(orderDetails.toJson()),
options: Options( options: Options(
headers: { headers: {

View File

@ -4,6 +4,7 @@ import 'package:get/get.dart';
class ProductController extends GetxController { class ProductController extends GetxController {
// Instantiate the product service
final ProductService productService = ProductService(); final ProductService productService = ProductService();
var products = <Product>[].obs; var products = <Product>[].obs;
var categories = <String>[].obs; // Holds the list of categories var categories = <String>[].obs; // Holds the list of categories
@ -14,12 +15,14 @@ class ProductController extends GetxController {
@override @override
void onInit() { void onInit() {
super.onInit(); super.onInit();
// Fetch categories when the controller initializes
getCategory(); getCategory();
// Fetch products when the controller initializes
getUser(); getUser();
} }
// Method to fetch products based on the selected category and current page
Future<void> getUser() async { Future<void> getUser() async {
if (isLoading) return; if (isLoading) return; // Prevent duplicate calls if already loading
isLoading = true; isLoading = true;
try { try {
final category = selectedCategory.value; // Get the selected category final category = selectedCategory.value; // Get the selected category
@ -29,7 +32,7 @@ class ProductController extends GetxController {
); );
if (fetchedProducts != null) { if (fetchedProducts != null) {
// Directly add the fetched products (which are of type List<Product>) to the list // If products were fetched, add them to the observable list
products.addAll(fetchedProducts); products.addAll(fetchedProducts);
print("fetchedProducts ,$fetchedProducts"); print("fetchedProducts ,$fetchedProducts");
} }
@ -40,28 +43,29 @@ class ProductController extends GetxController {
update(); update();
} }
} }
// Method to fetch categories from the product service
Future<void> getCategory() async { Future<void> getCategory() async {
try { try {
final fetchedCategories = await productService.getCategory(); final fetchedCategories = await productService.getCategory();
if (fetchedCategories != null) { if (fetchedCategories != null) {
// If categories were fetched, map them to the observable list
categories.assignAll(fetchedCategories.map((category) => category['categoryName'] as String)); 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) { } catch (e) {
print("Error fetching categories: $e"); print("Error fetching categories: $e");
} }
} }
// Method to set the selected category and fetch products
void setCategory(String category) { void setCategory(String category) {
selectedCategory.value = category == 'All' ? null : category; selectedCategory.value = category == 'All' ? null : category;
_currentPage = 1; _currentPage = 1;
products.clear(); products.clear(); // Clear the existing products
getUser(); getUser(); // Fetch products based on the new category
} }
// Method to load more products when reaching the end of the list
void loadMoreProducts() { void loadMoreProducts() {
_currentPage++; _currentPage++;
getUser(); getUser(); // Fetch products for the next page
} }
} }

View File

@ -6,6 +6,7 @@ import '../models/product_mannual_model.dart';
import '../utils/common_api_service.dart'; // Replace with your actual common API service import import '../utils/common_api_service.dart'; // Replace with your actual common API service import
class ProductMannualService { class ProductMannualService {
// Method to fetch product manuals using an authorization token
Future<List<ProductManualModel>?> getProductManuals(String token) async { Future<List<ProductManualModel>?> getProductManuals(String token) async {
try { try {
String url = ApiUrls.getProductManualUrl; // Base URL to fetch product manuals String url = ApiUrls.getProductManualUrl; // Base URL to fetch product manuals
@ -18,11 +19,11 @@ class ProductMannualService {
}, },
fromJson: (json) { fromJson: (json) {
if (json['productManuals'] != null) { 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<ProductManualModel> productManuals = (json['productManuals'] as List) final List<ProductManualModel> productManuals = (json['productManuals'] as List)
.map((manualJson) => ProductManualModel.fromJson(manualJson as Map<String, dynamic>)) .map((manualJson) => ProductManualModel.fromJson(manualJson as Map<String, dynamic>))
.toList(); .toList();
return productManuals; return productManuals; // Return the list of product manuals
} else { } else {
return []; return [];
} }

View File

@ -5,20 +5,23 @@ import '../utils/common_api_service.dart';
import '../utils/show_snackbar.dart'; import '../utils/show_snackbar.dart';
class ProductService { class ProductService {
// Method to fetch products based on the page number and optional category
Future<List<Product>?> getProduct(int page, {String? category}) async { Future<List<Product>?> getProduct(int page, {String? category}) async {
try { try {
String url; String url;
// Determine the URL based on the presence of a category filter
if (category != null && category.isNotEmpty) { if (category != null && category.isNotEmpty) {
url = "ApiUrls.getProductUrl?page=$page&category=$category"; url = "${ApiUrls.getCategoryUrl}?page=$page&category=$category";
} else { } 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<List<Product>>( final response = await commonApiService<List<Product>>(
method: "GET", method: "GET",
url: url, url: url,
fromJson: (json) { fromJson: (json) {
if (json['products'] != null) { if (json['products'] != null) {
// If the 'products' key exists, map it to a list of Product objects
final List<Product> products = (json['products'] as List) final List<Product> products = (json['products'] as List)
.map((productJson) => Product.fromJson(productJson as Map<String, dynamic>)) .map((productJson) => Product.fromJson(productJson as Map<String, dynamic>))
.toList(); .toList();
@ -36,9 +39,10 @@ class ProductService {
} }
} }
// Method to fetch product categories
Future<List<Map<String, dynamic>>?> getCategory() async { Future<List<Map<String, dynamic>>?> getCategory() async {
try { try {
// Make the API call to fetch categories
final response = await commonApiService<List<Map<String, dynamic>>>( final response = await commonApiService<List<Map<String, dynamic>>>(
method: "GET", method: "GET",
url: ApiUrls.getCategoryUrl, url: ApiUrls.getCategoryUrl,
@ -47,9 +51,9 @@ class ProductService {
final List<Map<String, dynamic>> category = (json['categories'] as List) final List<Map<String, dynamic>> category = (json['categories'] as List)
.map((productJson) => productJson as Map<String, dynamic>) .map((productJson) => productJson as Map<String, dynamic>)
.toList(); .toList();
return category; return category; // Return the list of categories
} else { } else {
return []; return []; // Return an empty list if no categories are found
} }
}, },
); );

75
lib/firebase_options.dart Normal file
View File

@ -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',
);
}

View File

@ -10,13 +10,13 @@ var box;
void main()async{ void main()async{
WidgetsFlutterBinding.ensureInitialized(); 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( await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform, options: DefaultFirebaseOptions.currentPlatform,
); );
await Hive.initFlutter(); await Hive.initFlutter(); // Initialize Hive for Flutter
await Hive.openBox('cartBox'); await Hive.openBox('cartBox');
runApp(const MyApp()); runApp(const MyApp());
} }
@ -26,6 +26,7 @@ class MyApp extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
// Use GetMaterialApp for navigation and state management with GetX
return const GetMaterialApp( return const GetMaterialApp(
debugShowCheckedModeBanner: false, debugShowCheckedModeBanner: false,
home: SplashScreen(), home: SplashScreen(),

View File

@ -1,23 +1,23 @@
class AddedBy { // class AddedBy {
String id; // String id;
String name; // String name;
//
AddedBy({ // AddedBy({
required this.id, // required this.id,
required this.name, // required this.name,
}); // });
//
factory AddedBy.fromJson(Map<String, dynamic> json) => AddedBy( // factory AddedBy.fromJson(Map<String, dynamic> json) => AddedBy(
id: json["_id"], // id: json["_id"],
name: json["name"], // name: json["name"],
); // );
//
Map<String, dynamic> toJson() => { // Map<String, dynamic> toJson() => {
"_id": id, // "_id": id,
"name": name, // "name": name,
}; // };
@override // @override
String toString() { // String toString() {
return 'AddedBy(id: $id, brandName: $AddedBy,)'; // return 'AddedBy(id: $id, brandName: $AddedBy,)';
} // }
} // }

View File

@ -1,27 +1,27 @@
// lib/models/cart_item.dart // // lib/models/cart_item.dart
import 'package:cheminova/models/product_model1.dart'; // import 'package:cheminova/models/product_model1.dart';
//
class CartItem { // class CartItem {
final Product product; // final Product product;
int quantity; // int quantity;
//
CartItem({ // CartItem({
required this.product, // required this.product,
this.quantity = 1, // this.quantity = 1,
}); // });
//
// Method to increase quantity // // Method to increase quantity
void increaseQuantity() { // void increaseQuantity() {
quantity++; // quantity++;
} // }
//
// Method to decrease quantity // // Method to decrease quantity
void decreaseQuantity() { // void decreaseQuantity() {
if (quantity > 1) { // if (quantity > 1) {
quantity--; // quantity--;
} // }
} // }
//
// Method to get total price of this item // // Method to get total price of this item
int get totalPrice => product.price * quantity; // int get totalPrice => product.price * quantity;
} // }

View File

@ -16,43 +16,47 @@ class ChangePasswordScreen extends StatefulWidget {
} }
class _ChangePasswordScreenState extends State<ChangePasswordScreen> { class _ChangePasswordScreenState extends State<ChangePasswordScreen> {
// Initialize the AuthController using GetX dependency injection
final authController = Get.put(AuthController()); final authController = Get.put(AuthController());
void dispose() { void dispose() {
// Dispose of the text controllers when the screen is closed to free up resources
authController.currentpassController.dispose(); authController.currentpassController.dispose();
authController.newpassController.dispose(); authController.newpassController.dispose();
authController.confirmpassController.dispose(); authController.confirmpassController.dispose();
super.dispose(); super.dispose();
} }
// Function to validate user input and initiate password change
void validateAndChangePassword() async { void validateAndChangePassword() async {
String oldPassword = authController.currentpassController.text.trim(); String oldPassword = authController.currentpassController.text.trim();
String newPassword = authController.newpassController.text.trim(); String newPassword = authController.newpassController.text.trim();
String confirmPassword = authController.confirmpassController.text.trim(); String confirmPassword = authController.confirmpassController.text.trim();
// Check if any of the fields are empty
if (newPassword.isEmpty || confirmPassword.isEmpty || oldPassword.isEmpty) { if (newPassword.isEmpty || confirmPassword.isEmpty || oldPassword.isEmpty) {
showSnackbar('All fields are required'); showSnackbar('All fields are required');
return; return;
} }
// Check if the new password meets the minimum length requirement
if (newPassword.length < 8) { if (newPassword.length < 8) {
showSnackbar('Password must be at least 8 characters long'); showSnackbar('Password must be at least 8 characters long');
return; return;
} }
// Check if the new password contains at least one special character
if (!RegExp(r'[!@#$%^&*(),.?":{}|<>]').hasMatch(newPassword)) { if (!RegExp(r'[!@#$%^&*(),.?":{}|<>]').hasMatch(newPassword)) {
showSnackbar('Password must contain at least one special character'); showSnackbar('Password must contain at least one special character');
return; return;
} }
// Check if new password and confirm password fields match
if (newPassword != confirmPassword) { if (newPassword != confirmPassword) {
showSnackbar('New Password and Confirm Password do not match'); showSnackbar('New Password and Confirm Password do not match');
return; return;
} }
// Call the changePassword method from AuthController
authController.changePassword(); authController.changePassword();
} }
@ -107,6 +111,7 @@ class _ChangePasswordScreenState extends State<ChangePasswordScreen> {
height: Get.height * 0.7, height: Get.height * 0.7,
), ),
), ),
// Main content area with a scrollable card
Center( Center(
child: SingleChildScrollView( child: SingleChildScrollView(
child: Card( child: Card(
@ -120,7 +125,7 @@ class _ChangePasswordScreenState extends State<ChangePasswordScreen> {
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),
child: Column( child: Column(
children: [ children: [
// Title for the Change Password screen
Container( Container(
padding: const EdgeInsets.only(bottom: 10), padding: const EdgeInsets.only(bottom: 10),
alignment: Alignment.centerLeft, alignment: Alignment.centerLeft,
@ -134,6 +139,7 @@ class _ChangePasswordScreenState extends State<ChangePasswordScreen> {
), ),
), ),
), ),
// Input field for current password
InputField( InputField(
hintText: "Current Password", hintText: "Current Password",
labelText: "Current Password", labelText: "Current Password",
@ -143,6 +149,7 @@ class _ChangePasswordScreenState extends State<ChangePasswordScreen> {
), ),
const SizedBox(height: 15), const SizedBox(height: 15),
// Input field for new password
InputField( InputField(
hintText: "New Password", hintText: "New Password",
labelText: "New Password", labelText: "New Password",
@ -151,6 +158,7 @@ class _ChangePasswordScreenState extends State<ChangePasswordScreen> {
keyboardType: TextInputType.text, keyboardType: TextInputType.text,
), ),
const SizedBox(height: 15), const SizedBox(height: 15),
// Input field for confirm password
InputField( InputField(
hintText: "Confirm Password", hintText: "Confirm Password",
labelText: "Confirm Password", labelText: "Confirm Password",

View File

@ -9,14 +9,14 @@ import 'package:get/get.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import '../../../notification_service.dart'; import '../../../notification_service.dart';
import '../../../utils/api_client.dart';
import '../../../utils/api_urls.dart'; import '../../../utils/api_urls.dart';
import '../../../utils/secure__storage_service.dart'; import '../../../utils/secure__storage_service.dart';
class AuthController extends GetxController { class AuthController extends GetxController {
final authService = AuthService(); final authService = AuthService();
final _apiClient = ApiClient();
final _storageService = SecureStorageService(); final _storageService = SecureStorageService();
TextEditingController emailController = TextEditingController(); TextEditingController emailController = TextEditingController();
@ -31,10 +31,13 @@ class AuthController extends GetxController {
@override @override
void onInit(){ void onInit(){
super.onInit(); super.onInit();
// Request notification permissions on initialization
NotificationServices().requestNotificationPermission(); NotificationServices().requestNotificationPermission();
} }
// Function to handle user login
Future<void> login() async { Future<void> login() async {
isLoading.value = true; isLoading.value = true;
// Call the login service with email and password
final response = await authService.login({ final response = await authService.login({
'email': emailController.text, 'email': emailController.text,
'password': passwordController.text, 'password': passwordController.text,
@ -98,7 +101,7 @@ class AuthController extends GetxController {
// } // }
// Function to handle forgotten password
Future<void> forgotpass() async{ Future<void> forgotpass() async{
isLoading.value = true; isLoading.value = true;
final response = await authService.forgotPassword( final response = await authService.forgotPassword(
@ -112,7 +115,7 @@ Future<void> forgotpass() async{
showSnackbar("Email sent successfully"); showSnackbar("Email sent successfully");
} }
} }
// Function to handle password change
Future<void> changePassword() async { Future<void> changePassword() async {
isLoading.value = true; isLoading.value = true;

View File

@ -2,12 +2,13 @@ import 'package:cheminova/utils/api_urls.dart';
import 'package:cheminova/utils/common_api_service.dart'; import 'package:cheminova/utils/common_api_service.dart';
import 'package:cheminova/utils/show_snackbar.dart'; import 'package:cheminova/utils/show_snackbar.dart';
import '../../../utils/api_client.dart';
class AuthService { class AuthService {
// Function to handle user login
Future<Map<String, dynamic>?> login(Map<String, dynamic> data) async { Future<Map<String, dynamic>?> login(Map<String, dynamic> data) async {
try { try {
// Making a POST request to the login URL using the common API service
final response = await commonApiService<Map<String, dynamic>>( final response = await commonApiService<Map<String, dynamic>>(
url: ApiUrls.loginUrl, url: ApiUrls.loginUrl,
method: 'POST', method: 'POST',
@ -20,10 +21,10 @@ class AuthService {
} }
return null; return null;
} }
// Function to handle forgot password functionality // Function to handle password change functionality
Future<Map<String, dynamic>?> forgotPassword(Map<String, dynamic> data) async { Future<Map<String, dynamic>?> forgotPassword(Map<String, dynamic> data) async {
try { try {
// Making a POST request to the forgot password URL using the common API service
final response = await commonApiService<Map<String, dynamic>>( final response = await commonApiService<Map<String, dynamic>>(
url: ApiUrls.forgetPasswordUrl, url: ApiUrls.forgetPasswordUrl,
method: 'POST', method: 'POST',
@ -38,8 +39,10 @@ class AuthService {
} }
// Function to handle password change functionality
Future<Map<String, dynamic>?> changePassword(Map<String, dynamic> data, {required String token}) async { Future<Map<String, dynamic>?> changePassword(Map<String, dynamic> data, {required String token}) async {
try { try {
// Making a PUT request to the change password URL using the common API service
final response = await commonApiService<Map<String, dynamic>>( final response = await commonApiService<Map<String, dynamic>>(
url: ApiUrls.changePasswordUrl, url: ApiUrls.changePasswordUrl,
method: 'PUT', method: 'PUT',

View File

@ -15,6 +15,7 @@ class ForgetPasswordScreen extends StatefulWidget {
} }
class _ForgetPasswordScreenState extends State<ForgetPasswordScreen> { class _ForgetPasswordScreenState extends State<ForgetPasswordScreen> {
// Controllers for handling user input and managing state
final userNameController = TextEditingController(); final userNameController = TextEditingController();
final passwordController = TextEditingController(); final passwordController = TextEditingController();
final authController = Get.put(AuthController()); final authController = Get.put(AuthController());
@ -60,6 +61,7 @@ class _ForgetPasswordScreenState extends State<ForgetPasswordScreen> {
height: Get.height * 0.7, height: Get.height * 0.7,
), ),
), ),
// Main content of the screen
Center( Center(
child: SingleChildScrollView( child: SingleChildScrollView(
child: Card( child: Card(
@ -94,6 +96,7 @@ class _ForgetPasswordScreenState extends State<ForgetPasswordScreen> {
), ),
), ),
), ),
// Instructional text for the user
Container( Container(
padding: const EdgeInsets.only(bottom: 10), padding: const EdgeInsets.only(bottom: 10),
alignment: Alignment.centerLeft, alignment: Alignment.centerLeft,
@ -107,6 +110,7 @@ class _ForgetPasswordScreenState extends State<ForgetPasswordScreen> {
), ),
), ),
), ),
// Input field for the user to enter their email
InputField( InputField(
hintText: "Email", hintText: "Email",
labelText: "Email", labelText: "Email",
@ -115,7 +119,7 @@ class _ForgetPasswordScreenState extends State<ForgetPasswordScreen> {
), ),
const SizedBox(height: 30), const SizedBox(height: 30),
GestureDetector( GestureDetector(
onTap: () => Get.back(), onTap: () => Get.back(), // Navigate back to login screen
child: Text( child: Text(
'Back to Login', 'Back to Login',
style: GoogleFonts.getFont( style: GoogleFonts.getFont(
@ -129,7 +133,7 @@ class _ForgetPasswordScreenState extends State<ForgetPasswordScreen> {
), ),
const SizedBox(height: 30), const SizedBox(height: 30),
CustomButton(text: "Send", CustomButton(text: "Send",
// Trigger forgot password function
onPressed: () => authController.forgotpass(), onPressed: () => authController.forgotpass(),
isLoading: authController.isLoading.value, isLoading: authController.isLoading.value,

View File

@ -16,9 +16,13 @@ class LoginScreen extends StatefulWidget {
} }
class _LoginScreenState extends State<LoginScreen> { class _LoginScreenState extends State<LoginScreen> {
// Global key for the form to validate user inputs
final formKey = GlobalKey<FormState>(); final formKey = GlobalKey<FormState>();
// Controller for handling authentication logic
final authController = Get.put(AuthController()); final authController = Get.put(AuthController());
// Email validation pattern
final String emailPattern = r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$'; 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 final String passwordPattern = r'^.{6,}$'; // At least 6 characters
@override @override
@ -43,6 +47,7 @@ class _LoginScreenState extends State<LoginScreen> {
height: Get.height * 0.7, height: Get.height * 0.7,
), ),
), ),
// Main content of the login screen wrapped in a scroll view
SingleChildScrollView( SingleChildScrollView(
child: Form( child: Form(
key: formKey, key: formKey,
@ -131,6 +136,7 @@ class _LoginScreenState extends State<LoginScreen> {
), ),
), ),
), ),
// Email input field with validation
CommonTextFormField( CommonTextFormField(
controller: authController.emailController, controller: authController.emailController,
keyboardType: TextInputType.emailAddress, keyboardType: TextInputType.emailAddress,
@ -147,6 +153,7 @@ class _LoginScreenState extends State<LoginScreen> {
label: "Email", label: "Email",
), ),
const SizedBox(height: 15), const SizedBox(height: 15),
// Password input field with validation
CommonTextFormField( CommonTextFormField(
controller: authController.passwordController, controller: authController.passwordController,
validator: (value) { validator: (value) {
@ -164,6 +171,7 @@ class _LoginScreenState extends State<LoginScreen> {
label: "Password", label: "Password",
), ),
const SizedBox(height: 30), const SizedBox(height: 30),
// Navigation to the forgot password screen
GestureDetector( GestureDetector(
onTap: () => onTap: () =>
Get.to(() => const ForgetPasswordScreen()), Get.to(() => const ForgetPasswordScreen()),

View File

@ -9,11 +9,7 @@ import '../../widgets/comman_background.dart';
import '../../widgets/common_appbar.dart'; import '../../widgets/common_appbar.dart';
class ProfileScreen extends StatefulWidget { class ProfileScreen extends StatefulWidget {
// String? name;
// final String uniqueId;
// final String email;
// final String mobileNumber;
// final String designation;
const ProfileScreen({ const ProfileScreen({
Key? key, Key? key,
@ -25,10 +21,11 @@ class ProfileScreen extends StatefulWidget {
} }
class _ProfileScreenState extends State<ProfileScreen> { class _ProfileScreenState extends State<ProfileScreen> {
// Initialize the HomeController using GetX
final homecontroller = Get.put(HomeController()); final homecontroller = Get.put(HomeController());
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
// Accessing the user details from the HomeController
final user = homecontroller!.user; final user = homecontroller!.user;
return Stack( return Stack(
children: [ children: [
@ -44,6 +41,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
actions: [ actions: [
IconButton( IconButton(
onPressed: () { onPressed: () {
// Navigates back to the previous screen
Navigator.pop(context); Navigator.pop(context);
}, },
icon: SvgPicture.asset( icon: SvgPicture.asset(
@ -53,6 +51,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
), ),
], ],
), ),
// Main content of the profile screen
body: SingleChildScrollView( body: SingleChildScrollView(
child: Column( child: Column(
children: [ children: [
@ -70,6 +69,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
const SizedBox(height: 20), const SizedBox(height: 20),
// Displaying individual profile items
_buildProfileItem('Name', user!.name), _buildProfileItem('Name', user!.name),
_buildProfileItem('ID', user.uniqueId), _buildProfileItem('ID', user.uniqueId),
_buildProfileItem('Email ID', user.email), _buildProfileItem('Email ID', user.email),

View File

@ -54,7 +54,7 @@ class _HomeScreenState extends State<HomeScreen> {
actions: [ actions: [
GestureDetector( GestureDetector(
onTap: () { onTap: () {
// Action for notification icon tap // Navigate to NotificationScreen when the notification icon is tapped
Get.to(() => NotificationScreen()); Get.to(() => NotificationScreen());
}, },
child: Padding( child: Padding(
@ -95,7 +95,7 @@ class _HomeScreenState extends State<HomeScreen> {
HomeCard( HomeCard(
title: 'Order Tracking', title: 'Order Tracking',
onTap: () => Get.to( onTap: () => Get.to(
() => const OrderTrackingScreen(), () => const OrderTrackingScreen(),
), ),
), ),
], ],
@ -107,13 +107,13 @@ class _HomeScreenState extends State<HomeScreen> {
HomeCard( HomeCard(
title: 'Order Management', title: 'Order Management',
onTap: () => Get.to( onTap: () => Get.to(
() => OrderManagementScreen(), () => OrderManagementScreen(),
), ),
), ),
HomeCard( HomeCard(
title: 'Shipping Management', title: 'Shipping Management',
onTap: () => Get.to( onTap: () => Get.to(
() => const ShippingManagementScreen(), () => const ShippingManagementScreen(),
), ),
), ),
], ],
@ -125,13 +125,13 @@ class _HomeScreenState extends State<HomeScreen> {
HomeCard( HomeCard(
title: 'Inventory Management', title: 'Inventory Management',
onTap: () => Get.to( onTap: () => Get.to(
() => const InventoryManagementScreen(), () => const InventoryManagementScreen(),
), ),
), ),
HomeCard( HomeCard(
title: 'Reporting & Analytics', title: 'Reporting & Analytics',
onTap: () => Get.to( onTap: () => Get.to(
() => const ReportingAnalyticsScreen(), () => const ReportingAnalyticsScreen(),
), ),
), ),
@ -144,13 +144,13 @@ class _HomeScreenState extends State<HomeScreen> {
HomeCard( HomeCard(
title: 'Order Data Export', title: 'Order Data Export',
onTap: () => Get.to( onTap: () => Get.to(
() => const OrderHistoryReportScreen(), () => const OrderHistoryReportScreen(),
), ),
), ),
HomeCard( HomeCard(
title: 'Retail Distributors Onboarding', title: 'Retail Distributors Onboarding',
onTap: () => Get.to( onTap: () => Get.to(
() => const RetailDistributerOnBoardingScreen(), () => const RetailDistributerOnBoardingScreen(),
), ),
), ),
], ],

View File

@ -1,4 +1,4 @@
import 'package:cheminova/screens/retail/kyc_verification_screen.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
@ -26,47 +26,95 @@ class _KycRetailerDetailScreenState
void _approveKyc() { void _approveKyc() {
if (widget.kycModel!.status == "approved") { 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 { } else {
_kycController.updateKycStatus(widget.kycModel!, "approved",""); // Update the status in the model before calling the controller method
Get.snackbar("Success", "KYC approved successfully.", snackPosition: SnackPosition.BOTTOM, backgroundColor: Colors.green, colorText: Colors.white); widget.kycModel!.status = "approved";
Get.back(); // Go back after approval _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() { void _rejectKyc() {
if (widget.kycModel!.status == "reject") { 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 { } else {
// Show dialog to enter a comment // Show dialog to enter a comment
Get.dialog( Get.dialog(
AlertDialog( AlertDialog(
title: Text("Reject KYC"), title: const Text("Reject KYC"),
content: TextField( content: TextField(
controller: commentController, // TextEditingController for comment controller: commentController,
decoration: InputDecoration(hintText: "Enter rejection comment"), decoration: const InputDecoration(hintText: "Enter rejection comment"),
), ),
actions: [ actions: [
TextButton( TextButton(
onPressed: () { onPressed: () {
Get.back(); // Close dialog without action Get.back(); // Close dialog without action
}, },
child: Text("Cancel"), child: const Text("Cancel"),
), ),
TextButton( TextButton(
onPressed: () { onPressed: () {
String comment = commentController.text; String comment = commentController.text;
if (comment.isNotEmpty) { 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); _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(); // Close the dialog
Get.back(); // Go back to the previous screen Get.back(result: widget.kycModel); // Pass the result back
} else { } 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 @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
@ -270,7 +320,7 @@ class _KycRetailerDetailScreenState
child: Padding( child: Padding(
padding: const EdgeInsets.all(12), padding: const EdgeInsets.all(12),
child: Text( child: Text(
"Comment:", "Comment:${widget.kycModel!.notes}",
style: GoogleFonts.roboto( style: GoogleFonts.roboto(
fontSize: Get.width * 0.04, fontSize: Get.width * 0.04,
fontWeight: FontWeight.w700, fontWeight: FontWeight.w700,

View File

@ -32,16 +32,19 @@ class _KycRetailerInfoScreenState extends State<KycRetailerInfoScreen> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_kycController.loadKycFromLocalStorage();
getKycData(); getKycData();
} }
Future<void> _onRefresh() async { Future<void> _onRefresh() async {
await getKycData(); // await getKycData();
//navigateToKycDetail(_kycController.kycList as KycModel);
await Future.delayed(Duration(seconds: 1)); await Future.delayed(Duration(seconds: 1));
} }
Future<void> getKycData() async { Future<void> getKycData() async {
await _kycController.fetchKycData(); await _kycController.fetchKycData();
print("kyc successfully"); print("kyc successfully");
} }
@ -56,6 +59,25 @@ class _KycRetailerInfoScreenState extends State<KycRetailerInfoScreen> {
return formattedDate; return formattedDate;
} }
Future<void> 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 @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
@ -177,11 +199,7 @@ class _KycRetailerInfoScreenState extends State<KycRetailerInfoScreen> {
List<KycModel> filteredOrders = List<KycModel> filteredOrders =
selectedStatus == "All" selectedStatus == "All"
? _kycController.kycList ? _kycController.kycList
: _kycController.kycList : _kycController.kycList.where((kyc) => kyc.status == selectedStatus).toList();
.where((order) =>
order.status ==
selectedStatus)
.toList();
return ListView.builder( return ListView.builder(
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
@ -189,6 +207,7 @@ class _KycRetailerInfoScreenState extends State<KycRetailerInfoScreen> {
itemCount: filteredOrders.length, itemCount: filteredOrders.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
final order = filteredOrders[index]; final order = filteredOrders[index];
final kyc = _kycController.kycList[index];
return Padding( return Padding(
padding: const EdgeInsets.symmetric( padding: const EdgeInsets.symmetric(
vertical: 8), vertical: 8),
@ -302,12 +321,12 @@ class _KycRetailerInfoScreenState extends State<KycRetailerInfoScreen> {
padding: padding:
const EdgeInsets.all(8.0), const EdgeInsets.all(8.0),
child: ElevatedButton( child: ElevatedButton(
onPressed: () => Get.to(() => onPressed: () => navigateToKycDetail(kyc), // KycRetailerDetailScreen(
KycRetailerDetailScreen( // kycModel:
kycModel: // _kycController
_kycController // .kycList[
.kycList[ // index])
index])),
style: style:
ElevatedButton.styleFrom( ElevatedButton.styleFrom(
foregroundColor: foregroundColor:
@ -349,279 +368,3 @@ class _KycRetailerInfoScreenState extends State<KycRetailerInfoScreen> {
); );
} }
} }
// 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<KycRetailerInfoScreen> createState() => _KycRetailerInfoScreenState();
// }
//
// class _KycRetailerInfoScreenState extends State<KycRetailerInfoScreen> {
// final _searchController = TextEditingController();
// final List<String> _filterList = ["Order Status", "Date Range"];
//
// final KycController _kycController = Get.put(KycController());
// final CartController _cartController = Get.put(CartController());
// final GlobalKey<RefreshIndicatorState> _refreshIndicatorKey =
// GlobalKey<RefreshIndicatorState>();
//
// @override
// void initState() {
// super.initState();
// getKycData();
// }
//
// Future<void> _onRefresh() async {
// await getKycData();
// await Future.delayed(Duration(seconds: 1));
// }
//
// Future<void> 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<String> uniqueOrderIds = {};
// // final List<PlacedOrderList> 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)),
// ),
// ),
// )
// ],
// ),
// ),
// );
// },
// );
// }),
// )
// ],
// ),
// ),
// ),
// ],
// ),
// ),
// ),
// ),
// ),
// ],
// ),
// );
// }
// }
//

View File

@ -114,10 +114,6 @@ class _CheckoutScreenState extends State<CheckoutScreen> {
}); });
} }
// void _getOrder(){
// final details = _getPlacedOrderController.getOrder(widget.productModel!.id);
// print("dffgfg,$details");
// }
void _onPlaceOrder() async { void _onPlaceOrder() async {
try { try {
// Map the cart items (Product) to OrderItem objects // Map the cart items (Product) to OrderItem objects

View File

@ -14,9 +14,11 @@ import '../../models/oder_place_model.dart';
import '../../models/product_model1.dart'; import '../../models/product_model1.dart';
class OrderConfermationScreen extends StatefulWidget { class OrderConfermationScreen extends StatefulWidget {
Product? productModel; Product? productModel; // The selected product model
PlacedOrderModel? placedOrder; PlacedOrderModel? placedOrder; // The order details after placement
List<Product>? selectedProducts; List<Product>? 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}); OrderConfermationScreen({super.key,this.productModel,this.placedOrder,this.selectedProducts});
@override @override
@ -25,28 +27,15 @@ class OrderConfermationScreen extends StatefulWidget {
} }
class _OrderConfermationScreenState extends State<OrderConfermationScreen> { class _OrderConfermationScreenState extends State<OrderConfermationScreen> {
final CartController _cartController = Get.put(CartController()); final CartController _cartController = Get.put(CartController()); // Instance of CartController
// Instance of OrderPlacedController
final OrderPlacedController _placedController = Get.put(OrderPlacedController()); final OrderPlacedController _placedController = Get.put(OrderPlacedController());
// Instance of GetPlacedOrderController
final GetPlacedOrderController _getPlacedOrderController = Get.put(GetPlacedOrderController()); final GetPlacedOrderController _getPlacedOrderController = Get.put(GetPlacedOrderController());
// final List<ProductModel> _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 @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final orderItems = _placedController.placedOrder1; final orderItems = _placedController.placedOrder1; // Fetching the placed order details
return Scaffold( return Scaffold(
extendBodyBehindAppBar: true, extendBodyBehindAppBar: true,
appBar: AppBar( appBar: AppBar(
@ -55,7 +44,7 @@ class _OrderConfermationScreenState extends State<OrderConfermationScreen> {
leading: Builder( leading: Builder(
builder: (context) { builder: (context) {
return GestureDetector( return GestureDetector(
onTap: () => Scaffold.of(context).openDrawer(), onTap: () => Scaffold.of(context).openDrawer(), // Open the drawer on tap
child: Padding( child: Padding(
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),
child: SvgPicture.asset( child: SvgPicture.asset(
@ -67,7 +56,7 @@ class _OrderConfermationScreenState extends State<OrderConfermationScreen> {
), ),
actions: [ actions: [
GestureDetector( GestureDetector(
onTap: () => Get.back(), onTap: () => Get.back(), // Go back on tap
child: Padding( child: Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: SvgPicture.asset( child: SvgPicture.asset(
@ -92,7 +81,7 @@ class _OrderConfermationScreenState extends State<OrderConfermationScreen> {
child: Column( child: Column(
children: [ children: [
SizedBox( SizedBox(
height: Get.height * 0.02, height: Get.height * 0.02, // Spacing from the top
), ),
Card( Card(
margin: const EdgeInsets.symmetric(horizontal: 18), margin: const EdgeInsets.symmetric(horizontal: 18),
@ -208,7 +197,7 @@ class _OrderConfermationScreenState extends State<OrderConfermationScreen> {
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: TextField( child: TextField(
controller: TextEditingController( controller: TextEditingController(
text: widget.placedOrder!.shipTo, text: widget.placedOrder!.shipTo, // Pre-filling the address
), ),
decoration: InputDecoration( decoration: InputDecoration(
hintText: "Address : ${widget.placedOrder!.shipTo}", hintText: "Address : ${widget.placedOrder!.shipTo}",

View File

@ -16,8 +16,10 @@ import '../../models/product_model1.dart';
class OrderManagementDetailScreen extends StatefulWidget { class OrderManagementDetailScreen extends StatefulWidget {
//final Product? productModel; //final Product? productModel;
// PlacedOrderList and PlacedOrderModel are optional parameters passed to this screen
PlacedOrderList? placedOrderList; PlacedOrderList? placedOrderList;
PlacedOrderModel? placedOrderModel; PlacedOrderModel? placedOrderModel;
// Constructor for initializing the screen with placed order details
OrderManagementDetailScreen({super.key,this.placedOrderList,this.placedOrderModel}); OrderManagementDetailScreen({super.key,this.placedOrderList,this.placedOrderModel});
@override @override
@ -28,8 +30,10 @@ class OrderManagementDetailScreen extends StatefulWidget {
class _OrderManagementDetailScreenState class _OrderManagementDetailScreenState
extends State<OrderManagementDetailScreen> { extends State<OrderManagementDetailScreen> {
// Controllers for managing cart and placed orders
final CartController _cartController = Get.put(CartController()); final CartController _cartController = Get.put(CartController());
final GetPlacedOrderController _getPlacedOrderController = Get.put(GetPlacedOrderController()); final GetPlacedOrderController _getPlacedOrderController = Get.put(GetPlacedOrderController());
// Function to format date from the API to a more readable format
String formatDate(String apiDate) { String formatDate(String apiDate) {
DateTime parsedDate = DateTime.parse(apiDate); DateTime parsedDate = DateTime.parse(apiDate);
@ -38,15 +42,16 @@ class _OrderManagementDetailScreenState
return formattedDate; return formattedDate;
} }
// Function to capitalize the first letter of a string
String capitalizeFirstLetter(String text) { String capitalizeFirstLetter(String text) {
if (text.isEmpty) return text; if (text.isEmpty) return text;
return text[0].toUpperCase() + text.substring(1).toLowerCase(); return text[0].toUpperCase() + text.substring(1).toLowerCase();
} }
// Function to collect unique order IDs and corresponding order details
Future<void> adduni()async { Future<void> adduni()async {
final Set<String> uniqueOrderIds = {}; final Set<String> uniqueOrderIds = {};
final List<PlacedOrderList> uniqueOrders = []; final List<PlacedOrderList> uniqueOrders = [];
// Loop through placed orders and add unique orders to the list
for (var order in _getPlacedOrderController.placedOrders) { for (var order in _getPlacedOrderController.placedOrders) {
if (uniqueOrderIds.add(order.uniqueId)) { if (uniqueOrderIds.add(order.uniqueId)) {
uniqueOrders.add(order); uniqueOrders.add(order);
@ -54,7 +59,7 @@ Future<void> adduni()async {
} }
final order = uniqueOrders[0]; final order = uniqueOrders[0];
// Combine product names into a single string // Combine product names, categories, and quantities into strings
final productNames = order.orderItem final productNames = order.orderItem
.map((item) => (item.name)) .map((item) => (item.name))
.join(', '); .join(', ');
@ -125,6 +130,7 @@ Future<void> adduni()async {
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Card( Card(
child: Column( child: Column(
children: [ children: [
@ -263,6 +269,7 @@ Future<void> adduni()async {
), ),
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
// Card for displaying shipping information
Card( Card(
child: Column( child: Column(
children: [ children: [
@ -301,19 +308,7 @@ Future<void> 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<void> adduni()async {
), ),
), ),
SizedBox(height: Get.height * 0.04), 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,
// ),
// ),
// ),
// ),
], ],
), ),
), ),

View File

@ -33,24 +33,24 @@ class _OrderManagementScreenState extends State<OrderManagementScreen> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
getOrder1(); getOrder1(); // Fetch orders when the screen initializes
} }
Future<void> _onRefresh() async { Future<void> _onRefresh() async {
await getOrder1(); await getOrder1();
await Future.delayed(Duration(seconds: 1)); await Future.delayed(Duration(seconds: 1));
} }
// Fetches orders from the API
Future<void> getOrder1() async { Future<void> getOrder1() async {
await _getPlacedOrderController.getOrders(); await _getPlacedOrderController.getOrders();
print("Order fetched successfully"); print("Order fetched successfully");
} }
// Capitalizes the first letter of the string
String capitalizeFirstLetter(String text) { String capitalizeFirstLetter(String text) {
if (text.isEmpty) return text; if (text.isEmpty) return text;
return text[0].toUpperCase() + text.substring(1).toLowerCase(); return text[0].toUpperCase() + text.substring(1).toLowerCase();
} }
// Formats the date received from the API
String formatDate(String apiDate) { String formatDate(String apiDate) {
DateTime parsedDate = DateTime.parse(apiDate); DateTime parsedDate = DateTime.parse(apiDate);
String formattedDate = DateFormat('dd-MMM-yyyy').format(parsedDate); String formattedDate = DateFormat('dd-MMM-yyyy').format(parsedDate);
@ -146,13 +146,13 @@ class _OrderManagementScreenState extends State<OrderManagementScreen> {
// Use a set to keep track of unique order IDs // Use a set to keep track of unique order IDs
final Set<String> uniqueOrderIds = {}; final Set<String> uniqueOrderIds = {};
final List<PlacedOrderList> uniqueOrders = []; final List<PlacedOrderList> uniqueOrders = [];
// Loop through the fetched orders to filter unique orders
for (var order in _getPlacedOrderController.placedOrders) { for (var order in _getPlacedOrderController.placedOrders) {
if (uniqueOrderIds.add(order.id)) { if (uniqueOrderIds.add(order.id)) {
uniqueOrders.add(order); uniqueOrders.add(order);
} }
} }
// Displaying unique orders in a ListView
return ListView.builder( return ListView.builder(
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
shrinkWrap: true, shrinkWrap: true,
@ -240,7 +240,7 @@ class _OrderManagementScreenState extends State<OrderManagementScreen> {
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: ElevatedButton( child: ElevatedButton(
onPressed: () => Get.to(() => OrderManagementDetailScreen( onPressed: () => Get.to(() => OrderManagementDetailScreen(
placedOrderList: uniqueOrders[index])), placedOrderList: uniqueOrders[index])), // Navigate to detail screen
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
foregroundColor: Colors.white, foregroundColor: Colors.white,
backgroundColor: const Color(0xFF004791), backgroundColor: const Color(0xFF004791),
@ -275,252 +275,3 @@ class _OrderManagementScreenState extends State<OrderManagementScreen> {
} }
} }
// 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<OrderManagementScreen> createState() => _OrderManagementScreenState();
// }
//
// class _OrderManagementScreenState extends State<OrderManagementScreen> {
// final _searchController = TextEditingController();
// final List<String> _filterList = ["Order Status", "Date Range"];
//
// final GetPlacedOrderController _getPlacedOrderController = Get.put(GetPlacedOrderController());
// final CartController _cartController = Get.put(CartController());
//
// @override
// void initState() {
// super.initState();
// getOrder1();
// }
//
// Future<void> 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)),
// ),
// ),
// )
// ],
// ),
// ),
// );
// },
// );
// }),
// )
// ],
// ),
// ),
// ),
// ],
// ),
// ),
// ),
// ),
// ],
// ),
// );
// }
// }
//

View File

@ -40,7 +40,7 @@ class _CartScreenState extends State<CartScreen> {
void _toggleSelectAll(bool? value) { void _toggleSelectAll(bool? value) {
setState(() { setState(() {
_selectAll = value ?? false; _selectAll = value ?? false;
_cartController.selectAllProducts(_selectAll); _cartController.selectAllProducts(_selectAll); // Select or deselect all products
}); });
} }
@ -148,7 +148,7 @@ class _CartScreenState extends State<CartScreen> {
onChanged: _toggleSelectAll, onChanged: _toggleSelectAll,
), ),
Text( Text(
"Select All", "Select All", // Label for the select all checkbox
style: GoogleFonts.roboto( style: GoogleFonts.roboto(
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
@ -166,7 +166,7 @@ class _CartScreenState extends State<CartScreen> {
children: [ children: [
Checkbox( Checkbox(
value: _cartController.selectedProducts.contains( value: _cartController.selectedProducts.contains(
_cartController.cartList[index]), _cartController.cartList[index]), // Checkbox for individual product selection
onChanged: (value) { onChanged: (value) {
_cartController.toggleProductSelection( _cartController.toggleProductSelection(
_cartController.cartList[index], _cartController.cartList[index],
@ -244,7 +244,7 @@ class _CartScreenState extends State<CartScreen> {
height: Get.height * 0.06, height: Get.height * 0.06,
child: ElevatedButton( child: ElevatedButton(
onPressed: () => Get.to(() => CheckoutScreen( onPressed: () => Get.to(() => CheckoutScreen(
selectedProducts: _cartController.selectedProducts, selectedProducts: _cartController.selectedProducts, // Pass selected products to checkout
)), )),
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
foregroundColor: Colors.white, foregroundColor: Colors.white,

View File

@ -3,22 +3,23 @@ import 'package:cheminova/models/product_mannual_model.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart'; import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart';
// The ViewPdfScreen widget to display a PDF document
class ViewPdfScreen extends StatefulWidget { class ViewPdfScreen extends StatefulWidget {
final ProductManualModel productManualModel; final ProductManualModel productManualModel;
// Constructor for ViewPdfScreen, requires a ProductManualModel
const ViewPdfScreen({super.key, required this.productManualModel}); const ViewPdfScreen({super.key, required this.productManualModel});
@override @override
State<ViewPdfScreen> createState() => _ViewPdfScreenState(); State<ViewPdfScreen> createState() => _ViewPdfScreenState();
} }
// State class for ViewPdfScreen
class _ViewPdfScreenState extends State<ViewPdfScreen> { class _ViewPdfScreenState extends State<ViewPdfScreen> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
body: SafeArea( body: SafeArea(
child: SfPdfViewer.network( child: SfPdfViewer.network(
widget.productManualModel.productManual.url, widget.productManualModel.productManual.url, // Fetch the PDF URL from the model
), ),
), ),
); );

View File

@ -18,14 +18,14 @@ class ProductCatalogScreen extends StatefulWidget {
} }
class _ProductCatalogScreenState extends State<ProductCatalogScreen> { class _ProductCatalogScreenState extends State<ProductCatalogScreen> {
final ProductService _productService = ProductService(); final ProductService _productService = ProductService(); // Service for fetching products
final ScrollController _scrollController = ScrollController(); final ScrollController _scrollController = ScrollController();
final CartController cartController = Get.put(CartController()); final CartController cartController = Get.put(CartController()); // Cart controller for managing cart state
List<Product> _products = []; // Use ProductModel here List<Product> _products = []; // List to hold fetched products
List<Map<String, dynamic>> _categories = []; List<Map<String, dynamic>> _categories = [];
int _currentPage = 1; int _currentPage = 1; // Current page for pagination
bool _isLoading = false; bool _isLoading = false;
bool _hasMoreData = true; bool _hasMoreData = true;
@ -36,9 +36,10 @@ class _ProductCatalogScreenState extends State<ProductCatalogScreen> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_fetchCategories(); _fetchCategories(); // Fetch categories on initialization
_fetchProducts(); _fetchProducts(); // Fetch initial products
_scrollController.addListener(() { _scrollController.addListener(() {
// Listener to fetch more products when scrolling to the bottom
if (_scrollController.position.pixels == if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent && _scrollController.position.maxScrollExtent &&
!_isLoading && !_isLoading &&
@ -47,25 +48,26 @@ class _ProductCatalogScreenState extends State<ProductCatalogScreen> {
} }
}); });
} }
// Function to fetch products based on current filters and pagination
Future<void> _fetchProducts() async { Future<void> _fetchProducts() async {
setState(() { setState(() {
_isLoading = true; _isLoading = true;
}); });
// Set the category based on the selected category; use null for 'All'
final category = _selectedCategory == 'All' ? null : _selectedCategory; final category = _selectedCategory == 'All' ? null : _selectedCategory;
// Fetch products from the service
final products = await _productService.getProduct( final products = await _productService.getProduct(
_currentPage, category: category); _currentPage, category: category);
setState(() { setState(() {
if (products != null) { if (products != null) {
_products.addAll(products); // Assuming products is a List<ProductModel> _products.addAll(products); // Add fetched products to the list
_hasMoreData = products.isNotEmpty; _hasMoreData = products.isNotEmpty;
} }
_isLoading = false; _isLoading = false;
}); });
} }
// Function to fetch categories from the service
Future<void> _fetchCategories() async { Future<void> _fetchCategories() async {
final categories = await _productService.getCategory(); final categories = await _productService.getCategory();
if (categories != null) { if (categories != null) {
@ -76,7 +78,7 @@ class _ProductCatalogScreenState extends State<ProductCatalogScreen> {
}); });
} }
} }
// Function to handle category change
void _onCategoryChanged(String? newCategory) { void _onCategoryChanged(String? newCategory) {
if (newCategory != null) { if (newCategory != null) {
setState(() { setState(() {
@ -84,34 +86,34 @@ class _ProductCatalogScreenState extends State<ProductCatalogScreen> {
_products.clear(); _products.clear();
_currentPage = 1; _currentPage = 1;
}); });
_fetchProducts(); _fetchProducts(); // Fetch products for the new category
} }
} }
// Function to fetch more products for pagination
Future<void> _fetchMoreProducts() async { Future<void> _fetchMoreProducts() async {
if (!_isLoading && _hasMoreData) { if (!_isLoading && _hasMoreData) {
setState(() { setState(() {
_isLoading = true; _isLoading = true;
_currentPage++; _currentPage++;
}); });
await _fetchProducts(); await _fetchProducts(); // Fetch more products
} }
} }
// Function to clear all filters
void _clearFilters() { void _clearFilters() {
setState(() { setState(() {
_selectedCategory = null; _selectedCategory = null;
_selectedPriceRange = null; _selectedPriceRange = null;
_selectedAvailability = null; _selectedAvailability = null;
_products.clear(); _products.clear(); // Clear existing products
_currentPage = 1; _currentPage = 1;
}); });
_fetchProducts(); _fetchProducts(); // Fetch products without filters
} }
@override @override
void dispose() { void dispose() {
_scrollController.dispose(); _scrollController.dispose(); // Dispose of the scroll controller
super.dispose(); super.dispose();
} }
@ -263,7 +265,7 @@ class _ProductCatalogScreenState extends State<ProductCatalogScreen> {
padding: const EdgeInsets.symmetric( padding: const EdgeInsets.symmetric(
vertical: 8), vertical: 8),
child: ProductCard( child: ProductCard(
productModel: _products[index], productModel: _products[index], // Product card for each product
// Use ProductModel here // Use ProductModel here
), ),
); );
@ -282,7 +284,7 @@ class _ProductCatalogScreenState extends State<ProductCatalogScreen> {
), ),
); );
} }
// Function to build filter dropdowns
Widget _buildFilterDropdown(int index) { Widget _buildFilterDropdown(int index) {
switch (index) { switch (index) {
case 0: case 0:

View File

@ -23,7 +23,8 @@ class ProductDetailScreen extends StatefulWidget {
} }
class _ProductDetailScreenState extends State<ProductDetailScreen> { class _ProductDetailScreenState extends State<ProductDetailScreen> {
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) { String capitalizeFirstLetter(String text) {
if (text.isEmpty) return text; if (text.isEmpty) return text;
return text[0].toUpperCase() + text.substring(1).toLowerCase(); return text[0].toUpperCase() + text.substring(1).toLowerCase();
@ -114,6 +115,7 @@ class _ProductDetailScreenState extends State<ProductDetailScreen> {
), ),
), ),
), ),
// Displaying product name
Padding( Padding(
padding: const EdgeInsets.symmetric(horizontal: 8), padding: const EdgeInsets.symmetric(horizontal: 8),
child: Row( child: Row(
@ -131,6 +133,7 @@ class _ProductDetailScreenState extends State<ProductDetailScreen> {
], ],
), ),
), ),
// Displaying product price
Padding( Padding(
padding: const EdgeInsets.symmetric(horizontal: 8), padding: const EdgeInsets.symmetric(horizontal: 8),
child: Row( child: Row(
@ -148,6 +151,7 @@ class _ProductDetailScreenState extends State<ProductDetailScreen> {
], ],
), ),
), ),
// Displaying product category
Padding( Padding(
padding: const EdgeInsets.symmetric(horizontal: 8), padding: const EdgeInsets.symmetric(horizontal: 8),
child: Row( child: Row(
@ -166,6 +170,7 @@ class _ProductDetailScreenState extends State<ProductDetailScreen> {
), ),
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
// Displaying product description
Padding( Padding(
padding: const EdgeInsets.symmetric(horizontal: 8), padding: const EdgeInsets.symmetric(horizontal: 8),
child: Row( child: Row(
@ -187,13 +192,14 @@ class _ProductDetailScreenState extends State<ProductDetailScreen> {
), ),
), ),
SizedBox(height: Get.height * 0.04), SizedBox(height: Get.height * 0.04),
// Add to Cart button
SizedBox( SizedBox(
width: Get.width * 0.9, width: Get.width * 0.9,
height: Get.height * 0.06, height: Get.height * 0.06,
child: ElevatedButton( child: ElevatedButton(
onPressed: () { onPressed: () {
// Pass the product data to the CartScreen // 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"); showSnackbar("Product successfully added to your cart");
}, },
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(

View File

@ -14,12 +14,14 @@ class ProductsManualScreen extends StatefulWidget {
} }
class _ProductsManualScreenState extends State<ProductsManualScreen> { class _ProductsManualScreenState extends State<ProductsManualScreen> {
// Initialize the ProductManualController using GetX for managing state
final ProductManualController _productManualController = Get.put(ProductManualController()); final ProductManualController _productManualController = Get.put(ProductManualController());
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_productManualController.fetchProductManuals(); // Fetch product manual list from API // Fetch product manual list from API when the screen initializes
_productManualController.fetchProductManuals();
} }
@override @override
@ -83,17 +85,17 @@ class _ProductsManualScreenState extends State<ProductsManualScreen> {
); );
} }
// Build the card content // Method to build the main card content with the list of product manuals
Widget _buildCardContent() { Widget _buildCardContent() {
return Obx(() { return Obx(() {
if (_productManualController.isLoading.value) { if (_productManualController.isLoading.value) {
return const CircularProgressIndicator(); // Loading state return const CircularProgressIndicator(); // Loading state
} }
// Check if the product manual list is empty
if (_productManualController.productManualList.isEmpty) { if (_productManualController.productManualList.isEmpty) {
return const Text("No product manuals available"); // Empty state return const Text("No product manuals available"); // Empty state
} }
// Display the card with a list of product manual buttons
return Card( return Card(
margin: const EdgeInsets.symmetric(horizontal: 24), margin: const EdgeInsets.symmetric(horizontal: 24),
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
@ -104,7 +106,7 @@ class _ProductsManualScreenState extends State<ProductsManualScreen> {
child: Padding( child: Padding(
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),
child: Column( child: Column(
children: _buildProductButtons(), children: _buildProductButtons(), // Dynamically build buttons from API data
), ),
), ),
); );
@ -116,18 +118,18 @@ class _ProductsManualScreenState extends State<ProductsManualScreen> {
return _productManualController.productManualList.map((productManual) { return _productManualController.productManualList.map((productManual) {
return CustomButton( return CustomButton(
text: productManual.title ?? "No Title", // Dynamically fetch product name text: productManual.title ?? "No Title", // Dynamically fetch product name
onPressed: () => _navigateToPdfScreen(productManual), onPressed: () => _navigateToPdfScreen(productManual), // Navigate to PDF screen on button press
); );
}).toList(); }).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) { void _navigateToPdfScreen(ProductManualModel productManual) {
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (context) => ViewPdfScreen( builder: (context) => ViewPdfScreen(
productManualModel: productManual, productManualModel: productManual, // Pass the selected product manual data to the PDF screen
), ),
), ),
); );

View File

@ -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<dynamic> get(String path, {Map<String, dynamic>? queryParameters}) {
return _dio.get(path, queryParameters: queryParameters);
}
Future<Response> post(String path, {dynamic data}) {
return _dio.post(path, data: data);
}
Future<Response> put(String path, {Map<String, dynamic>? data}) {
return _dio.put(path, data: data);
}
Future<Response> delete(String path, {Map<String, dynamic>? data}) {
return _dio.delete(path, data: data);
}
}

View File

@ -1,18 +1,40 @@
class ApiUrls { class ApiUrls {
// static const String baseUrl = 'https://cheminova-api-2.onrender.com/api/'; // static const String baseUrl = 'https://cheminova-api-2.onrender.com/api/';
//============================== Base Url =========================================//
static const String baseUrl = 'https://api.cnapp.co.in'; static const String baseUrl = 'https://api.cnapp.co.in';
//============================== Login =========================================//
static const String loginUrl = '/api/v1/user/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 forgetPasswordUrl = '/api/v1/user/password/forgot';
static const String changePasswordUrl = '/api/v1/user/password/update'; static const String changePasswordUrl = '/api/v1/user/password/update';
static const String fcmUrl = '/api/v1/user/fcm-token'; 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 getCategoryUrl = '/api/category/getCategories';
static const String getProductUrl = '/api/category/getCategories'; // static const String getProductUrl = '/api/category/getCategories';
static const String getProductManualUrl = '/api/productmanual/getall'; static const String getallProductUrl = '/api/product/getAll/user';
static const String getKycUrl = '/api/kyc/getAll';
static const String getNotificationUrl = '/api/get-notification-pd'; //============================== Placed Order Details ==============================//
static const String getPlacedOrderUrl ='/api/get-placed-order-pd'; static const String getPlacedOrderUrl ='/api/get-placed-order-pd';
static const String getSinglePlacedOrderUrl ='/api/get-single-placed-order-pd'; static const String getSinglePlacedOrderUrl ='/api/get-single-placed-order-pd';
static const String placedOrderUrl ='${baseUrl}/api/order-place'; 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';
} }

View File

@ -1,20 +1,22 @@
import 'dart:io'; import 'dart:io';
import 'package:cheminova/utils/api_urls.dart';
import 'package:cheminova/utils/constants.dart'; import 'package:cheminova/utils/constants.dart';
import 'package:cheminova/utils/show_snackbar.dart'; import 'package:cheminova/utils/show_snackbar.dart';
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
// Generic API service function that handles API requests with optional file uploads
Future<BodyType?> commonApiService<BodyType>({ Future<BodyType?> commonApiService<BodyType>({
required String url, required String url,
required String method, required String method,
Map<String, dynamic> body = const {}, Map<String, dynamic> body = const {}, // Request body
File? imageFile, File? imageFile, // Optional image file for upload
bool isformData = true, bool isformData = true,
Map<String, String>? additionalHeaders, Map<String, String>? additionalHeaders, // Additional headers for the request
required BodyType Function(Map<String, dynamic>) fromJson, required BodyType Function(Map<String, dynamic>) fromJson,// Function to parse the response data
}) async { }) async {
try { try {
// Initialize Dio for making HTTP requests
Dio dio = Dio(); Dio dio = Dio();
final Response response; final Response response;
@ -23,22 +25,23 @@ Future<BodyType?> commonApiService<BodyType>({
// Fetch the token from SharedPreferences // Fetch the token from SharedPreferences
SharedPreferences prefs = await SharedPreferences.getInstance(); SharedPreferences prefs = await SharedPreferences.getInstance();
String? token = prefs.getString('token'); String? token = prefs.getString('token');
// Setting default headers, including Content-Type and Authorization if token is present
Map<String, String> headers = { Map<String, String> headers = {
'Content-Type': isformData ? 'multipart/form-data' : 'application/json', 'Content-Type': isformData ? 'multipart/form-data' : 'application/json',
}; };
// Adding the token to the headers if available
if (token != null) { if (token != null) {
headers['Authorization'] = 'Bearer $token'; headers['Authorization'] = 'Bearer $token';
} }
// Adding any additional headers provided in the request
if (additionalHeaders != null) { if (additionalHeaders != null) {
headers.addAll(additionalHeaders); headers.addAll(additionalHeaders);
} }
// Setting options with the headers
Options options = Options(headers: headers); Options options = Options(headers: headers);
// Preparing form data for requests, especially if files are involved
FormData formData = FormData.fromMap(body); FormData formData = FormData.fromMap(body);
// Adding the image file to the form data if present
if (imageFile != null) { if (imageFile != null) {
String fileName = imageFile.path.split('/').last; String fileName = imageFile.path.split('/').last;
formData.files.add(MapEntry( formData.files.add(MapEntry(
@ -46,25 +49,26 @@ Future<BodyType?> commonApiService<BodyType>({
await MultipartFile.fromFile(imageFile.path, filename: fileName), await MultipartFile.fromFile(imageFile.path, filename: fileName),
)); ));
} }
// Handling different HTTP methods based on the provided method parameter
if (method == "POST") { if (method == "POST") {
response = await dio.post("$baseUrl$url", response = await dio.post("${ApiUrls.baseUrl}$url",
data: isformData ? formData : body, options: options); data: isformData ? formData : body, options: options);
} else if (method == "PUT") { } else if (method == "PUT") {
response = await dio.put("$baseUrl$url", response = await dio.put("${ApiUrls.baseUrl}$url",
data: isformData ? formData : body, options: options); data: isformData ? formData : body, options: options);
} else if (method == "DELETE") { } 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") { } else if (method == "PATCH") {
response = await dio.patch("$baseUrl$url", response = await dio.patch("${ApiUrls.baseUrl}$url",
data: isformData ? formData : body, options: options); data: isformData ? formData : body, options: options);
} else { } 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"); print("response of $url : $response");
// Special handling for login endpoint to store token in SharedPreferences
if (url == "/api/v1/user/login/" && if (url == "/api/v1/user/login/" &&
response.data['token'] != null) { response.data['token'] != null) {
prefs.setString('token', response.data['token']); prefs.setString('token', response.data['token']);
@ -73,14 +77,14 @@ Future<BodyType?> commonApiService<BodyType>({
// if (url == "/api/territorymanager/my-profile") { // if (url == "/api/territorymanager/my-profile") {
// return fromJson(response.data['myData']); // return fromJson(response.data['myData']);
// } // }
// Returning parsed response data using the fromJson function provided
return fromJson(response.data); return fromJson(response.data);
} on DioException catch (e) { } on DioException catch (e) {
print("dio exception $url ${e.response?.data}}"); print("dio exception $url ${e.response?.data}}");
print("dio exception details: ${e.message} ${e.response?.statusCode}"); print("dio exception details: ${e.message} ${e.response?.statusCode}");
String errorMessage = "An error occurred"; String errorMessage = "An error occurred";
// Extracting error message from the response if available
if (e.response?.data is Map<String, dynamic>) { if (e.response?.data is Map<String, dynamic>) {
errorMessage = e.response?.data['message'] ?? errorMessage; errorMessage = e.response?.data['message'] ?? errorMessage;
} else if (e.response?.data is String) { } else if (e.response?.data is String) {
@ -91,5 +95,6 @@ Future<BodyType?> commonApiService<BodyType>({
} catch (e) { } catch (e) {
print("exception $url $e"); print("exception $url $e");
} }
// Returning null in case of any exception
return null; return null;
} }

View File

@ -1,3 +1,3 @@
//String baseUrl = "https://cheminova-api-2.onrender.com"; //String baseUrl = "https://cheminova-api-2.onrender.com";
String baseUrl = "https://api.cnapp.co.in"; //String baseUrl = "https://api.cnapp.co.in";

View File

@ -1,46 +1,46 @@
import 'package:flutter/material.dart'; // import 'package:flutter/material.dart';
//
class CommonElevatedButton extends StatelessWidget { // class CommonElevatedButton extends StatelessWidget {
final String text; // final String text;
final void Function()? onPressed; // final void Function()? onPressed;
final double? height; // final double? height;
final double? width; // final double? width;
final double? borderRadius; // final double? borderRadius;
final Color? backgroundColor; // final Color? backgroundColor;
final bool isLoading; // final bool isLoading;
//
const CommonElevatedButton( // const CommonElevatedButton(
{super.key, // {super.key,
required this.text, // required this.text,
this.onPressed, // this.onPressed,
this.borderRadius, // this.borderRadius,
this.backgroundColor, // this.backgroundColor,
this.height, // this.height,
this.width, // this.width,
this.isLoading = false}); // this.isLoading = false});
//
@override // @override
Widget build(BuildContext context) { // Widget build(BuildContext context) {
return SizedBox( // return SizedBox(
height: height ?? kToolbarHeight - 25, // height: height ?? kToolbarHeight - 25,
width: width ?? 200, // width: width ?? 200,
child: ElevatedButton( // child: ElevatedButton(
onPressed: isLoading ? null : onPressed, // onPressed: isLoading ? null : onPressed,
style: ElevatedButton.styleFrom( // style: ElevatedButton.styleFrom(
shape: RoundedRectangleBorder( // shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(borderRadius ?? 6)), // borderRadius: BorderRadius.circular(borderRadius ?? 6)),
backgroundColor: backgroundColor ?? const Color(0xff1E1E1E), // backgroundColor: backgroundColor ?? const Color(0xff1E1E1E),
side: const BorderSide(color: Colors.transparent)), // side: const BorderSide(color: Colors.transparent)),
child: Center( // child: Center(
child: isLoading // child: isLoading
? const CircularProgressIndicator( // ? const CircularProgressIndicator(
backgroundColor: Colors.white, // backgroundColor: Colors.white,
valueColor: AlwaysStoppedAnimation<Color>(Colors.black)) // valueColor: AlwaysStoppedAnimation<Color>(Colors.black))
: Text(text, // : Text(text,
style: const TextStyle( // style: const TextStyle(
fontSize: 15, // fontSize: 15,
color: Colors.white, // color: Colors.white,
fontWeight: FontWeight.w400, // fontWeight: FontWeight.w400,
fontFamily: 'Anek'))))); // fontFamily: 'Anek')))));
} // }
} // }

View File

@ -5,8 +5,8 @@ import 'package:google_fonts/google_fonts.dart';
class HomeCard extends StatelessWidget { class HomeCard extends StatelessWidget {
final String title; 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({ const HomeCard({
super.key, super.key,
required this.title, required this.title,
@ -16,7 +16,7 @@ class HomeCard extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return GestureDetector( return GestureDetector(
onTap: onTap, onTap: onTap, // Handling tap event on the card
child: Container( child: Container(
margin: const EdgeInsets.fromLTRB(0, 0, 20, 0), margin: const EdgeInsets.fromLTRB(0, 0, 20, 0),
child: ClipRect( child: ClipRect(

View File

@ -17,16 +17,17 @@ class MyDrawer extends StatefulWidget {
} }
class _MyDrawerState extends State<MyDrawer> { class _MyDrawerState extends State<MyDrawer> {
final homecontroller = Get.put(HomeController()); final homecontroller = Get.put(HomeController()); // Initialize HomeController
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final user = homecontroller.user; final user = homecontroller.user; // Get the current user from HomeController
return Drawer( return Drawer(
child: ListView( child: ListView(
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
children: <Widget>[ children: <Widget>[
SizedBox( SizedBox(
height: 150, height: 150,
// Drawer header displaying user information
child: DrawerHeader( child: DrawerHeader(
decoration: const BoxDecoration( decoration: const BoxDecoration(
color: Colors.black87, color: Colors.black87,
@ -53,6 +54,7 @@ class _MyDrawerState extends State<MyDrawer> {
), ),
), ),
), ),
// Navigation tile for Home
ListTile( ListTile(
leading: const Icon(Icons.home), leading: const Icon(Icons.home),
title: const Text('Home'), title: const Text('Home'),
@ -60,10 +62,11 @@ class _MyDrawerState extends State<MyDrawer> {
Navigator.pushAndRemoveUntil( Navigator.pushAndRemoveUntil(
context, context,
MaterialPageRoute(builder: (context) => const HomeScreen()), MaterialPageRoute(builder: (context) => const HomeScreen()),
(route) => false, (route) => false, // Remove all previous routes
); );
}, },
), ),
// Navigation tile for Profile
ListTile( ListTile(
leading: const Icon(Icons.account_circle), leading: const Icon(Icons.account_circle),
title: const Text('Profile'), title: const Text('Profile'),
@ -74,6 +77,7 @@ class _MyDrawerState extends State<MyDrawer> {
); );
}, },
), ),
// Navigation tile for Change Password
ListTile( ListTile(
leading: const Icon(Icons.settings), leading: const Icon(Icons.settings),
title: const Text('Change Password'), title: const Text('Change Password'),
@ -84,6 +88,7 @@ class _MyDrawerState extends State<MyDrawer> {
); );
}, },
), ),
// Navigation tile for Logout
ListTile( ListTile(
leading: const Icon(Icons.exit_to_app), leading: const Icon(Icons.exit_to_app),
title: const Text('Logout'), title: const Text('Logout'),
@ -96,7 +101,7 @@ class _MyDrawerState extends State<MyDrawer> {
); );
} }
} }
// Function to display logout confirmation dialog
Future logoutBox(BuildContext context) { Future logoutBox(BuildContext context) {
Size size = MediaQuery.of(context).size; Size size = MediaQuery.of(context).size;
return showDialog( return showDialog(

View File

@ -50,12 +50,13 @@ class _ProductCardState extends State<ProductCard> {
final CartController _cartController = Get.put(CartController()); final CartController _cartController = Get.put(CartController());
bool showQuantity = widget.isInCart || widget.isCheckout || widget.isConfirmation; bool showQuantity = widget.isInCart || widget.isCheckout || widget.isConfirmation;
bool isProductInCart = _cartController.cartList.any((p) => p.id == widget.productModel!.id); 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 int currentQuantity = isProductInCart
? _cartController.cartList.firstWhere((p) => p.id == widget.productModel!.id).quantity ? _cartController.cartList.firstWhere((p) => p.id == widget.productModel!.id).quantity
: widget.productModel!.quantity; : widget.productModel!.quantity;
return GestureDetector( return GestureDetector(
// Navigate to the ProductDetailScreen on tap unless the product is in cart or checkout
onTap: () => widget.isInCart || widget.isCheckout onTap: () => widget.isInCart || widget.isCheckout
? null ? null
: Get.to(() => ProductDetailScreen(productModel: widget.productModel)), : Get.to(() => ProductDetailScreen(productModel: widget.productModel)),
@ -84,6 +85,7 @@ class _ProductCardState extends State<ProductCard> {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
// Display the product name with the first letter capitalized
Text( Text(
capitalizeFirstLetter(widget.productModel!.name), capitalizeFirstLetter(widget.productModel!.name),
style: GoogleFonts.roboto( style: GoogleFonts.roboto(
@ -91,6 +93,7 @@ class _ProductCardState extends State<ProductCard> {
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
), ),
), ),
// Display the category name of the product
Text( Text(
capitalizeFirstLetter(widget.productModel!.category!.categoryName), capitalizeFirstLetter(widget.productModel!.category!.categoryName),
style: GoogleFonts.roboto( style: GoogleFonts.roboto(
@ -98,6 +101,7 @@ class _ProductCardState extends State<ProductCard> {
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
), ),
), ),
// Display the price of the product
Text( Text(
"${widget.productModel!.price.toString()}", "${widget.productModel!.price.toString()}",
style: GoogleFonts.roboto( style: GoogleFonts.roboto(
@ -113,6 +117,7 @@ class _ProductCardState extends State<ProductCard> {
fontWeight: FontWeight.w700, fontWeight: FontWeight.w700,
), ),
), ),
// Display quantity adjustment buttons and remove button if the product is in cart
if (!widget.isCheckout) if (!widget.isCheckout)
widget.isInCart widget.isInCart
? Row( ? Row(