1)All files comments added
This commit is contained in:
parent
fadbad07bf
commit
545b43aef5
29
android/app/google-services.json
Normal file
29
android/app/google-services.json
Normal 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
1
firebase.json
Normal 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"}}}}}}
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
|
||||||
// // }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
@ -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();
|
||||||
|
@ -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';
|
|
||||||
// }
|
|
||||||
// }
|
|
@ -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: {
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 [];
|
||||||
}
|
}
|
||||||
|
@ -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
75
lib/firebase_options.dart
Normal 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',
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
@ -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(),
|
||||||
|
@ -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,)';
|
||||||
}
|
// }
|
||||||
}
|
// }
|
@ -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;
|
||||||
}
|
// }
|
||||||
|
@ -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",
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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',
|
||||||
|
@ -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,
|
||||||
|
|
||||||
|
@ -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()),
|
||||||
|
@ -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),
|
||||||
|
@ -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(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -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,
|
||||||
|
@ -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)),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// )
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
// },
|
|
||||||
// );
|
|
||||||
// }),
|
|
||||||
// )
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
|
@ -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
|
||||||
|
@ -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}",
|
||||||
|
@ -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,
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -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)),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// )
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
// },
|
|
||||||
// );
|
|
||||||
// }),
|
|
||||||
// )
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -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:
|
||||||
|
@ -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(
|
||||||
|
@ -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
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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';
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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";
|
@ -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')))));
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
@ -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(
|
||||||
|
@ -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(
|
||||||
|
@ -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(
|
||||||
|
Loading…
Reference in New Issue
Block a user