Compare commits
10 Commits
37e8ebbe30
...
c246d1cbeb
Author | SHA1 | Date | |
---|---|---|---|
![]() |
c246d1cbeb | ||
a4160498e1 | |||
61553fd7f1 | |||
545637e035 | |||
174d7afa99 | |||
e1d96ee34e | |||
50b0828726 | |||
215877afc4 | |||
43413ac168 | |||
7aa59ca145 |
@ -1,4 +1,8 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<application
|
||||
android:label="cheminova"
|
||||
android:name="${applicationName}"
|
||||
|
BIN
assets/images/cart.png
Normal file
BIN
assets/images/cart.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
178
lib/controller/cart_controller.dart
Normal file
178
lib/controller/cart_controller.dart
Normal file
@ -0,0 +1,178 @@
|
||||
import 'package:get/get.dart';
|
||||
import '../models/product_model.dart';
|
||||
import '../models/product_model1.dart';
|
||||
|
||||
class CartController extends GetxController {
|
||||
var cartList = <Product>[].obs;
|
||||
var cartCount = 0.obs;
|
||||
var subtotal = 0.0.obs;
|
||||
var gstTotal = 0.0.obs;
|
||||
var grandTotal = 0.0.obs;
|
||||
|
||||
// Track the selected products
|
||||
var selectedProducts = <Product>[].obs;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
// Initialize the cart list or other initializations if needed
|
||||
initializeSelections();
|
||||
}
|
||||
|
||||
void addToCart(Product product) {
|
||||
var existingProduct = cartList.firstWhereOrNull((p) => p.id == product.id);
|
||||
if (existingProduct != null) {
|
||||
existingProduct.quantity++;
|
||||
} else {
|
||||
cartList.add(product);
|
||||
}
|
||||
cartCount.value = cartList.length;
|
||||
updateTotalPrice();
|
||||
}
|
||||
|
||||
void updateTotalPrice() {
|
||||
double subTotal = 0.0;
|
||||
double gstTotalAmount = 0.0;
|
||||
|
||||
for (var product in selectedProducts) {
|
||||
subTotal += product.price * product.quantity;
|
||||
gstTotalAmount += (product.price * product.quantity * (product.gst / 100));
|
||||
}
|
||||
|
||||
subtotal.value = subTotal;
|
||||
gstTotal.value = gstTotalAmount;
|
||||
grandTotal.value = subtotal.value + gstTotal.value;
|
||||
}
|
||||
|
||||
void increaseQuantity(Product product) {
|
||||
final index = cartList.indexWhere((item) => item.id == product.id);
|
||||
if (index != -1) {
|
||||
cartList[index].quantity++;
|
||||
if (selectedProducts.contains(cartList[index])) {
|
||||
updateTotalPrice();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void decreaseQuantity(Product product) {
|
||||
final index = cartList.indexWhere((item) => item.id == product.id);
|
||||
if (index != -1 && cartList[index].quantity > 1) {
|
||||
cartList[index].quantity--;
|
||||
if (selectedProducts.contains(cartList[index])) {
|
||||
updateTotalPrice();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void removeFromCart(Product product) {
|
||||
cartList.removeWhere((item) => item.id == product.id);
|
||||
selectedProducts.remove(product);
|
||||
cartCount.value = cartList.length;
|
||||
updateTotalPrice();
|
||||
}
|
||||
|
||||
void toggleProductSelection(Product product, bool isSelected) {
|
||||
if (isSelected) {
|
||||
if (!selectedProducts.contains(product)) {
|
||||
selectedProducts.add(product);
|
||||
}
|
||||
} else {
|
||||
selectedProducts.remove(product);
|
||||
}
|
||||
updateTotalPrice();
|
||||
}
|
||||
|
||||
void selectAllProducts(bool selectAll) {
|
||||
if (selectAll) {
|
||||
selectedProducts.assignAll(cartList);
|
||||
} else {
|
||||
selectedProducts.clear();
|
||||
}
|
||||
updateTotalPrice();
|
||||
}
|
||||
|
||||
void initializeSelections() {
|
||||
selectAllProducts(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// import 'package:get/get.dart';
|
||||
// import '../models/product_model.dart';
|
||||
// import 'package:collection/collection.dart';
|
||||
//
|
||||
// import '../models/product_model1.dart';
|
||||
//
|
||||
// class CartController extends GetxController {
|
||||
//
|
||||
// var cartList = <Product>[].obs;
|
||||
// var cartCount = 0.obs;
|
||||
// var subtotal = 0.0.obs;
|
||||
// var gstTotal = 0.0.obs;
|
||||
// var grandTotal = 0.0.obs;
|
||||
//
|
||||
// // Add item to cart
|
||||
// void addToCart(Product product) {
|
||||
// var existingProduct = cartList.firstWhereOrNull((p) => p.id == product.id);
|
||||
// if (existingProduct != null) {
|
||||
// // Update quantity if already in cart
|
||||
// existingProduct.quantity++;
|
||||
// } else {
|
||||
// // Add new product to cart
|
||||
// cartList.add(product);
|
||||
// }
|
||||
// cartCount.value = cartList.length;
|
||||
// updateTotalPrice();
|
||||
// }
|
||||
//
|
||||
// void updateTotalPrice() {
|
||||
// double subTotal = 0.0;
|
||||
// double gstTotalAmount = 0.0;
|
||||
//
|
||||
// for (var product in cartList.where((p) => p.selected)) {
|
||||
// subTotal += product.price * product.quantity;
|
||||
// gstTotalAmount += (product.price * product.quantity * (product.gst / 100));
|
||||
// }
|
||||
//
|
||||
// subtotal.value = subTotal;
|
||||
// gstTotal.value = gstTotalAmount;
|
||||
// grandTotal.value = subtotal.value + gstTotal.value;
|
||||
// }
|
||||
//
|
||||
// // Increase the quantity of a product
|
||||
// void increaseQuantity(Product product) {
|
||||
// final index = cartList.indexWhere((item) => item.id == product.id);
|
||||
// if (index != -1) {
|
||||
// cartList[index].quantity++;
|
||||
// updateTotalPrice();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Decrease the quantity of a product
|
||||
// void decreaseQuantity(Product product) {
|
||||
// final index = cartList.indexWhere((item) => item.id == product.id);
|
||||
// if (index != -1 && cartList[index].quantity > 1) {
|
||||
// cartList[index].quantity--;
|
||||
// updateTotalPrice();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Remove item from cart
|
||||
// void removeFromCart(Product product) {
|
||||
// cartList.removeWhere((item) => item.id == product.id);
|
||||
// cartCount.value = cartList.length;
|
||||
// updateTotalPrice();
|
||||
// }
|
||||
//
|
||||
// // Toggle product selection
|
||||
// void toggleProductSelection(Product product, bool isSelected) {
|
||||
// final index = cartList.indexWhere((item) => item.id == product.id);
|
||||
// if (index != -1) {
|
||||
// cartList[index].selected = isSelected;
|
||||
// updateTotalPrice();
|
||||
// }
|
||||
// }
|
||||
// }
|
63
lib/controller/get_order_placed_controller.dart
Normal file
63
lib/controller/get_order_placed_controller.dart
Normal file
@ -0,0 +1,63 @@
|
||||
import 'package:cheminova/controller/get_single_placed_order_service.dart';
|
||||
import 'package:cheminova/controller/place_order_controller.dart';
|
||||
import 'package:cheminova/models/place_order_list_model.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import '../models/oder_place_model.dart';
|
||||
import '../models/product_model1.dart';
|
||||
import '../utils/log_service.dart';
|
||||
import 'get_place_order_service.dart';
|
||||
|
||||
class GetPlacedOrderController extends GetxController {
|
||||
final GetOrderPlacedService _getOrderPlacedService = GetOrderPlacedService();
|
||||
final OrderPlacedController _orderPlacedController = Get.put(OrderPlacedController());
|
||||
final GetSingleOrderPlacedService _getSingleOrderPlacedService = GetSingleOrderPlacedService();
|
||||
var placedOrders = <PlacedOrderList>[].obs;
|
||||
var products = <Product>[].obs;
|
||||
|
||||
var isLoading = false.obs;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
getOrders(); // Fetch the orders immediately on initialization
|
||||
}
|
||||
|
||||
Future<void> getOrders() async {
|
||||
|
||||
final fetchedOrders = await _getOrderPlacedService.getPlacedOrders();
|
||||
|
||||
if (fetchedOrders != null && fetchedOrders.isNotEmpty) {
|
||||
placedOrders.addAll(fetchedOrders);
|
||||
//logger.w("Fetched orders: $fetchedOrders");
|
||||
|
||||
} else {
|
||||
//logger.w("No orders fetched");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Future<void> searchOrder() async {
|
||||
try {
|
||||
isLoading.value = true;
|
||||
final order = await _getSingleOrderPlacedService.getSinglePlacedOrder(placedOrders[0].id);
|
||||
if (order != null) {
|
||||
placedOrders.clear(); // Clear existing orders if needed
|
||||
placedOrders.add(order);
|
||||
} else {
|
||||
// Handle order not found case
|
||||
}
|
||||
} catch (e) {
|
||||
// Handle exceptions
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Optional: Reset the pagination if needed
|
||||
void resetPagination() {
|
||||
_getOrderPlacedService.resetPagination();
|
||||
placedOrders.clear(); // Clear existing data
|
||||
getOrders(); // Fetch fresh data
|
||||
}
|
||||
}
|
122
lib/controller/get_place_order_service.dart
Normal file
122
lib/controller/get_place_order_service.dart
Normal file
@ -0,0 +1,122 @@
|
||||
import 'package:cheminova/models/place_order_list_model.dart';
|
||||
import '../models/oder_place_model.dart';
|
||||
import '../utils/common_api_service.dart';
|
||||
import '../utils/show_snackbar.dart';
|
||||
|
||||
class GetOrderPlacedService {
|
||||
int _currentPage = 1; // Initialize with the first page
|
||||
//int _limit = 100; // Start with a fixed limit, can be adjusted
|
||||
final List<PlacedOrderList> _allOrders = []; // To store all fetched orders
|
||||
bool _hasMoreOrders = true; // To check if there are more orders to fetch
|
||||
|
||||
Future<List<PlacedOrderList>?> getPlacedOrders() async {
|
||||
try {
|
||||
while (_hasMoreOrders) {
|
||||
// Construct the API URL with pagination parameters
|
||||
String url = "api/rd-place-order?page=$_currentPage";
|
||||
|
||||
final response = await commonApiService<List<PlacedOrderList>>(
|
||||
method: "GET",
|
||||
url: url,
|
||||
fromJson: (json) {
|
||||
if (json['plcaedOrders'] != null) {
|
||||
final List<PlacedOrderList> orders = (json['plcaedOrders'] as List)
|
||||
.map((orderJson) => PlacedOrderList.fromJson(orderJson as Map<String, dynamic>))
|
||||
.toList();
|
||||
|
||||
if (orders.isNotEmpty) {
|
||||
_allOrders.addAll(orders);
|
||||
_currentPage++;
|
||||
// _limit += orders.length; // Adjust limit based on the number of fetched orders
|
||||
} else {
|
||||
_hasMoreOrders = false; // Stop fetching if no more orders are returned
|
||||
}
|
||||
|
||||
return orders;
|
||||
} else {
|
||||
_hasMoreOrders = false; // Stop if there are no orders at all
|
||||
return [];
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
if (response == null || response.isEmpty) {
|
||||
_hasMoreOrders = false; // Stop fetching if the response is empty
|
||||
}
|
||||
}
|
||||
|
||||
return _allOrders;
|
||||
} catch (e) {
|
||||
showSnackbar(e.toString());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Optional: Reset the pagination and orders when needed
|
||||
void resetPagination() {
|
||||
_currentPage = 1;
|
||||
//_limit = 100; // Reset the limit to the initial value
|
||||
_allOrders.clear(); // Clear the list of orders
|
||||
_hasMoreOrders = true; // Reset the flag to allow fetching again
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// import 'package:cheminova/models/place_order_list_model.dart';
|
||||
//
|
||||
// import '../models/oder_place_model.dart';
|
||||
// import '../utils/common_api_service.dart';
|
||||
// import '../utils/show_snackbar.dart';
|
||||
//
|
||||
// class GetOrderPlacedService {
|
||||
// int _currentPage = 1; // Initialize with the first page
|
||||
// int _limit = 10; // Fixed limit, you can change this as needed
|
||||
// final List<PlacedOrderList> _allOrders = [];
|
||||
// int? totalOrders ;
|
||||
// Future<List<PlacedOrderList>?> getPlacedOrders() async {
|
||||
// try {
|
||||
// // Construct the API URL with pagination parameters
|
||||
// String url = "/api/get-placed-order-pd?page=$_currentPage&limit=$_limit";
|
||||
//
|
||||
// final response = await commonApiService<List<PlacedOrderList>>(
|
||||
// method: "GET",
|
||||
// url: url,
|
||||
// fromJson: (json) {
|
||||
// if (json['plcaedOrders'] != null) {
|
||||
// final List<PlacedOrderList> orders = (json['plcaedOrders'] as List)
|
||||
// .map((orderJson) => PlacedOrderList.fromJson(orderJson as Map<String, dynamic>))
|
||||
// .toList();
|
||||
// // Automatically increase the page number for the next request
|
||||
// if (orders.isNotEmpty) {
|
||||
// _currentPage++;
|
||||
// _limit+= orders.length;
|
||||
//
|
||||
// }
|
||||
// return orders;
|
||||
// } else {
|
||||
// return [];
|
||||
// }
|
||||
// },
|
||||
// );
|
||||
//
|
||||
// return response;
|
||||
// } catch (e) {
|
||||
// showSnackbar(e.toString());
|
||||
// return null;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Optional: Reset the pagination when needed
|
||||
// void resetPagination() {
|
||||
// _currentPage = 1;
|
||||
// _limit = 100;
|
||||
// }
|
||||
// }
|
30
lib/controller/get_single_placed_order_service.dart
Normal file
30
lib/controller/get_single_placed_order_service.dart
Normal file
@ -0,0 +1,30 @@
|
||||
import 'package:cheminova/models/place_order_list_model.dart'; // Import your model
|
||||
import '../utils/common_api_service.dart';
|
||||
import '../utils/show_snackbar.dart';
|
||||
|
||||
class GetSingleOrderPlacedService {
|
||||
Future<PlacedOrderList?> getSinglePlacedOrder(String orderId) async {
|
||||
try {
|
||||
// Construct the API URL for the single placed order
|
||||
String url = "/api/get-single-placed-order-pd/$orderId";
|
||||
|
||||
final response = await commonApiService<PlacedOrderList>(
|
||||
method: "GET",
|
||||
url: url,
|
||||
fromJson: (json) {
|
||||
if (json['singleOrder'] != null) {
|
||||
// Convert the JSON response to a PlacedOrderList model
|
||||
return PlacedOrderList.fromJson(json['singleOrder'] as Map<String, dynamic>);
|
||||
} else {
|
||||
throw Exception("Order not found"); // Throw an exception if not found
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
return response;
|
||||
} catch (e) {
|
||||
showSnackbar(e.toString());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,10 +1,24 @@
|
||||
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';
|
||||
|
||||
class HomeController extends GetxController {
|
||||
final HomeService homeService = HomeService();
|
||||
var user = Rxn<UserModel>();
|
||||
|
||||
UserModel? user;
|
||||
|
||||
// var userModel = UserModel(
|
||||
// id: '',
|
||||
// uniqueId: '',
|
||||
// name: '',
|
||||
// email: '',
|
||||
// phone: '',
|
||||
// role: '',
|
||||
// sbu: '',
|
||||
// createdAt: '',
|
||||
// updatedAt: '',
|
||||
// ).obs; // Observable for UserModel
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
@ -13,7 +27,84 @@ class HomeController extends GetxController {
|
||||
}
|
||||
|
||||
Future<void> getUser() async {
|
||||
user.value = await homeService.getUser();
|
||||
try {
|
||||
print("Starting getUser function in controller");
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
String? token = prefs.getString('token');
|
||||
|
||||
print("Token from SharedPreferences: $token");
|
||||
|
||||
HomeService homeService = HomeService();
|
||||
print("Calling homeService.getUser");
|
||||
user = await homeService.getUser(token: token);
|
||||
print("homeService.getUser completed. User: $user");
|
||||
|
||||
update();
|
||||
|
||||
if (user != null) {
|
||||
print("User fetched successfully: $user");
|
||||
} else {
|
||||
print('Failed to fetch user data');
|
||||
}
|
||||
} catch (e) {
|
||||
print("Error in getUser controller function: ${e.toString()}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 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
|
||||
// // }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
|
@ -1,20 +1,54 @@
|
||||
import 'package:cheminova/models/user_model.dart';
|
||||
import 'package:cheminova/utils/common_api_service.dart';
|
||||
import 'package:cheminova/utils/show_snackbar.dart';
|
||||
import '../utils/api_urls.dart';
|
||||
|
||||
class HomeService {
|
||||
Future<UserModel?> getUser() async {
|
||||
Future<UserModel?> getUser({String? token}) async {
|
||||
try {
|
||||
final response = await commonApiService<UserModel>(
|
||||
print("Starting getUser method in HomeService");
|
||||
print("Token: $token");
|
||||
print("URL: ${ApiUrls.profileUrl}");
|
||||
|
||||
final response = await commonApiService<Map<String, dynamic>>(
|
||||
method: "GET",
|
||||
url: "/api/territorymanager/my-profile",
|
||||
fromJson: (json) => UserModel.fromJson(json),
|
||||
url: ApiUrls.profileUrl,
|
||||
additionalHeaders: {
|
||||
'Authorization': 'Bearer $token',
|
||||
},
|
||||
fromJson: (json) => json as Map<String, dynamic>,
|
||||
);
|
||||
|
||||
return response;
|
||||
} catch (e) {
|
||||
showSnackbar(e.toString());
|
||||
print("Raw API response: $response");
|
||||
|
||||
if (response == null) {
|
||||
print("API response is null");
|
||||
showSnackbar("Failed to get a response from the server");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (response['success'] != true) {
|
||||
print("API call was not successful");
|
||||
showSnackbar(response['message'] ?? "API call was not successful");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (response['myData'] == null) {
|
||||
print("myData is null in the response");
|
||||
showSnackbar("User data not found in the response");
|
||||
return null;
|
||||
}
|
||||
|
||||
print("Attempting to create UserModel from myData");
|
||||
final userModel = UserModel.fromJson(response['myData']);
|
||||
print("UserModel created successfully: $userModel");
|
||||
return userModel;
|
||||
} catch (e) {
|
||||
print("Error in getUser: ${e.toString()}");
|
||||
showSnackbar("Error fetching user data: ${e.toString()}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// ... keep the fcmToken method as it was
|
||||
}
|
45
lib/controller/place_order_controller.dart
Normal file
45
lib/controller/place_order_controller.dart
Normal file
@ -0,0 +1,45 @@
|
||||
import 'dart:convert';
|
||||
import 'package:cheminova/controller/place_order_service.dart';
|
||||
import 'package:cheminova/models/product_model.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import '../models/oder_place_model.dart';
|
||||
|
||||
|
||||
class OrderPlacedController extends GetxController {
|
||||
var placedOrder1 = PlacedOrderModel(
|
||||
paymentMode: 'cheque',
|
||||
shipTo: '456, Park Street, Kolkata, West Bengal - 700016',
|
||||
billTo: '456, Park Street, Kolkata, West Bengal - 700016',
|
||||
subtotal: 300,
|
||||
gstTotal: 100,
|
||||
grandTotal: 400,
|
||||
orderItems: [
|
||||
],
|
||||
).obs;
|
||||
|
||||
var isLoading = false.obs;
|
||||
|
||||
final OrderPlacedService _orderPlacedService = OrderPlacedService();
|
||||
|
||||
Future<void> placeOrder() async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
String? token = prefs.getString('token');
|
||||
isLoading.value = true;
|
||||
//try {
|
||||
// Construct order details
|
||||
PlacedOrderModel orderDetails = placedOrder1.value;
|
||||
print("Order Details: $orderDetails");
|
||||
|
||||
// Call the service to place the order
|
||||
await _orderPlacedService.placeOrder(orderDetails, token!);
|
||||
|
||||
}
|
||||
// catch (e) {
|
||||
//
|
||||
// } finally {
|
||||
// isLoading.value = false;
|
||||
// }
|
||||
}
|
33
lib/controller/place_order_service.dart
Normal file
33
lib/controller/place_order_service.dart
Normal file
@ -0,0 +1,33 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:cheminova/models/product_model.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
|
||||
import '../models/oder_place_model.dart';
|
||||
import '../utils/log_service.dart';
|
||||
|
||||
class OrderPlacedService {
|
||||
final Dio dio = Dio();
|
||||
|
||||
Future<void> placeOrder(PlacedOrderModel orderDetails, String token) async {
|
||||
//try {
|
||||
// logger.w("orderjson ${jsonEncode(orderDetails.toJson())}");
|
||||
final response = await dio.post(
|
||||
'https://api.cnapp.co.in/api/rd-place-order',
|
||||
// Ensure this is your correct endpoint
|
||||
data: jsonEncode(orderDetails.toJson()),
|
||||
options: Options(
|
||||
headers: {
|
||||
'Authorization': 'Bearer $token',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
),
|
||||
);
|
||||
if (response.statusCode != 201) {
|
||||
|
||||
throw Exception('Failed to place order');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
67
lib/controller/product_controller.dart
Normal file
67
lib/controller/product_controller.dart
Normal file
@ -0,0 +1,67 @@
|
||||
import 'package:cheminova/controller/product_service.dart';
|
||||
import 'package:cheminova/models/product_model1.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
|
||||
class ProductController extends GetxController {
|
||||
final ProductService productService = ProductService();
|
||||
var products = <Product>[].obs;
|
||||
var categories = <String>[].obs; // Holds the list of categories
|
||||
var selectedCategory = Rxn<String>(); // Holds the selected category
|
||||
int _currentPage = 1;
|
||||
bool isLoading = false;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
getCategory();
|
||||
getUser();
|
||||
}
|
||||
|
||||
Future<void> getUser() async {
|
||||
if (isLoading) return;
|
||||
isLoading = true;
|
||||
try {
|
||||
final category = selectedCategory.value; // Get the selected category
|
||||
final fetchedProducts = await productService.getProduct(
|
||||
_currentPage,
|
||||
category: category,
|
||||
);
|
||||
|
||||
if (fetchedProducts != null) {
|
||||
// Directly add the fetched products (which are of type List<Product>) to the list
|
||||
products.addAll(fetchedProducts);
|
||||
print("fetchedProducts ,$fetchedProducts");
|
||||
}
|
||||
} catch (e) {
|
||||
print("Error fetching products: $e");
|
||||
} finally {
|
||||
isLoading = false;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> getCategory() async {
|
||||
try {
|
||||
final fetchedCategories = await productService.getCategory();
|
||||
if (fetchedCategories != null) {
|
||||
categories.assignAll(fetchedCategories.map((category) => category['categoryName'] as String));
|
||||
categories.insert(0, 'All'); // Add "All" option
|
||||
}
|
||||
} catch (e) {
|
||||
print("Error fetching categories: $e");
|
||||
}
|
||||
}
|
||||
|
||||
void setCategory(String category) {
|
||||
selectedCategory.value = category == 'All' ? null : category;
|
||||
_currentPage = 1;
|
||||
products.clear();
|
||||
getUser();
|
||||
}
|
||||
|
||||
void loadMoreProducts() {
|
||||
_currentPage++;
|
||||
getUser();
|
||||
}
|
||||
}
|
47
lib/controller/product_mannual_controller.dart
Normal file
47
lib/controller/product_mannual_controller.dart
Normal file
@ -0,0 +1,47 @@
|
||||
import 'package:cheminova/controller/product_mannual_service.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import '../models/product_mannual_model.dart'; // Your model import
|
||||
// Your service import
|
||||
|
||||
class ProductManualController extends GetxController {
|
||||
|
||||
var productManualList = <ProductManualModel>[].obs;
|
||||
|
||||
// Service to fetch data
|
||||
final ProductMannualService productMannualService = ProductMannualService();
|
||||
|
||||
// Loading state
|
||||
var isLoading = false.obs;
|
||||
|
||||
// Method to fetch product manuals from the service
|
||||
void fetchProductManuals() async {
|
||||
try {
|
||||
// Set loading to true
|
||||
isLoading.value = true;
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
String? token = prefs.getString('token');
|
||||
var manuals = await productMannualService.getProductManuals(token!);
|
||||
|
||||
// If data is returned, update the list
|
||||
if (manuals != null) {
|
||||
productManualList.value = manuals;
|
||||
} else {
|
||||
productManualList.value = []; // If no data, set an empty list
|
||||
}
|
||||
} catch (e) {
|
||||
// Handle error here, for example logging or showing an error message
|
||||
print("Error fetching product manuals: $e");
|
||||
} finally {
|
||||
// Set loading to false
|
||||
isLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
// Fetch product manuals when the controller is initialized
|
||||
fetchProductManuals();
|
||||
super.onInit();
|
||||
}
|
||||
}
|
36
lib/controller/product_mannual_service.dart
Normal file
36
lib/controller/product_mannual_service.dart
Normal file
@ -0,0 +1,36 @@
|
||||
|
||||
|
||||
import '../models/product_mannual_model.dart';
|
||||
import '../utils/common_api_service.dart'; // Replace with your actual common API service import
|
||||
|
||||
class ProductMannualService {
|
||||
Future<List<ProductManualModel>?> getProductManuals(String token) async {
|
||||
try {
|
||||
String url = "/api/productmanual/getall"; // Base URL to fetch product manuals
|
||||
|
||||
final response = await commonApiService<List<ProductManualModel>>(
|
||||
method: "GET",
|
||||
url: url,
|
||||
additionalHeaders: { // Pass the token here
|
||||
'Authorization': 'Bearer $token',
|
||||
},
|
||||
fromJson: (json) {
|
||||
if (json['productManuals'] != null) {
|
||||
// Map the list of product manuals from the response
|
||||
final List<ProductManualModel> productManuals = (json['productManuals'] as List)
|
||||
.map((manualJson) => ProductManualModel.fromJson(manualJson as Map<String, dynamic>))
|
||||
.toList();
|
||||
return productManuals;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
);
|
||||
return response;
|
||||
} catch (e) {
|
||||
|
||||
print(e.toString());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
61
lib/controller/product_service.dart
Normal file
61
lib/controller/product_service.dart
Normal file
@ -0,0 +1,61 @@
|
||||
import '../models/product_model1.dart';
|
||||
import '../utils/common_api_service.dart';
|
||||
import '../utils/show_snackbar.dart';
|
||||
|
||||
class ProductService {
|
||||
Future<List<Product>?> getProduct(int page, {String? category}) async {
|
||||
try {
|
||||
String url;
|
||||
if (category != null && category.isNotEmpty) {
|
||||
url = "/api/product/getAll/user/?page=$page&category=$category";
|
||||
} else {
|
||||
url = "/api/product/getAll/user/?page=$page"; // URL without category filter
|
||||
}
|
||||
|
||||
final response = await commonApiService<List<Product>>(
|
||||
method: "GET",
|
||||
url: url,
|
||||
fromJson: (json) {
|
||||
if (json['products'] != null) {
|
||||
final List<Product> products = (json['products'] as List)
|
||||
.map((productJson) => Product.fromJson(productJson as Map<String, dynamic>))
|
||||
.toList();
|
||||
return products;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
);
|
||||
return response;
|
||||
} catch (e) {
|
||||
// showSnackbar(e.toString());
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Future<List<Map<String, dynamic>>?> getCategory() async {
|
||||
try {
|
||||
final response = await commonApiService<List<Map<String, dynamic>>>(
|
||||
method: "GET",
|
||||
url: "/api/category/getCategories",
|
||||
fromJson: (json) {
|
||||
if (json['categories'] != null) {
|
||||
final List<Map<String, dynamic>> category = (json['categories'] as List)
|
||||
.map((productJson) => productJson as Map<String, dynamic>)
|
||||
.toList();
|
||||
return category;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
);
|
||||
return response;
|
||||
} catch (e) {
|
||||
showSnackbar(e.toString());
|
||||
print("Error: $e");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -2,7 +2,7 @@ import 'package:cheminova/screens/splash_screen.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
void main() {
|
||||
void main()async{
|
||||
runApp(const MyApp());
|
||||
}
|
||||
|
||||
@ -12,6 +12,7 @@ class MyApp extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return const GetMaterialApp(
|
||||
debugShowCheckedModeBanner: false,
|
||||
home: SplashScreen(),
|
||||
);
|
||||
}
|
||||
|
23
lib/models/added_by_model.dart
Normal file
23
lib/models/added_by_model.dart
Normal file
@ -0,0 +1,23 @@
|
||||
class AddedBy {
|
||||
String id;
|
||||
String name;
|
||||
|
||||
AddedBy({
|
||||
required this.id,
|
||||
required this.name,
|
||||
});
|
||||
|
||||
factory AddedBy.fromJson(Map<String, dynamic> json) => AddedBy(
|
||||
id: json["_id"],
|
||||
name: json["name"],
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
"_id": id,
|
||||
"name": name,
|
||||
};
|
||||
@override
|
||||
String toString() {
|
||||
return 'AddedBy(id: $id, brandName: $AddedBy,)';
|
||||
}
|
||||
}
|
27
lib/models/brand_model.dart
Normal file
27
lib/models/brand_model.dart
Normal file
@ -0,0 +1,27 @@
|
||||
class Brand {
|
||||
final String id;
|
||||
final String brandName;
|
||||
|
||||
Brand({
|
||||
required this.id,
|
||||
required this.brandName,
|
||||
});
|
||||
|
||||
factory Brand.fromJson(Map<String, dynamic> json) {
|
||||
return Brand(
|
||||
id: json['_id'],
|
||||
brandName: json['brandName'],
|
||||
);
|
||||
}
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'_id': id,
|
||||
'brandName': brandName,
|
||||
|
||||
};
|
||||
}
|
||||
@override
|
||||
String toString() {
|
||||
return 'Brand(id: $id, brandName: $brandName,)';
|
||||
}
|
||||
}
|
27
lib/models/cart_item_model.dart
Normal file
27
lib/models/cart_item_model.dart
Normal file
@ -0,0 +1,27 @@
|
||||
// lib/models/cart_item.dart
|
||||
import 'package:cheminova/models/product_model1.dart';
|
||||
|
||||
class CartItem {
|
||||
final Product product;
|
||||
int quantity;
|
||||
|
||||
CartItem({
|
||||
required this.product,
|
||||
this.quantity = 1,
|
||||
});
|
||||
|
||||
// Method to increase quantity
|
||||
void increaseQuantity() {
|
||||
quantity++;
|
||||
}
|
||||
|
||||
// Method to decrease quantity
|
||||
void decreaseQuantity() {
|
||||
if (quantity > 1) {
|
||||
quantity--;
|
||||
}
|
||||
}
|
||||
|
||||
// Method to get total price of this item
|
||||
int get totalPrice => product.price * quantity;
|
||||
}
|
27
lib/models/category_model.dart
Normal file
27
lib/models/category_model.dart
Normal file
@ -0,0 +1,27 @@
|
||||
class Category {
|
||||
final String id;
|
||||
final String categoryName;
|
||||
|
||||
Category({
|
||||
required this.id,
|
||||
required this.categoryName,
|
||||
});
|
||||
|
||||
factory Category.fromJson(Map<String, dynamic> json) {
|
||||
return Category(
|
||||
id: json['_id'],
|
||||
categoryName: json['categoryName'],
|
||||
);
|
||||
}
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'_id': id,
|
||||
'categoryName': categoryName,
|
||||
|
||||
};
|
||||
}
|
||||
@override
|
||||
String toString() {
|
||||
return 'Category(id: $id, categoryName: $categoryName,)';
|
||||
}
|
||||
}
|
141
lib/models/oder_place_model.dart
Normal file
141
lib/models/oder_place_model.dart
Normal file
@ -0,0 +1,141 @@
|
||||
import 'added_by_model.dart';
|
||||
import 'brand_model.dart';
|
||||
import 'category_model.dart';
|
||||
|
||||
class PlacedOrderModel {
|
||||
String paymentMode;
|
||||
String shipTo;
|
||||
String billTo;
|
||||
double subtotal;
|
||||
double gstTotal;
|
||||
double grandTotal;
|
||||
List<OrderItem> orderItems;
|
||||
|
||||
PlacedOrderModel({
|
||||
required this.paymentMode,
|
||||
required this.shipTo,
|
||||
required this.billTo,
|
||||
required this.subtotal,
|
||||
required this.gstTotal,
|
||||
required this.grandTotal,
|
||||
required this.orderItems,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'paymentMode': paymentMode,
|
||||
'shipTo': shipTo,
|
||||
'billTo': billTo,
|
||||
'subtotal': subtotal,
|
||||
'gstTotal': gstTotal,
|
||||
'grandTotal': grandTotal,
|
||||
'orderItems': orderItems.map((item) => item.toJson()).toList(),
|
||||
};
|
||||
|
||||
factory PlacedOrderModel.fromJson(Map<String, dynamic> json) => PlacedOrderModel(
|
||||
paymentMode: json['paymentMode'],
|
||||
shipTo: json['shipTo'],
|
||||
billTo: json['billTo'],
|
||||
subtotal: json['subtotal'].toDouble(),
|
||||
gstTotal: json['gstTotal'].toDouble(),
|
||||
grandTotal: json['grandTotal'].toDouble(),
|
||||
orderItems: (json['orderItems'] as List).map((item) => OrderItem.fromJson(item)).toList(),
|
||||
);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'PlacedOrderModel{paymentMode: $paymentMode, '
|
||||
'shipTo: $shipTo, '
|
||||
'billTo: $billTo, '
|
||||
'subtotal: $subtotal, '
|
||||
'gstTotal: $gstTotal, '
|
||||
'grandTotal: $grandTotal, '
|
||||
'orderItems: ${orderItems.map((item) => item.toString()).join(', ')})';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class OrderItem {
|
||||
String id;
|
||||
String sku;
|
||||
String name;
|
||||
double price;
|
||||
double gst;
|
||||
int hsnCode;
|
||||
String description;
|
||||
String productStatus;
|
||||
final String addedBy;
|
||||
List<String> image;
|
||||
DateTime createdAt;
|
||||
DateTime updatedAt;
|
||||
int count;
|
||||
Category category;
|
||||
Brand brand;
|
||||
int v;
|
||||
|
||||
OrderItem({
|
||||
required this.id,
|
||||
required this.sku,
|
||||
required this.name,
|
||||
required this.price,
|
||||
required this.gst,
|
||||
required this.hsnCode,
|
||||
required this.description,
|
||||
required this.productStatus,
|
||||
required this.addedBy,
|
||||
required this.image,
|
||||
required this.createdAt,
|
||||
required this.updatedAt,
|
||||
required this.count,
|
||||
required this.category,
|
||||
required this.brand,
|
||||
required this.v,
|
||||
});
|
||||
|
||||
// Adjusted toJson method to match the desired format
|
||||
Map<String, dynamic> toJson() => {
|
||||
'_id': id,
|
||||
'SKU': sku,
|
||||
'name': name,
|
||||
'category': category.toJson(), // Ensure Category has a proper toJson method
|
||||
'brand': brand.toJson(), // Ensure Brand has a proper toJson method
|
||||
'price': price,
|
||||
'GST': gst,
|
||||
'HSN_Code': hsnCode,
|
||||
'description': description,
|
||||
'product_Status': productStatus,
|
||||
'addedBy': {
|
||||
'_id': id, // Assuming the addedBy is represented by the id
|
||||
'name': addedBy // If addedBy is just a name, use it directly here
|
||||
},
|
||||
'image': image,
|
||||
'createdAt': createdAt.toIso8601String(),
|
||||
'updatedAt': updatedAt.toIso8601String(),
|
||||
'__v': v,
|
||||
'count': count,
|
||||
};
|
||||
|
||||
factory OrderItem.fromJson(Map<String, dynamic> json) => OrderItem(
|
||||
id: json['_id'],
|
||||
sku: json['SKU'],
|
||||
name: json['name'],
|
||||
price: json['price'].toDouble(),
|
||||
gst: json['GST'].toDouble(),
|
||||
hsnCode: json['HSN_Code'],
|
||||
description: json['description'],
|
||||
productStatus: json['product_Status'],
|
||||
addedBy: json['addedBy']['name'], // Assuming addedBy has a 'name' key
|
||||
image: List<String>.from(json['image']),
|
||||
createdAt: DateTime.parse(json['createdAt']),
|
||||
updatedAt: DateTime.parse(json['updatedAt']),
|
||||
count: json['count'],
|
||||
category: Category.fromJson(json['category']),
|
||||
brand: Brand.fromJson(json['brand']),
|
||||
v: json['__v'],
|
||||
);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'OrderItem(id: $id, sku: $sku, name: $name, price: $price, gst: $gst, hsnCode: $hsnCode, description: $description, productStatus: $productStatus, addedBy: $addedBy, image: $image, createdAt: $createdAt, updatedAt: $updatedAt, count: $count, category: $category, brand: $brand, v: $v)';
|
||||
}
|
||||
}
|
||||
|
51
lib/models/order_item_model.dart
Normal file
51
lib/models/order_item_model.dart
Normal file
@ -0,0 +1,51 @@
|
||||
class PlaceOrderItem1 {
|
||||
final String sku;
|
||||
String? id;
|
||||
List<String>? image;
|
||||
final String name;
|
||||
final String categoryName;
|
||||
final String brandName;
|
||||
final double price;
|
||||
final int quantity;
|
||||
|
||||
PlaceOrderItem1({
|
||||
required this.sku,
|
||||
this.id,
|
||||
this.image,
|
||||
required this.name,
|
||||
required this.categoryName,
|
||||
required this.brandName,
|
||||
required this.price,
|
||||
required this.quantity,
|
||||
});
|
||||
|
||||
factory PlaceOrderItem1.fromJson(Map<String, dynamic> json) {
|
||||
return PlaceOrderItem1(
|
||||
id: json['id'],
|
||||
sku: json['SKU'],
|
||||
name: json['name'],
|
||||
categoryName: json['categoryName'],
|
||||
brandName: json['brandName'],
|
||||
price: json['price'].toDouble(),
|
||||
quantity: json['quantity'], image: null,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'SKU': sku,
|
||||
'name': name,
|
||||
'categoryName': categoryName,
|
||||
'brandName': brandName,
|
||||
'price': price,
|
||||
'quantity': quantity,
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'OrderItem(sku: $sku, name: $name, categoryName: $categoryName, '
|
||||
'brandName: $brandName, price: $price, quantity: $quantity)';
|
||||
}
|
||||
}
|
||||
|
136
lib/models/place_order_list_model.dart
Normal file
136
lib/models/place_order_list_model.dart
Normal file
@ -0,0 +1,136 @@
|
||||
class PlacedOrderList {
|
||||
final String id;
|
||||
final String paymentMode;
|
||||
final String shipTo;
|
||||
final String billTo;
|
||||
final List<OrderItem1> orderItem;
|
||||
final double subtotal;
|
||||
final double gstTotal;
|
||||
final double grandTotal;
|
||||
final String status;
|
||||
final String addedBy;
|
||||
final bool isCancelled;
|
||||
final bool isDelivered;
|
||||
final String deliveredDate;
|
||||
final String uniqueId;
|
||||
final DateTime createdAt;
|
||||
final DateTime updatedAt;
|
||||
|
||||
PlacedOrderList({
|
||||
required this.id,
|
||||
required this.paymentMode,
|
||||
required this.shipTo,
|
||||
required this.billTo,
|
||||
required this.orderItem,
|
||||
required this.subtotal,
|
||||
required this.gstTotal,
|
||||
required this.grandTotal,
|
||||
required this.status,
|
||||
required this.addedBy,
|
||||
required this.isCancelled,
|
||||
required this.isDelivered,
|
||||
required this.deliveredDate,
|
||||
required this.uniqueId,
|
||||
required this.createdAt,
|
||||
required this.updatedAt,
|
||||
});
|
||||
|
||||
factory PlacedOrderList.fromJson(Map<String, dynamic> json) {
|
||||
return PlacedOrderList(
|
||||
id: json['_id'],
|
||||
paymentMode: json['paymentMode'],
|
||||
shipTo: json['shipTo'],
|
||||
billTo: json['billTo'],
|
||||
orderItem: (json['orderItem'] as List)
|
||||
.map((item) => OrderItem1.fromJson(item))
|
||||
.toList(),
|
||||
subtotal: json['subtotal'].toDouble(),
|
||||
gstTotal: json['gstTotal'].toDouble(),
|
||||
grandTotal: json['grandTotal'].toDouble(),
|
||||
status: json['status'],
|
||||
addedBy: json['addedBy'],
|
||||
isCancelled: json['iscancelled'],
|
||||
isDelivered: json['isDelivered'],
|
||||
deliveredDate: json['DeliveredDate'],
|
||||
uniqueId: json['uniqueId'],
|
||||
createdAt: DateTime.parse(json['createdAt']),
|
||||
updatedAt: DateTime.parse(json['updatedAt']),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'_id': id,
|
||||
'paymentMode': paymentMode,
|
||||
'shipTo': shipTo,
|
||||
'billTo': billTo,
|
||||
'orderItem': orderItem.map((item) => item.toJson()).toList(),
|
||||
'subtotal': subtotal,
|
||||
'gstTotal': gstTotal,
|
||||
'grandTotal': grandTotal,
|
||||
'status': status,
|
||||
'addedBy': addedBy,
|
||||
'iscancelled': isCancelled,
|
||||
'isDelivered': isDelivered,
|
||||
'DeliveredDate': deliveredDate,
|
||||
'uniqueId': uniqueId,
|
||||
'createdAt': createdAt.toIso8601String(),
|
||||
'updatedAt': updatedAt.toIso8601String(),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'PlacedOrderList(id: $id, paymentMode: $paymentMode, shipTo: $shipTo, billTo: $billTo, '
|
||||
'orderItem: $orderItem, subtotal: $subtotal, gstTotal: $gstTotal, grandTotal: $grandTotal, '
|
||||
'status: $status, addedBy: $addedBy, isCancelled: $isCancelled, isDelivered: $isDelivered, '
|
||||
'deliveredDate: $deliveredDate, uniqueId: $uniqueId, createdAt: $createdAt, updatedAt: $updatedAt)';
|
||||
}
|
||||
}
|
||||
|
||||
class OrderItem1 {
|
||||
final String sku;
|
||||
final String name;
|
||||
final String categoryName;
|
||||
final String brandName;
|
||||
final double price;
|
||||
final int quantity;
|
||||
|
||||
OrderItem1({
|
||||
required this.sku,
|
||||
required this.name,
|
||||
required this.categoryName,
|
||||
required this.brandName,
|
||||
required this.price,
|
||||
required this.quantity,
|
||||
});
|
||||
|
||||
factory OrderItem1.fromJson(Map<String, dynamic> json) {
|
||||
return OrderItem1(
|
||||
sku: json['SKU'],
|
||||
name: json['name'],
|
||||
categoryName: json['categoryName'],
|
||||
brandName: json['brandName'],
|
||||
price: json['price'].toDouble(),
|
||||
quantity: json['quantity'],
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'SKU': sku,
|
||||
'name': name,
|
||||
'categoryName': categoryName,
|
||||
'brandName': brandName,
|
||||
'price': price,
|
||||
'quantity': quantity,
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'OrderItem(sku: $sku, name: $name, categoryName: $categoryName, '
|
||||
'brandName: $brandName, price: $price, quantity: $quantity)';
|
||||
}
|
||||
}
|
||||
|
120
lib/models/product_mannual_model.dart
Normal file
120
lib/models/product_mannual_model.dart
Normal file
@ -0,0 +1,120 @@
|
||||
class ProductManualModel {
|
||||
final String id;
|
||||
final String title;
|
||||
final ProductManualDetails productManual;
|
||||
final String createdAt;
|
||||
final String updatedAt;
|
||||
|
||||
ProductManualModel({
|
||||
required this.id,
|
||||
required this.title,
|
||||
required this.productManual,
|
||||
required this.createdAt,
|
||||
required this.updatedAt,
|
||||
});
|
||||
|
||||
// Factory method to create a ProductManualModel from JSON
|
||||
factory ProductManualModel.fromJson(Map<String, dynamic> json) {
|
||||
return ProductManualModel(
|
||||
id: json['_id'] ?? '',
|
||||
title: json['title'] ?? '',
|
||||
productManual: ProductManualDetails.fromJson(json['product_manual']),
|
||||
createdAt: json['createdAt'],
|
||||
updatedAt: json['updatedAt'],
|
||||
);
|
||||
}
|
||||
|
||||
// Method to convert a ProductManualModel to JSON
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'_id': id,
|
||||
'title': title,
|
||||
'product_manual': productManual.toJson(),
|
||||
'createdAt': createdAt,
|
||||
'updatedAt': updatedAt,
|
||||
};
|
||||
}
|
||||
|
||||
// Override toString for better debugging
|
||||
@override
|
||||
String toString() {
|
||||
return 'ProductManualModel(id: $id, title: $title, productManual: $productManual, createdAt: $createdAt, updatedAt: $updatedAt)';
|
||||
}
|
||||
}
|
||||
|
||||
class ProductManualDetails {
|
||||
final String publicId;
|
||||
final String url;
|
||||
final String filename;
|
||||
|
||||
ProductManualDetails({
|
||||
required this.publicId,
|
||||
required this.url,
|
||||
required this.filename,
|
||||
});
|
||||
|
||||
// Factory method to create ProductManualDetails from JSON
|
||||
factory ProductManualDetails.fromJson(Map<String, dynamic> json) {
|
||||
return ProductManualDetails(
|
||||
publicId: json['public_id'] ?? '',
|
||||
url: json['url'] ?? '',
|
||||
filename: json['filename'] ?? '',
|
||||
);
|
||||
}
|
||||
|
||||
// Method to convert ProductManualDetails to JSON
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'public_id': publicId,
|
||||
'url': url,
|
||||
'filename': filename,
|
||||
};
|
||||
}
|
||||
|
||||
// Override toString for better debugging
|
||||
@override
|
||||
String toString() {
|
||||
return 'ProductManualDetails(publicId: $publicId, url: $url, filename: $filename)';
|
||||
}
|
||||
}
|
||||
|
||||
// Model for handling the entire response
|
||||
class ProductManualResponse {
|
||||
final bool success;
|
||||
final List<ProductManualModel> productManuals;
|
||||
final int total;
|
||||
|
||||
ProductManualResponse({
|
||||
required this.success,
|
||||
required this.productManuals,
|
||||
required this.total,
|
||||
});
|
||||
|
||||
// Factory method to create ProductManualResponse from JSON
|
||||
factory ProductManualResponse.fromJson(Map<String, dynamic> json) {
|
||||
var productList = (json['productManuals'] as List)
|
||||
.map((manual) => ProductManualModel.fromJson(manual))
|
||||
.toList();
|
||||
|
||||
return ProductManualResponse(
|
||||
success: json['success'] ?? false,
|
||||
productManuals: productList,
|
||||
total: json['total'] ?? 0,
|
||||
);
|
||||
}
|
||||
|
||||
// Method to convert ProductManualResponse to JSON
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'success': success,
|
||||
'productManuals': productManuals.map((manual) => manual.toJson()).toList(),
|
||||
'total': total,
|
||||
};
|
||||
}
|
||||
|
||||
// Override toString for better debugging
|
||||
@override
|
||||
String toString() {
|
||||
return 'ProductManualResponse(success: $success, total: $total, productManuals: $productManuals)';
|
||||
}
|
||||
}
|
@ -5,6 +5,8 @@ class ProductModel {
|
||||
final String image;
|
||||
final String description;
|
||||
final double price;
|
||||
String? category1;
|
||||
String? brandname;
|
||||
final ProductCategory category;
|
||||
final String id;
|
||||
int quantity;
|
||||
@ -15,7 +17,39 @@ class ProductModel {
|
||||
required this.description,
|
||||
required this.price,
|
||||
required this.category,
|
||||
this.category1,
|
||||
this.brandname,
|
||||
required this.id,
|
||||
this.quantity = 1,
|
||||
});
|
||||
|
||||
// Factory constructor
|
||||
factory ProductModel.fromJson(Map<String, dynamic> json) {
|
||||
return ProductModel(
|
||||
name: json['name']??"",
|
||||
image: json['image']??"",
|
||||
description: json['description']??"",
|
||||
price: json['price']??"",
|
||||
category: ProductCategory.values.firstWhere((e) => e.toString().split('.').last == json['category']),
|
||||
category1: json['category1']??"",
|
||||
brandname: json['brandname']??"",
|
||||
id: json['id'],
|
||||
quantity: json['quantity'] ?? 1,
|
||||
);
|
||||
}
|
||||
|
||||
// Optional: toJson method if you need to convert the model back to JSON
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'name': name,
|
||||
'image': image,
|
||||
'description': description,
|
||||
'price': price,
|
||||
'category': category.toString().split('.').last,
|
||||
'category1': category1,
|
||||
'brandname': brandname,
|
||||
'id': id,
|
||||
'quantity': quantity,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
118
lib/models/product_model1.dart
Normal file
118
lib/models/product_model1.dart
Normal file
@ -0,0 +1,118 @@
|
||||
import 'brand_model.dart';
|
||||
import 'category_model.dart';
|
||||
|
||||
class Product {
|
||||
final String id;
|
||||
final String sku;
|
||||
final String name;
|
||||
final Category category;
|
||||
final Brand brand;
|
||||
final int price;
|
||||
int quantity;
|
||||
bool selected;
|
||||
final int gst;
|
||||
final int hsnCode;
|
||||
final String description;
|
||||
final String productStatus;
|
||||
final String addedBy;
|
||||
final DateTime createdAt;
|
||||
|
||||
Product({
|
||||
required this.id,
|
||||
required this.sku,
|
||||
required this.name,
|
||||
required this.category,
|
||||
required this.brand,
|
||||
required this.price,
|
||||
this.quantity =1,
|
||||
this.selected=false,
|
||||
required this.gst,
|
||||
required this.hsnCode,
|
||||
required this.description,
|
||||
required this.productStatus,
|
||||
required this.addedBy,
|
||||
required this.createdAt,
|
||||
});
|
||||
|
||||
factory Product.fromJson(Map<String, dynamic> json) {
|
||||
return Product(
|
||||
id: json['_id'] as String,
|
||||
sku: json['SKU'] as String,
|
||||
name: json['name'] as String,
|
||||
category:Category.fromJson(json['category'] as Map<String, dynamic>),
|
||||
brand: Brand.fromJson(json['brand'] as Map<String, dynamic>),
|
||||
price: json['price'] as int,
|
||||
gst: json['GST'] as int,
|
||||
hsnCode: json['HSN_Code'] as int,
|
||||
description: json['description'] ?? '',
|
||||
productStatus: json['product_Status'] as String,
|
||||
addedBy: json['addedBy']['name'] as String,
|
||||
createdAt: DateTime.parse(json['createdAt'] as String),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Method to convert a Product to JSON
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'_id': id,
|
||||
'SKU': sku,
|
||||
'name': name,
|
||||
'category':toJson(),
|
||||
'brand':toJson(),
|
||||
'price': price,
|
||||
'GST': gst,
|
||||
'HSN_Code': hsnCode,
|
||||
'description': description,
|
||||
'product_Status': productStatus,
|
||||
'addedBy': {
|
||||
'name': addedBy,
|
||||
},
|
||||
'createdAt': createdAt.toIso8601String(),
|
||||
};
|
||||
}
|
||||
|
||||
// Override toString method for easy printing of Product details
|
||||
@override
|
||||
String toString() {
|
||||
return 'Product(id: $id, sku: $sku, name: $name, category: $category, '
|
||||
'brand: $brand, price: $price, quantity: $quantity, gst: $gst, '
|
||||
'hsnCode: $hsnCode, description: $description, productStatus: $productStatus, '
|
||||
'addedBy: $addedBy, createdAt: $createdAt)';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// class Category {
|
||||
// final String id;
|
||||
// final String categoryName;
|
||||
//
|
||||
// Category({
|
||||
// required this.id,
|
||||
// required this.categoryName,
|
||||
// });
|
||||
//
|
||||
// factory Category.fromJson(Map<String, dynamic> json) {
|
||||
// return Category(
|
||||
// id: json['_id'],
|
||||
// categoryName: json['categoryName'],
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// class Brand {
|
||||
// final String id;
|
||||
// final String brandName;
|
||||
//
|
||||
// Brand({
|
||||
// required this.id,
|
||||
// required this.brandName,
|
||||
// });
|
||||
//
|
||||
// factory Brand.fromJson(Map<String, dynamic> json) {
|
||||
// return Brand(
|
||||
// id: json['_id'],
|
||||
// brandName: json['brandName'],
|
||||
// );
|
||||
// }
|
||||
// }
|
@ -1,37 +1,76 @@
|
||||
class UserModel {
|
||||
String id;
|
||||
String name;
|
||||
String uniqueId;
|
||||
String email;
|
||||
bool isVerified;
|
||||
final String id;
|
||||
final String uniqueId;
|
||||
final String name;
|
||||
final String email;
|
||||
final String mobileNumber;
|
||||
final String designation;
|
||||
final String userType;
|
||||
final String? principalDistributer;
|
||||
final String? addedBy;
|
||||
final String? kyc;
|
||||
final String? fcmToken;
|
||||
final String createdAt;
|
||||
final String updatedAt;
|
||||
final String? mappedSC;
|
||||
|
||||
UserModel({
|
||||
required this.id,
|
||||
required this.name,
|
||||
required this.uniqueId,
|
||||
required this.name,
|
||||
required this.email,
|
||||
required this.isVerified,
|
||||
required this.mobileNumber,
|
||||
required this.designation,
|
||||
required this.userType,
|
||||
this.principalDistributer,
|
||||
this.addedBy,
|
||||
this.kyc,
|
||||
this.fcmToken,
|
||||
required this.createdAt,
|
||||
required this.updatedAt,
|
||||
this.mappedSC,
|
||||
});
|
||||
|
||||
// Factory constructor to create an instance of UserModel from a JSON map
|
||||
factory UserModel.fromJson(Map<String, dynamic> json) {
|
||||
return UserModel(
|
||||
id: json['_id'] as String,
|
||||
name: json['name'] as String,
|
||||
uniqueId: json['uniqueId'] as String,
|
||||
email: json['email'] as String,
|
||||
isVerified: json['isVerified'] as bool,
|
||||
id: json['_id'],
|
||||
uniqueId: json['uniqueId'],
|
||||
name: json['name'],
|
||||
email: json['email'],
|
||||
mobileNumber: json['mobile_number'],
|
||||
designation: json['designation'],
|
||||
userType: json['userType'],
|
||||
principalDistributer: json['principal_distributer'],
|
||||
addedBy: json['addedBy'],
|
||||
kyc: json['kyc'],
|
||||
fcmToken: json['fcm_token'],
|
||||
createdAt: json['createdAt'],
|
||||
updatedAt: json['updatedAt'],
|
||||
mappedSC: json['mappedSC'],
|
||||
);
|
||||
}
|
||||
|
||||
// Method to convert an instance of UserModel to a JSON map
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'_id': id,
|
||||
'name': name,
|
||||
'uniqueId': uniqueId,
|
||||
'name': name,
|
||||
'email': email,
|
||||
'isVerified': isVerified,
|
||||
'mobile_number': mobileNumber,
|
||||
'designation': designation,
|
||||
'userType': userType,
|
||||
'principal_distributer': principalDistributer,
|
||||
'addedBy': addedBy,
|
||||
'kyc': kyc,
|
||||
'fcm_token': fcmToken,
|
||||
'createdAt': createdAt,
|
||||
'updatedAt': updatedAt,
|
||||
'mappedSC': mappedSC,
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'UserModel{id: $id, uniqueId: $uniqueId, name: $name, email: $email, mobileNumber: $mobileNumber, designation: $designation, userType: $userType, principalDistributer: $principalDistributer, addedBy: $addedBy, kyc: $kyc, fcmToken: $fcmToken, createdAt: $createdAt, updatedAt: $updatedAt, mappedSC: $mappedSC}';
|
||||
}
|
||||
}
|
117
lib/screens/authentication/Profile.dart
Normal file
117
lib/screens/authentication/Profile.dart
Normal file
@ -0,0 +1,117 @@
|
||||
import 'package:cheminova/controller/home_controller.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 '../../widgets/comman_background.dart';
|
||||
import '../../widgets/common_appbar.dart';
|
||||
|
||||
class ProfileScreen extends StatefulWidget {
|
||||
// String? name;
|
||||
// final String uniqueId;
|
||||
// final String email;
|
||||
// final String mobileNumber;
|
||||
// final String designation;
|
||||
|
||||
const ProfileScreen({
|
||||
Key? key,
|
||||
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<ProfileScreen> createState() => _ProfileScreenState();
|
||||
}
|
||||
|
||||
class _ProfileScreenState extends State<ProfileScreen> {
|
||||
|
||||
final homecontroller = Get.put(HomeController());
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final user = homecontroller!.user;
|
||||
return Stack(
|
||||
children: [
|
||||
CommonBackground(
|
||||
isFullWidth: true,
|
||||
child: Scaffold(
|
||||
drawer: MyDrawer(),
|
||||
backgroundColor: Colors.transparent,
|
||||
appBar: CommonAppBar(
|
||||
title: const Text('Profile'),
|
||||
backgroundColor: Colors.transparent,
|
||||
elevation: 0,
|
||||
actions: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
icon: SvgPicture.asset(
|
||||
'assets/svg/back_arrow.svg',
|
||||
),
|
||||
padding: const EdgeInsets.only(right: 20),
|
||||
),
|
||||
],
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(20.0)
|
||||
.copyWith(top: 15, bottom: 30),
|
||||
margin: const EdgeInsets.symmetric(
|
||||
horizontal: 30.0, vertical: 20.0),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: Colors.white),
|
||||
color: const Color(0xffB4D1E5).withOpacity(0.9),
|
||||
borderRadius: BorderRadius.circular(26.0),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 20),
|
||||
_buildProfileItem('Name', user!.name),
|
||||
_buildProfileItem('ID', user.uniqueId),
|
||||
_buildProfileItem('Email ID', user.email),
|
||||
// _buildProfileItem('Mobile Number', user.phone),
|
||||
// _buildProfileItem('Designation', user.role),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildProfileItem(String label, String value) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
label,
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Color(0xff004791),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
Text(
|
||||
value,
|
||||
style: const TextStyle(
|
||||
fontSize: 18,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
const Divider(color: Colors.grey),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
181
lib/screens/authentication/change_password_screen.dart
Normal file
181
lib/screens/authentication/change_password_screen.dart
Normal file
@ -0,0 +1,181 @@
|
||||
import 'package:cheminova/widgets/custom_button.dart';
|
||||
import 'package:cheminova/widgets/input_field.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 '../../utils/show_snackbar.dart';
|
||||
import 'controller/auth_controller.dart';
|
||||
|
||||
|
||||
class ChangePasswordScreen extends StatefulWidget {
|
||||
const ChangePasswordScreen({super.key});
|
||||
|
||||
@override
|
||||
State<ChangePasswordScreen> createState() => _ChangePasswordScreenState();
|
||||
}
|
||||
|
||||
class _ChangePasswordScreenState extends State<ChangePasswordScreen> {
|
||||
final authController = Get.put(AuthController());
|
||||
|
||||
|
||||
void dispose() {
|
||||
authController.currentpassController.dispose();
|
||||
authController.newpassController.dispose();
|
||||
authController.confirmpassController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void validateAndChangePassword() async {
|
||||
String oldPassword = authController.currentpassController.text.trim();
|
||||
String newPassword = authController.newpassController.text.trim();
|
||||
String confirmPassword = authController.confirmpassController.text.trim();
|
||||
|
||||
if (newPassword.isEmpty || confirmPassword.isEmpty || oldPassword.isEmpty) {
|
||||
showSnackbar('All fields are required');
|
||||
return;
|
||||
}
|
||||
|
||||
if (newPassword.length < 8) {
|
||||
showSnackbar('Password must be at least 8 characters long');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!RegExp(r'[!@#$%^&*(),.?":{}|<>]').hasMatch(newPassword)) {
|
||||
showSnackbar('Password must contain at least one special character');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (newPassword != confirmPassword) {
|
||||
showSnackbar('New Password and Confirm Password do not match');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
authController.changePassword();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
extendBodyBehindAppBar: true,
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.transparent,
|
||||
|
||||
elevation: 0,
|
||||
leading: GestureDetector(
|
||||
onTap: () => Get.back(),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: SizedBox(
|
||||
width: 20,
|
||||
height: 20,
|
||||
child: SvgPicture.asset('assets/svg/menu.svg')),
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
GestureDetector(
|
||||
onTap: () => Get.back(),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: SvgPicture.asset('assets/svg/back_arrow.svg'),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
body: Stack(
|
||||
alignment: Alignment.topCenter,
|
||||
children: [
|
||||
Container(
|
||||
decoration: const BoxDecoration(
|
||||
image: DecorationImage(
|
||||
fit: BoxFit.cover,
|
||||
image: AssetImage(
|
||||
'assets/images/image_1.png',
|
||||
),
|
||||
),
|
||||
borderRadius: BorderRadius.only(
|
||||
bottomLeft: Radius.circular(50.0),
|
||||
bottomRight: Radius.circular(50.0),
|
||||
),
|
||||
),
|
||||
child: SizedBox(
|
||||
width: Get.width,
|
||||
height: Get.height * 0.7,
|
||||
),
|
||||
),
|
||||
Center(
|
||||
child: SingleChildScrollView(
|
||||
child: Card(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 24),
|
||||
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(16.0),
|
||||
child: Column(
|
||||
children: [
|
||||
|
||||
Container(
|
||||
padding: const EdgeInsets.only(bottom: 10),
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
'Change Password',
|
||||
style: GoogleFonts.getFont(
|
||||
'Roboto',
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 30,
|
||||
height: 1.2,
|
||||
),
|
||||
),
|
||||
),
|
||||
InputField(
|
||||
hintText: "Current Password",
|
||||
labelText: "Current Password",
|
||||
controller: authController.currentpassController,
|
||||
obscureText: false,
|
||||
keyboardType: TextInputType.text,
|
||||
),
|
||||
|
||||
const SizedBox(height: 15),
|
||||
InputField(
|
||||
hintText: "New Password",
|
||||
labelText: "New Password",
|
||||
obscureText: false,
|
||||
controller: authController.newpassController,
|
||||
keyboardType: TextInputType.text,
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
InputField(
|
||||
hintText: "Confirm Password",
|
||||
labelText: "Confirm Password",
|
||||
obscureText: false,
|
||||
controller: authController.confirmpassController,
|
||||
keyboardType: TextInputType.text,
|
||||
),
|
||||
const SizedBox(height: 30),
|
||||
CustomButton(
|
||||
text: "RESET PASSWORD",
|
||||
onPressed: () async {
|
||||
|
||||
validateAndChangePassword();
|
||||
|
||||
},
|
||||
isLoading: authController.isLoading.value,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,7 +1,9 @@
|
||||
import 'package:cheminova/screens/authentication/controller/auth_service.dart';
|
||||
import 'package:cheminova/screens/home_screen.dart';
|
||||
import 'package:cheminova/utils/show_snackbar.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
class AuthController extends GetxController {
|
||||
final authService = AuthService();
|
||||
@ -9,6 +11,10 @@ class AuthController extends GetxController {
|
||||
TextEditingController emailController = TextEditingController();
|
||||
TextEditingController passwordController = TextEditingController();
|
||||
TextEditingController phoneController = TextEditingController();
|
||||
TextEditingController currentpassController = TextEditingController();
|
||||
TextEditingController newpassController = TextEditingController();
|
||||
TextEditingController confirmpassController = TextEditingController();
|
||||
|
||||
RxBool isLoading = false.obs;
|
||||
|
||||
Future<void> login() async {
|
||||
@ -20,7 +26,60 @@ class AuthController extends GetxController {
|
||||
isLoading.value = false;
|
||||
update();
|
||||
if (response != null) {
|
||||
showSnackbar("Your Successfully logged In!");
|
||||
Get.offAll(() => const HomeScreen());
|
||||
}
|
||||
else if(response == null){
|
||||
showSnackbar("Please Enter Valid Email or Password");
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> forgotpass() async{
|
||||
isLoading.value = true;
|
||||
final response = await authService.forgotPassword(
|
||||
{
|
||||
'email': emailController.text,
|
||||
}
|
||||
);
|
||||
isLoading.value = false;
|
||||
update();
|
||||
if(response != null){
|
||||
showSnackbar("Email sent successfully");
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> changePassword() async {
|
||||
isLoading.value = true;
|
||||
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
String? token = prefs.getString('token');
|
||||
|
||||
if (token != null) {
|
||||
final response = await authService.changePassword(
|
||||
{
|
||||
'oldPassword': currentpassController.text,
|
||||
'newPassword': newpassController.text,
|
||||
'confirmPassword': confirmpassController.text,
|
||||
},
|
||||
token: token, // Pass the token here
|
||||
);
|
||||
print("tokemn ,$token");
|
||||
isLoading.value = false;
|
||||
update();
|
||||
|
||||
if (response != null) {
|
||||
|
||||
Get.snackbar('Success', 'Password changed successfully');
|
||||
} else {
|
||||
|
||||
Get.snackbar('Error', 'Failed to change password');
|
||||
}
|
||||
} else {
|
||||
isLoading.value = false;
|
||||
update();
|
||||
Get.snackbar('Error', 'Token not found. Please login again.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ class AuthService {
|
||||
Future<Map<String, dynamic>?> login(Map<String, dynamic> data) async {
|
||||
try {
|
||||
final response = await commonApiService<Map<String, dynamic>>(
|
||||
url: '/api/territorymanager/login',
|
||||
url: '/api/rd-login',
|
||||
method: 'POST',
|
||||
body: data,
|
||||
fromJson: (json) => json, // Simply return the JSON map as is
|
||||
@ -16,4 +16,41 @@ class AuthService {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
Future<Map<String, dynamic>?> forgotPassword(Map<String, dynamic> data) async {
|
||||
try {
|
||||
final response = await commonApiService<Map<String, dynamic>>(
|
||||
url: '/api/forgot-password',
|
||||
method: 'POST',
|
||||
body: data,
|
||||
fromJson: (json) => json, // Simply return the JSON map as is
|
||||
);
|
||||
return response;
|
||||
} catch (e) {
|
||||
showSnackbar(e.toString());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
Future<Map<String, dynamic>?> changePassword(Map<String, dynamic> data, {required String token}) async {
|
||||
try {
|
||||
final response = await commonApiService<Map<String, dynamic>>(
|
||||
url: '/api/rd-password/update',
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
fromJson: (json) => json, // Simply return the JSON map as is
|
||||
additionalHeaders: { // Pass the token here
|
||||
'Authorization': 'Bearer $token',
|
||||
},
|
||||
);
|
||||
return response;
|
||||
} catch (e) {
|
||||
showSnackbar(e.toString());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ import 'package:flutter_svg/svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
|
||||
import 'controller/auth_controller.dart';
|
||||
|
||||
class ForgetPasswordScreen extends StatefulWidget {
|
||||
const ForgetPasswordScreen({super.key});
|
||||
|
||||
@ -15,6 +17,7 @@ class ForgetPasswordScreen extends StatefulWidget {
|
||||
class _ForgetPasswordScreenState extends State<ForgetPasswordScreen> {
|
||||
final userNameController = TextEditingController();
|
||||
final passwordController = TextEditingController();
|
||||
final authController = Get.put(AuthController());
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
@ -107,7 +110,7 @@ class _ForgetPasswordScreenState extends State<ForgetPasswordScreen> {
|
||||
InputField(
|
||||
hintText: "Email",
|
||||
labelText: "Email",
|
||||
controller: userNameController,
|
||||
controller: authController.emailController,
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
),
|
||||
const SizedBox(height: 30),
|
||||
@ -125,7 +128,12 @@ class _ForgetPasswordScreenState extends State<ForgetPasswordScreen> {
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 30),
|
||||
CustomButton(text: "Send", onPressed: () {}),
|
||||
CustomButton(text: "Send",
|
||||
|
||||
onPressed: () => authController.forgotpass(),
|
||||
isLoading: authController.isLoading.value,
|
||||
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -1,13 +1,12 @@
|
||||
import 'dart:ui';
|
||||
import 'package:cheminova/screens/authentication/controller/auth_controller.dart';
|
||||
import 'package:cheminova/screens/authentication/forget_password_screen.dart';
|
||||
import 'package:cheminova/screens/authentication/verify_phone_screen.dart';
|
||||
import 'package:cheminova/widgets/custom_button.dart';
|
||||
import 'package:cheminova/widgets/input_field.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 '../../widgets/comman_text_from_filed.dart';
|
||||
import '../../widgets/custom_button.dart';
|
||||
import 'controller/auth_controller.dart';
|
||||
import 'forget_password_screen.dart';
|
||||
// Make sure you import HomeScreen
|
||||
|
||||
class LoginScreen extends StatefulWidget {
|
||||
const LoginScreen({super.key});
|
||||
@ -19,6 +18,8 @@ class LoginScreen extends StatefulWidget {
|
||||
class _LoginScreenState extends State<LoginScreen> {
|
||||
final formKey = GlobalKey<FormState>();
|
||||
final authController = Get.put(AuthController());
|
||||
final String emailPattern = r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$';
|
||||
final String passwordPattern = r'^.{6,}$'; // At least 6 characters
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -30,9 +31,7 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
decoration: const BoxDecoration(
|
||||
image: DecorationImage(
|
||||
fit: BoxFit.cover,
|
||||
image: AssetImage(
|
||||
'assets/images/image_1.png',
|
||||
),
|
||||
image: AssetImage('assets/images/image_1.png'),
|
||||
),
|
||||
borderRadius: BorderRadius.only(
|
||||
bottomLeft: Radius.circular(50.0),
|
||||
@ -45,6 +44,8 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
),
|
||||
),
|
||||
SingleChildScrollView(
|
||||
child: Form(
|
||||
key: formKey,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
@ -130,17 +131,37 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
),
|
||||
),
|
||||
),
|
||||
InputField(
|
||||
hintText: "Email",
|
||||
labelText: "Email",
|
||||
CommonTextFormField(
|
||||
controller: authController.emailController,
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter your email id';
|
||||
}
|
||||
if (!RegExp(emailPattern).hasMatch(value)) {
|
||||
return 'Please Enter valid email';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
title: 'Email',
|
||||
label: "Email",
|
||||
),
|
||||
InputField(
|
||||
hintText: "Password",
|
||||
labelText: "Password",
|
||||
const SizedBox(height: 15),
|
||||
CommonTextFormField(
|
||||
controller: authController.passwordController,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter your password';
|
||||
}
|
||||
if (!RegExp(passwordPattern).hasMatch(value)) {
|
||||
return 'Please Enter valid password';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
obscureText: true,
|
||||
title: 'Password',
|
||||
maxLines: 1,
|
||||
label: "Password",
|
||||
),
|
||||
const SizedBox(height: 30),
|
||||
GestureDetector(
|
||||
@ -161,7 +182,12 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
Obx(
|
||||
() => CustomButton(
|
||||
text: "Login",
|
||||
onPressed: () => authController.login(),
|
||||
onPressed: () {
|
||||
if (formKey.currentState!.validate()) {
|
||||
// Perform login action
|
||||
authController.login();
|
||||
}
|
||||
},
|
||||
isLoading: authController.isLoading.value,
|
||||
),
|
||||
),
|
||||
@ -172,6 +198,7 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
@ -85,7 +85,7 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||
HomeCard(
|
||||
title: 'Order Management',
|
||||
onTap: () => Get.to(
|
||||
() => const OrderManagementScreen(),
|
||||
() => OrderManagementScreen(),
|
||||
),
|
||||
),
|
||||
HomeCard(
|
||||
|
@ -1,36 +1,175 @@
|
||||
import 'package:cheminova/models/product_model.dart';
|
||||
import 'package:cheminova/screens/order/order_confermation_screen.dart';
|
||||
import 'package:cheminova/widgets/input_field.dart';
|
||||
import 'package:cheminova/widgets/my_drawer.dart';
|
||||
import 'package:cheminova/widgets/product_card.dart';
|
||||
import 'dart:ffi';
|
||||
import 'package:cheminova/controller/get_order_placed_controller.dart';
|
||||
import 'package:cheminova/models/added_by_model.dart';
|
||||
import 'package:cheminova/models/category_model.dart';
|
||||
import 'package:cheminova/utils/show_snackbar.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:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import '../../controller/cart_controller.dart';
|
||||
import '../../controller/place_order_controller.dart';
|
||||
import '../../controller/place_order_service.dart';
|
||||
import '../../controller/product_controller.dart';
|
||||
import '../../controller/product_service.dart';
|
||||
import '../../models/brand_model.dart';
|
||||
import '../../models/oder_place_model.dart';
|
||||
import '../../models/product_model1.dart';
|
||||
import '../../widgets/my_drawer.dart';
|
||||
import '../../widgets/product_card.dart';
|
||||
import 'order_confermation_screen.dart';
|
||||
|
||||
class CheckoutScreen extends StatefulWidget {
|
||||
const CheckoutScreen({super.key});
|
||||
final Product? productModel;
|
||||
|
||||
PlacedOrderModel? placeOrder;
|
||||
List<Product>? selectedProducts;
|
||||
CheckoutScreen({super.key, this.productModel, this.placeOrder,this.selectedProducts});
|
||||
|
||||
@override
|
||||
State<CheckoutScreen> createState() => _CheckoutScreenState();
|
||||
}
|
||||
|
||||
class _CheckoutScreenState extends State<CheckoutScreen> {
|
||||
final TextEditingController _addressController = TextEditingController();
|
||||
final TextEditingController _contactController = TextEditingController();
|
||||
final CartController _cartController = Get.put(CartController());
|
||||
final ProductService _productService = ProductService();
|
||||
final ProductController _productController = Get.put(ProductController());
|
||||
final OrderPlacedController _orderPlacedController =
|
||||
Get.put(OrderPlacedController());
|
||||
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,
|
||||
),
|
||||
int currentPage = 1;
|
||||
String _groupValue = "cheque";
|
||||
|
||||
final List<String> _addressList = [
|
||||
'Home - 123 Street, City',
|
||||
'Office - 456 Avenue, City',
|
||||
'Warehouse - 789 Blvd, City',
|
||||
];
|
||||
|
||||
String _groupValue = "Credit Card";
|
||||
String? _selectedShippingAddress;
|
||||
String? _selectedBillingAddress;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
// _getOrder();
|
||||
_loadSelectedAddress();
|
||||
_loadSelectedPaymentMode();
|
||||
|
||||
if (_addressList.isNotEmpty) {
|
||||
_selectedShippingAddress = _addressList.first;
|
||||
_selectedBillingAddress = _addressList.first;
|
||||
}
|
||||
}
|
||||
|
||||
void _saveSelectedAddress() async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setString('selectedShippingAddress', _selectedShippingAddress!);
|
||||
await prefs.setString('selectedBillingAddress', _selectedBillingAddress!);
|
||||
}
|
||||
|
||||
void _onShippingAddressChanged(String? value) {
|
||||
setState(() {
|
||||
_selectedShippingAddress = value;
|
||||
});
|
||||
_saveSelectedAddress();
|
||||
}
|
||||
|
||||
void _onBillingAddressChanged(String? value) {
|
||||
setState(() {
|
||||
_selectedBillingAddress = value;
|
||||
});
|
||||
_saveSelectedAddress();
|
||||
}
|
||||
|
||||
void _loadSelectedAddress() async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
setState(() {
|
||||
_selectedShippingAddress =
|
||||
prefs.getString('selectedShippingAddress') ?? _addressList.first;
|
||||
_selectedBillingAddress =
|
||||
prefs.getString('selectedBillingAddress') ?? _addressList.first;
|
||||
});
|
||||
}
|
||||
|
||||
void _onPaymentModeChanged(String? value) {
|
||||
setState(() {
|
||||
_groupValue = value!;
|
||||
});
|
||||
_saveSelectedPaymentMode();
|
||||
}
|
||||
|
||||
void _saveSelectedPaymentMode() async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setString('selectedPaymentMode', _groupValue);
|
||||
}
|
||||
|
||||
void _loadSelectedPaymentMode() async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
setState(() {
|
||||
_groupValue = prefs.getString('selectedPaymentMode') ?? 'cheque';
|
||||
});
|
||||
}
|
||||
|
||||
// void _getOrder(){
|
||||
// final details = _getPlacedOrderController.getOrder(widget.productModel!.id);
|
||||
// print("dffgfg,$details");
|
||||
// }
|
||||
void _onPlaceOrder() async {
|
||||
try {
|
||||
// Map the cart items (Product) to OrderItem objects
|
||||
List<OrderItem> orderItems = _cartController.selectedProducts.map<OrderItem>((product) {
|
||||
return OrderItem(
|
||||
id: product.id,
|
||||
name: product.name,
|
||||
price: product.price.toDouble(),
|
||||
sku: product.sku,
|
||||
gst: product.gst.toDouble(),
|
||||
hsnCode: product.hsnCode,
|
||||
description: product.description,
|
||||
productStatus: product.productStatus,
|
||||
image: [],
|
||||
createdAt: product.createdAt,
|
||||
updatedAt: product.createdAt,
|
||||
count: product.quantity,
|
||||
|
||||
//category:product.category,
|
||||
category:Category(id: product.category.id, categoryName: product.category.categoryName),
|
||||
// brand:product.brand,
|
||||
brand:Brand(id: product.brand.id, brandName: product.brand.brandName),
|
||||
v: 0, addedBy: product.addedBy,
|
||||
);
|
||||
}).toList();
|
||||
|
||||
// Update the placedOrder1 value
|
||||
_orderPlacedController.placedOrder1.value= PlacedOrderModel(
|
||||
paymentMode: _groupValue,
|
||||
shipTo: _selectedShippingAddress!,
|
||||
billTo: _selectedBillingAddress!,
|
||||
orderItems: orderItems,
|
||||
gstTotal: _cartController.gstTotal.value,
|
||||
grandTotal: _cartController.grandTotal.value,
|
||||
subtotal: _cartController.subtotal.value,
|
||||
);
|
||||
|
||||
await _orderPlacedController.placeOrder();
|
||||
|
||||
if (_orderPlacedController.isLoading.value) {
|
||||
showSnackbar("Order Placed Successfully");
|
||||
Get.to(() => OrderConfermationScreen(
|
||||
placedOrder: _orderPlacedController.placedOrder1.value,
|
||||
));
|
||||
}
|
||||
} catch (e) {
|
||||
print("PlaceOrderScreen error: $e");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -63,9 +202,7 @@ class _CheckoutScreenState extends State<CheckoutScreen> {
|
||||
),
|
||||
),
|
||||
],
|
||||
title: const Text(
|
||||
"Checkout",
|
||||
),
|
||||
title: const Text("Checkout"),
|
||||
),
|
||||
drawer: const MyDrawer(),
|
||||
body: Stack(
|
||||
@ -78,9 +215,7 @@ class _CheckoutScreenState extends State<CheckoutScreen> {
|
||||
SafeArea(
|
||||
child: Column(
|
||||
children: [
|
||||
SizedBox(
|
||||
height: Get.height * 0.02,
|
||||
),
|
||||
SizedBox(height: Get.height * 0.02),
|
||||
Card(
|
||||
margin: EdgeInsets.symmetric(horizontal: Get.width * 0.05),
|
||||
shape: RoundedRectangleBorder(
|
||||
@ -106,15 +241,37 @@ class _CheckoutScreenState extends State<CheckoutScreen> {
|
||||
),
|
||||
),
|
||||
),
|
||||
InputField(
|
||||
hintText: 'Address:',
|
||||
labelText: 'Address:',
|
||||
controller: _addressController,
|
||||
SizedBox(height: 5,),
|
||||
DropdownButtonFormField<String>(
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Shipping Address:',
|
||||
hintText: 'Select Shipping Address',
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
InputField(
|
||||
hintText: 'Contact:',
|
||||
labelText: 'Contact:',
|
||||
controller: _contactController,
|
||||
value: _selectedShippingAddress,
|
||||
items: _addressList.map((String address) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: address,
|
||||
child: Text(address),
|
||||
);
|
||||
}).toList(),
|
||||
onChanged: _onShippingAddressChanged,
|
||||
),
|
||||
SizedBox(height: Get.height * 0.02),
|
||||
DropdownButtonFormField<String>(
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Billing Address:',
|
||||
hintText: 'Select Billing Address',
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
value: _selectedBillingAddress,
|
||||
items: _addressList.map((String address) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: address,
|
||||
child: Text(address),
|
||||
);
|
||||
}).toList(),
|
||||
onChanged: _onBillingAddressChanged,
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
@ -136,42 +293,30 @@ class _CheckoutScreenState extends State<CheckoutScreen> {
|
||||
SizedBox(
|
||||
height: Get.height * 0.035,
|
||||
child: RadioListTile(
|
||||
title: const Text("Credit Card"),
|
||||
title: const Text("Cheque"),
|
||||
contentPadding: EdgeInsets.zero,
|
||||
value: "Credit Card",
|
||||
value: "cheque",
|
||||
groupValue: _groupValue,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_groupValue = value.toString();
|
||||
});
|
||||
},
|
||||
onChanged: _onPaymentModeChanged,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: Get.height * 0.035,
|
||||
child: RadioListTile(
|
||||
title: const Text("Net Banking"),
|
||||
title: const Text("Online transfer"),
|
||||
contentPadding: EdgeInsets.zero,
|
||||
value: "Net Banking",
|
||||
value: "online-transfer",
|
||||
groupValue: _groupValue,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_groupValue = value.toString();
|
||||
});
|
||||
},
|
||||
onChanged: _onPaymentModeChanged,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
child: RadioListTile(
|
||||
title: const Text("Cash on Delivery"),
|
||||
title: const Text("Credit"),
|
||||
contentPadding: EdgeInsets.zero,
|
||||
value: "Cash on Delivery",
|
||||
value: "credit",
|
||||
groupValue: _groupValue,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_groupValue = value.toString();
|
||||
});
|
||||
},
|
||||
onChanged: _onPaymentModeChanged,
|
||||
),
|
||||
),
|
||||
],
|
||||
@ -198,26 +343,52 @@ class _CheckoutScreenState extends State<CheckoutScreen> {
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(Get.width * 0.02),
|
||||
child: ListView.builder(
|
||||
padding: EdgeInsets.zero,
|
||||
itemCount: 10,
|
||||
itemBuilder: (context, index) =>
|
||||
ProductCard(
|
||||
product: _checkoutList[0],
|
||||
itemCount: _cartController.selectedProducts.length,
|
||||
itemBuilder: (context, index) {
|
||||
final cartItem =
|
||||
_cartController.cartList[index];
|
||||
return ProductCard(
|
||||
productModel:_cartController.selectedProducts[index] ,
|
||||
isCheckout: true,
|
||||
),
|
||||
quantity: _cartController.cartList[0].quantity,
|
||||
|
||||
|
||||
// ListTile(
|
||||
// title: Text(cartItem.name ?? 'N/A'),
|
||||
// subtitle: Text(
|
||||
// 'Quantity: ${cartItem.quantity}'),
|
||||
// trailing: Text(
|
||||
// 'Price: \₹${cartItem.price.toStringAsFixed(2)}'),
|
||||
// );
|
||||
);},
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.all(Get.width * 0.04),
|
||||
child: Text(
|
||||
'Total Price: ₹ 1000.00',
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: Get.width * 0.05,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: Colors.black,
|
||||
padding: EdgeInsets.all(Get.width * 0.02),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text('Subtotal',style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
Text('₹${_cartController.subtotal.value.toStringAsFixed(2)}'),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text('GST',style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
Text('₹${_cartController.gstTotal.value.toStringAsFixed(2)}'),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text('Total Amount',style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
Text('₹${_cartController.grandTotal.value.toStringAsFixed(2)}'),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
@ -225,31 +396,30 @@ class _CheckoutScreenState extends State<CheckoutScreen> {
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
height: Get.height * 0.025,
|
||||
),
|
||||
SizedBox(
|
||||
width: Get.width * 0.9,
|
||||
height: Get.height * 0.06,
|
||||
child: ElevatedButton(
|
||||
onPressed: () =>
|
||||
Get.to(() => const OrderConfermationScreen()),
|
||||
),
|
||||
SizedBox(height: 10.0,),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
ElevatedButton(
|
||||
onPressed: _onPlaceOrder,
|
||||
style: ElevatedButton.styleFrom(
|
||||
foregroundColor: Colors.white,
|
||||
backgroundColor: const Color(0xFF00784C),
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: Get.width * 0.20,
|
||||
vertical: Get.height * 0.02),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
"Place Order",
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: Get.width * 0.04,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
child: const Text("Place Order"),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
|
@ -1,4 +1,6 @@
|
||||
import 'package:cheminova/controller/get_order_placed_controller.dart';
|
||||
import 'package:cheminova/models/product_model.dart';
|
||||
import 'package:cheminova/utils/show_snackbar.dart';
|
||||
import 'package:cheminova/widgets/my_drawer.dart';
|
||||
import 'package:cheminova/widgets/product_card.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@ -6,8 +8,16 @@ import 'package:flutter_svg/svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
|
||||
import '../../controller/cart_controller.dart';
|
||||
import '../../controller/place_order_controller.dart';
|
||||
import '../../models/oder_place_model.dart';
|
||||
import '../../models/product_model1.dart';
|
||||
|
||||
class OrderConfermationScreen extends StatefulWidget {
|
||||
const OrderConfermationScreen({super.key});
|
||||
Product? productModel;
|
||||
PlacedOrderModel? placedOrder;
|
||||
List<Product>? selectedProducts;
|
||||
OrderConfermationScreen({super.key,this.productModel,this.placedOrder,this.selectedProducts});
|
||||
|
||||
@override
|
||||
State<OrderConfermationScreen> createState() =>
|
||||
@ -15,18 +25,28 @@ class OrderConfermationScreen extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _OrderConfermationScreenState extends State<OrderConfermationScreen> {
|
||||
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,
|
||||
),
|
||||
];
|
||||
final CartController _cartController = Get.put(CartController());
|
||||
final OrderPlacedController _placedController = Get.put(OrderPlacedController());
|
||||
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
|
||||
Widget build(BuildContext context) {
|
||||
final orderItems = _placedController.placedOrder1;
|
||||
return Scaffold(
|
||||
extendBodyBehindAppBar: true,
|
||||
appBar: AppBar(
|
||||
@ -94,7 +114,7 @@ class _OrderConfermationScreenState extends State<OrderConfermationScreen> {
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(
|
||||
"Order Number: 123456",
|
||||
"Order Number:1234",
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: Get.width * 0.04,
|
||||
fontWeight: FontWeight.w400,
|
||||
@ -109,7 +129,7 @@ class _OrderConfermationScreenState extends State<OrderConfermationScreen> {
|
||||
'Order Summary',
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: Get.width * 0.04,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
@ -124,26 +144,45 @@ class _OrderConfermationScreenState extends State<OrderConfermationScreen> {
|
||||
padding: EdgeInsets.all(Get.width * 0.02),
|
||||
child: ListView.builder(
|
||||
padding: EdgeInsets.zero,
|
||||
itemCount: 10,
|
||||
itemCount: _cartController.selectedProducts.length,
|
||||
itemBuilder: (context, index) =>
|
||||
ProductCard(
|
||||
product: _checkoutList[0],
|
||||
productModel:_cartController.selectedProducts[index],
|
||||
isCheckout: true,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.all(Get.width * 0.04),
|
||||
child: Text(
|
||||
'Total Price: ₹ 1000.00',
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: Get.width * 0.05,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: Colors.black,
|
||||
),
|
||||
padding: EdgeInsets.all(Get.width * 0.02),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text('Subtotal',style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
Text('₹${_cartController.subtotal.value.toStringAsFixed(2)}'),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text('GST',style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
Text('₹${_cartController.gstTotal.value.toStringAsFixed(2)}'),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text('Total Amount',style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
Text('₹${_cartController.grandTotal.value.toStringAsFixed(2)}'),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -161,32 +200,28 @@ class _OrderConfermationScreenState extends State<OrderConfermationScreen> {
|
||||
Card(
|
||||
child: SizedBox(
|
||||
width: Get.width,
|
||||
height: Get.height * 0.2,
|
||||
height: Get.height * 0.1,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(
|
||||
"Address: Lorem Ipsum is simply dummy text of the printing and typesetting industry",
|
||||
style: GoogleFonts.roboto(
|
||||
child: TextField(
|
||||
controller: TextEditingController(
|
||||
text: widget.placedOrder!.shipTo,
|
||||
),
|
||||
decoration: InputDecoration(
|
||||
hintText: "Address : ${widget.placedOrder!.shipTo}",
|
||||
hintStyle: GoogleFonts.roboto(
|
||||
fontSize: Get.width * 0.04,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(
|
||||
"Contact: +91 9123456789",
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: Get.width * 0.04,
|
||||
fontWeight: FontWeight.w400,
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
]),
|
||||
),
|
||||
),
|
||||
Card(
|
||||
@ -196,7 +231,7 @@ class _OrderConfermationScreenState extends State<OrderConfermationScreen> {
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(
|
||||
"Estimated Delivery Date: [Date]",
|
||||
"Estimated Delivery Date: ${widget.placedOrder!.orderItems[0].createdAt}",
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: Get.width * 0.04,
|
||||
fontWeight: FontWeight.w400,
|
||||
@ -205,10 +240,12 @@ class _OrderConfermationScreenState extends State<OrderConfermationScreen> {
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -1,3 +1,4 @@
|
||||
import 'package:cheminova/models/place_order_list_model.dart';
|
||||
import 'package:cheminova/models/product_model.dart';
|
||||
import 'package:cheminova/screens/order_management/order_status_update_screen.dart';
|
||||
import 'package:cheminova/widgets/product_card.dart';
|
||||
@ -6,24 +7,20 @@ import 'package:flutter_svg/svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
|
||||
import '../../controller/cart_controller.dart';
|
||||
import '../../models/product_model1.dart';
|
||||
|
||||
class OrderFullfilmentScreen extends StatefulWidget {
|
||||
const OrderFullfilmentScreen({super.key});
|
||||
//final Product? productModel;
|
||||
PlacedOrderList? placedOrderList;
|
||||
OrderFullfilmentScreen({super.key,this.placedOrderList});
|
||||
|
||||
@override
|
||||
State<OrderFullfilmentScreen> createState() => _OrderFullfilmentScreenState();
|
||||
}
|
||||
|
||||
class _OrderFullfilmentScreenState extends State<OrderFullfilmentScreen> {
|
||||
final List<ProductModel> _checkoutList = [
|
||||
ProductModel(
|
||||
id: "1",
|
||||
image: 'assets/images/image_1.png',
|
||||
name: "Product 1",
|
||||
category: ProductCategory.food,
|
||||
description: 'Product 1 description',
|
||||
price: 100,
|
||||
),
|
||||
];
|
||||
final CartController _cartController = Get.put(CartController());
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
@ -153,7 +150,7 @@ class _OrderFullfilmentScreenState extends State<OrderFullfilmentScreen> {
|
||||
padding: EdgeInsets.zero,
|
||||
itemCount: 10,
|
||||
itemBuilder: (context, index) => ProductCard(
|
||||
product: _checkoutList[0],
|
||||
placedOrderList:widget.placedOrderList,
|
||||
isCheckout: true,
|
||||
),
|
||||
),
|
||||
|
@ -1,31 +1,72 @@
|
||||
import 'package:cheminova/models/product_model.dart';
|
||||
import 'package:cheminova/screens/order_management/order_fullfilment_screen.dart';
|
||||
import 'package:cheminova/widgets/product_card.dart';
|
||||
import 'package:auto_size_text/auto_size_text.dart';
|
||||
import 'package:cheminova/controller/get_order_placed_controller.dart';
|
||||
import 'package:cheminova/models/oder_place_model.dart';
|
||||
import 'package:cheminova/models/order_item_model.dart';
|
||||
import 'package:cheminova/models/place_order_list_model.dart';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
import '../../controller/cart_controller.dart';
|
||||
import '../../models/product_model1.dart';
|
||||
|
||||
class OrderManagementDetailScreen extends StatefulWidget {
|
||||
const OrderManagementDetailScreen({super.key});
|
||||
//final Product? productModel;
|
||||
PlacedOrderList? placedOrderList;
|
||||
PlacedOrderModel? placedOrderModel;
|
||||
OrderManagementDetailScreen({super.key,this.placedOrderList,this.placedOrderModel});
|
||||
|
||||
@override
|
||||
State<OrderManagementDetailScreen> createState() =>
|
||||
_OrderManagementDetailScreenState();
|
||||
}
|
||||
|
||||
|
||||
class _OrderManagementDetailScreenState
|
||||
extends State<OrderManagementDetailScreen> {
|
||||
final List<ProductModel> _checkoutList = [
|
||||
ProductModel(
|
||||
id: "1",
|
||||
image: 'assets/images/image_1.png',
|
||||
name: "Product 1",
|
||||
category: ProductCategory.food,
|
||||
description: 'Product 1 description',
|
||||
price: 100,
|
||||
),
|
||||
];
|
||||
final CartController _cartController = Get.put(CartController());
|
||||
final GetPlacedOrderController _getPlacedOrderController = Get.put(GetPlacedOrderController());
|
||||
String formatDate(String apiDate) {
|
||||
|
||||
DateTime parsedDate = DateTime.parse(apiDate);
|
||||
|
||||
String formattedDate = DateFormat('dd-MMM-yyyy').format(parsedDate);
|
||||
|
||||
return formattedDate;
|
||||
}
|
||||
String capitalizeFirstLetter(String text) {
|
||||
if (text.isEmpty) return text;
|
||||
return text[0].toUpperCase() + text.substring(1).toLowerCase();
|
||||
}
|
||||
|
||||
Future<void> adduni()async {
|
||||
final Set<String> uniqueOrderIds = {};
|
||||
final List<PlacedOrderList> uniqueOrders = [];
|
||||
|
||||
for (var order in _getPlacedOrderController.placedOrders) {
|
||||
if (uniqueOrderIds.add(order.uniqueId)) {
|
||||
uniqueOrders.add(order);
|
||||
}
|
||||
}
|
||||
final order = uniqueOrders[0];
|
||||
|
||||
// Combine product names into a single string
|
||||
final productNames = order.orderItem
|
||||
.map((item) => (item.name))
|
||||
.join(', ');
|
||||
final categotyName = order.orderItem
|
||||
.map((item) => (item.categoryName))
|
||||
.join(', ');
|
||||
final quantity = order.orderItem
|
||||
.map((item) => (item.quantity))
|
||||
.join(', ');
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
@ -95,8 +136,8 @@ class _OrderManagementDetailScreenState
|
||||
child: Text(
|
||||
"Order Summary",
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: Get.width * 0.04,
|
||||
fontWeight: FontWeight.w400,
|
||||
fontSize: Get.width * 0.05,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -106,13 +147,19 @@ class _OrderManagementDetailScreenState
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets.fromLTRB(8, 8, 8, 0),
|
||||
child: Text(
|
||||
"Order ID: 123456",
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"Order ID:",
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: Get.width * 0.04,
|
||||
fontWeight: FontWeight.w400,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
Text(widget.placedOrderList!.uniqueId),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
@ -120,26 +167,38 @@ class _OrderManagementDetailScreenState
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets.fromLTRB(8, 8, 8, 0),
|
||||
child: Text(
|
||||
"Order Date: MM/DD/YYYY",
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"Order Date: ",
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: Get.width * 0.04,
|
||||
fontWeight: FontWeight.w400,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
Text(formatDate("${widget.placedOrderList!.createdAt}")),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: Get.width,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(
|
||||
"Total Price: ₹ Total",
|
||||
padding: EdgeInsets.all(8.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"Total Amount: ",
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: Get.width * 0.04,
|
||||
fontWeight: FontWeight.w400,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
Text("₹ ${widget.placedOrderList!.grandTotal}"),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
@ -153,11 +212,52 @@ class _OrderManagementDetailScreenState
|
||||
padding: EdgeInsets.all(Get.width * 0.02),
|
||||
child: ListView.builder(
|
||||
padding: EdgeInsets.zero,
|
||||
itemCount: 10,
|
||||
itemBuilder: (context, index) => ProductCard(
|
||||
product: _checkoutList[0],
|
||||
isCheckout: true,
|
||||
itemCount: widget.placedOrderList?.orderItem.length ?? 0,
|
||||
itemBuilder: (context, index) {
|
||||
final orderItem = widget.placedOrderList!.orderItem[index];
|
||||
return orderItem != null
|
||||
? Card(
|
||||
margin: const EdgeInsets.symmetric(vertical: 5.0),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Row(
|
||||
children: [
|
||||
Image.asset(
|
||||
"assets/images/product.png", // Add the image URL here
|
||||
height: 50,
|
||||
width: 50,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
Text(
|
||||
capitalizeFirstLetter(orderItem.name),
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: Get.width * 0.04,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"Quantity: ${orderItem.quantity}",
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: Get.width * 0.03,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
: const SizedBox.shrink();
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -182,31 +282,38 @@ class _OrderManagementDetailScreenState
|
||||
),
|
||||
SizedBox(
|
||||
width: Get.width,
|
||||
height: Get.height*0.06,
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets.fromLTRB(8, 8, 8, 0),
|
||||
child: Text(
|
||||
"Address: Hyderabad",
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
"Address: ",
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: Get.width * 0.04,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
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,
|
||||
),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
AutoSizeText("${widget.placedOrderList!.shipTo}",maxLines: 4,
|
||||
overflow:TextOverflow.ellipsis,)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
// 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,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -216,13 +323,18 @@ class _OrderManagementDetailScreenState
|
||||
width: Get.width,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: Text(
|
||||
"Status: Processing/ Shipped/ Delivered",
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
"Status: ",
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: Get.width * 0.04,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
Text(capitalizeFirstLetter("${widget.placedOrderList!.status}")),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -231,29 +343,31 @@ class _OrderManagementDetailScreenState
|
||||
),
|
||||
),
|
||||
SizedBox(height: Get.height * 0.04),
|
||||
SizedBox(
|
||||
width: Get.width * 0.9,
|
||||
height: Get.height * 0.06,
|
||||
child: ElevatedButton(
|
||||
onPressed: () => Get.to(
|
||||
() => const OrderFullfilmentScreen(),
|
||||
),
|
||||
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,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
// 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,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -1,3 +1,4 @@
|
||||
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';
|
||||
@ -5,9 +6,16 @@ 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';
|
||||
|
||||
|
||||
class OrderManagementScreen extends StatefulWidget {
|
||||
const OrderManagementScreen({super.key});
|
||||
final Product? productModel;
|
||||
PlacedOrderList? placeOrder;
|
||||
OrderManagementScreen({super.key, this.productModel, this.placeOrder});
|
||||
|
||||
@override
|
||||
State<OrderManagementScreen> createState() => _OrderManagementScreenState();
|
||||
@ -15,10 +23,39 @@ class OrderManagementScreen extends StatefulWidget {
|
||||
|
||||
class _OrderManagementScreenState extends State<OrderManagementScreen> {
|
||||
final _searchController = TextEditingController();
|
||||
final List<String> _filterList = [
|
||||
"Order Status",
|
||||
"Date Range",
|
||||
];
|
||||
final List<String> _filterList = ["Order Status", "Date Range"];
|
||||
|
||||
final GetPlacedOrderController _getPlacedOrderController = Get.put(GetPlacedOrderController());
|
||||
final CartController _cartController = Get.put(CartController());
|
||||
final GlobalKey<RefreshIndicatorState> _refreshIndicatorKey =
|
||||
GlobalKey<RefreshIndicatorState>();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
getOrder1();
|
||||
}
|
||||
|
||||
Future<void> _onRefresh() async {
|
||||
await getOrder1();
|
||||
await Future.delayed(Duration(seconds: 1));
|
||||
}
|
||||
|
||||
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').format(parsedDate);
|
||||
return formattedDate;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -34,9 +71,7 @@ class _OrderManagementScreenState extends State<OrderManagementScreen> {
|
||||
onTap: () => Scaffold.of(context).openDrawer(),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: SvgPicture.asset(
|
||||
'assets/svg/menu.svg',
|
||||
),
|
||||
child: SvgPicture.asset('assets/svg/menu.svg'),
|
||||
),
|
||||
);
|
||||
},
|
||||
@ -46,29 +81,26 @@ class _OrderManagementScreenState extends State<OrderManagementScreen> {
|
||||
onTap: () => Get.back(),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: SvgPicture.asset(
|
||||
'assets/svg/back_arrow.svg',
|
||||
),
|
||||
child: SvgPicture.asset('assets/svg/back_arrow.svg'),
|
||||
),
|
||||
),
|
||||
],
|
||||
title: const Text(
|
||||
"Order Management",
|
||||
),
|
||||
title: const Text("Order Management"),
|
||||
),
|
||||
drawer: const MyDrawer(),
|
||||
body: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
Image.asset(
|
||||
'assets/images/image_1.png',
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
Image.asset('assets/images/image_1.png', fit: BoxFit.cover),
|
||||
SafeArea(
|
||||
child: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(
|
||||
bottom: MediaQuery.of(context).viewInsets.bottom),
|
||||
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,
|
||||
@ -98,15 +130,11 @@ class _OrderManagementScreenState extends State<OrderManagementScreen> {
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemCount: _filterList.length,
|
||||
itemBuilder: (context, index) => Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 4),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 4),
|
||||
child: Chip(
|
||||
label: Text(
|
||||
_filterList[index],
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.w500),
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -114,60 +142,96 @@ class _OrderManagementScreenState extends State<OrderManagementScreen> {
|
||||
),
|
||||
SizedBox(
|
||||
height: Get.height * 0.6,
|
||||
child: ListView.builder(
|
||||
child: Obx(() {
|
||||
// Use a set to keep track of unique order IDs
|
||||
final Set<String> uniqueOrderIds = {};
|
||||
final List<PlacedOrderList> uniqueOrders = [];
|
||||
|
||||
for (var order in _getPlacedOrderController.placedOrders) {
|
||||
if (uniqueOrderIds.add(order.id)) {
|
||||
uniqueOrders.add(order);
|
||||
}
|
||||
}
|
||||
|
||||
return ListView.builder(
|
||||
padding: EdgeInsets.zero,
|
||||
shrinkWrap: true,
|
||||
itemCount: 2,
|
||||
itemBuilder: (context, index) => Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(vertical: 8),
|
||||
itemCount: uniqueOrders.length,
|
||||
itemBuilder: (context, index) {
|
||||
final order = uniqueOrders[index];
|
||||
|
||||
// Combine product names into a single string
|
||||
final productNames = order.orderItem
|
||||
.map((item) => capitalizeFirstLetter(item.name))
|
||||
.join(', ');
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
child: Card(
|
||||
child: Column(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(
|
||||
16, 8, 8, 0),
|
||||
child: Text(
|
||||
"Order ID: 123456",
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
padding: const EdgeInsets.fromLTRB(16, 8, 8, 0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text("Order ID: ", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.bold)),
|
||||
Text("${order.uniqueId}")
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(
|
||||
16, 8, 8, 0),
|
||||
child: Text(
|
||||
"Product Name: XYZ",
|
||||
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.w400,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start, // Aligns text to the right within the Column
|
||||
children: [
|
||||
const SizedBox(height: 4), // Adds a small space between the label and the product names
|
||||
for (int i = 0; i < productNames.split(",").length; i++)
|
||||
Text(
|
||||
'${i + 1}. ${productNames.split(",")[i].trim()}', // Adds index and trims whitespace
|
||||
textAlign: TextAlign.left, // Aligns text to the right
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 8, 8, 0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text("Order Date: ", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.bold)),
|
||||
Text(formatDate("${order.createdAt}"))
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(
|
||||
16, 8, 8, 0),
|
||||
child: Text(
|
||||
"Order Date: MM/DD/YYYY",
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(
|
||||
16, 8, 8, 8),
|
||||
child: Text(
|
||||
"Status: Processing/shipped/delivered",
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
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(
|
||||
@ -175,34 +239,25 @@ class _OrderManagementScreenState extends State<OrderManagementScreen> {
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: ElevatedButton(
|
||||
onPressed: () => Get.to(
|
||||
() =>
|
||||
const OrderManagementDetailScreen(),
|
||||
),
|
||||
onPressed: () => Get.to(() => OrderManagementDetailScreen(
|
||||
placedOrderList: uniqueOrders[index])),
|
||||
style: ElevatedButton.styleFrom(
|
||||
foregroundColor: Colors.white,
|
||||
backgroundColor:
|
||||
const Color(0xFF004791),
|
||||
backgroundColor: const Color(0xFF004791),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius:
|
||||
BorderRadius.circular(10),
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
"View Details",
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(10)),
|
||||
),
|
||||
child: Text("View Details", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.w400)),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}),
|
||||
)
|
||||
],
|
||||
),
|
||||
@ -213,8 +268,259 @@ 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)),
|
||||
// ),
|
||||
// ),
|
||||
// )
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
// },
|
||||
// );
|
||||
// }),
|
||||
// )
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
//
|
||||
|
@ -1,31 +1,58 @@
|
||||
import 'package:cheminova/models/product_model.dart';
|
||||
|
||||
import 'package:cheminova/screens/order/checkout_screen.dart';
|
||||
import 'package:cheminova/widgets/my_drawer.dart';
|
||||
import 'package:cheminova/widgets/product_card.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:get/get_core/get_core.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
|
||||
import '../../controller/cart_controller.dart';
|
||||
import '../../models/oder_place_model.dart';
|
||||
import '../../models/product_model1.dart';
|
||||
|
||||
class CartScreen extends StatefulWidget {
|
||||
const CartScreen({super.key});
|
||||
Product? productModel;
|
||||
PlacedOrderModel? placedOrder;
|
||||
|
||||
CartScreen({super.key, this.productModel, this.placedOrder});
|
||||
|
||||
@override
|
||||
State<CartScreen> createState() => _CartScreenState();
|
||||
}
|
||||
|
||||
class _CartScreenState extends State<CartScreen> {
|
||||
final List<ProductModel> _cartList = [
|
||||
ProductModel(
|
||||
id: "1",
|
||||
image: 'assets/images/product.png',
|
||||
name: "Product 1",
|
||||
category: ProductCategory.food,
|
||||
description: 'Product 1 description',
|
||||
price: 100,
|
||||
),
|
||||
];
|
||||
final CartController _cartController = Get.find<CartController>();
|
||||
|
||||
bool _selectAll = true; // Default to true to select all products
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
if (widget.productModel != null) {
|
||||
_cartController.addToCart(widget.productModel!);
|
||||
}
|
||||
// Ensure all products are pre-selected by default
|
||||
_cartController.initializeSelections();
|
||||
_checkIfAllSelected(); // Check if all products are selected by default
|
||||
}
|
||||
|
||||
void _toggleSelectAll(bool? value) {
|
||||
setState(() {
|
||||
_selectAll = value ?? false;
|
||||
_cartController.selectAllProducts(_selectAll);
|
||||
});
|
||||
}
|
||||
|
||||
void _checkIfAllSelected() {
|
||||
// This function checks if all items are selected or not and updates _selectAll
|
||||
setState(() {
|
||||
_selectAll = _cartController.cartList.every(
|
||||
(product) => _cartController.selectedProducts.contains(product),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
@ -57,10 +84,12 @@ class _CartScreenState extends State<CartScreen> {
|
||||
),
|
||||
),
|
||||
],
|
||||
title: const Text(
|
||||
title: const Center(
|
||||
child: Text(
|
||||
"Cart",
|
||||
),
|
||||
),
|
||||
),
|
||||
drawer: const MyDrawer(),
|
||||
body: Stack(
|
||||
fit: StackFit.expand,
|
||||
@ -70,7 +99,31 @@ class _CartScreenState extends State<CartScreen> {
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
SafeArea(
|
||||
child: Obx(() {
|
||||
if (_cartController.cartList.isEmpty) {
|
||||
return Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Image.asset(
|
||||
'assets/images/cart.png',
|
||||
width: Get.width * 0.5,
|
||||
height: Get.width * 0.5,
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Text(
|
||||
'Your Cart is empty',
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
return Column(
|
||||
children: [
|
||||
SizedBox(
|
||||
height: Get.height * 0.02,
|
||||
@ -87,43 +140,112 @@ class _CartScreenState extends State<CartScreen> {
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
// "Select All" Checkbox
|
||||
Row(
|
||||
children: [
|
||||
Checkbox(
|
||||
value: _selectAll,
|
||||
onChanged: _toggleSelectAll,
|
||||
),
|
||||
Text(
|
||||
"Select All",
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
height: Get.height * 0.6,
|
||||
child: ListView.builder(
|
||||
padding: EdgeInsets.zero,
|
||||
itemCount: 10,
|
||||
itemBuilder: (context, index) => ProductCard(
|
||||
product: _cartList[0],
|
||||
itemCount: _cartController.cartList.length,
|
||||
itemBuilder: (context, index) {
|
||||
return Row(
|
||||
children: [
|
||||
Checkbox(
|
||||
value: _cartController.selectedProducts.contains(
|
||||
_cartController.cartList[index]),
|
||||
onChanged: (value) {
|
||||
_cartController.toggleProductSelection(
|
||||
_cartController.cartList[index],
|
||||
value!,
|
||||
);
|
||||
_checkIfAllSelected(); // Check if all are selected after each toggle
|
||||
},
|
||||
),
|
||||
Expanded(
|
||||
child: ProductCard(
|
||||
productModel:
|
||||
_cartController.cartList[index],
|
||||
isInCart: true,
|
||||
placedOrder: widget.placedOrder,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"Total Price: ₹ Total",
|
||||
"Subtotal ",
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: Colors.white,
|
||||
fontSize: 15,
|
||||
color: Colors.black,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 16,
|
||||
Obx(() =>
|
||||
Text("₹ ${_cartController.subtotal.value}")),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"GST ",
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: 15,
|
||||
color: Colors.black,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
Obx(() =>
|
||||
Text("₹ ${_cartController.gstTotal.value}")),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"Total Amount ",
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: 15,
|
||||
color: Colors.black,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
Obx(() => Text(
|
||||
"₹ ${_cartController.grandTotal.value}")),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: Get.height * 0.025,
|
||||
),
|
||||
SizedBox(height: Get.height * 0.020),
|
||||
SizedBox(
|
||||
width: Get.width * 0.9,
|
||||
height: Get.height * 0.06,
|
||||
child: ElevatedButton(
|
||||
onPressed: () => Get.to(() => const CheckoutScreen()),
|
||||
onPressed: () => Get.to(() => CheckoutScreen(
|
||||
selectedProducts: _cartController.selectedProducts,
|
||||
)),
|
||||
style: ElevatedButton.styleFrom(
|
||||
foregroundColor: Colors.white,
|
||||
backgroundColor: const Color(0xFF00784C),
|
||||
@ -141,10 +263,277 @@ class _CartScreenState extends State<CartScreen> {
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// import 'package:cheminova/models/oder_place_model.dart';
|
||||
// import 'package:cheminova/models/product_model.dart';
|
||||
// import 'package:cheminova/screens/order/checkout_screen.dart';
|
||||
// import 'package:cheminova/widgets/my_drawer.dart';
|
||||
// import 'package:cheminova/widgets/product_card.dart';
|
||||
// import 'package:flutter/material.dart';
|
||||
// import 'package:flutter_svg/svg.dart';
|
||||
// import 'package:get/get.dart';
|
||||
// import 'package:google_fonts/google_fonts.dart';
|
||||
//
|
||||
// import '../../controller/cart_controller.dart';
|
||||
// import '../../models/product_model1.dart';
|
||||
//
|
||||
// class CartScreen extends StatefulWidget {
|
||||
// Product? productModel;
|
||||
// PlacedOrderModel? placedOrder;
|
||||
//
|
||||
// CartScreen({super.key, this.productModel, this.placedOrder});
|
||||
//
|
||||
// @override
|
||||
// State<CartScreen> createState() => _CartScreenState();
|
||||
// }
|
||||
//
|
||||
// class _CartScreenState extends State<CartScreen> {
|
||||
// final CartController _cartController = Get.find<CartController>();
|
||||
//
|
||||
// bool _selectAll = false; // State to track "Select All" checkbox
|
||||
//
|
||||
// @override
|
||||
// void initState() {
|
||||
// super.initState();
|
||||
// if (widget.productModel != null) {
|
||||
// _cartController.addToCart(widget.productModel!);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// void _toggleSelectAll(bool? value) {
|
||||
// setState(() {
|
||||
// _selectAll = value ?? false;
|
||||
// _cartController.cartList.forEach((product) {
|
||||
// _cartController.toggleProductSelection(product, _selectAll);
|
||||
// });
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// return Scaffold(
|
||||
// extendBodyBehindAppBar: true,
|
||||
// appBar: AppBar(
|
||||
// backgroundColor: Colors.transparent,
|
||||
// elevation: 0,
|
||||
// leading: Builder(
|
||||
// builder: (context) {
|
||||
// return GestureDetector(
|
||||
// onTap: () => Scaffold.of(context).openDrawer(),
|
||||
// child: Padding(
|
||||
// padding: const EdgeInsets.all(16.0),
|
||||
// child: SvgPicture.asset(
|
||||
// 'assets/svg/menu.svg',
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
// },
|
||||
// ),
|
||||
// actions: [
|
||||
// GestureDetector(
|
||||
// onTap: () => Get.back(),
|
||||
// child: Padding(
|
||||
// padding: const EdgeInsets.all(8.0),
|
||||
// child: SvgPicture.asset(
|
||||
// 'assets/svg/back_arrow.svg',
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// title: Center(
|
||||
// child: const Text(
|
||||
// "Cart",
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// drawer: const MyDrawer(),
|
||||
// body: Stack(
|
||||
// fit: StackFit.expand,
|
||||
// children: [
|
||||
// Image.asset(
|
||||
// 'assets/images/image_1.png',
|
||||
// fit: BoxFit.cover,
|
||||
// ),
|
||||
// SafeArea(
|
||||
// child: Obx(() {
|
||||
// if (_cartController.cartList.isEmpty) {
|
||||
// return Center(
|
||||
// child: Column(
|
||||
// mainAxisAlignment: MainAxisAlignment.center,
|
||||
// children: [
|
||||
// Image.asset(
|
||||
// 'assets/images/cart.png',
|
||||
// width: Get.width * 0.5,
|
||||
// height: Get.width * 0.5,
|
||||
// ),
|
||||
// const SizedBox(height: 20),
|
||||
// Text(
|
||||
// 'Your Cart is empty',
|
||||
// style: GoogleFonts.roboto(
|
||||
// fontSize: 24,
|
||||
// fontWeight: FontWeight.w500,
|
||||
// color: Colors.white,
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
// return Column(
|
||||
// children: [
|
||||
// SizedBox(
|
||||
// height: Get.height * 0.02,
|
||||
// ),
|
||||
// Card(
|
||||
// margin: const EdgeInsets.symmetric(horizontal: 18),
|
||||
// shape: RoundedRectangleBorder(
|
||||
// borderRadius: BorderRadius.circular(19),
|
||||
// side: const BorderSide(color: Color(0xFFFDFDFD)),
|
||||
// ),
|
||||
// color: const Color(0xFFB4D1E5).withOpacity(0.9),
|
||||
// child: Padding(
|
||||
// padding: const EdgeInsets.all(12.0),
|
||||
// child: Column(
|
||||
// mainAxisSize: MainAxisSize.min,
|
||||
// children: [
|
||||
// // "Select All" Checkbox
|
||||
// Row(
|
||||
// children: [
|
||||
// Checkbox(
|
||||
// value: _selectAll,
|
||||
// onChanged: _toggleSelectAll,
|
||||
// ),
|
||||
// Text(
|
||||
// "Select All",
|
||||
// style: GoogleFonts.roboto(
|
||||
// fontSize: 16,
|
||||
// fontWeight: FontWeight.w500,
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// SizedBox(
|
||||
// height: Get.height * 0.6,
|
||||
// child: ListView.builder(
|
||||
// padding: EdgeInsets.zero,
|
||||
// itemCount: _cartController.cartList.length,
|
||||
// itemBuilder: (context, index) {
|
||||
// return Row(
|
||||
// children: [
|
||||
// Checkbox(
|
||||
// value: _cartController
|
||||
// .cartList[index].selected,
|
||||
// onChanged: (value) {
|
||||
// setState(() {
|
||||
//
|
||||
// });
|
||||
// _cartController.toggleProductSelection(
|
||||
// _cartController.cartList[index],
|
||||
// value!);
|
||||
// },
|
||||
// ),
|
||||
// Expanded(
|
||||
// child: ProductCard(
|
||||
// productModel:
|
||||
// _cartController.cartList[index],
|
||||
// isInCart: true,
|
||||
// placedOrder: widget.placedOrder,
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
// },
|
||||
// ),
|
||||
// ),
|
||||
// const SizedBox(height: 10),
|
||||
// Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
// children: [
|
||||
// Text(
|
||||
// "Subtotal ",
|
||||
// style: GoogleFonts.roboto(
|
||||
// fontSize: 15,
|
||||
// color: Colors.black,
|
||||
// fontWeight: FontWeight.bold,
|
||||
// ),
|
||||
// ),
|
||||
// Obx(() => Text("₹ ${_cartController.subtotal.value}")),
|
||||
// ],
|
||||
// ),
|
||||
// Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
// children: [
|
||||
// Text(
|
||||
// "GST ",
|
||||
// style: GoogleFonts.roboto(
|
||||
// fontSize: 15,
|
||||
// color: Colors.black,
|
||||
// fontWeight: FontWeight.bold,
|
||||
// ),
|
||||
// ),
|
||||
// Obx(() => Text("₹ ${_cartController.gstTotal.value}")),
|
||||
// ],
|
||||
// ),
|
||||
// Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
// children: [
|
||||
// Text(
|
||||
// "Total Amount ",
|
||||
// style: GoogleFonts.roboto(
|
||||
// fontSize: 15,
|
||||
// color: Colors.black,
|
||||
// fontWeight: FontWeight.bold,
|
||||
// ),
|
||||
// ),
|
||||
// Obx(() => Text("₹ ${_cartController.grandTotal.value}")),
|
||||
// ],
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// SizedBox(height: Get.height * 0.020),
|
||||
// SizedBox(
|
||||
// width: Get.width * 0.9,
|
||||
// height: Get.height * 0.06,
|
||||
// child: ElevatedButton(
|
||||
// onPressed: () => Get.to(() => CheckoutScreen(
|
||||
// productModel: widget.productModel,
|
||||
// )),
|
||||
// style: ElevatedButton.styleFrom(
|
||||
// foregroundColor: Colors.white,
|
||||
// backgroundColor: const Color(0xFF00784C),
|
||||
// shape: RoundedRectangleBorder(
|
||||
// borderRadius: BorderRadius.circular(10),
|
||||
// ),
|
||||
// ),
|
||||
// child: Text(
|
||||
// "Proceed to Checkout",
|
||||
// style: GoogleFonts.roboto(
|
||||
// fontSize: 16,
|
||||
// fontWeight: FontWeight.w600,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
// }),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
26
lib/screens/product/pdf_screen.dart
Normal file
26
lib/screens/product/pdf_screen.dart
Normal file
@ -0,0 +1,26 @@
|
||||
|
||||
import 'package:cheminova/models/product_mannual_model.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart';
|
||||
|
||||
|
||||
class ViewPdfScreen extends StatefulWidget {
|
||||
final ProductManualModel productManualModel;
|
||||
const ViewPdfScreen({super.key, required this.productManualModel});
|
||||
|
||||
@override
|
||||
State<ViewPdfScreen> createState() => _ViewPdfScreenState();
|
||||
}
|
||||
|
||||
class _ViewPdfScreenState extends State<ViewPdfScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: SafeArea(
|
||||
child: SfPdfViewer.network(
|
||||
widget.productManualModel.productManual.url,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,10 +1,14 @@
|
||||
import 'package:cheminova/models/product_model.dart';
|
||||
import 'package:cheminova/widgets/my_drawer.dart';
|
||||
import 'package:cheminova/widgets/product_card.dart';
|
||||
import 'package:cheminova/models/product_model1.dart';
|
||||
import 'package:cheminova/screens/product/cart_screen.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import '../../controller/cart_controller.dart';
|
||||
import '../../widgets/my_drawer.dart';
|
||||
import '../../widgets/product_card.dart';
|
||||
import '../../controller/product_service.dart';
|
||||
import '../../models/product_model.dart'; // Import your ProductModel
|
||||
|
||||
class ProductCatalogScreen extends StatefulWidget {
|
||||
const ProductCatalogScreen({super.key});
|
||||
@ -14,22 +18,103 @@ class ProductCatalogScreen extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _ProductCatalogScreenState extends State<ProductCatalogScreen> {
|
||||
final List<ProductModel> _productList = [
|
||||
ProductModel(
|
||||
id: '1',
|
||||
name: 'Product 1',
|
||||
price: 100,
|
||||
description: 'Description 1',
|
||||
category: ProductCategory.food,
|
||||
image: 'assets/images/product.png',
|
||||
)
|
||||
];
|
||||
final ProductService _productService = ProductService();
|
||||
final ScrollController _scrollController = ScrollController();
|
||||
final CartController cartController = Get.put(CartController());
|
||||
|
||||
List<Product> _products = []; // Use ProductModel here
|
||||
List<Map<String, dynamic>> _categories = [];
|
||||
|
||||
int _currentPage = 1;
|
||||
bool _isLoading = false;
|
||||
bool _hasMoreData = true;
|
||||
|
||||
String? _selectedCategory;
|
||||
String? _selectedPriceRange;
|
||||
String? _selectedAvailability;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_fetchCategories();
|
||||
_fetchProducts();
|
||||
_scrollController.addListener(() {
|
||||
if (_scrollController.position.pixels ==
|
||||
_scrollController.position.maxScrollExtent &&
|
||||
!_isLoading &&
|
||||
_hasMoreData) {
|
||||
_fetchMoreProducts();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _fetchProducts() async {
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
});
|
||||
|
||||
final category = _selectedCategory == 'All' ? null : _selectedCategory;
|
||||
|
||||
final products = await _productService.getProduct(
|
||||
_currentPage, category: category);
|
||||
setState(() {
|
||||
if (products != null) {
|
||||
_products.addAll(products); // Assuming products is a List<ProductModel>
|
||||
_hasMoreData = products.isNotEmpty;
|
||||
}
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _fetchCategories() async {
|
||||
final categories = await _productService.getCategory();
|
||||
if (categories != null) {
|
||||
setState(() {
|
||||
_categories = categories;
|
||||
_categories.insert(1, {'categoryName': 'All'});
|
||||
_selectedCategory = 'All';
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void _onCategoryChanged(String? newCategory) {
|
||||
if (newCategory != null) {
|
||||
setState(() {
|
||||
_selectedCategory = newCategory;
|
||||
_products.clear();
|
||||
_currentPage = 1;
|
||||
});
|
||||
_fetchProducts();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _fetchMoreProducts() async {
|
||||
if (!_isLoading && _hasMoreData) {
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
_currentPage++;
|
||||
});
|
||||
await _fetchProducts();
|
||||
}
|
||||
}
|
||||
|
||||
void _clearFilters() {
|
||||
setState(() {
|
||||
_selectedCategory = null;
|
||||
_selectedPriceRange = null;
|
||||
_selectedAvailability = null;
|
||||
_products.clear();
|
||||
_currentPage = 1;
|
||||
});
|
||||
_fetchProducts();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_scrollController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
final List<String> _filterList = [
|
||||
"Category",
|
||||
"Price Range",
|
||||
"Availability",
|
||||
];
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
@ -52,19 +137,44 @@ class _ProductCatalogScreenState extends State<ProductCatalogScreen> {
|
||||
),
|
||||
actions: [
|
||||
GestureDetector(
|
||||
onTap: () => Get.back(),
|
||||
onTap: () => Get.to(CartScreen()),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: SvgPicture.asset(
|
||||
'assets/svg/back_arrow.svg',
|
||||
child: Stack(
|
||||
children: [
|
||||
Icon(Icons.shopping_cart, size: 30,),
|
||||
// Cart count display
|
||||
Positioned(
|
||||
right: 0,
|
||||
child: Obx(() =>
|
||||
cartController.cartCount.value > 0
|
||||
? Container(
|
||||
padding: EdgeInsets.all(4),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.red,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: Text(
|
||||
'${cartController.cartCount.value}',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
)
|
||||
: SizedBox.shrink()),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
title: const Text(
|
||||
title: Center(
|
||||
child: const Text(
|
||||
"Product Catalogue",
|
||||
),
|
||||
),
|
||||
),
|
||||
drawer: const MyDrawer(),
|
||||
body: Stack(
|
||||
fit: StackFit.expand,
|
||||
@ -74,11 +184,24 @@ class _ProductCatalogScreenState extends State<ProductCatalogScreen> {
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
SafeArea(
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
SizedBox(
|
||||
height: Get.height * 0.02,
|
||||
SizedBox(height: Get.height * 0.02),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 18.0),
|
||||
child: TextField(
|
||||
decoration: InputDecoration(
|
||||
hintText: "Search Products",
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
),
|
||||
filled: true,
|
||||
fillColor: Colors.white.withOpacity(0.9),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: Get.height * 0.02),
|
||||
Card(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 18),
|
||||
shape: RoundedRectangleBorder(
|
||||
@ -91,41 +214,62 @@ class _ProductCatalogScreenState extends State<ProductCatalogScreen> {
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"Filter",
|
||||
style: GoogleFonts.poppins(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: _clearFilters,
|
||||
child: Text(
|
||||
"Clear Filter",
|
||||
style: GoogleFonts.poppins(
|
||||
color: Colors.red,
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
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,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
itemCount: 3,
|
||||
itemBuilder: (context, index) =>
|
||||
_buildFilterDropdown(index),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: Get.height * 0.6,
|
||||
child: ListView.builder(
|
||||
controller: _scrollController,
|
||||
padding: EdgeInsets.zero,
|
||||
shrinkWrap: true,
|
||||
itemCount: 10,
|
||||
itemBuilder: (context, index) => Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
itemCount: _products.length +
|
||||
(_isLoading ? 1 : 0),
|
||||
itemBuilder: (context, index) {
|
||||
if (index >= _products.length) {
|
||||
print("Product length $_products");
|
||||
return const Center(
|
||||
child: CircularProgressIndicator());
|
||||
}
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 8),
|
||||
child: ProductCard(
|
||||
product: _productList[0],
|
||||
productModel: _products[index],
|
||||
// Use ProductModel here
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -133,8 +277,98 @@ class _ProductCatalogScreenState extends State<ProductCatalogScreen> {
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildFilterDropdown(int index) {
|
||||
switch (index) {
|
||||
case 0:
|
||||
return _buildStyledDropdown(
|
||||
value: _selectedCategory,
|
||||
onChanged: _onCategoryChanged,
|
||||
items: _categories.map((category) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: category['categoryName'],
|
||||
child: Text(category['categoryName']),
|
||||
);
|
||||
}).toList(),
|
||||
hint: "Category",
|
||||
);
|
||||
// case 1:
|
||||
// return _buildStyledDropdown(
|
||||
// value: _selectedPriceRange,
|
||||
// onChanged: (value) {
|
||||
// setState(() {
|
||||
// _selectedPriceRange = value;
|
||||
// });
|
||||
// },
|
||||
// items: [
|
||||
// const DropdownMenuItem<String>(
|
||||
// value: "Under ₹50",
|
||||
// child: Text("Under ₹50"),
|
||||
// ),
|
||||
// const DropdownMenuItem<String>(
|
||||
// value: "₹50 - ₹100",
|
||||
// child: Text("₹50 - ₹100"),
|
||||
// ),
|
||||
// const DropdownMenuItem<String>(
|
||||
// value: "Above ₹100",
|
||||
// child: Text("Above ₹100"),
|
||||
// ),
|
||||
// ],
|
||||
// hint: "Price Range",
|
||||
// );
|
||||
// case 2:
|
||||
// return _buildStyledDropdown(
|
||||
// value: _selectedAvailability,
|
||||
// onChanged: (value) {
|
||||
// setState(() {
|
||||
// _selectedAvailability = value;
|
||||
// });
|
||||
// },
|
||||
// items: [
|
||||
// const DropdownMenuItem<String>(
|
||||
// value: "In Stock",
|
||||
// child: Text("In Stock"),
|
||||
// ),
|
||||
// const DropdownMenuItem<String>(
|
||||
// value: "Out of Stock",
|
||||
// child: Text("Out of Stock"),
|
||||
// ),
|
||||
// ],
|
||||
// hint: "Availability",
|
||||
// );
|
||||
default:
|
||||
return const SizedBox();
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildStyledDropdown({
|
||||
required String? value,
|
||||
required ValueChanged<String?> onChanged,
|
||||
required List<DropdownMenuItem<String>> items,
|
||||
required String hint,
|
||||
}) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8.0),
|
||||
border: Border.all(color: Colors.grey.shade300),
|
||||
color: Colors.white,
|
||||
),
|
||||
child: DropdownButtonHideUnderline(
|
||||
child: DropdownButton<String>(
|
||||
value: value,
|
||||
onChanged: onChanged,
|
||||
items: items,
|
||||
hint: Text(hint),
|
||||
icon: const Icon(Icons.arrow_drop_down),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,20 +1,30 @@
|
||||
import 'package:cheminova/models/product_model.dart';
|
||||
import 'package:cheminova/screens/product/cart_screen.dart';
|
||||
import 'package:cheminova/models/product_model1.dart';
|
||||
import 'package:cheminova/utils/show_snackbar.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 '../../controller/cart_controller.dart';
|
||||
|
||||
class ProductDetailScreen extends StatefulWidget {
|
||||
final ProductModel product;
|
||||
const ProductDetailScreen({super.key, required this.product});
|
||||
Product? productModel;
|
||||
ProductModel? product;
|
||||
|
||||
ProductDetailScreen({super.key, this.product, this.productModel});
|
||||
|
||||
@override
|
||||
State<ProductDetailScreen> createState() => _ProductDetailScreenState();
|
||||
}
|
||||
|
||||
class _ProductDetailScreenState extends State<ProductDetailScreen> {
|
||||
final CartController _cartController = Get.put(CartController());
|
||||
String capitalizeFirstLetter(String text) {
|
||||
if (text.isEmpty) return text;
|
||||
return text[0].toUpperCase() + text.substring(1).toLowerCase();
|
||||
}
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
@ -83,7 +93,7 @@ class _ProductDetailScreenState extends State<ProductDetailScreen> {
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Container(
|
||||
height: Get.height * 0.4,
|
||||
width: Get.width * 0.7,
|
||||
width: Get.width * 0.8,
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
width: 4,
|
||||
@ -93,57 +103,81 @@ class _ProductDetailScreenState extends State<ProductDetailScreen> {
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
child: Image.asset(
|
||||
widget.product.image,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
child: Image.asset("assets/images/product.png", fit: BoxFit.cover,),
|
||||
// Image.asset(
|
||||
// widget.product.image,
|
||||
// fit: BoxFit.cover,
|
||||
// ),
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: Text(
|
||||
widget.product.name,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text("Product Name ",style: TextStyle(fontWeight: FontWeight.bold,fontSize: 16),),
|
||||
Text(
|
||||
capitalizeFirstLetter(widget.productModel!.name),
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.white,
|
||||
fontSize: 16,
|
||||
// fontWeight: FontWeight.w600,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: Text(
|
||||
"₹ ${widget.product.price.toString()}",
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text("Price ",style: TextStyle(fontSize: 16,fontWeight: FontWeight.bold),),
|
||||
Text(
|
||||
"₹ ${widget.productModel!.price.toString()}",
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.w800,
|
||||
color: Colors.white,
|
||||
fontSize: 16,
|
||||
//fontWeight: FontWeight.w800,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: Text(
|
||||
widget.product.category.name,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text("Category ",style: TextStyle(fontWeight: FontWeight.bold,fontSize: 16),),
|
||||
Text(
|
||||
capitalizeFirstLetter(widget.productModel!.category.categoryName),
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Colors.white,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: Text(
|
||||
widget.product.description,
|
||||
child: Row(
|
||||
children: [
|
||||
const Text("Description",style: TextStyle(fontWeight: FontWeight.bold,fontSize: 16)),
|
||||
Text(
|
||||
capitalizeFirstLetter(widget.productModel!.description),
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Colors.white,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
@ -154,7 +188,11 @@ class _ProductDetailScreenState extends State<ProductDetailScreen> {
|
||||
width: Get.width * 0.9,
|
||||
height: Get.height * 0.06,
|
||||
child: ElevatedButton(
|
||||
onPressed: () => Get.to(() => const CartScreen()),
|
||||
onPressed: () {
|
||||
// Pass the product data to the CartScreen
|
||||
_cartController.addToCart(widget.productModel!);
|
||||
showSnackbar("Product successfully added to your cart");
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
foregroundColor: Colors.white,
|
||||
backgroundColor: const Color(0xFF00784C),
|
||||
|
134
lib/screens/product/product_manual.dart
Normal file
134
lib/screens/product/product_manual.dart
Normal file
@ -0,0 +1,134 @@
|
||||
import 'package:cheminova/controller/product_mannual_controller.dart';
|
||||
import 'package:cheminova/models/product_mannual_model.dart';
|
||||
import 'package:cheminova/screens/product/pdf_screen.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import '../../widgets/custom_button.dart';
|
||||
|
||||
class ProductsManualScreen extends StatefulWidget {
|
||||
const ProductsManualScreen({super.key});
|
||||
|
||||
@override
|
||||
_ProductsManualScreenState createState() => _ProductsManualScreenState();
|
||||
}
|
||||
|
||||
class _ProductsManualScreenState extends State<ProductsManualScreen> {
|
||||
final ProductManualController _productManualController = Get.put(ProductManualController());
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_productManualController.fetchProductManuals(); // Fetch product manual list from API
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
extendBodyBehindAppBar: true,
|
||||
appBar: _buildAppBar(),
|
||||
body: Stack(
|
||||
alignment: Alignment.topCenter,
|
||||
children: [
|
||||
_buildBackgroundImage(),
|
||||
Center(
|
||||
child: SingleChildScrollView(
|
||||
child: _buildCardContent(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Extract AppBar to its own method
|
||||
AppBar _buildAppBar() {
|
||||
return AppBar(
|
||||
backgroundColor: Colors.transparent,
|
||||
elevation: 0,
|
||||
leading: GestureDetector(
|
||||
onTap: () => Get.back(),
|
||||
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'),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// Extract background image widget
|
||||
Widget _buildBackgroundImage() {
|
||||
return Container(
|
||||
height: 900,
|
||||
decoration: const BoxDecoration(
|
||||
image: DecorationImage(
|
||||
fit: BoxFit.cover,
|
||||
image: AssetImage('assets/images/image_1.png'),
|
||||
),
|
||||
),
|
||||
child: SizedBox(
|
||||
width: Get.width,
|
||||
height: Get.height * 0.7,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Build the card content
|
||||
Widget _buildCardContent() {
|
||||
return Obx(() {
|
||||
if (_productManualController.isLoading.value) {
|
||||
return const CircularProgressIndicator(); // Loading state
|
||||
}
|
||||
|
||||
if (_productManualController.productManualList.isEmpty) {
|
||||
return const Text("No product manuals available"); // Empty state
|
||||
}
|
||||
|
||||
return Card(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 24),
|
||||
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(16.0),
|
||||
child: Column(
|
||||
children: _buildProductButtons(),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// Method to create a list of CustomButtons for products dynamically from API data
|
||||
List<Widget> _buildProductButtons() {
|
||||
return _productManualController.productManualList.map((productManual) {
|
||||
return CustomButton(
|
||||
text: productManual.title ?? "No Title", // Dynamically fetch product name
|
||||
onPressed: () => _navigateToPdfScreen(productManual),
|
||||
);
|
||||
}).toList();
|
||||
}
|
||||
|
||||
// Method to handle navigation to PDF screen
|
||||
void _navigateToPdfScreen(ProductManualModel productManual) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => ViewPdfScreen(
|
||||
productManualModel: productManual,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
99
lib/screens/profile_screen.dart
Normal file
99
lib/screens/profile_screen.dart
Normal file
@ -0,0 +1,99 @@
|
||||
// import 'package:cheminova/controller/home_controller.dart';
|
||||
// import 'package:cheminova/widgets/my_drawer.dart';
|
||||
// import 'package:flutter/cupertino.dart';
|
||||
// import 'package:flutter/material.dart';
|
||||
//
|
||||
// import '../widgets/comman_background.dart';
|
||||
// import '../widgets/common_appbar.dart';
|
||||
//
|
||||
// class ProfileScreen extends StatelessWidget {
|
||||
// const ProfileScreen({Key? key}) : super(key: key);
|
||||
//
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// return Stack(
|
||||
// children: [
|
||||
// CommonBackground(
|
||||
// isFullWidth: true,
|
||||
// child: Scaffold(
|
||||
// drawer: const MyDrawer(),
|
||||
// backgroundColor: Colors.transparent,
|
||||
// appBar: CommonAppBar(
|
||||
// title: const Text('Profile'),
|
||||
// backgroundColor: Colors.transparent,
|
||||
// elevation: 0,
|
||||
// actions: [
|
||||
// IconButton(
|
||||
// onPressed: () {
|
||||
// Navigator.pop(context);
|
||||
// },
|
||||
// icon: Image.asset('assets/Back_attendance.png'),
|
||||
// padding: const EdgeInsets.only(right: 20),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// body: Consumer<HomeController>(
|
||||
// builder: (context, profileProvider, child) {
|
||||
// final profileData = profileProvider.profileResponse?.myData!;
|
||||
// return SingleChildScrollView(
|
||||
// child: Column(
|
||||
// children: [
|
||||
// Container(
|
||||
// padding: const EdgeInsets.all(20.0).copyWith(top: 15, bottom: 30),
|
||||
// margin: const EdgeInsets.symmetric(horizontal: 30.0, vertical: 20.0),
|
||||
// decoration: BoxDecoration(
|
||||
// border: Border.all(color: Colors.white),
|
||||
// color: const Color(0xffB4D1E5).withOpacity(0.9),
|
||||
// borderRadius: BorderRadius.circular(26.0),
|
||||
// ),
|
||||
// child: Column(
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// children: [
|
||||
// SizedBox(height: 20),
|
||||
// _buildProfileItem('Name', profileData?.name ?? ''),
|
||||
// _buildProfileItem('ID', profileData?.uniqueId ?? ''),
|
||||
// _buildProfileItem('Email ID', profileData?.email ?? ''),
|
||||
// _buildProfileItem('Mobile Number', profileData?.mobileNumber ?? ''),
|
||||
// _buildProfileItem('Designation', profileData?.designation ?? ''),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// );
|
||||
// },
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// Widget _buildProfileItem(String label, String value) {
|
||||
// return Padding(
|
||||
// padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
// child: Column(
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// children: [
|
||||
// Text(
|
||||
// label,
|
||||
// style: const TextStyle(
|
||||
// fontSize: 16,
|
||||
// fontWeight: FontWeight.bold,
|
||||
// color: Color(0xff004791),
|
||||
// ),
|
||||
// ),
|
||||
// const SizedBox(height: 5),
|
||||
// Text(
|
||||
// value,
|
||||
// style: const TextStyle(
|
||||
// fontSize: 18,
|
||||
// color: Colors.black,
|
||||
// ),
|
||||
// ),
|
||||
// const Divider(color: Colors.grey),
|
||||
// ],
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
// }
|
@ -1,9 +1,11 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:cheminova/screens/authentication/login_screen.dart';
|
||||
import 'package:cheminova/screens/home_screen.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
class SplashScreen extends StatefulWidget {
|
||||
const SplashScreen({super.key});
|
||||
@ -15,12 +17,25 @@ class SplashScreen extends StatefulWidget {
|
||||
class _SplashScreenState extends State<SplashScreen> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
Timer(const Duration(seconds: 2), () {
|
||||
Get.offAll(() => const LoginScreen());
|
||||
Timer(const Duration(seconds: 3), () {
|
||||
checkLogin();
|
||||
});
|
||||
super.initState();
|
||||
|
||||
}
|
||||
|
||||
checkLogin() async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
String? token = prefs.getString('token');
|
||||
if (token != null) {
|
||||
Get.offAll(() => const HomeScreen());
|
||||
} else {
|
||||
Get.offAll(() => const LoginScreen());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
|
18
lib/utils/api_urls.dart
Normal file
18
lib/utils/api_urls.dart
Normal file
@ -0,0 +1,18 @@
|
||||
class ApiUrls {
|
||||
// static const String baseUrl = 'https://cheminova-api-2.onrender.com/api/';
|
||||
static const String baseUrl = 'https://api.cnapp.co.in';
|
||||
static const String loginUrl = '/api/v1/user/login/';
|
||||
static const String profileUrl = '/api/rd-get-me';
|
||||
static const String forgetPasswordUrl = '/api/v1/user/password/forgot';
|
||||
static const String changePasswordUrl = '/api/v1/user/password/update';
|
||||
static const String fcmUrl = '/api/v1/user/fcm-token';
|
||||
static const String getCategoryUrl = '/api/category/getCategories';
|
||||
static const String getProductUrl = '/api/category/getCategories';
|
||||
static const String getProductManualUrl = '/api/productmanual/getall';
|
||||
static const String getKycUrl = '/api/kyc/getAll';
|
||||
static const String getNotificationUrl = '/api/get-notification-pd';
|
||||
static const String getPlacedOrderUrl ='/api/get-placed-order-pd';
|
||||
static const String getSinglePlacedOrderUrl ='/api/get-single-placed-order-pd';
|
||||
static const String placedOrderUrl ='${baseUrl}/api/order-place';
|
||||
|
||||
}
|
@ -1,80 +1,86 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:cheminova/utils/constants.dart';
|
||||
import 'package:cheminova/utils/show_snackbar.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:pretty_dio_logger/pretty_dio_logger.dart';
|
||||
|
||||
Future<BodyType?> commonApiService<BodyType>({
|
||||
required String url,
|
||||
required String method,
|
||||
Map<String, dynamic> body = const {},
|
||||
File? imageFile,
|
||||
bool isformData = true,
|
||||
bool isFormData = false,
|
||||
Map<String, String>? additionalHeaders,
|
||||
required BodyType Function(Map<String, dynamic>) fromJson,
|
||||
}) async {
|
||||
try {
|
||||
Dio dio = Dio();
|
||||
final Response response;
|
||||
final dio = Dio();
|
||||
|
||||
print("body : $body");
|
||||
// Add PrettyDioLogger
|
||||
dio.interceptors.add(PrettyDioLogger(
|
||||
requestHeader: true,
|
||||
requestBody: true,
|
||||
responseBody: true,
|
||||
responseHeader: false,
|
||||
error: true,
|
||||
compact: true,
|
||||
maxWidth: 90,
|
||||
));
|
||||
|
||||
// Fetch the token from SharedPreferences
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
String? token = prefs.getString('token');
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final token = prefs.getString('token');
|
||||
|
||||
Map<String, String> headers = {
|
||||
'Content-Type': isformData ? 'multipart/form-data' : 'application/json',
|
||||
final headers = <String, String>{
|
||||
'Content-Type': isFormData ? 'multipart/form-data' : 'application/json',
|
||||
if (token != null) 'Authorization': 'Bearer $token',
|
||||
...?additionalHeaders,
|
||||
};
|
||||
|
||||
if (token != null) {
|
||||
headers['Authorization'] = 'Bearer $token';
|
||||
}
|
||||
final options = Options(headers: headers);
|
||||
|
||||
Options options = Options(headers: headers);
|
||||
dynamic requestData = isFormData ? FormData.fromMap(body) : body;
|
||||
|
||||
FormData formData = FormData.fromMap(body);
|
||||
|
||||
if (imageFile != null) {
|
||||
String fileName = imageFile.path.split('/').last;
|
||||
formData.files.add(MapEntry(
|
||||
if (imageFile != null && isFormData) {
|
||||
final fileName = imageFile.path.split('/').last;
|
||||
(requestData as FormData).files.add(MapEntry(
|
||||
"image",
|
||||
await MultipartFile.fromFile(imageFile.path, filename: fileName),
|
||||
));
|
||||
}
|
||||
|
||||
if (method == "POST") {
|
||||
response = await dio.post("$baseUrl$url",
|
||||
data: isformData ? formData : body, options: options);
|
||||
} else if (method == "PUT") {
|
||||
response = await dio.put("$baseUrl$url",
|
||||
data: isformData ? formData : body, options: options);
|
||||
} else if (method == "DELETE") {
|
||||
final Response response;
|
||||
switch (method.toUpperCase()) {
|
||||
case "POST":
|
||||
response = await dio.post("$baseUrl$url", data: requestData, options: options);
|
||||
break;
|
||||
case "PUT":
|
||||
response = await dio.put("$baseUrl$url", data: requestData, options: options);
|
||||
break;
|
||||
case "DELETE":
|
||||
response = await dio.delete("$baseUrl$url", options: options);
|
||||
} else if (method == "PATCH") {
|
||||
response = await dio.patch("$baseUrl$url",
|
||||
data: isformData ? formData : body, options: options);
|
||||
} else {
|
||||
break;
|
||||
case "PATCH":
|
||||
response = await dio.patch("$baseUrl$url", data: requestData, options: options);
|
||||
break;
|
||||
case "GET":
|
||||
response = await dio.get("$baseUrl$url", options: options);
|
||||
break;
|
||||
default:
|
||||
throw Exception("Unsupported HTTP method: $method");
|
||||
}
|
||||
|
||||
print("response of $url : $response");
|
||||
|
||||
if (url == "/api/territorymanager/login" &&
|
||||
response.data['token'] != null) {
|
||||
prefs.setString('token', response.data['token']);
|
||||
if (url == "/api/rd-login" && response.data['token'] != null) {
|
||||
await prefs.setString('token', response.data['token']);
|
||||
}
|
||||
|
||||
if (url == "/api/territorymanager/my-profile") {
|
||||
if (url == "/api/rd-get-me" && response.data['myData'] != null) {
|
||||
return fromJson(response.data['myData']);
|
||||
}
|
||||
|
||||
return fromJson(response.data);
|
||||
} on DioException catch (e) {
|
||||
print("dio exception $url ${e.response?.data}}");
|
||||
print("dio exception details: ${e.message} ${e.response?.statusCode}");
|
||||
String errorMessage = "An error occurred";
|
||||
|
||||
if (e.response?.data is Map<String, dynamic>) {
|
||||
errorMessage = e.response?.data['message'] ?? errorMessage;
|
||||
} else if (e.response?.data is String) {
|
||||
@ -82,8 +88,10 @@ Future<BodyType?> commonApiService<BodyType>({
|
||||
}
|
||||
|
||||
showSnackbar(errorMessage);
|
||||
return null;
|
||||
} catch (e) {
|
||||
print("exception $url $e");
|
||||
}
|
||||
print("Unexpected error for $url: $e");
|
||||
showSnackbar("An unexpected error occurred");
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1 +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";
|
7
lib/utils/log_service.dart
Normal file
7
lib/utils/log_service.dart
Normal file
@ -0,0 +1,7 @@
|
||||
import 'package:logger/logger.dart';
|
||||
|
||||
final logger = Logger(
|
||||
printer: PrettyPrinter(
|
||||
lineLength: 500
|
||||
)
|
||||
);
|
27
lib/widgets/comman_background.dart
Normal file
27
lib/widgets/comman_background.dart
Normal file
@ -0,0 +1,27 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class CommonBackground extends StatelessWidget {
|
||||
final Widget child;
|
||||
final bool isFullWidth;
|
||||
|
||||
const CommonBackground(
|
||||
{super.key, required this.child, this.isFullWidth = true, appBar});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
color: Colors.white,
|
||||
child: Stack(children: [
|
||||
Container(
|
||||
height: isFullWidth
|
||||
? MediaQuery.sizeOf(context).height
|
||||
: MediaQuery.sizeOf(context).height * 0.90,
|
||||
decoration: BoxDecoration(
|
||||
image: const DecorationImage(
|
||||
image: AssetImage('assets/images/image_1.png'),
|
||||
fit: BoxFit.cover))),
|
||||
child
|
||||
]),
|
||||
);
|
||||
}
|
||||
}
|
93
lib/widgets/comman_text_from_filed.dart
Normal file
93
lib/widgets/comman_text_from_filed.dart
Normal file
@ -0,0 +1,93 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
class CommonTextFormField extends StatefulWidget {
|
||||
final String title;
|
||||
final String? label;
|
||||
final TextEditingController? controller;
|
||||
//final TextCapitalization textCapitalization;
|
||||
final String? Function(String?)? validator;
|
||||
final Color? fillColor;
|
||||
final bool? readOnly;
|
||||
final int? maxLines;
|
||||
final double? height;
|
||||
final TextInputType? keyboardType;
|
||||
final List<TextInputFormatter>? inputFormatters;
|
||||
final int? maxLength;
|
||||
final bool obscureText;
|
||||
final void Function(String)? onChanged;
|
||||
|
||||
const CommonTextFormField({
|
||||
super.key,
|
||||
required this.title,
|
||||
this.label,
|
||||
this.controller,
|
||||
this.validator,
|
||||
this.fillColor,
|
||||
this.readOnly,
|
||||
this.maxLines,
|
||||
this.height,
|
||||
this.keyboardType,
|
||||
this.inputFormatters,
|
||||
this.maxLength,
|
||||
this.onChanged,
|
||||
// this.textCapitalization = TextCapitalization.sentences,
|
||||
this.obscureText = false,
|
||||
});
|
||||
|
||||
@override
|
||||
_CommonTextFormFieldState createState() => _CommonTextFormFieldState();
|
||||
}
|
||||
|
||||
class _CommonTextFormFieldState extends State<CommonTextFormField> {
|
||||
bool _isObscured = true;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
TextFormField(
|
||||
controller: widget.controller,
|
||||
//textCapitalization: widget.textCapitalization,
|
||||
readOnly: widget.readOnly ?? false,
|
||||
maxLines: widget.maxLines ?? 1,
|
||||
maxLength: widget.maxLength,
|
||||
onChanged: widget.onChanged,
|
||||
onTapOutside: (event) => FocusScope.of(context).unfocus(),
|
||||
validator: widget.validator,
|
||||
keyboardType: widget.keyboardType,
|
||||
inputFormatters: widget.inputFormatters,
|
||||
obscureText: widget.obscureText && _isObscured,
|
||||
decoration: InputDecoration(
|
||||
hintText: widget.title,
|
||||
labelText: widget.label,
|
||||
contentPadding: const EdgeInsets.only(bottom: 10, left: 10),
|
||||
filled: true,
|
||||
suffixIcon: widget.obscureText
|
||||
? IconButton(
|
||||
icon: Icon(
|
||||
_isObscured ? Icons.visibility : Icons.visibility_off,
|
||||
color: Colors.grey,
|
||||
),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_isObscured = !_isObscured;
|
||||
});
|
||||
},
|
||||
)
|
||||
: null,
|
||||
focusedBorder: const OutlineInputBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(6)),
|
||||
borderSide: BorderSide(color: Colors.transparent),
|
||||
),
|
||||
enabledBorder: const OutlineInputBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(6)),
|
||||
borderSide: BorderSide(color: Colors.transparent),
|
||||
),
|
||||
fillColor: widget.fillColor ?? Colors.white,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
29
lib/widgets/common_appbar.dart
Normal file
29
lib/widgets/common_appbar.dart
Normal file
@ -0,0 +1,29 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class CommonAppBar extends StatelessWidget implements PreferredSizeWidget {
|
||||
final Widget title;
|
||||
final List<Widget>? actions;
|
||||
final TabBar? bottom;
|
||||
|
||||
const CommonAppBar({super.key, required this.title, this.actions, required Color backgroundColor, required int elevation, this.bottom});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AppBar(
|
||||
centerTitle: true,
|
||||
leading: Builder(builder: (context) {
|
||||
return IconButton(
|
||||
onPressed: () => Scaffold.of(context).openDrawer(),
|
||||
icon: const Icon(Icons.menu),
|
||||
color: Colors.white);
|
||||
}),
|
||||
backgroundColor: Colors.transparent,
|
||||
bottom: bottom,
|
||||
title: title,
|
||||
toolbarHeight: kToolbarHeight+20,
|
||||
actions: actions);
|
||||
}
|
||||
|
||||
@override
|
||||
Size get preferredSize => const Size.fromHeight(kToolbarHeight);
|
||||
}
|
46
lib/widgets/common_elevated_button.dart
Normal file
46
lib/widgets/common_elevated_button.dart
Normal file
@ -0,0 +1,46 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class CommonElevatedButton extends StatelessWidget {
|
||||
final String text;
|
||||
final void Function()? onPressed;
|
||||
final double? height;
|
||||
final double? width;
|
||||
final double? borderRadius;
|
||||
final Color? backgroundColor;
|
||||
final bool isLoading;
|
||||
|
||||
const CommonElevatedButton(
|
||||
{super.key,
|
||||
required this.text,
|
||||
this.onPressed,
|
||||
this.borderRadius,
|
||||
this.backgroundColor,
|
||||
this.height,
|
||||
this.width,
|
||||
this.isLoading = false});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
height: height ?? kToolbarHeight - 25,
|
||||
width: width ?? 200,
|
||||
child: ElevatedButton(
|
||||
onPressed: isLoading ? null : onPressed,
|
||||
style: ElevatedButton.styleFrom(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(borderRadius ?? 6)),
|
||||
backgroundColor: backgroundColor ?? const Color(0xff1E1E1E),
|
||||
side: const BorderSide(color: Colors.transparent)),
|
||||
child: Center(
|
||||
child: isLoading
|
||||
? const CircularProgressIndicator(
|
||||
backgroundColor: Colors.white,
|
||||
valueColor: AlwaysStoppedAnimation<Color>(Colors.black))
|
||||
: Text(text,
|
||||
style: const TextStyle(
|
||||
fontSize: 15,
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.w400,
|
||||
fontFamily: 'Anek')))));
|
||||
}
|
||||
}
|
@ -1,22 +1,31 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class InputField extends StatelessWidget {
|
||||
class InputField extends StatefulWidget {
|
||||
final String hintText;
|
||||
final String labelText;
|
||||
final TextEditingController controller;
|
||||
final bool obscureText;
|
||||
final TextInputType? keyboardType;
|
||||
final String? Function(String?)? validator;// Add this line for validation
|
||||
|
||||
const InputField({
|
||||
InputField({
|
||||
super.key,
|
||||
required this.hintText,
|
||||
required this.labelText,
|
||||
required this.controller,
|
||||
this.obscureText = false,
|
||||
this.keyboardType = TextInputType.text,
|
||||
this.validator, // Add this
|
||||
});
|
||||
|
||||
@override
|
||||
State<InputField> createState() => _InputFieldState();
|
||||
}
|
||||
|
||||
class _InputFieldState extends State<InputField> {
|
||||
bool _isObscured = true;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
@ -24,15 +33,16 @@ class InputField extends StatelessWidget {
|
||||
width: Get.width * 0.9,
|
||||
padding: const EdgeInsets.fromLTRB(6, 10, 10, 0),
|
||||
child: TextFormField(
|
||||
controller: controller,
|
||||
obscureText: obscureText,
|
||||
keyboardType: keyboardType,
|
||||
controller: widget.controller,
|
||||
obscureText: widget.obscureText && _isObscured,
|
||||
keyboardType: widget.keyboardType,
|
||||
decoration: InputDecoration(
|
||||
labelText: labelText,
|
||||
hintText: hintText,
|
||||
labelText: widget.labelText,
|
||||
hintText: widget.hintText,
|
||||
labelStyle: const TextStyle(
|
||||
color: Color(0xFF000000),
|
||||
),
|
||||
|
||||
enabledBorder: const OutlineInputBorder(
|
||||
borderSide: BorderSide(color: Colors.grey),
|
||||
borderRadius: BorderRadius.all(Radius.circular(8)),
|
||||
@ -45,7 +55,21 @@ class InputField extends StatelessWidget {
|
||||
const EdgeInsets.symmetric(vertical: 10, horizontal: 16),
|
||||
fillColor: Colors.white,
|
||||
filled: true,
|
||||
// suffixIcon: widget.obscureText
|
||||
// ? IconButton(
|
||||
// icon: Icon(
|
||||
// _isObscured ? Icons.visibility : Icons.visibility_off,
|
||||
// color: Colors.grey,
|
||||
// ),
|
||||
// onPressed: () {
|
||||
// setState(() {
|
||||
// _isObscured = !_isObscured;
|
||||
// });
|
||||
// },
|
||||
// )
|
||||
// : null,
|
||||
),
|
||||
validator: widget.validator, // Add this for validation
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -1,9 +1,12 @@
|
||||
import 'package:cheminova/controller/home_controller.dart';
|
||||
import 'package:cheminova/screens/authentication/change_password_screen.dart';
|
||||
import 'package:cheminova/screens/authentication/login_screen.dart';
|
||||
import 'package:cheminova/screens/home_screen.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import '../screens/authentication/Profile.dart';
|
||||
|
||||
class MyDrawer extends StatefulWidget {
|
||||
const MyDrawer({super.key});
|
||||
|
||||
@ -21,32 +24,37 @@ class _MyDrawerState extends State<MyDrawer> {
|
||||
children: <Widget>[
|
||||
SizedBox(
|
||||
height: 150,
|
||||
child: Obx(
|
||||
() => DrawerHeader(
|
||||
child:(
|
||||
DrawerHeader(
|
||||
decoration: const BoxDecoration(
|
||||
color: Colors.black87,
|
||||
),
|
||||
child: Column(
|
||||
child: GetBuilder(
|
||||
init: homeController,
|
||||
builder: (controller) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
homeController.user.value?.name ?? "username",
|
||||
controller.user?.name?? "username",
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 18,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
homeController.user.value?.uniqueId ?? 'Employee ID',
|
||||
controller.user?.uniqueId?? 'Employee ID',
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 20,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
),
|
||||
),
|
||||
)
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
@ -58,13 +66,15 @@ class _MyDrawerState extends State<MyDrawer> {
|
||||
leading: const Icon(Icons.account_circle),
|
||||
title: const Text('Profile'),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
Get.to(ProfileScreen());
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.settings),
|
||||
title: const Text('Change Password'),
|
||||
onTap: () {},
|
||||
onTap: () {
|
||||
Get.to(ChangePasswordScreen());
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.exit_to_app),
|
||||
|
@ -1,26 +1,64 @@
|
||||
import 'package:cheminova/controller/cart_controller.dart';
|
||||
import 'package:cheminova/models/oder_place_model.dart';
|
||||
import 'package:cheminova/models/order_item_model.dart';
|
||||
import 'package:cheminova/models/place_order_list_model.dart';
|
||||
import 'package:cheminova/models/product_model.dart';
|
||||
import 'package:cheminova/screens/product/product_detail_screen.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
|
||||
class ProductCard extends StatelessWidget {
|
||||
final ProductModel product;
|
||||
import '../models/product_model1.dart';
|
||||
import '../utils/show_snackbar.dart';
|
||||
|
||||
class ProductCard extends StatefulWidget {
|
||||
final Product? productModel;
|
||||
PlacedOrderModel? placedOrder;
|
||||
PlacedOrderList? placedOrderList;
|
||||
PlaceOrderItem1? placeorderItem;
|
||||
ProductModel? product;
|
||||
final bool isInCart;
|
||||
final bool isCheckout;
|
||||
const ProductCard({
|
||||
final bool isConfirmation;
|
||||
int? quantity;
|
||||
|
||||
ProductCard({
|
||||
super.key,
|
||||
required this.product,
|
||||
this.product,
|
||||
this.quantity = 1,
|
||||
this.productModel,
|
||||
this.placedOrder,
|
||||
this.placedOrderList,
|
||||
this.placeorderItem,
|
||||
this.isInCart = false,
|
||||
this.isCheckout = false,
|
||||
this.isConfirmation = false,
|
||||
});
|
||||
|
||||
@override
|
||||
State<ProductCard> createState() => _ProductCardState();
|
||||
}
|
||||
|
||||
class _ProductCardState extends State<ProductCard> {
|
||||
String capitalizeFirstLetter(String text) {
|
||||
if (text.isEmpty) return text;
|
||||
return text[0].toUpperCase() + text.substring(1).toLowerCase();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final CartController _cartController = Get.put(CartController());
|
||||
bool showQuantity = widget.isInCart || widget.isCheckout || widget.isConfirmation;
|
||||
bool isProductInCart = _cartController.cartList.any((p) => p.id == widget.productModel!.id);
|
||||
|
||||
int currentQuantity = isProductInCart
|
||||
? _cartController.cartList.firstWhere((p) => p.id == widget.productModel!.id).quantity
|
||||
: widget.productModel!.quantity;
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () => isInCart || isCheckout
|
||||
onTap: () => widget.isInCart || widget.isCheckout
|
||||
? null
|
||||
: Get.to(() => ProductDetailScreen(product: product)),
|
||||
: Get.to(() => ProductDetailScreen(productModel: widget.productModel)),
|
||||
child: Card(
|
||||
child: Row(
|
||||
children: [
|
||||
@ -30,98 +68,83 @@ class ProductCard extends StatelessWidget {
|
||||
borderRadius: BorderRadius.circular(15.0),
|
||||
child: Container(
|
||||
height: Get.height * 0.15,
|
||||
width: Get.width * 0.30,
|
||||
width: Get.width * 0.31,
|
||||
decoration: BoxDecoration(
|
||||
image: DecorationImage(
|
||||
image: Image.asset(product.image).image,
|
||||
image: AssetImage("assets/images/product.png"),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Column(
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 3.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
product.name,
|
||||
capitalizeFirstLetter(widget.productModel!.name),
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
product.category.name,
|
||||
capitalizeFirstLetter(widget.productModel!.category!.categoryName),
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"₹ ${product.price.toString()}0",
|
||||
"₹ ${widget.productModel!.price.toString()}",
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: 22,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
),
|
||||
isCheckout
|
||||
? const SizedBox()
|
||||
: isInCart
|
||||
if (showQuantity)
|
||||
Text(
|
||||
"Quantity: ${currentQuantity}",
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
),
|
||||
if (!widget.isCheckout)
|
||||
widget.isInCart
|
||||
? Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Container(
|
||||
height: 40,
|
||||
width: 100,
|
||||
height: Get.height * 0.04,
|
||||
width: Get.width * 0.21,
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFF004791),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceAround,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 24,
|
||||
width: 24,
|
||||
child: ElevatedButton(
|
||||
onPressed: () {},
|
||||
onPressed: () {
|
||||
_cartController.decreaseQuantity(widget.productModel!);
|
||||
setState(() {
|
||||
currentQuantity = _cartController
|
||||
.cartList
|
||||
.firstWhere((p) => p.id == widget.productModel!.id)
|
||||
.quantity;
|
||||
});
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
padding: EdgeInsets.zero,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius:
|
||||
BorderRadius.circular(8.0),
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
'+',
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w800,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
product.quantity.toString(),
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 24,
|
||||
width: 24,
|
||||
child: ElevatedButton(
|
||||
onPressed: () {},
|
||||
style: ElevatedButton.styleFrom(
|
||||
padding: EdgeInsets.zero,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius:
|
||||
BorderRadius.circular(8.0),
|
||||
borderRadius: BorderRadius.circular(8.0),
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
@ -133,25 +156,75 @@ class ProductCard extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"${currentQuantity}",
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 22,
|
||||
width: 22,
|
||||
child: ElevatedButton(
|
||||
onPressed: () {
|
||||
_cartController.increaseQuantity(widget.productModel!);
|
||||
setState(() {
|
||||
currentQuantity = _cartController
|
||||
.cartList
|
||||
.firstWhere((p) => p.id == widget.productModel!.id)
|
||||
.quantity;
|
||||
});
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
padding: EdgeInsets.zero,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8.0),
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
'+',
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w800,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 2.0,
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () {},
|
||||
onPressed: () {
|
||||
_cartController.removeFromCart(widget.productModel!);
|
||||
showSnackbar("Product has been removed successfully!");
|
||||
setState(() {
|
||||
currentQuantity = 1;
|
||||
});
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.delete_outline_rounded,
|
||||
color: Colors.red,
|
||||
),
|
||||
)
|
||||
),
|
||||
],
|
||||
)
|
||||
: ElevatedButton(
|
||||
onPressed: () {},
|
||||
onPressed: () {
|
||||
if (isProductInCart) {
|
||||
showSnackbar("Product already added to cart");
|
||||
} else {
|
||||
_cartController.addToCart(widget.productModel!);
|
||||
showSnackbar("Product successfully added to your cart");
|
||||
}
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
foregroundColor: Colors.white,
|
||||
backgroundColor: const Color(0xFF00784C),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 18, vertical: 8),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 8),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(30),
|
||||
),
|
||||
@ -165,7 +238,9 @@ class ProductCard extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -6,6 +6,14 @@
|
||||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <file_selector_linux/file_selector_plugin.h>
|
||||
#include <url_launcher_linux/url_launcher_plugin.h>
|
||||
|
||||
void fl_register_plugins(FlPluginRegistry* registry) {
|
||||
g_autoptr(FlPluginRegistrar) file_selector_linux_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin");
|
||||
file_selector_plugin_register_with_registrar(file_selector_linux_registrar);
|
||||
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
|
||||
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
|
||||
}
|
||||
|
@ -3,6 +3,8 @@
|
||||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
file_selector_linux
|
||||
url_launcher_linux
|
||||
)
|
||||
|
||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||
|
@ -5,10 +5,28 @@
|
||||
import FlutterMacOS
|
||||
import Foundation
|
||||
|
||||
import device_info_plus
|
||||
import file_selector_macos
|
||||
import firebase_analytics
|
||||
import firebase_core
|
||||
import firebase_crashlytics
|
||||
import firebase_messaging
|
||||
import flutter_local_notifications
|
||||
import path_provider_foundation
|
||||
import shared_preferences_foundation
|
||||
import syncfusion_pdfviewer_macos
|
||||
import url_launcher_macos
|
||||
|
||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
|
||||
FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
|
||||
FLTFirebaseAnalyticsPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAnalyticsPlugin"))
|
||||
FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin"))
|
||||
FLTFirebaseCrashlyticsPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCrashlyticsPlugin"))
|
||||
FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin"))
|
||||
FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin"))
|
||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
||||
SyncfusionFlutterPdfViewerPlugin.register(with: registry.registrar(forPlugin: "SyncfusionFlutterPdfViewerPlugin"))
|
||||
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
|
||||
}
|
||||
|
544
pubspec.lock
544
pubspec.lock
@ -1,6 +1,14 @@
|
||||
# Generated by pub
|
||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||
packages:
|
||||
_flutterfire_internals:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: _flutterfire_internals
|
||||
sha256: ddc6f775260b89176d329dee26f88b9469ef46aa3228ff6a0b91caf2b2989692
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.42"
|
||||
args:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -17,6 +25,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.11.0"
|
||||
auto_size_text:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: auto_size_text
|
||||
sha256: "3f5261cd3fb5f2a9ab4e2fc3fba84fd9fcaac8821f20a1d4e71f557521b22599"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.0"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -49,6 +65,22 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.18.0"
|
||||
convert:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: convert
|
||||
sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.1"
|
||||
cross_file:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: cross_file
|
||||
sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.3.4+2"
|
||||
crypto:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -57,6 +89,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.3"
|
||||
csc_picker:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: csc_picker
|
||||
sha256: "7e5d6023a81f53b89a7fb0369953fd4dc676f7ea20e9a0c0707973a5f0aedf14"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.7"
|
||||
cupertino_icons:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -65,6 +105,30 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.8"
|
||||
dbus:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: dbus
|
||||
sha256: "365c771ac3b0e58845f39ec6deebc76e3276aa9922b0cc60840712094d9047ac"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.10"
|
||||
device_info_plus:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: device_info_plus
|
||||
sha256: a7fd703482b391a87d60b6061d04dfdeab07826b96f9abd8f5ed98068acc0074
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "10.1.2"
|
||||
device_info_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: device_info_plus_platform_interface
|
||||
sha256: "282d3cf731045a2feb66abfe61bbc40870ae50a3ed10a4d3d217556c35c8c2ba"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.1"
|
||||
dio:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -105,6 +169,134 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.0"
|
||||
file_selector_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file_selector_linux
|
||||
sha256: "045d372bf19b02aeb69cacf8b4009555fb5f6f0b7ad8016e5f46dd1387ddd492"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.9.2+1"
|
||||
file_selector_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file_selector_macos
|
||||
sha256: f42eacb83b318e183b1ae24eead1373ab1334084404c8c16e0354f9a3e55d385
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.9.4"
|
||||
file_selector_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file_selector_platform_interface
|
||||
sha256: a3994c26f10378a039faa11de174d7b78eb8f79e4dd0af2a451410c1a5c3f66b
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.6.2"
|
||||
file_selector_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file_selector_windows
|
||||
sha256: "2ad726953f6e8affbc4df8dc78b77c3b4a060967a291e528ef72ae846c60fb69"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.9.3+2"
|
||||
firebase_analytics:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: firebase_analytics
|
||||
sha256: "7b5ae39d853ead76f9d030dc23389bfec4ea826d7cccb4eea4873dcb0cdd172b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "11.3.1"
|
||||
firebase_analytics_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: firebase_analytics_platform_interface
|
||||
sha256: "0205e05bb37abd29d5dec5cd89aeb04f3f58bf849aad21dd938be0507d52a40c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.2.3"
|
||||
firebase_analytics_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: firebase_analytics_web
|
||||
sha256: "434807f8b30526e21cc062410c28ee5c6680a13626c4443b5ffede29f84b0c74"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.5.10"
|
||||
firebase_core:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: firebase_core
|
||||
sha256: "40921de9795fbf5887ed5c0adfdf4972d5a8d7ae7e1b2bb98dea39bc02626a88"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.4.1"
|
||||
firebase_core_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: firebase_core_platform_interface
|
||||
sha256: f7d7180c7f99babd4b4c517754d41a09a4943a0f7a69b65c894ca5c68ba66315
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.2.1"
|
||||
firebase_core_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: firebase_core_web
|
||||
sha256: f4ee170441ca141c5f9ee5ad8737daba3ee9c8e7efb6902aee90b4fbd178ce25
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.18.0"
|
||||
firebase_crashlytics:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: firebase_crashlytics
|
||||
sha256: c4fdbb14ba6f36794f89dc27fb5c759c9cc67ecbaeb079edc4dba515bbf9f555
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.1.1"
|
||||
firebase_crashlytics_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: firebase_crashlytics_platform_interface
|
||||
sha256: "891d6f7ba4b93672d0e1265f27b6a9dccd56ba2cc30ce6496586b32d1d8770ac"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.6.42"
|
||||
firebase_messaging:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: firebase_messaging
|
||||
sha256: cc02c4afd6510cd84586020670140c4a23fbe52af16cd260ccf8ede101bb8d1b
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "15.1.1"
|
||||
firebase_messaging_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: firebase_messaging_platform_interface
|
||||
sha256: d8a4984635f09213302243ea670fe5c42f3261d7d8c7c0a5f7dcd5d6c84be459
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.5.44"
|
||||
firebase_messaging_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: firebase_messaging_web
|
||||
sha256: "258b9d637965db7855299b123533609ed95e52350746a723dfd1d8d6f3fac678"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.9.0"
|
||||
fixnum:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fixnum
|
||||
sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
@ -118,6 +310,38 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.2"
|
||||
flutter_local_notifications:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_local_notifications
|
||||
sha256: c500d5d9e7e553f06b61877ca6b9c8b92c570a4c8db371038702e8ce57f8a50f
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "17.2.2"
|
||||
flutter_local_notifications_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_local_notifications_linux
|
||||
sha256: c49bd06165cad9beeb79090b18cd1eb0296f4bf4b23b84426e37dd7c027fc3af
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.1"
|
||||
flutter_local_notifications_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_local_notifications_platform_interface
|
||||
sha256: "85f8d07fe708c1bdcf45037f2c0109753b26ae077e9d9e899d55971711a4ea66"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.2.0"
|
||||
flutter_plugin_android_lifecycle:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_plugin_android_lifecycle
|
||||
sha256: "9ee02950848f61c4129af3d6ec84a1cfc0e47931abc746b03e7a3bc3e8ff6eda"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.22"
|
||||
flutter_svg:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -144,6 +368,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.6.6"
|
||||
get_storage:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: get_storage
|
||||
sha256: "39db1fffe779d0c22b3a744376e86febe4ade43bf65e06eab5af707dc84185a2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
google_fonts:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -152,6 +384,22 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.2.1"
|
||||
hive:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: hive
|
||||
sha256: "8dcf6db979d7933da8217edcec84e9df1bdb4e4edc7fc77dbd5aa74356d6d941"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.3"
|
||||
hive_flutter:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: hive_flutter
|
||||
sha256: dca1da446b1d808a51689fb5d0c6c9510c0a2ba01e22805d492c73b68e33eecc
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
http:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -168,22 +416,102 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.2"
|
||||
image_picker:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: image_picker
|
||||
sha256: "021834d9c0c3de46bf0fe40341fa07168407f694d9b2bb18d532dc1261867f7a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.2"
|
||||
image_picker_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image_picker_android
|
||||
sha256: "8c5abf0dcc24fe6e8e0b4a5c0b51a5cf30cefdf6407a3213dae61edc75a70f56"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.8.12+12"
|
||||
image_picker_for_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image_picker_for_web
|
||||
sha256: "65d94623e15372c5c51bebbcb820848d7bcb323836e12dfdba60b5d3a8b39e50"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.5"
|
||||
image_picker_ios:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image_picker_ios
|
||||
sha256: "6703696ad49f5c3c8356d576d7ace84d1faf459afb07accbb0fae780753ff447"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.8.12"
|
||||
image_picker_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image_picker_linux
|
||||
sha256: "4ed1d9bb36f7cd60aa6e6cd479779cc56a4cb4e4de8f49d487b1aaad831300fa"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.1+1"
|
||||
image_picker_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image_picker_macos
|
||||
sha256: "3f5ad1e8112a9a6111c46d0b57a7be2286a9a07fc6e1976fdf5be2bd31d4ff62"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.1+1"
|
||||
image_picker_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image_picker_platform_interface
|
||||
sha256: "9ec26d410ff46f483c5519c29c02ef0e02e13a543f882b152d4bfd2f06802f80"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.10.0"
|
||||
image_picker_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image_picker_windows
|
||||
sha256: "6ad07afc4eb1bc25f3a01084d28520496c4a3bb0cb13685435838167c9dcedeb"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.1+1"
|
||||
intl:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: intl
|
||||
sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.19.0"
|
||||
js:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: js
|
||||
sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.1"
|
||||
leak_tracker:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker
|
||||
sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a"
|
||||
sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "10.0.4"
|
||||
version: "10.0.5"
|
||||
leak_tracker_flutter_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker_flutter_testing
|
||||
sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8"
|
||||
sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.3"
|
||||
version: "3.0.5"
|
||||
leak_tracker_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -200,6 +528,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.0"
|
||||
logger:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: logger
|
||||
sha256: "697d067c60c20999686a0add96cf6aba723b3aa1f83ecf806a8097231529ec32"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.0"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -212,18 +548,26 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: material_color_utilities
|
||||
sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a"
|
||||
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.8.0"
|
||||
version: "0.11.1"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
|
||||
sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.12.0"
|
||||
version: "1.15.0"
|
||||
mime:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: mime
|
||||
sha256: "801fd0b26f14a4a58ccb09d5892c3fbdeff209594300a542492cf13fba9d247a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.6"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -320,6 +664,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.8"
|
||||
pretty_dio_logger:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: pretty_dio_logger
|
||||
sha256: "36f2101299786d567869493e2f5731de61ce130faa14679473b26905a92b6407"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
shared_preferences:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -389,6 +741,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.10.0"
|
||||
sprintf:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sprintf
|
||||
sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.0"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -413,6 +773,70 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
syncfusion_flutter_core:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: syncfusion_flutter_core
|
||||
sha256: "6e67726b85812afc7105725a23620b876ab7f6b04b8410e211330ffb8c2cdbe8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "26.2.14"
|
||||
syncfusion_flutter_pdf:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: syncfusion_flutter_pdf
|
||||
sha256: "59a1173dc34a1fac0a41aff7a2bb6f3c1578f1bfd749ea8b24379018434ba5a5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "26.2.14"
|
||||
syncfusion_flutter_pdfviewer:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: syncfusion_flutter_pdfviewer
|
||||
sha256: b54ffe621a0e2155cfc913ee55efcd160e2dc8d21c2b9185f4a9996e0ccc9424
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "26.2.14"
|
||||
syncfusion_flutter_signaturepad:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: syncfusion_flutter_signaturepad
|
||||
sha256: "5f8955d4ee64f342b389928111ebfad041e75003415eedee802f3af1d4ce7036"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "26.2.14"
|
||||
syncfusion_pdfviewer_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: syncfusion_pdfviewer_macos
|
||||
sha256: "1eec60fe44cc357072a0b872e4b0a82edef741463fda2b3a95a6973d7a615ec1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "26.2.14"
|
||||
syncfusion_pdfviewer_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: syncfusion_pdfviewer_platform_interface
|
||||
sha256: e128a2875226dc1d922ac0366d0804aa0ee7a52be23799cc6d84d78fd32ce092
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "26.2.14"
|
||||
syncfusion_pdfviewer_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: syncfusion_pdfviewer_web
|
||||
sha256: "5625c2e658e5d680ea240ea5f5daedf6a0acd563cec026a38b8cb5643783ce4f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "26.2.14"
|
||||
syncfusion_pdfviewer_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: syncfusion_pdfviewer_windows
|
||||
sha256: f6c56fea4b77ada9d7ddab6ed67a4a25317a2efd1007309e8938c01f1d952b20
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "26.2.14"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -425,10 +849,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f"
|
||||
sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.0"
|
||||
version: "0.7.2"
|
||||
timezone:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: timezone
|
||||
sha256: "2236ec079a174ce07434e89fcd3fcda430025eb7692244139a9cf54fdcf1fc7d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.9.4"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -437,6 +869,78 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.2"
|
||||
url_launcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher
|
||||
sha256: "21b704ce5fa560ea9f3b525b43601c678728ba46725bab9b01187b4831377ed3"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.3.0"
|
||||
url_launcher_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_android
|
||||
sha256: f0c73347dfcfa5b3db8bc06e1502668265d39c08f310c29bff4e28eea9699f79
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.3.9"
|
||||
url_launcher_ios:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_ios
|
||||
sha256: e43b677296fadce447e987a2f519dcf5f6d1e527dc35d01ffab4fff5b8a7063e
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.3.1"
|
||||
url_launcher_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_linux
|
||||
sha256: e2b9622b4007f97f504cd64c0128309dfb978ae66adbe944125ed9e1750f06af
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.0"
|
||||
url_launcher_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_macos
|
||||
sha256: "9a1a42d5d2d95400c795b2914c36fdcb525870c752569438e4ebb09a2b5d90de"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.0"
|
||||
url_launcher_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_platform_interface
|
||||
sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.2"
|
||||
url_launcher_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_web
|
||||
sha256: "772638d3b34c779ede05ba3d38af34657a05ac55b06279ea6edd409e323dca8e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.3"
|
||||
url_launcher_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_windows
|
||||
sha256: "49c10f879746271804767cb45551ec5592cdab00ee105c06dddde1a98f73b185"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.2"
|
||||
uuid:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: uuid
|
||||
sha256: f33d6bb662f0e4f79dcd7ada2e6170f3b3a2530c28fc41f49a411ddedd576a77
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.5.0"
|
||||
vector_graphics:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -473,10 +977,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vm_service
|
||||
sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec"
|
||||
sha256: f652077d0bdf60abe4c1f6377448e8655008eef28f128bc023f7b5e8dfeb48fc
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "14.2.1"
|
||||
version: "14.2.4"
|
||||
web:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -485,6 +989,22 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
win32:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: win32
|
||||
sha256: "68d1e89a91ed61ad9c370f9f8b6effed9ae5e0ede22a270bdfa6daf79fc2290a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.5.4"
|
||||
win32_registry:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: win32_registry
|
||||
sha256: "723b7f851e5724c55409bb3d5a32b203b3afe8587eaf5dafb93a5fed8ecda0d6"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.4"
|
||||
xdg_directories:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
14
pubspec.yaml
14
pubspec.yaml
@ -41,6 +41,20 @@ dependencies:
|
||||
dio: ^5.5.0+1
|
||||
http: ^1.2.2
|
||||
shared_preferences: ^2.2.3
|
||||
logger: ^2.4.0
|
||||
get_storage: ^2.1.1
|
||||
intl: ^0.19.0
|
||||
hive_flutter: ^1.1.0
|
||||
syncfusion_flutter_pdfviewer: ^26.2.14
|
||||
image_picker: ^1.1.2
|
||||
csc_picker: ^0.2.7
|
||||
auto_size_text: ^3.0.0
|
||||
firebase_core: ^3.3.0
|
||||
firebase_messaging: ^15.0.4
|
||||
flutter_local_notifications: ^17.2.1+2
|
||||
firebase_crashlytics: ^4.0.4
|
||||
firebase_analytics: ^11.2.1
|
||||
pretty_dio_logger: ^1.3.1
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
@ -6,6 +6,18 @@
|
||||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <file_selector_windows/file_selector_windows.h>
|
||||
#include <firebase_core/firebase_core_plugin_c_api.h>
|
||||
#include <syncfusion_pdfviewer_windows/syncfusion_pdfviewer_windows_plugin.h>
|
||||
#include <url_launcher_windows/url_launcher_windows.h>
|
||||
|
||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
FileSelectorWindowsRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("FileSelectorWindows"));
|
||||
FirebaseCorePluginCApiRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("FirebaseCorePluginCApi"));
|
||||
SyncfusionPdfviewerWindowsPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("SyncfusionPdfviewerWindowsPlugin"));
|
||||
UrlLauncherWindowsRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
|
||||
}
|
||||
|
@ -3,6 +3,10 @@
|
||||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
file_selector_windows
|
||||
firebase_core
|
||||
syncfusion_pdfviewer_windows
|
||||
url_launcher_windows
|
||||
)
|
||||
|
||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||
|
Loading…
Reference in New Issue
Block a user