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">
|
<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
|
<application
|
||||||
android:label="cheminova"
|
android:label="cheminova"
|
||||||
android:name="${applicationName}"
|
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/controller/home_service.dart';
|
||||||
import 'package:cheminova/models/user_model.dart';
|
import 'package:cheminova/models/user_model.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
class HomeController extends GetxController {
|
class HomeController extends GetxController {
|
||||||
final HomeService homeService = HomeService();
|
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
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
@ -13,7 +27,84 @@ class HomeController extends GetxController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> getUser() async {
|
Future<void> getUser() async {
|
||||||
user.value = await homeService.getUser();
|
try {
|
||||||
update();
|
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/models/user_model.dart';
|
||||||
import 'package:cheminova/utils/common_api_service.dart';
|
import 'package:cheminova/utils/common_api_service.dart';
|
||||||
import 'package:cheminova/utils/show_snackbar.dart';
|
import 'package:cheminova/utils/show_snackbar.dart';
|
||||||
|
import '../utils/api_urls.dart';
|
||||||
|
|
||||||
class HomeService {
|
class HomeService {
|
||||||
Future<UserModel?> getUser() async {
|
Future<UserModel?> getUser({String? token}) async {
|
||||||
try {
|
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",
|
method: "GET",
|
||||||
url: "/api/territorymanager/my-profile",
|
url: ApiUrls.profileUrl,
|
||||||
fromJson: (json) => UserModel.fromJson(json),
|
additionalHeaders: {
|
||||||
|
'Authorization': 'Bearer $token',
|
||||||
|
},
|
||||||
|
fromJson: (json) => json as Map<String, dynamic>,
|
||||||
);
|
);
|
||||||
|
|
||||||
return response;
|
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) {
|
} catch (e) {
|
||||||
showSnackbar(e.toString());
|
print("Error in getUser: ${e.toString()}");
|
||||||
|
showSnackbar("Error fetching user data: ${e.toString()}");
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
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:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
void main() {
|
void main()async{
|
||||||
runApp(const MyApp());
|
runApp(const MyApp());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -12,6 +12,7 @@ class MyApp extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return const GetMaterialApp(
|
return const GetMaterialApp(
|
||||||
|
debugShowCheckedModeBanner: false,
|
||||||
home: SplashScreen(),
|
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 image;
|
||||||
final String description;
|
final String description;
|
||||||
final double price;
|
final double price;
|
||||||
|
String? category1;
|
||||||
|
String? brandname;
|
||||||
final ProductCategory category;
|
final ProductCategory category;
|
||||||
final String id;
|
final String id;
|
||||||
int quantity;
|
int quantity;
|
||||||
@ -15,7 +17,39 @@ class ProductModel {
|
|||||||
required this.description,
|
required this.description,
|
||||||
required this.price,
|
required this.price,
|
||||||
required this.category,
|
required this.category,
|
||||||
|
this.category1,
|
||||||
|
this.brandname,
|
||||||
required this.id,
|
required this.id,
|
||||||
this.quantity = 1,
|
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 {
|
class UserModel {
|
||||||
String id;
|
final String id;
|
||||||
String name;
|
final String uniqueId;
|
||||||
String uniqueId;
|
final String name;
|
||||||
String email;
|
final String email;
|
||||||
bool isVerified;
|
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({
|
UserModel({
|
||||||
required this.id,
|
required this.id,
|
||||||
required this.name,
|
|
||||||
required this.uniqueId,
|
required this.uniqueId,
|
||||||
|
required this.name,
|
||||||
required this.email,
|
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) {
|
factory UserModel.fromJson(Map<String, dynamic> json) {
|
||||||
return UserModel(
|
return UserModel(
|
||||||
id: json['_id'] as String,
|
id: json['_id'],
|
||||||
name: json['name'] as String,
|
uniqueId: json['uniqueId'],
|
||||||
uniqueId: json['uniqueId'] as String,
|
name: json['name'],
|
||||||
email: json['email'] as String,
|
email: json['email'],
|
||||||
isVerified: json['isVerified'] as bool,
|
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() {
|
Map<String, dynamic> toJson() {
|
||||||
return {
|
return {
|
||||||
'_id': id,
|
'_id': id,
|
||||||
'name': name,
|
|
||||||
'uniqueId': uniqueId,
|
'uniqueId': uniqueId,
|
||||||
|
'name': name,
|
||||||
'email': email,
|
'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/authentication/controller/auth_service.dart';
|
||||||
import 'package:cheminova/screens/home_screen.dart';
|
import 'package:cheminova/screens/home_screen.dart';
|
||||||
|
import 'package:cheminova/utils/show_snackbar.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
class AuthController extends GetxController {
|
class AuthController extends GetxController {
|
||||||
final authService = AuthService();
|
final authService = AuthService();
|
||||||
@ -9,6 +11,10 @@ class AuthController extends GetxController {
|
|||||||
TextEditingController emailController = TextEditingController();
|
TextEditingController emailController = TextEditingController();
|
||||||
TextEditingController passwordController = TextEditingController();
|
TextEditingController passwordController = TextEditingController();
|
||||||
TextEditingController phoneController = TextEditingController();
|
TextEditingController phoneController = TextEditingController();
|
||||||
|
TextEditingController currentpassController = TextEditingController();
|
||||||
|
TextEditingController newpassController = TextEditingController();
|
||||||
|
TextEditingController confirmpassController = TextEditingController();
|
||||||
|
|
||||||
RxBool isLoading = false.obs;
|
RxBool isLoading = false.obs;
|
||||||
|
|
||||||
Future<void> login() async {
|
Future<void> login() async {
|
||||||
@ -20,7 +26,60 @@ class AuthController extends GetxController {
|
|||||||
isLoading.value = false;
|
isLoading.value = false;
|
||||||
update();
|
update();
|
||||||
if (response != null) {
|
if (response != null) {
|
||||||
|
showSnackbar("Your Successfully logged In!");
|
||||||
Get.offAll(() => const HomeScreen());
|
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 {
|
Future<Map<String, dynamic>?> login(Map<String, dynamic> data) async {
|
||||||
try {
|
try {
|
||||||
final response = await commonApiService<Map<String, dynamic>>(
|
final response = await commonApiService<Map<String, dynamic>>(
|
||||||
url: '/api/territorymanager/login',
|
url: '/api/rd-login',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: data,
|
body: data,
|
||||||
fromJson: (json) => json, // Simply return the JSON map as is
|
fromJson: (json) => json, // Simply return the JSON map as is
|
||||||
@ -16,4 +16,41 @@ class AuthService {
|
|||||||
}
|
}
|
||||||
return null;
|
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:get/get.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
|
|
||||||
|
import 'controller/auth_controller.dart';
|
||||||
|
|
||||||
class ForgetPasswordScreen extends StatefulWidget {
|
class ForgetPasswordScreen extends StatefulWidget {
|
||||||
const ForgetPasswordScreen({super.key});
|
const ForgetPasswordScreen({super.key});
|
||||||
|
|
||||||
@ -15,6 +17,7 @@ class ForgetPasswordScreen extends StatefulWidget {
|
|||||||
class _ForgetPasswordScreenState extends State<ForgetPasswordScreen> {
|
class _ForgetPasswordScreenState extends State<ForgetPasswordScreen> {
|
||||||
final userNameController = TextEditingController();
|
final userNameController = TextEditingController();
|
||||||
final passwordController = TextEditingController();
|
final passwordController = TextEditingController();
|
||||||
|
final authController = Get.put(AuthController());
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
@ -107,7 +110,7 @@ class _ForgetPasswordScreenState extends State<ForgetPasswordScreen> {
|
|||||||
InputField(
|
InputField(
|
||||||
hintText: "Email",
|
hintText: "Email",
|
||||||
labelText: "Email",
|
labelText: "Email",
|
||||||
controller: userNameController,
|
controller: authController.emailController,
|
||||||
keyboardType: TextInputType.emailAddress,
|
keyboardType: TextInputType.emailAddress,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 30),
|
const SizedBox(height: 30),
|
||||||
@ -125,7 +128,12 @@ class _ForgetPasswordScreenState extends State<ForgetPasswordScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 30),
|
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/material.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:google_fonts/google_fonts.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 {
|
class LoginScreen extends StatefulWidget {
|
||||||
const LoginScreen({super.key});
|
const LoginScreen({super.key});
|
||||||
@ -19,6 +18,8 @@ class LoginScreen extends StatefulWidget {
|
|||||||
class _LoginScreenState extends State<LoginScreen> {
|
class _LoginScreenState extends State<LoginScreen> {
|
||||||
final formKey = GlobalKey<FormState>();
|
final formKey = GlobalKey<FormState>();
|
||||||
final authController = Get.put(AuthController());
|
final authController = Get.put(AuthController());
|
||||||
|
final String emailPattern = r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$';
|
||||||
|
final String passwordPattern = r'^.{6,}$'; // At least 6 characters
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -30,9 +31,7 @@ class _LoginScreenState extends State<LoginScreen> {
|
|||||||
decoration: const BoxDecoration(
|
decoration: const BoxDecoration(
|
||||||
image: DecorationImage(
|
image: DecorationImage(
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
image: AssetImage(
|
image: AssetImage('assets/images/image_1.png'),
|
||||||
'assets/images/image_1.png',
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
borderRadius: BorderRadius.only(
|
borderRadius: BorderRadius.only(
|
||||||
bottomLeft: Radius.circular(50.0),
|
bottomLeft: Radius.circular(50.0),
|
||||||
@ -45,131 +44,159 @@ class _LoginScreenState extends State<LoginScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
SingleChildScrollView(
|
SingleChildScrollView(
|
||||||
child: Column(
|
child: Form(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
key: formKey,
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
child: Column(
|
||||||
children: [
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
SizedBox(height: Get.height * 0.1),
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
Container(
|
children: [
|
||||||
margin: const EdgeInsets.symmetric(vertical: 20),
|
SizedBox(height: Get.height * 0.1),
|
||||||
child: Text(
|
Container(
|
||||||
'Welcome',
|
margin: const EdgeInsets.symmetric(vertical: 20),
|
||||||
style: GoogleFonts.getFont(
|
child: Text(
|
||||||
'Roboto',
|
'Welcome',
|
||||||
fontWeight: FontWeight.w400,
|
style: GoogleFonts.getFont(
|
||||||
fontSize: 24,
|
'Roboto',
|
||||||
height: 1.5,
|
fontWeight: FontWeight.w400,
|
||||||
color: const Color(0xFFFFFFFF),
|
fontSize: 24,
|
||||||
|
height: 1.5,
|
||||||
|
color: const Color(0xFFFFFFFF),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
Container(
|
||||||
Container(
|
decoration: BoxDecoration(
|
||||||
decoration: BoxDecoration(
|
color: const Color(0xFFFFFFFF),
|
||||||
color: const Color(0xFFFFFFFF),
|
borderRadius: BorderRadius.circular(14),
|
||||||
borderRadius: BorderRadius.circular(14),
|
),
|
||||||
),
|
|
||||||
child: Container(
|
|
||||||
width: Get.width * 0.7,
|
|
||||||
height: Get.height * 0.07,
|
|
||||||
padding: const EdgeInsets.all(10),
|
|
||||||
child: Container(
|
child: Container(
|
||||||
decoration: const BoxDecoration(
|
width: Get.width * 0.7,
|
||||||
image: DecorationImage(
|
height: Get.height * 0.07,
|
||||||
fit: BoxFit.fill,
|
padding: const EdgeInsets.all(10),
|
||||||
image: AssetImage(
|
child: Container(
|
||||||
'assets/images/px_cheminova_svg.png',
|
decoration: const BoxDecoration(
|
||||||
|
image: DecorationImage(
|
||||||
|
fit: BoxFit.fill,
|
||||||
|
image: AssetImage(
|
||||||
|
'assets/images/px_cheminova_svg.png',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
SizedBox(height: Get.height * 0.05),
|
||||||
SizedBox(height: Get.height * 0.05),
|
Card(
|
||||||
Card(
|
margin: const EdgeInsets.symmetric(horizontal: 24),
|
||||||
margin: const EdgeInsets.symmetric(horizontal: 24),
|
shape: RoundedRectangleBorder(
|
||||||
shape: RoundedRectangleBorder(
|
borderRadius: BorderRadius.circular(19),
|
||||||
borderRadius: BorderRadius.circular(19),
|
side: const BorderSide(color: Color(0xFFFDFDFD)),
|
||||||
side: const BorderSide(color: Color(0xFFFDFDFD)),
|
),
|
||||||
),
|
color: const Color(0xFFB4D1E5).withOpacity(0.9),
|
||||||
color: const Color(0xFFB4D1E5).withOpacity(0.9),
|
child: Padding(
|
||||||
child: Padding(
|
padding: const EdgeInsets.all(16.0),
|
||||||
padding: const EdgeInsets.all(16.0),
|
child: Column(
|
||||||
child: Column(
|
children: [
|
||||||
children: [
|
Container(
|
||||||
Container(
|
alignment: Alignment.centerLeft,
|
||||||
alignment: Alignment.centerLeft,
|
padding: const EdgeInsets.only(bottom: 10),
|
||||||
padding: const EdgeInsets.only(bottom: 10),
|
child: SvgPicture.asset(
|
||||||
child: SvgPicture.asset(
|
'assets/svg/login.svg',
|
||||||
'assets/svg/login.svg',
|
height: Get.height * 0.05,
|
||||||
height: Get.height * 0.05,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.only(bottom: 10),
|
|
||||||
alignment: Alignment.centerLeft,
|
|
||||||
child: Text(
|
|
||||||
'Login',
|
|
||||||
style: GoogleFonts.getFont(
|
|
||||||
'Roboto',
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
fontSize: 30,
|
|
||||||
height: 1.2,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
Container(
|
||||||
Container(
|
padding: const EdgeInsets.only(bottom: 10),
|
||||||
padding: const EdgeInsets.only(bottom: 10),
|
alignment: Alignment.centerLeft,
|
||||||
alignment: Alignment.centerLeft,
|
child: Text(
|
||||||
child: Text(
|
'Login',
|
||||||
'Sign in to Continue',
|
style: GoogleFonts.getFont(
|
||||||
style: GoogleFonts.getFont(
|
'Roboto',
|
||||||
'Roboto',
|
fontWeight: FontWeight.w500,
|
||||||
fontWeight: FontWeight.w300,
|
fontSize: 30,
|
||||||
fontSize: 14,
|
height: 1.2,
|
||||||
height: 1.8,
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
Container(
|
||||||
InputField(
|
padding: const EdgeInsets.only(bottom: 10),
|
||||||
hintText: "Email",
|
alignment: Alignment.centerLeft,
|
||||||
labelText: "Email",
|
child: Text(
|
||||||
controller: authController.emailController,
|
'Sign in to Continue',
|
||||||
keyboardType: TextInputType.emailAddress,
|
style: GoogleFonts.getFont(
|
||||||
),
|
'Roboto',
|
||||||
InputField(
|
fontWeight: FontWeight.w300,
|
||||||
hintText: "Password",
|
fontSize: 14,
|
||||||
labelText: "Password",
|
height: 1.8,
|
||||||
controller: authController.passwordController,
|
),
|
||||||
obscureText: true,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 30),
|
|
||||||
GestureDetector(
|
|
||||||
onTap: () =>
|
|
||||||
Get.to(() => const ForgetPasswordScreen()),
|
|
||||||
child: Text(
|
|
||||||
'Forgot password?',
|
|
||||||
style: GoogleFonts.getFont(
|
|
||||||
'Roboto',
|
|
||||||
fontWeight: FontWeight.w400,
|
|
||||||
fontSize: 20,
|
|
||||||
height: 1,
|
|
||||||
letterSpacing: -0.2,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
CommonTextFormField(
|
||||||
const SizedBox(height: 30),
|
controller: authController.emailController,
|
||||||
Obx(
|
keyboardType: TextInputType.emailAddress,
|
||||||
() => CustomButton(
|
validator: (value) {
|
||||||
text: "Login",
|
if (value == null || value.isEmpty) {
|
||||||
onPressed: () => authController.login(),
|
return 'Please enter your email id';
|
||||||
isLoading: authController.isLoading.value,
|
}
|
||||||
|
if (!RegExp(emailPattern).hasMatch(value)) {
|
||||||
|
return 'Please Enter valid email';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
title: 'Email',
|
||||||
|
label: "Email",
|
||||||
),
|
),
|
||||||
),
|
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(
|
||||||
|
onTap: () =>
|
||||||
|
Get.to(() => const ForgetPasswordScreen()),
|
||||||
|
child: Text(
|
||||||
|
'Forgot password?',
|
||||||
|
style: GoogleFonts.getFont(
|
||||||
|
'Roboto',
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
fontSize: 20,
|
||||||
|
height: 1,
|
||||||
|
letterSpacing: -0.2,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 30),
|
||||||
|
Obx(
|
||||||
|
() => CustomButton(
|
||||||
|
text: "Login",
|
||||||
|
onPressed: () {
|
||||||
|
if (formKey.currentState!.validate()) {
|
||||||
|
// Perform login action
|
||||||
|
authController.login();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isLoading: authController.isLoading.value,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -85,7 +85,7 @@ class _HomeScreenState extends State<HomeScreen> {
|
|||||||
HomeCard(
|
HomeCard(
|
||||||
title: 'Order Management',
|
title: 'Order Management',
|
||||||
onTap: () => Get.to(
|
onTap: () => Get.to(
|
||||||
() => const OrderManagementScreen(),
|
() => OrderManagementScreen(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
HomeCard(
|
HomeCard(
|
||||||
|
@ -1,36 +1,175 @@
|
|||||||
import 'package:cheminova/models/product_model.dart';
|
import 'dart:ffi';
|
||||||
import 'package:cheminova/screens/order/order_confermation_screen.dart';
|
import 'package:cheminova/controller/get_order_placed_controller.dart';
|
||||||
import 'package:cheminova/widgets/input_field.dart';
|
import 'package:cheminova/models/added_by_model.dart';
|
||||||
import 'package:cheminova/widgets/my_drawer.dart';
|
import 'package:cheminova/models/category_model.dart';
|
||||||
import 'package:cheminova/widgets/product_card.dart';
|
import 'package:cheminova/utils/show_snackbar.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:google_fonts/google_fonts.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 {
|
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
|
@override
|
||||||
State<CheckoutScreen> createState() => _CheckoutScreenState();
|
State<CheckoutScreen> createState() => _CheckoutScreenState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _CheckoutScreenState extends State<CheckoutScreen> {
|
class _CheckoutScreenState extends State<CheckoutScreen> {
|
||||||
final TextEditingController _addressController = TextEditingController();
|
final CartController _cartController = Get.put(CartController());
|
||||||
final TextEditingController _contactController = TextEditingController();
|
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 = [
|
int currentPage = 1;
|
||||||
ProductModel(
|
String _groupValue = "cheque";
|
||||||
id: "1",
|
|
||||||
image: 'assets/images/product.png',
|
final List<String> _addressList = [
|
||||||
name: "Product 1",
|
'Home - 123 Street, City',
|
||||||
category: ProductCategory.food,
|
'Office - 456 Avenue, City',
|
||||||
description: 'Product 1 description',
|
'Warehouse - 789 Blvd, City',
|
||||||
price: 100,
|
|
||||||
),
|
|
||||||
];
|
];
|
||||||
|
|
||||||
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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -63,9 +202,7 @@ class _CheckoutScreenState extends State<CheckoutScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
title: const Text(
|
title: const Text("Checkout"),
|
||||||
"Checkout",
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
drawer: const MyDrawer(),
|
drawer: const MyDrawer(),
|
||||||
body: Stack(
|
body: Stack(
|
||||||
@ -78,9 +215,7 @@ class _CheckoutScreenState extends State<CheckoutScreen> {
|
|||||||
SafeArea(
|
SafeArea(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
SizedBox(
|
SizedBox(height: Get.height * 0.02),
|
||||||
height: Get.height * 0.02,
|
|
||||||
),
|
|
||||||
Card(
|
Card(
|
||||||
margin: EdgeInsets.symmetric(horizontal: Get.width * 0.05),
|
margin: EdgeInsets.symmetric(horizontal: Get.width * 0.05),
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
@ -106,15 +241,37 @@ class _CheckoutScreenState extends State<CheckoutScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
InputField(
|
SizedBox(height: 5,),
|
||||||
hintText: 'Address:',
|
DropdownButtonFormField<String>(
|
||||||
labelText: 'Address:',
|
decoration: InputDecoration(
|
||||||
controller: _addressController,
|
labelText: 'Shipping Address:',
|
||||||
|
hintText: 'Select Shipping Address',
|
||||||
|
border: OutlineInputBorder(),
|
||||||
|
),
|
||||||
|
value: _selectedShippingAddress,
|
||||||
|
items: _addressList.map((String address) {
|
||||||
|
return DropdownMenuItem<String>(
|
||||||
|
value: address,
|
||||||
|
child: Text(address),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
onChanged: _onShippingAddressChanged,
|
||||||
),
|
),
|
||||||
InputField(
|
SizedBox(height: Get.height * 0.02),
|
||||||
hintText: 'Contact:',
|
DropdownButtonFormField<String>(
|
||||||
labelText: 'Contact:',
|
decoration: InputDecoration(
|
||||||
controller: _contactController,
|
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(
|
||||||
padding: EdgeInsets.symmetric(
|
padding: EdgeInsets.symmetric(
|
||||||
@ -136,42 +293,30 @@ class _CheckoutScreenState extends State<CheckoutScreen> {
|
|||||||
SizedBox(
|
SizedBox(
|
||||||
height: Get.height * 0.035,
|
height: Get.height * 0.035,
|
||||||
child: RadioListTile(
|
child: RadioListTile(
|
||||||
title: const Text("Credit Card"),
|
title: const Text("Cheque"),
|
||||||
contentPadding: EdgeInsets.zero,
|
contentPadding: EdgeInsets.zero,
|
||||||
value: "Credit Card",
|
value: "cheque",
|
||||||
groupValue: _groupValue,
|
groupValue: _groupValue,
|
||||||
onChanged: (value) {
|
onChanged: _onPaymentModeChanged,
|
||||||
setState(() {
|
|
||||||
_groupValue = value.toString();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: Get.height * 0.035,
|
height: Get.height * 0.035,
|
||||||
child: RadioListTile(
|
child: RadioListTile(
|
||||||
title: const Text("Net Banking"),
|
title: const Text("Online transfer"),
|
||||||
contentPadding: EdgeInsets.zero,
|
contentPadding: EdgeInsets.zero,
|
||||||
value: "Net Banking",
|
value: "online-transfer",
|
||||||
groupValue: _groupValue,
|
groupValue: _groupValue,
|
||||||
onChanged: (value) {
|
onChanged: _onPaymentModeChanged,
|
||||||
setState(() {
|
|
||||||
_groupValue = value.toString();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
child: RadioListTile(
|
child: RadioListTile(
|
||||||
title: const Text("Cash on Delivery"),
|
title: const Text("Credit"),
|
||||||
contentPadding: EdgeInsets.zero,
|
contentPadding: EdgeInsets.zero,
|
||||||
value: "Cash on Delivery",
|
value: "credit",
|
||||||
groupValue: _groupValue,
|
groupValue: _groupValue,
|
||||||
onChanged: (value) {
|
onChanged: _onPaymentModeChanged,
|
||||||
setState(() {
|
|
||||||
_groupValue = value.toString();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -198,58 +343,83 @@ class _CheckoutScreenState extends State<CheckoutScreen> {
|
|||||||
child: Padding(
|
child: Padding(
|
||||||
padding: EdgeInsets.all(Get.width * 0.02),
|
padding: EdgeInsets.all(Get.width * 0.02),
|
||||||
child: ListView.builder(
|
child: ListView.builder(
|
||||||
padding: EdgeInsets.zero,
|
itemCount: _cartController.selectedProducts.length,
|
||||||
itemCount: 10,
|
itemBuilder: (context, index) {
|
||||||
itemBuilder: (context, index) =>
|
final cartItem =
|
||||||
ProductCard(
|
_cartController.cartList[index];
|
||||||
product: _checkoutList[0],
|
return ProductCard(
|
||||||
isCheckout: true,
|
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(
|
||||||
padding: EdgeInsets.all(Get.width * 0.04),
|
padding: EdgeInsets.all(Get.width * 0.02),
|
||||||
child: Text(
|
child: Column(
|
||||||
'Total Price: ₹ 1000.00',
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
style: GoogleFonts.roboto(
|
children: [
|
||||||
fontSize: Get.width * 0.05,
|
Row(
|
||||||
fontWeight: FontWeight.w700,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
color: Colors.black,
|
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)}'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(height: 10.0,),
|
||||||
height: Get.height * 0.025,
|
Row(
|
||||||
),
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
SizedBox(
|
children: [
|
||||||
width: Get.width * 0.9,
|
ElevatedButton(
|
||||||
height: Get.height * 0.06,
|
onPressed: _onPlaceOrder,
|
||||||
child: ElevatedButton(
|
style: ElevatedButton.styleFrom(
|
||||||
onPressed: () =>
|
foregroundColor: Colors.white,
|
||||||
Get.to(() => const OrderConfermationScreen()),
|
backgroundColor: const Color(0xFF00784C),
|
||||||
style: ElevatedButton.styleFrom(
|
padding: EdgeInsets.symmetric(
|
||||||
foregroundColor: Colors.white,
|
horizontal: Get.width * 0.20,
|
||||||
backgroundColor: const Color(0xFF00784C),
|
vertical: Get.height * 0.02),
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
|
child: const Text("Place Order"),
|
||||||
),
|
),
|
||||||
child: Text(
|
],
|
||||||
"Place Order",
|
|
||||||
style: GoogleFonts.roboto(
|
|
||||||
fontSize: Get.width * 0.04,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -258,4 +428,4 @@ class _CheckoutScreenState extends State<CheckoutScreen> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,6 @@
|
|||||||
|
import 'package:cheminova/controller/get_order_placed_controller.dart';
|
||||||
import 'package:cheminova/models/product_model.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/my_drawer.dart';
|
||||||
import 'package:cheminova/widgets/product_card.dart';
|
import 'package:cheminova/widgets/product_card.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@ -6,8 +8,16 @@ import 'package:flutter_svg/svg.dart';
|
|||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:google_fonts/google_fonts.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 {
|
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
|
@override
|
||||||
State<OrderConfermationScreen> createState() =>
|
State<OrderConfermationScreen> createState() =>
|
||||||
@ -15,18 +25,28 @@ class OrderConfermationScreen extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _OrderConfermationScreenState extends State<OrderConfermationScreen> {
|
class _OrderConfermationScreenState extends State<OrderConfermationScreen> {
|
||||||
final List<ProductModel> _checkoutList = [
|
final CartController _cartController = Get.put(CartController());
|
||||||
ProductModel(
|
final OrderPlacedController _placedController = Get.put(OrderPlacedController());
|
||||||
id: "1",
|
final GetPlacedOrderController _getPlacedOrderController = Get.put(GetPlacedOrderController());
|
||||||
image: 'assets/images/product.png',
|
// final List<ProductModel> _checkoutList = [
|
||||||
name: "Product 1",
|
// ProductModel(
|
||||||
category: ProductCategory.food,
|
// id: "1",
|
||||||
description: 'Product 1 description',
|
// image: 'assets/images/product.png',
|
||||||
price: 100.00,
|
// name: "Product 1",
|
||||||
),
|
// category: ProductCategory.food,
|
||||||
];
|
// description: 'Product 1 description',
|
||||||
|
// price: 100.00,
|
||||||
|
// ),
|
||||||
|
// ];
|
||||||
|
|
||||||
|
// void _getOrder(){
|
||||||
|
// final details = _getPlacedOrderController.getOrder();
|
||||||
|
// showSnackbar("Get Placed Order Sucessfully");
|
||||||
|
// print("dffgfg,$details");
|
||||||
|
// }
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final orderItems = _placedController.placedOrder1;
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
extendBodyBehindAppBar: true,
|
extendBodyBehindAppBar: true,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
@ -94,7 +114,7 @@ class _OrderConfermationScreenState extends State<OrderConfermationScreen> {
|
|||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
"Order Number: 123456",
|
"Order Number:1234",
|
||||||
style: GoogleFonts.roboto(
|
style: GoogleFonts.roboto(
|
||||||
fontSize: Get.width * 0.04,
|
fontSize: Get.width * 0.04,
|
||||||
fontWeight: FontWeight.w400,
|
fontWeight: FontWeight.w400,
|
||||||
@ -109,7 +129,7 @@ class _OrderConfermationScreenState extends State<OrderConfermationScreen> {
|
|||||||
'Order Summary',
|
'Order Summary',
|
||||||
style: GoogleFonts.roboto(
|
style: GoogleFonts.roboto(
|
||||||
fontSize: Get.width * 0.04,
|
fontSize: Get.width * 0.04,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.bold,
|
||||||
color: Colors.black,
|
color: Colors.black,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -124,26 +144,45 @@ class _OrderConfermationScreenState extends State<OrderConfermationScreen> {
|
|||||||
padding: EdgeInsets.all(Get.width * 0.02),
|
padding: EdgeInsets.all(Get.width * 0.02),
|
||||||
child: ListView.builder(
|
child: ListView.builder(
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
itemCount: 10,
|
itemCount: _cartController.selectedProducts.length,
|
||||||
itemBuilder: (context, index) =>
|
itemBuilder: (context, index) =>
|
||||||
ProductCard(
|
ProductCard(
|
||||||
product: _checkoutList[0],
|
productModel:_cartController.selectedProducts[index],
|
||||||
isCheckout: true,
|
isCheckout: true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.all(Get.width * 0.04),
|
padding: EdgeInsets.all(Get.width * 0.02),
|
||||||
child: Text(
|
child: Column(
|
||||||
'Total Price: ₹ 1000.00',
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
style: GoogleFonts.roboto(
|
children: [
|
||||||
fontSize: Get.width * 0.05,
|
Row(
|
||||||
fontWeight: FontWeight.w700,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
color: Colors.black,
|
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(
|
Card(
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: Get.width,
|
width: Get.width,
|
||||||
height: Get.height * 0.2,
|
height: Get.height * 0.1,
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: Text(
|
child: TextField(
|
||||||
"Address: Lorem Ipsum is simply dummy text of the printing and typesetting industry",
|
controller: TextEditingController(
|
||||||
style: GoogleFonts.roboto(
|
text: widget.placedOrder!.shipTo,
|
||||||
fontSize: Get.width * 0.04,
|
),
|
||||||
fontWeight: FontWeight.w400,
|
decoration: InputDecoration(
|
||||||
|
hintText: "Address : ${widget.placedOrder!.shipTo}",
|
||||||
|
hintStyle: GoogleFonts.roboto(
|
||||||
|
fontSize: Get.width * 0.04,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
border: OutlineInputBorder(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
]),
|
||||||
child: Text(
|
|
||||||
"Contact: +91 9123456789",
|
|
||||||
style: GoogleFonts.roboto(
|
|
||||||
fontSize: Get.width * 0.04,
|
|
||||||
fontWeight: FontWeight.w400,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Card(
|
Card(
|
||||||
@ -196,7 +231,7 @@ class _OrderConfermationScreenState extends State<OrderConfermationScreen> {
|
|||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
"Estimated Delivery Date: [Date]",
|
"Estimated Delivery Date: ${widget.placedOrder!.orderItems[0].createdAt}",
|
||||||
style: GoogleFonts.roboto(
|
style: GoogleFonts.roboto(
|
||||||
fontSize: Get.width * 0.04,
|
fontSize: Get.width * 0.04,
|
||||||
fontWeight: FontWeight.w400,
|
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/models/product_model.dart';
|
||||||
import 'package:cheminova/screens/order_management/order_status_update_screen.dart';
|
import 'package:cheminova/screens/order_management/order_status_update_screen.dart';
|
||||||
import 'package:cheminova/widgets/product_card.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:get/get.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
|
|
||||||
|
import '../../controller/cart_controller.dart';
|
||||||
|
import '../../models/product_model1.dart';
|
||||||
|
|
||||||
class OrderFullfilmentScreen extends StatefulWidget {
|
class OrderFullfilmentScreen extends StatefulWidget {
|
||||||
const OrderFullfilmentScreen({super.key});
|
//final Product? productModel;
|
||||||
|
PlacedOrderList? placedOrderList;
|
||||||
|
OrderFullfilmentScreen({super.key,this.placedOrderList});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<OrderFullfilmentScreen> createState() => _OrderFullfilmentScreenState();
|
State<OrderFullfilmentScreen> createState() => _OrderFullfilmentScreenState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _OrderFullfilmentScreenState extends State<OrderFullfilmentScreen> {
|
class _OrderFullfilmentScreenState extends State<OrderFullfilmentScreen> {
|
||||||
final List<ProductModel> _checkoutList = [
|
final CartController _cartController = Get.put(CartController());
|
||||||
ProductModel(
|
|
||||||
id: "1",
|
|
||||||
image: 'assets/images/image_1.png',
|
|
||||||
name: "Product 1",
|
|
||||||
category: ProductCategory.food,
|
|
||||||
description: 'Product 1 description',
|
|
||||||
price: 100,
|
|
||||||
),
|
|
||||||
];
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
@ -153,7 +150,7 @@ class _OrderFullfilmentScreenState extends State<OrderFullfilmentScreen> {
|
|||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
itemCount: 10,
|
itemCount: 10,
|
||||||
itemBuilder: (context, index) => ProductCard(
|
itemBuilder: (context, index) => ProductCard(
|
||||||
product: _checkoutList[0],
|
placedOrderList:widget.placedOrderList,
|
||||||
isCheckout: true,
|
isCheckout: true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -1,32 +1,73 @@
|
|||||||
import 'package:cheminova/models/product_model.dart';
|
import 'package:auto_size_text/auto_size_text.dart';
|
||||||
import 'package:cheminova/screens/order_management/order_fullfilment_screen.dart';
|
import 'package:cheminova/controller/get_order_placed_controller.dart';
|
||||||
import 'package:cheminova/widgets/product_card.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/material.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:google_fonts/google_fonts.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 {
|
class OrderManagementDetailScreen extends StatefulWidget {
|
||||||
const OrderManagementDetailScreen({super.key});
|
//final Product? productModel;
|
||||||
|
PlacedOrderList? placedOrderList;
|
||||||
|
PlacedOrderModel? placedOrderModel;
|
||||||
|
OrderManagementDetailScreen({super.key,this.placedOrderList,this.placedOrderModel});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<OrderManagementDetailScreen> createState() =>
|
State<OrderManagementDetailScreen> createState() =>
|
||||||
_OrderManagementDetailScreenState();
|
_OrderManagementDetailScreenState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class _OrderManagementDetailScreenState
|
class _OrderManagementDetailScreenState
|
||||||
extends State<OrderManagementDetailScreen> {
|
extends State<OrderManagementDetailScreen> {
|
||||||
final List<ProductModel> _checkoutList = [
|
final CartController _cartController = Get.put(CartController());
|
||||||
ProductModel(
|
final GetPlacedOrderController _getPlacedOrderController = Get.put(GetPlacedOrderController());
|
||||||
id: "1",
|
String formatDate(String apiDate) {
|
||||||
image: 'assets/images/image_1.png',
|
|
||||||
name: "Product 1",
|
DateTime parsedDate = DateTime.parse(apiDate);
|
||||||
category: ProductCategory.food,
|
|
||||||
description: 'Product 1 description',
|
String formattedDate = DateFormat('dd-MMM-yyyy').format(parsedDate);
|
||||||
price: 100,
|
|
||||||
),
|
return formattedDate;
|
||||||
];
|
}
|
||||||
@override
|
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) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
extendBodyBehindAppBar: true,
|
extendBodyBehindAppBar: true,
|
||||||
@ -95,8 +136,8 @@ class _OrderManagementDetailScreenState
|
|||||||
child: Text(
|
child: Text(
|
||||||
"Order Summary",
|
"Order Summary",
|
||||||
style: GoogleFonts.roboto(
|
style: GoogleFonts.roboto(
|
||||||
fontSize: Get.width * 0.04,
|
fontSize: Get.width * 0.05,
|
||||||
fontWeight: FontWeight.w400,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -106,12 +147,18 @@ class _OrderManagementDetailScreenState
|
|||||||
child: Padding(
|
child: Padding(
|
||||||
padding:
|
padding:
|
||||||
const EdgeInsets.fromLTRB(8, 8, 8, 0),
|
const EdgeInsets.fromLTRB(8, 8, 8, 0),
|
||||||
child: Text(
|
child: Row(
|
||||||
"Order ID: 123456",
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
style: GoogleFonts.roboto(
|
children: [
|
||||||
fontSize: Get.width * 0.04,
|
Text(
|
||||||
fontWeight: FontWeight.w400,
|
"Order ID:",
|
||||||
),
|
style: GoogleFonts.roboto(
|
||||||
|
fontSize: Get.width * 0.04,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(widget.placedOrderList!.uniqueId),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -120,25 +167,37 @@ class _OrderManagementDetailScreenState
|
|||||||
child: Padding(
|
child: Padding(
|
||||||
padding:
|
padding:
|
||||||
const EdgeInsets.fromLTRB(8, 8, 8, 0),
|
const EdgeInsets.fromLTRB(8, 8, 8, 0),
|
||||||
child: Text(
|
child: Row(
|
||||||
"Order Date: MM/DD/YYYY",
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
style: GoogleFonts.roboto(
|
children: [
|
||||||
fontSize: Get.width * 0.04,
|
Text(
|
||||||
fontWeight: FontWeight.w400,
|
"Order Date: ",
|
||||||
),
|
style: GoogleFonts.roboto(
|
||||||
|
fontSize: Get.width * 0.04,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(formatDate("${widget.placedOrderList!.createdAt}")),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: Get.width,
|
width: Get.width,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: EdgeInsets.all(8.0),
|
||||||
child: Text(
|
child: Row(
|
||||||
"Total Price: ₹ Total",
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
style: GoogleFonts.roboto(
|
children: [
|
||||||
fontSize: Get.width * 0.04,
|
Text(
|
||||||
fontWeight: FontWeight.w400,
|
"Total Amount: ",
|
||||||
),
|
style: GoogleFonts.roboto(
|
||||||
|
fontSize: Get.width * 0.04,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text("₹ ${widget.placedOrderList!.grandTotal}"),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -153,11 +212,52 @@ class _OrderManagementDetailScreenState
|
|||||||
padding: EdgeInsets.all(Get.width * 0.02),
|
padding: EdgeInsets.all(Get.width * 0.02),
|
||||||
child: ListView.builder(
|
child: ListView.builder(
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
itemCount: 10,
|
itemCount: widget.placedOrderList?.orderItem.length ?? 0,
|
||||||
itemBuilder: (context, index) => ProductCard(
|
itemBuilder: (context, index) {
|
||||||
product: _checkoutList[0],
|
final orderItem = widget.placedOrderList!.orderItem[index];
|
||||||
isCheckout: true,
|
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(
|
SizedBox(
|
||||||
width: Get.width,
|
width: Get.width,
|
||||||
|
height: Get.height*0.06,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding:
|
padding:
|
||||||
const EdgeInsets.fromLTRB(8, 8, 8, 0),
|
const EdgeInsets.fromLTRB(8, 8, 8, 0),
|
||||||
child: Text(
|
child: Row(
|
||||||
"Address: Hyderabad",
|
children: [
|
||||||
style: GoogleFonts.roboto(
|
Text(
|
||||||
fontSize: Get.width * 0.04,
|
"Address: ",
|
||||||
fontWeight: FontWeight.w400,
|
style: GoogleFonts.roboto(
|
||||||
),
|
fontSize: Get.width * 0.04,
|
||||||
),
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(
|
AutoSizeText("${widget.placedOrderList!.shipTo}",maxLines: 4,
|
||||||
width: Get.width,
|
overflow:TextOverflow.ellipsis,)
|
||||||
child: Padding(
|
],
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: Text(
|
|
||||||
"Contact: +91 9123456789",
|
|
||||||
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,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -216,12 +323,17 @@ class _OrderManagementDetailScreenState
|
|||||||
width: Get.width,
|
width: Get.width,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(8),
|
padding: const EdgeInsets.all(8),
|
||||||
child: Text(
|
child: Row(
|
||||||
"Status: Processing/ Shipped/ Delivered",
|
children: [
|
||||||
style: GoogleFonts.roboto(
|
Text(
|
||||||
fontSize: Get.width * 0.04,
|
"Status: ",
|
||||||
fontWeight: FontWeight.w600,
|
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(height: Get.height * 0.04),
|
||||||
SizedBox(
|
// SizedBox(
|
||||||
width: Get.width * 0.9,
|
// width: Get.width * 0.9,
|
||||||
height: Get.height * 0.06,
|
// height: Get.height * 0.06,
|
||||||
child: ElevatedButton(
|
// child: ElevatedButton(
|
||||||
onPressed: () => Get.to(
|
// onPressed: () => Get.to(
|
||||||
() => const OrderFullfilmentScreen(),
|
// () => OrderFullfilmentScreen(
|
||||||
),
|
// placedOrderList:widget.placedOrderList ,
|
||||||
style: ElevatedButton.styleFrom(
|
// ),
|
||||||
foregroundColor: Colors.white,
|
// ),
|
||||||
backgroundColor: const Color(0xFF00784C),
|
// style: ElevatedButton.styleFrom(
|
||||||
shape: RoundedRectangleBorder(
|
// foregroundColor: Colors.white,
|
||||||
borderRadius: BorderRadius.circular(10),
|
// backgroundColor: const Color(0xFF00784C),
|
||||||
),
|
// shape: RoundedRectangleBorder(
|
||||||
),
|
// borderRadius: BorderRadius.circular(10),
|
||||||
child: Text(
|
// ),
|
||||||
"Fulfill Order",
|
// ),
|
||||||
style: GoogleFonts.roboto(
|
// child: Text(
|
||||||
fontSize: Get.width * 0.04,
|
// "Fulfill Order",
|
||||||
fontWeight: FontWeight.w600,
|
// 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/screens/order_management/order_management_detail_screen.dart';
|
||||||
import 'package:cheminova/widgets/input_field.dart';
|
import 'package:cheminova/widgets/input_field.dart';
|
||||||
import 'package:cheminova/widgets/my_drawer.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:flutter_svg/svg.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:google_fonts/google_fonts.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 {
|
class OrderManagementScreen extends StatefulWidget {
|
||||||
const OrderManagementScreen({super.key});
|
final Product? productModel;
|
||||||
|
PlacedOrderList? placeOrder;
|
||||||
|
OrderManagementScreen({super.key, this.productModel, this.placeOrder});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<OrderManagementScreen> createState() => _OrderManagementScreenState();
|
State<OrderManagementScreen> createState() => _OrderManagementScreenState();
|
||||||
@ -15,10 +23,39 @@ class OrderManagementScreen extends StatefulWidget {
|
|||||||
|
|
||||||
class _OrderManagementScreenState extends State<OrderManagementScreen> {
|
class _OrderManagementScreenState extends State<OrderManagementScreen> {
|
||||||
final _searchController = TextEditingController();
|
final _searchController = TextEditingController();
|
||||||
final List<String> _filterList = [
|
final List<String> _filterList = ["Order Status", "Date Range"];
|
||||||
"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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -34,9 +71,7 @@ class _OrderManagementScreenState extends State<OrderManagementScreen> {
|
|||||||
onTap: () => Scaffold.of(context).openDrawer(),
|
onTap: () => Scaffold.of(context).openDrawer(),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: SvgPicture.asset(
|
child: SvgPicture.asset('assets/svg/menu.svg'),
|
||||||
'assets/svg/menu.svg',
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -46,169 +81,190 @@ class _OrderManagementScreenState extends State<OrderManagementScreen> {
|
|||||||
onTap: () => Get.back(),
|
onTap: () => Get.back(),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: SvgPicture.asset(
|
child: SvgPicture.asset('assets/svg/back_arrow.svg'),
|
||||||
'assets/svg/back_arrow.svg',
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
title: const Text(
|
title: const Text("Order Management"),
|
||||||
"Order Management",
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
drawer: const MyDrawer(),
|
drawer: const MyDrawer(),
|
||||||
body: Stack(
|
body: Stack(
|
||||||
fit: StackFit.expand,
|
fit: StackFit.expand,
|
||||||
children: [
|
children: [
|
||||||
Image.asset(
|
Image.asset('assets/images/image_1.png', fit: BoxFit.cover),
|
||||||
'assets/images/image_1.png',
|
|
||||||
fit: BoxFit.cover,
|
|
||||||
),
|
|
||||||
SafeArea(
|
SafeArea(
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: EdgeInsets.only(
|
padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
|
||||||
bottom: MediaQuery.of(context).viewInsets.bottom),
|
child: RefreshIndicator(
|
||||||
child: Column(
|
key: _refreshIndicatorKey,
|
||||||
mainAxisSize: MainAxisSize.min,
|
onRefresh: _onRefresh,
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
color: Colors.black,
|
||||||
children: [
|
backgroundColor: Colors.white,
|
||||||
InputField(
|
child: Column(
|
||||||
hintText: "Search Order",
|
mainAxisSize: MainAxisSize.min,
|
||||||
labelText: "Search Order",
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
controller: _searchController,
|
children: [
|
||||||
),
|
InputField(
|
||||||
SizedBox(height: Get.height * 0.035),
|
hintText: "Search Order",
|
||||||
Card(
|
labelText: "Search Order",
|
||||||
margin: const EdgeInsets.symmetric(horizontal: 18),
|
controller: _searchController,
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(19),
|
|
||||||
side: const BorderSide(color: Color(0xFFFDFDFD)),
|
|
||||||
),
|
),
|
||||||
color: const Color(0xFFB4D1E5).withOpacity(0.9),
|
SizedBox(height: Get.height * 0.035),
|
||||||
child: Padding(
|
Card(
|
||||||
padding: const EdgeInsets.all(12.0),
|
margin: const EdgeInsets.symmetric(horizontal: 18),
|
||||||
child: Column(
|
shape: RoundedRectangleBorder(
|
||||||
mainAxisSize: MainAxisSize.min,
|
borderRadius: BorderRadius.circular(19),
|
||||||
children: [
|
side: const BorderSide(color: Color(0xFFFDFDFD)),
|
||||||
SizedBox(
|
),
|
||||||
height: Get.height * 0.05,
|
color: const Color(0xFFB4D1E5).withOpacity(0.9),
|
||||||
child: ListView.builder(
|
child: Padding(
|
||||||
shrinkWrap: true,
|
padding: const EdgeInsets.all(12.0),
|
||||||
scrollDirection: Axis.horizontal,
|
child: Column(
|
||||||
itemCount: _filterList.length,
|
mainAxisSize: MainAxisSize.min,
|
||||||
itemBuilder: (context, index) => Padding(
|
children: [
|
||||||
padding:
|
SizedBox(
|
||||||
const EdgeInsets.symmetric(horizontal: 4),
|
height: Get.height * 0.05,
|
||||||
child: Chip(
|
child: ListView.builder(
|
||||||
label: Text(
|
shrinkWrap: true,
|
||||||
_filterList[index],
|
scrollDirection: Axis.horizontal,
|
||||||
style: GoogleFonts.roboto(
|
itemCount: _filterList.length,
|
||||||
fontSize: 14,
|
itemBuilder: (context, index) => Padding(
|
||||||
fontWeight: FontWeight.w500,
|
padding: const EdgeInsets.symmetric(horizontal: 4),
|
||||||
|
child: Chip(
|
||||||
|
label: Text(
|
||||||
|
_filterList[index],
|
||||||
|
style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.w500),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
SizedBox(
|
||||||
SizedBox(
|
height: Get.height * 0.6,
|
||||||
height: Get.height * 0.6,
|
child: Obx(() {
|
||||||
child: ListView.builder(
|
// Use a set to keep track of unique order IDs
|
||||||
padding: EdgeInsets.zero,
|
final Set<String> uniqueOrderIds = {};
|
||||||
shrinkWrap: true,
|
final List<PlacedOrderList> uniqueOrders = [];
|
||||||
itemCount: 2,
|
|
||||||
itemBuilder: (context, index) => Padding(
|
for (var order in _getPlacedOrderController.placedOrders) {
|
||||||
padding:
|
if (uniqueOrderIds.add(order.id)) {
|
||||||
const EdgeInsets.symmetric(vertical: 8),
|
uniqueOrders.add(order);
|
||||||
child: Card(
|
}
|
||||||
child: Column(
|
}
|
||||||
crossAxisAlignment:
|
|
||||||
CrossAxisAlignment.start,
|
return ListView.builder(
|
||||||
children: [
|
padding: EdgeInsets.zero,
|
||||||
Padding(
|
shrinkWrap: true,
|
||||||
padding: const EdgeInsets.fromLTRB(
|
itemCount: uniqueOrders.length,
|
||||||
16, 8, 8, 0),
|
itemBuilder: (context, index) {
|
||||||
child: Text(
|
final order = uniqueOrders[index];
|
||||||
"Order ID: 123456",
|
|
||||||
style: GoogleFonts.roboto(
|
// Combine product names into a single string
|
||||||
fontSize: 14,
|
final productNames = order.orderItem
|
||||||
fontWeight: FontWeight.w400,
|
.map((item) => capitalizeFirstLetter(item.name))
|
||||||
),
|
.join(', ');
|
||||||
),
|
|
||||||
),
|
return Padding(
|
||||||
Padding(
|
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||||
padding: const EdgeInsets.fromLTRB(
|
child: Card(
|
||||||
16, 8, 8, 0),
|
child: Column(
|
||||||
child: Text(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
"Product Name: XYZ",
|
children: [
|
||||||
style: GoogleFonts.roboto(
|
Padding(
|
||||||
fontSize: 14,
|
padding: const EdgeInsets.fromLTRB(16, 8, 8, 0),
|
||||||
fontWeight: FontWeight.w400,
|
child: Row(
|
||||||
),
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
),
|
children: [
|
||||||
),
|
Text("Order ID: ", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.bold)),
|
||||||
Padding(
|
Text("${order.uniqueId}")
|
||||||
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,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
width: Get.width * 0.4,
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: ElevatedButton(
|
|
||||||
onPressed: () => Get.to(
|
|
||||||
() =>
|
|
||||||
const OrderManagementDetailScreen(),
|
|
||||||
),
|
|
||||||
style: ElevatedButton.styleFrom(
|
|
||||||
foregroundColor: Colors.white,
|
|
||||||
backgroundColor:
|
|
||||||
const Color(0xFF004791),
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius:
|
|
||||||
BorderRadius.circular(10),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: Text(
|
Padding(
|
||||||
"View Details",
|
padding: const EdgeInsets.fromLTRB(16, 8, 8, 0),
|
||||||
style: GoogleFonts.roboto(
|
child: Row(
|
||||||
fontSize: 14,
|
crossAxisAlignment: CrossAxisAlignment.start, // Aligns the Column to the top of the Text
|
||||||
fontWeight: FontWeight.w400,
|
children: [
|
||||||
|
Text(
|
||||||
|
"Product Names: ",
|
||||||
|
style: GoogleFonts.roboto(
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start, // Aligns text to the right within the Column
|
||||||
|
children: [
|
||||||
|
const SizedBox(height: 4), // Adds a small space between the label and the product names
|
||||||
|
for (int i = 0; i < productNames.split(",").length; i++)
|
||||||
|
Text(
|
||||||
|
'${i + 1}. ${productNames.split(",")[i].trim()}', // Adds index and trims whitespace
|
||||||
|
textAlign: TextAlign.left, // Aligns text to the right
|
||||||
|
style: GoogleFonts.roboto(
|
||||||
|
fontSize: 14,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
|
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(16, 8, 8, 0),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text("Order Date: ", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.bold)),
|
||||||
|
Text(formatDate("${order.createdAt}"))
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(16, 8, 8, 8),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text("Status: ", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.bold)),
|
||||||
|
Text(capitalizeFirstLetter("${order.status}"))
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: Get.width * 0.4,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: () => Get.to(() => OrderManagementDetailScreen(
|
||||||
|
placedOrderList: uniqueOrders[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)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
],
|
);
|
||||||
),
|
},
|
||||||
),
|
);
|
||||||
),
|
}),
|
||||||
),
|
)
|
||||||
)
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -218,3 +274,253 @@ 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/screens/order/checkout_screen.dart';
|
||||||
import 'package:cheminova/widgets/my_drawer.dart';
|
import 'package:cheminova/widgets/my_drawer.dart';
|
||||||
import 'package:cheminova/widgets/product_card.dart';
|
import 'package:cheminova/widgets/product_card.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:get/get_core/get_core.dart';
|
|
||||||
import 'package:google_fonts/google_fonts.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 {
|
class CartScreen extends StatefulWidget {
|
||||||
const CartScreen({super.key});
|
Product? productModel;
|
||||||
|
PlacedOrderModel? placedOrder;
|
||||||
|
|
||||||
|
CartScreen({super.key, this.productModel, this.placedOrder});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<CartScreen> createState() => _CartScreenState();
|
State<CartScreen> createState() => _CartScreenState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _CartScreenState extends State<CartScreen> {
|
class _CartScreenState extends State<CartScreen> {
|
||||||
final List<ProductModel> _cartList = [
|
final CartController _cartController = Get.find<CartController>();
|
||||||
ProductModel(
|
|
||||||
id: "1",
|
bool _selectAll = true; // Default to true to select all products
|
||||||
image: 'assets/images/product.png',
|
|
||||||
name: "Product 1",
|
@override
|
||||||
category: ProductCategory.food,
|
void initState() {
|
||||||
description: 'Product 1 description',
|
super.initState();
|
||||||
price: 100,
|
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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
@ -57,8 +84,10 @@ class _CartScreenState extends State<CartScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
title: const Text(
|
title: const Center(
|
||||||
"Cart",
|
child: Text(
|
||||||
|
"Cart",
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
drawer: const MyDrawer(),
|
drawer: const MyDrawer(),
|
||||||
@ -70,81 +99,441 @@ class _CartScreenState extends State<CartScreen> {
|
|||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
),
|
),
|
||||||
SafeArea(
|
SafeArea(
|
||||||
child: Column(
|
child: Obx(() {
|
||||||
children: [
|
if (_cartController.cartList.isEmpty) {
|
||||||
SizedBox(
|
return Center(
|
||||||
height: Get.height * 0.02,
|
child: Column(
|
||||||
),
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
Card(
|
children: [
|
||||||
margin: const EdgeInsets.symmetric(horizontal: 18),
|
Image.asset(
|
||||||
shape: RoundedRectangleBorder(
|
'assets/images/cart.png',
|
||||||
borderRadius: BorderRadius.circular(19),
|
width: Get.width * 0.5,
|
||||||
side: const BorderSide(color: Color(0xFFFDFDFD)),
|
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,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
color: const Color(0xFFB4D1E5).withOpacity(0.9),
|
);
|
||||||
child: Padding(
|
}
|
||||||
padding: const EdgeInsets.all(12.0),
|
return Column(
|
||||||
child: Column(
|
children: [
|
||||||
mainAxisSize: MainAxisSize.min,
|
SizedBox(
|
||||||
children: [
|
height: Get.height * 0.02,
|
||||||
SizedBox(
|
),
|
||||||
height: Get.height * 0.6,
|
Card(
|
||||||
child: ListView.builder(
|
margin: const EdgeInsets.symmetric(horizontal: 18),
|
||||||
padding: EdgeInsets.zero,
|
shape: RoundedRectangleBorder(
|
||||||
itemCount: 10,
|
borderRadius: BorderRadius.circular(19),
|
||||||
itemBuilder: (context, index) => ProductCard(
|
side: const BorderSide(color: Color(0xFFFDFDFD)),
|
||||||
product: _cartList[0],
|
),
|
||||||
isInCart: true,
|
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.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(
|
Row(
|
||||||
height: 10,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
),
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Total Price: ₹ Total",
|
"Subtotal ",
|
||||||
style: GoogleFonts.roboto(
|
style: GoogleFonts.roboto(
|
||||||
fontSize: 20,
|
fontSize: 15,
|
||||||
fontWeight: FontWeight.w700,
|
color: Colors.black,
|
||||||
color: Colors.white,
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Obx(() =>
|
||||||
|
Text("₹ ${_cartController.subtotal.value}")),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
Row(
|
||||||
const SizedBox(
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
height: 16,
|
children: [
|
||||||
),
|
Text(
|
||||||
],
|
"GST ",
|
||||||
),
|
style: GoogleFonts.roboto(
|
||||||
),
|
fontSize: 15,
|
||||||
),
|
color: Colors.black,
|
||||||
SizedBox(
|
fontWeight: FontWeight.bold,
|
||||||
height: Get.height * 0.025,
|
),
|
||||||
),
|
),
|
||||||
SizedBox(
|
Obx(() =>
|
||||||
width: Get.width * 0.9,
|
Text("₹ ${_cartController.gstTotal.value}")),
|
||||||
height: Get.height * 0.06,
|
],
|
||||||
child: ElevatedButton(
|
),
|
||||||
onPressed: () => Get.to(() => const CheckoutScreen()),
|
Row(
|
||||||
style: ElevatedButton.styleFrom(
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
foregroundColor: Colors.white,
|
children: [
|
||||||
backgroundColor: const Color(0xFF00784C),
|
Text(
|
||||||
shape: RoundedRectangleBorder(
|
"Total Amount ",
|
||||||
borderRadius: BorderRadius.circular(10),
|
style: GoogleFonts.roboto(
|
||||||
),
|
fontSize: 15,
|
||||||
),
|
color: Colors.black,
|
||||||
child: Text(
|
fontWeight: FontWeight.bold,
|
||||||
"Proceed to Checkout",
|
),
|
||||||
style: GoogleFonts.roboto(
|
),
|
||||||
fontSize: 16,
|
Obx(() => Text(
|
||||||
fontWeight: FontWeight.w600,
|
"₹ ${_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(
|
||||||
|
selectedProducts: _cartController.selectedProducts,
|
||||||
|
)),
|
||||||
|
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,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 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/models/product_model1.dart';
|
||||||
import 'package:cheminova/widgets/my_drawer.dart';
|
import 'package:cheminova/screens/product/cart_screen.dart';
|
||||||
import 'package:cheminova/widgets/product_card.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:google_fonts/google_fonts.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 {
|
class ProductCatalogScreen extends StatefulWidget {
|
||||||
const ProductCatalogScreen({super.key});
|
const ProductCatalogScreen({super.key});
|
||||||
@ -14,22 +18,103 @@ class ProductCatalogScreen extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _ProductCatalogScreenState extends State<ProductCatalogScreen> {
|
class _ProductCatalogScreenState extends State<ProductCatalogScreen> {
|
||||||
final List<ProductModel> _productList = [
|
final ProductService _productService = ProductService();
|
||||||
ProductModel(
|
final ScrollController _scrollController = ScrollController();
|
||||||
id: '1',
|
final CartController cartController = Get.put(CartController());
|
||||||
name: 'Product 1',
|
|
||||||
price: 100,
|
List<Product> _products = []; // Use ProductModel here
|
||||||
description: 'Description 1',
|
List<Map<String, dynamic>> _categories = [];
|
||||||
category: ProductCategory.food,
|
|
||||||
image: 'assets/images/product.png',
|
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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
@ -52,17 +137,42 @@ class _ProductCatalogScreenState extends State<ProductCatalogScreen> {
|
|||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () => Get.back(),
|
onTap: () => Get.to(CartScreen()),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: SvgPicture.asset(
|
child: Stack(
|
||||||
'assets/svg/back_arrow.svg',
|
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(
|
||||||
"Product Catalogue",
|
child: const Text(
|
||||||
|
"Product Catalogue",
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
drawer: const MyDrawer(),
|
drawer: const MyDrawer(),
|
||||||
@ -74,67 +184,191 @@ class _ProductCatalogScreenState extends State<ProductCatalogScreen> {
|
|||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
),
|
),
|
||||||
SafeArea(
|
SafeArea(
|
||||||
child: Column(
|
child: SingleChildScrollView(
|
||||||
children: [
|
child: Column(
|
||||||
SizedBox(
|
children: [
|
||||||
height: Get.height * 0.02,
|
SizedBox(height: Get.height * 0.02),
|
||||||
),
|
Padding(
|
||||||
Card(
|
padding: const EdgeInsets.symmetric(horizontal: 18.0),
|
||||||
margin: const EdgeInsets.symmetric(horizontal: 18),
|
child: TextField(
|
||||||
shape: RoundedRectangleBorder(
|
decoration: InputDecoration(
|
||||||
borderRadius: BorderRadius.circular(19),
|
hintText: "Search Products",
|
||||||
side: const BorderSide(color: Color(0xFFFDFDFD)),
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(15),
|
||||||
|
),
|
||||||
|
filled: true,
|
||||||
|
fillColor: Colors.white.withOpacity(0.9),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
color: const Color(0xFFB4D1E5).withOpacity(0.9),
|
SizedBox(height: Get.height * 0.02),
|
||||||
child: Padding(
|
Card(
|
||||||
padding: const EdgeInsets.all(12.0),
|
margin: const EdgeInsets.symmetric(horizontal: 18),
|
||||||
child: Column(
|
shape: RoundedRectangleBorder(
|
||||||
mainAxisSize: MainAxisSize.min,
|
borderRadius: BorderRadius.circular(19),
|
||||||
children: [
|
side: const BorderSide(color: Color(0xFFFDFDFD)),
|
||||||
SizedBox(
|
),
|
||||||
height: Get.height * 0.05,
|
color: const Color(0xFFB4D1E5).withOpacity(0.9),
|
||||||
child: ListView.builder(
|
child: Padding(
|
||||||
shrinkWrap: true,
|
padding: const EdgeInsets.all(12.0),
|
||||||
scrollDirection: Axis.horizontal,
|
child: Column(
|
||||||
itemCount: _filterList.length,
|
mainAxisSize: MainAxisSize.min,
|
||||||
itemBuilder: (context, index) => Padding(
|
children: [
|
||||||
padding:
|
Row(
|
||||||
const EdgeInsets.symmetric(horizontal: 4),
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
child: Chip(
|
children: [
|
||||||
label: Text(
|
Text(
|
||||||
_filterList[index],
|
"Filter",
|
||||||
style: GoogleFonts.roboto(
|
style: GoogleFonts.poppins(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
fontSize: 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: _clearFilters,
|
||||||
|
child: Text(
|
||||||
|
"Clear Filter",
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
color: Colors.red,
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: Get.height * 0.05,
|
||||||
|
child: ListView.builder(
|
||||||
|
shrinkWrap: true,
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
itemCount: 3,
|
||||||
|
itemBuilder: (context, index) =>
|
||||||
|
_buildFilterDropdown(index),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
SizedBox(
|
||||||
SizedBox(
|
height: Get.height * 0.6,
|
||||||
height: Get.height * 0.6,
|
child: ListView.builder(
|
||||||
child: ListView.builder(
|
controller: _scrollController,
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
shrinkWrap: true,
|
itemCount: _products.length +
|
||||||
itemCount: 10,
|
(_isLoading ? 1 : 0),
|
||||||
itemBuilder: (context, index) => Padding(
|
itemBuilder: (context, index) {
|
||||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
if (index >= _products.length) {
|
||||||
child: ProductCard(
|
print("Product length $_products");
|
||||||
product: _productList[0],
|
return const Center(
|
||||||
),
|
child: CircularProgressIndicator());
|
||||||
|
}
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 8),
|
||||||
|
child: ProductCard(
|
||||||
|
productModel: _products[index],
|
||||||
|
// Use ProductModel here
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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/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:cheminova/widgets/my_drawer.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
|
|
||||||
|
import '../../controller/cart_controller.dart';
|
||||||
|
|
||||||
class ProductDetailScreen extends StatefulWidget {
|
class ProductDetailScreen extends StatefulWidget {
|
||||||
final ProductModel product;
|
Product? productModel;
|
||||||
const ProductDetailScreen({super.key, required this.product});
|
ProductModel? product;
|
||||||
|
|
||||||
|
ProductDetailScreen({super.key, this.product, this.productModel});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<ProductDetailScreen> createState() => _ProductDetailScreenState();
|
State<ProductDetailScreen> createState() => _ProductDetailScreenState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ProductDetailScreenState extends State<ProductDetailScreen> {
|
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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
@ -83,7 +93,7 @@ class _ProductDetailScreenState extends State<ProductDetailScreen> {
|
|||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: Container(
|
child: Container(
|
||||||
height: Get.height * 0.4,
|
height: Get.height * 0.4,
|
||||||
width: Get.width * 0.7,
|
width: Get.width * 0.8,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
width: 4,
|
width: 4,
|
||||||
@ -93,56 +103,80 @@ class _ProductDetailScreenState extends State<ProductDetailScreen> {
|
|||||||
),
|
),
|
||||||
child: ClipRRect(
|
child: ClipRRect(
|
||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.circular(10),
|
||||||
child: Image.asset(
|
child: Image.asset("assets/images/product.png", fit: BoxFit.cover,),
|
||||||
widget.product.image,
|
// Image.asset(
|
||||||
fit: BoxFit.cover,
|
// widget.product.image,
|
||||||
|
// fit: BoxFit.cover,
|
||||||
|
// ),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||||
|
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: 16,
|
||||||
|
// fontWeight: FontWeight.w600,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||||
child: Text(
|
child: Row(
|
||||||
widget.product.name,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
style: GoogleFonts.roboto(
|
children: [
|
||||||
fontSize: 20,
|
const Text("Price ",style: TextStyle(fontSize: 16,fontWeight: FontWeight.bold),),
|
||||||
fontWeight: FontWeight.w600,
|
Text(
|
||||||
color: Colors.white,
|
"₹ ${widget.productModel!.price.toString()}",
|
||||||
),
|
style: GoogleFonts.roboto(
|
||||||
|
fontSize: 16,
|
||||||
|
//fontWeight: FontWeight.w800,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||||
child: Text(
|
child: Row(
|
||||||
"₹ ${widget.product.price.toString()}",
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
style: GoogleFonts.roboto(
|
children: [
|
||||||
fontSize: 24,
|
const Text("Category ",style: TextStyle(fontWeight: FontWeight.bold,fontSize: 16),),
|
||||||
fontWeight: FontWeight.w800,
|
Text(
|
||||||
color: Colors.white,
|
capitalizeFirstLetter(widget.productModel!.category.categoryName),
|
||||||
),
|
style: GoogleFonts.roboto(
|
||||||
),
|
fontSize: 16,
|
||||||
),
|
fontWeight: FontWeight.w400,
|
||||||
Padding(
|
color: Colors.black,
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
),
|
||||||
child: Text(
|
),
|
||||||
widget.product.category.name,
|
],
|
||||||
style: GoogleFonts.roboto(
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: FontWeight.w400,
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||||
child: Text(
|
child: Row(
|
||||||
widget.product.description,
|
children: [
|
||||||
style: GoogleFonts.roboto(
|
const Text("Description",style: TextStyle(fontWeight: FontWeight.bold,fontSize: 16)),
|
||||||
fontSize: 16,
|
Text(
|
||||||
fontWeight: FontWeight.w400,
|
capitalizeFirstLetter(widget.productModel!.description),
|
||||||
color: Colors.white,
|
style: GoogleFonts.roboto(
|
||||||
),
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -154,7 +188,11 @@ class _ProductDetailScreenState extends State<ProductDetailScreen> {
|
|||||||
width: Get.width * 0.9,
|
width: Get.width * 0.9,
|
||||||
height: Get.height * 0.06,
|
height: Get.height * 0.06,
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
onPressed: () => 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(
|
style: ElevatedButton.styleFrom(
|
||||||
foregroundColor: Colors.white,
|
foregroundColor: Colors.white,
|
||||||
backgroundColor: const Color(0xFF00784C),
|
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 'dart:async';
|
||||||
|
|
||||||
import 'package:cheminova/screens/authentication/login_screen.dart';
|
import 'package:cheminova/screens/authentication/login_screen.dart';
|
||||||
|
import 'package:cheminova/screens/home_screen.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
class SplashScreen extends StatefulWidget {
|
class SplashScreen extends StatefulWidget {
|
||||||
const SplashScreen({super.key});
|
const SplashScreen({super.key});
|
||||||
@ -15,12 +17,25 @@ class SplashScreen extends StatefulWidget {
|
|||||||
class _SplashScreenState extends State<SplashScreen> {
|
class _SplashScreenState extends State<SplashScreen> {
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
Timer(const Duration(seconds: 3), () {
|
||||||
Timer(const Duration(seconds: 2), () {
|
checkLogin();
|
||||||
Get.offAll(() => const LoginScreen());
|
|
||||||
});
|
});
|
||||||
|
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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
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 'dart:io';
|
||||||
|
|
||||||
import 'package:cheminova/utils/constants.dart';
|
import 'package:cheminova/utils/constants.dart';
|
||||||
import 'package:cheminova/utils/show_snackbar.dart';
|
import 'package:cheminova/utils/show_snackbar.dart';
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
import 'package:pretty_dio_logger/pretty_dio_logger.dart';
|
||||||
|
|
||||||
Future<BodyType?> commonApiService<BodyType>({
|
Future<BodyType?> commonApiService<BodyType>({
|
||||||
required String url,
|
required String url,
|
||||||
required String method,
|
required String method,
|
||||||
Map<String, dynamic> body = const {},
|
Map<String, dynamic> body = const {},
|
||||||
File? imageFile,
|
File? imageFile,
|
||||||
bool isformData = true,
|
bool isFormData = false,
|
||||||
|
Map<String, String>? additionalHeaders,
|
||||||
required BodyType Function(Map<String, dynamic>) fromJson,
|
required BodyType Function(Map<String, dynamic>) fromJson,
|
||||||
}) async {
|
}) async {
|
||||||
try {
|
try {
|
||||||
Dio dio = Dio();
|
final dio = Dio();
|
||||||
final Response response;
|
|
||||||
|
|
||||||
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
|
final prefs = await SharedPreferences.getInstance();
|
||||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
final token = prefs.getString('token');
|
||||||
String? token = prefs.getString('token');
|
|
||||||
|
|
||||||
Map<String, String> headers = {
|
final headers = <String, String>{
|
||||||
'Content-Type': isformData ? 'multipart/form-data' : 'application/json',
|
'Content-Type': isFormData ? 'multipart/form-data' : 'application/json',
|
||||||
|
if (token != null) 'Authorization': 'Bearer $token',
|
||||||
|
...?additionalHeaders,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (token != null) {
|
final options = Options(headers: headers);
|
||||||
headers['Authorization'] = 'Bearer $token';
|
|
||||||
}
|
|
||||||
|
|
||||||
Options options = Options(headers: headers);
|
dynamic requestData = isFormData ? FormData.fromMap(body) : body;
|
||||||
|
|
||||||
FormData formData = FormData.fromMap(body);
|
if (imageFile != null && isFormData) {
|
||||||
|
final fileName = imageFile.path.split('/').last;
|
||||||
if (imageFile != null) {
|
(requestData as FormData).files.add(MapEntry(
|
||||||
String fileName = imageFile.path.split('/').last;
|
|
||||||
formData.files.add(MapEntry(
|
|
||||||
"image",
|
"image",
|
||||||
await MultipartFile.fromFile(imageFile.path, filename: fileName),
|
await MultipartFile.fromFile(imageFile.path, filename: fileName),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (method == "POST") {
|
final Response response;
|
||||||
response = await dio.post("$baseUrl$url",
|
switch (method.toUpperCase()) {
|
||||||
data: isformData ? formData : body, options: options);
|
case "POST":
|
||||||
} else if (method == "PUT") {
|
response = await dio.post("$baseUrl$url", data: requestData, options: options);
|
||||||
response = await dio.put("$baseUrl$url",
|
break;
|
||||||
data: isformData ? formData : body, options: options);
|
case "PUT":
|
||||||
} else if (method == "DELETE") {
|
response = await dio.put("$baseUrl$url", data: requestData, options: options);
|
||||||
response = await dio.delete("$baseUrl$url", options: options);
|
break;
|
||||||
} else if (method == "PATCH") {
|
case "DELETE":
|
||||||
response = await dio.patch("$baseUrl$url",
|
response = await dio.delete("$baseUrl$url", options: options);
|
||||||
data: isformData ? formData : body, options: options);
|
break;
|
||||||
} else {
|
case "PATCH":
|
||||||
response = await dio.get("$baseUrl$url", options: options);
|
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/rd-login" && response.data['token'] != null) {
|
||||||
|
await prefs.setString('token', response.data['token']);
|
||||||
if (url == "/api/territorymanager/login" &&
|
|
||||||
response.data['token'] != null) {
|
|
||||||
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['myData']);
|
||||||
}
|
}
|
||||||
|
|
||||||
return fromJson(response.data);
|
return fromJson(response.data);
|
||||||
} on DioException catch (e) {
|
} on DioException catch (e) {
|
||||||
print("dio exception $url ${e.response?.data}}");
|
|
||||||
print("dio exception details: ${e.message} ${e.response?.statusCode}");
|
|
||||||
String errorMessage = "An error occurred";
|
String errorMessage = "An error occurred";
|
||||||
|
|
||||||
if (e.response?.data is Map<String, dynamic>) {
|
if (e.response?.data is Map<String, dynamic>) {
|
||||||
errorMessage = e.response?.data['message'] ?? errorMessage;
|
errorMessage = e.response?.data['message'] ?? errorMessage;
|
||||||
} else if (e.response?.data is String) {
|
} else if (e.response?.data is String) {
|
||||||
@ -82,8 +88,10 @@ Future<BodyType?> commonApiService<BodyType>({
|
|||||||
}
|
}
|
||||||
|
|
||||||
showSnackbar(errorMessage);
|
showSnackbar(errorMessage);
|
||||||
|
return null;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print("exception $url $e");
|
print("Unexpected error for $url: $e");
|
||||||
|
showSnackbar("An unexpected error occurred");
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
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:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
class InputField extends StatelessWidget {
|
class InputField extends StatefulWidget {
|
||||||
final String hintText;
|
final String hintText;
|
||||||
final String labelText;
|
final String labelText;
|
||||||
final TextEditingController controller;
|
final TextEditingController controller;
|
||||||
final bool obscureText;
|
final bool obscureText;
|
||||||
final TextInputType? keyboardType;
|
final TextInputType? keyboardType;
|
||||||
|
final String? Function(String?)? validator;// Add this line for validation
|
||||||
|
|
||||||
const InputField({
|
InputField({
|
||||||
super.key,
|
super.key,
|
||||||
required this.hintText,
|
required this.hintText,
|
||||||
required this.labelText,
|
required this.labelText,
|
||||||
required this.controller,
|
required this.controller,
|
||||||
this.obscureText = false,
|
this.obscureText = false,
|
||||||
this.keyboardType = TextInputType.text,
|
this.keyboardType = TextInputType.text,
|
||||||
|
this.validator, // Add this
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<InputField> createState() => _InputFieldState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _InputFieldState extends State<InputField> {
|
||||||
|
bool _isObscured = true;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return Container(
|
||||||
@ -24,15 +33,16 @@ class InputField extends StatelessWidget {
|
|||||||
width: Get.width * 0.9,
|
width: Get.width * 0.9,
|
||||||
padding: const EdgeInsets.fromLTRB(6, 10, 10, 0),
|
padding: const EdgeInsets.fromLTRB(6, 10, 10, 0),
|
||||||
child: TextFormField(
|
child: TextFormField(
|
||||||
controller: controller,
|
controller: widget.controller,
|
||||||
obscureText: obscureText,
|
obscureText: widget.obscureText && _isObscured,
|
||||||
keyboardType: keyboardType,
|
keyboardType: widget.keyboardType,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: labelText,
|
labelText: widget.labelText,
|
||||||
hintText: hintText,
|
hintText: widget.hintText,
|
||||||
labelStyle: const TextStyle(
|
labelStyle: const TextStyle(
|
||||||
color: Color(0xFF000000),
|
color: Color(0xFF000000),
|
||||||
),
|
),
|
||||||
|
|
||||||
enabledBorder: const OutlineInputBorder(
|
enabledBorder: const OutlineInputBorder(
|
||||||
borderSide: BorderSide(color: Colors.grey),
|
borderSide: BorderSide(color: Colors.grey),
|
||||||
borderRadius: BorderRadius.all(Radius.circular(8)),
|
borderRadius: BorderRadius.all(Radius.circular(8)),
|
||||||
@ -42,10 +52,24 @@ class InputField extends StatelessWidget {
|
|||||||
borderRadius: BorderRadius.all(Radius.circular(8)),
|
borderRadius: BorderRadius.all(Radius.circular(8)),
|
||||||
),
|
),
|
||||||
contentPadding:
|
contentPadding:
|
||||||
const EdgeInsets.symmetric(vertical: 10, horizontal: 16),
|
const EdgeInsets.symmetric(vertical: 10, horizontal: 16),
|
||||||
fillColor: Colors.white,
|
fillColor: Colors.white,
|
||||||
filled: true,
|
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/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/authentication/login_screen.dart';
|
||||||
import 'package:cheminova/screens/home_screen.dart';
|
import 'package:cheminova/screens/home_screen.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
|
import '../screens/authentication/Profile.dart';
|
||||||
|
|
||||||
class MyDrawer extends StatefulWidget {
|
class MyDrawer extends StatefulWidget {
|
||||||
const MyDrawer({super.key});
|
const MyDrawer({super.key});
|
||||||
|
|
||||||
@ -21,32 +24,37 @@ class _MyDrawerState extends State<MyDrawer> {
|
|||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: 150,
|
height: 150,
|
||||||
child: Obx(
|
child:(
|
||||||
() => DrawerHeader(
|
DrawerHeader(
|
||||||
decoration: const BoxDecoration(
|
decoration: const BoxDecoration(
|
||||||
color: Colors.black87,
|
color: Colors.black87,
|
||||||
),
|
),
|
||||||
child: Column(
|
child: GetBuilder(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
init: homeController,
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
builder: (controller) {
|
||||||
children: [
|
return Column(
|
||||||
Text(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
homeController.user.value?.name ?? "username",
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
style: const TextStyle(
|
children: [
|
||||||
color: Colors.white,
|
Text(
|
||||||
fontSize: 18,
|
controller.user?.name?? "username",
|
||||||
),
|
style: const TextStyle(
|
||||||
),
|
color: Colors.white,
|
||||||
Text(
|
fontSize: 18,
|
||||||
homeController.user.value?.uniqueId ?? 'Employee ID',
|
),
|
||||||
style: const TextStyle(
|
),
|
||||||
color: Colors.white,
|
Text(
|
||||||
fontSize: 20,
|
controller.user?.uniqueId?? 'Employee ID',
|
||||||
),
|
style: const TextStyle(
|
||||||
),
|
color: Colors.white,
|
||||||
],
|
fontSize: 20,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
),
|
||||||
|
)
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
@ -58,13 +66,15 @@ class _MyDrawerState extends State<MyDrawer> {
|
|||||||
leading: const Icon(Icons.account_circle),
|
leading: const Icon(Icons.account_circle),
|
||||||
title: const Text('Profile'),
|
title: const Text('Profile'),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.pop(context);
|
Get.to(ProfileScreen());
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.settings),
|
leading: const Icon(Icons.settings),
|
||||||
title: const Text('Change Password'),
|
title: const Text('Change Password'),
|
||||||
onTap: () {},
|
onTap: () {
|
||||||
|
Get.to(ChangePasswordScreen());
|
||||||
|
},
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.exit_to_app),
|
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/models/product_model.dart';
|
||||||
import 'package:cheminova/screens/product/product_detail_screen.dart';
|
import 'package:cheminova/screens/product/product_detail_screen.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
|
|
||||||
class ProductCard extends StatelessWidget {
|
import '../models/product_model1.dart';
|
||||||
final ProductModel product;
|
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 isInCart;
|
||||||
final bool isCheckout;
|
final bool isCheckout;
|
||||||
const ProductCard({
|
final bool isConfirmation;
|
||||||
|
int? quantity;
|
||||||
|
|
||||||
|
ProductCard({
|
||||||
super.key,
|
super.key,
|
||||||
required this.product,
|
this.product,
|
||||||
|
this.quantity = 1,
|
||||||
|
this.productModel,
|
||||||
|
this.placedOrder,
|
||||||
|
this.placedOrderList,
|
||||||
|
this.placeorderItem,
|
||||||
this.isInCart = false,
|
this.isInCart = false,
|
||||||
this.isCheckout = 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
|
@override
|
||||||
Widget build(BuildContext context) {
|
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(
|
return GestureDetector(
|
||||||
onTap: () => isInCart || isCheckout
|
onTap: () => widget.isInCart || widget.isCheckout
|
||||||
? null
|
? null
|
||||||
: Get.to(() => ProductDetailScreen(product: product)),
|
: Get.to(() => ProductDetailScreen(productModel: widget.productModel)),
|
||||||
child: Card(
|
child: Card(
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
@ -30,142 +68,179 @@ class ProductCard extends StatelessWidget {
|
|||||||
borderRadius: BorderRadius.circular(15.0),
|
borderRadius: BorderRadius.circular(15.0),
|
||||||
child: Container(
|
child: Container(
|
||||||
height: Get.height * 0.15,
|
height: Get.height * 0.15,
|
||||||
width: Get.width * 0.30,
|
width: Get.width * 0.31,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
image: DecorationImage(
|
image: DecorationImage(
|
||||||
image: Image.asset(product.image).image,
|
image: AssetImage("assets/images/product.png"),
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(
|
Expanded(
|
||||||
width: 10,
|
child: Padding(
|
||||||
),
|
padding: const EdgeInsets.symmetric(horizontal: 3.0),
|
||||||
Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
product.name,
|
capitalizeFirstLetter(widget.productModel!.name),
|
||||||
style: GoogleFonts.roboto(
|
style: GoogleFonts.roboto(
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
product.category.name,
|
capitalizeFirstLetter(widget.productModel!.category!.categoryName),
|
||||||
style: GoogleFonts.roboto(
|
style: GoogleFonts.roboto(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
fontWeight: FontWeight.w400,
|
fontWeight: FontWeight.w400,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
"₹ ${product.price.toString()}0",
|
"₹ ${widget.productModel!.price.toString()}",
|
||||||
style: GoogleFonts.roboto(
|
style: GoogleFonts.roboto(
|
||||||
fontSize: 22,
|
fontSize: 22,
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w700,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
isCheckout
|
if (showQuantity)
|
||||||
? const SizedBox()
|
Text(
|
||||||
: isInCart
|
"Quantity: ${currentQuantity}",
|
||||||
? Row(
|
style: GoogleFonts.roboto(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
fontSize: 15,
|
||||||
children: [
|
fontWeight: FontWeight.w700,
|
||||||
Container(
|
),
|
||||||
height: 40,
|
),
|
||||||
width: 100,
|
if (!widget.isCheckout)
|
||||||
decoration: BoxDecoration(
|
widget.isInCart
|
||||||
color: const Color(0xFF004791),
|
? Row(
|
||||||
borderRadius: BorderRadius.circular(10),
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
),
|
children: [
|
||||||
child: Row(
|
Container(
|
||||||
mainAxisAlignment:
|
height: Get.height * 0.04,
|
||||||
MainAxisAlignment.spaceAround,
|
width: Get.width * 0.21,
|
||||||
children: [
|
decoration: BoxDecoration(
|
||||||
SizedBox(
|
color: const Color(0xFF004791),
|
||||||
height: 24,
|
borderRadius: BorderRadius.circular(10),
|
||||||
width: 24,
|
|
||||||
child: ElevatedButton(
|
|
||||||
onPressed: () {},
|
|
||||||
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),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: Text(
|
|
||||||
'-',
|
|
||||||
style: GoogleFonts.roboto(
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: FontWeight.w800,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
onPressed: () {},
|
|
||||||
icon: const Icon(
|
|
||||||
Icons.delete_outline_rounded,
|
|
||||||
color: Colors.red,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
)
|
|
||||||
: ElevatedButton(
|
|
||||||
onPressed: () {},
|
|
||||||
style: ElevatedButton.styleFrom(
|
|
||||||
foregroundColor: Colors.white,
|
|
||||||
backgroundColor: const Color(0xFF00784C),
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
horizontal: 18, vertical: 8),
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(30),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Row(
|
||||||
"Add To Cart",
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
style: GoogleFonts.roboto(
|
children: [
|
||||||
fontSize: 14,
|
SizedBox(
|
||||||
fontWeight: FontWeight.w600,
|
height: 24,
|
||||||
),
|
width: 24,
|
||||||
|
child: ElevatedButton(
|
||||||
|
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(
|
||||||
|
"${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: () {
|
||||||
|
_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: () {
|
||||||
|
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),
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(30),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
"Add To Cart",
|
||||||
|
style: GoogleFonts.roboto(
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -6,6 +6,14 @@
|
|||||||
|
|
||||||
#include "generated_plugin_registrant.h"
|
#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) {
|
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
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
|
file_selector_linux
|
||||||
|
url_launcher_linux
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||||
|
@ -5,10 +5,28 @@
|
|||||||
import FlutterMacOS
|
import FlutterMacOS
|
||||||
import Foundation
|
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 path_provider_foundation
|
||||||
import shared_preferences_foundation
|
import shared_preferences_foundation
|
||||||
|
import syncfusion_pdfviewer_macos
|
||||||
|
import url_launcher_macos
|
||||||
|
|
||||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
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"))
|
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||||
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
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
|
# Generated by pub
|
||||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||||
packages:
|
packages:
|
||||||
|
_flutterfire_internals:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: _flutterfire_internals
|
||||||
|
sha256: ddc6f775260b89176d329dee26f88b9469ef46aa3228ff6a0b91caf2b2989692
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.3.42"
|
||||||
args:
|
args:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -17,6 +25,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.11.0"
|
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:
|
boolean_selector:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -49,6 +65,22 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.18.0"
|
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:
|
crypto:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -57,6 +89,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.3"
|
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:
|
cupertino_icons:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -65,6 +105,30 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.8"
|
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:
|
dio:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -105,6 +169,134 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "7.0.0"
|
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:
|
flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -118,6 +310,38 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.2"
|
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:
|
flutter_svg:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -144,6 +368,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.6.6"
|
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:
|
google_fonts:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -152,6 +384,22 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.2.1"
|
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:
|
http:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -168,22 +416,102 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.2"
|
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:
|
leak_tracker:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: leak_tracker
|
name: leak_tracker
|
||||||
sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a"
|
sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "10.0.4"
|
version: "10.0.5"
|
||||||
leak_tracker_flutter_testing:
|
leak_tracker_flutter_testing:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: leak_tracker_flutter_testing
|
name: leak_tracker_flutter_testing
|
||||||
sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8"
|
sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.3"
|
version: "3.0.5"
|
||||||
leak_tracker_testing:
|
leak_tracker_testing:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -200,6 +528,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.0"
|
version: "3.0.0"
|
||||||
|
logger:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: logger
|
||||||
|
sha256: "697d067c60c20999686a0add96cf6aba723b3aa1f83ecf806a8097231529ec32"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.0"
|
||||||
matcher:
|
matcher:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -212,18 +548,26 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: material_color_utilities
|
name: material_color_utilities
|
||||||
sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a"
|
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.8.0"
|
version: "0.11.1"
|
||||||
meta:
|
meta:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: meta
|
name: meta
|
||||||
sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
|
sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
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:
|
path:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -320,6 +664,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.8"
|
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:
|
shared_preferences:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -389,6 +741,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.10.0"
|
version: "1.10.0"
|
||||||
|
sprintf:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: sprintf
|
||||||
|
sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "7.0.0"
|
||||||
stack_trace:
|
stack_trace:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -413,6 +773,70 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0"
|
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:
|
term_glyph:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -425,10 +849,18 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_api
|
name: test_api
|
||||||
sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f"
|
sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
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:
|
typed_data:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -437,6 +869,78 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.2"
|
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:
|
vector_graphics:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -473,10 +977,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: vm_service
|
name: vm_service
|
||||||
sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec"
|
sha256: f652077d0bdf60abe4c1f6377448e8655008eef28f128bc023f7b5e8dfeb48fc
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "14.2.1"
|
version: "14.2.4"
|
||||||
web:
|
web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -485,6 +989,22 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.0"
|
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:
|
xdg_directories:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
14
pubspec.yaml
14
pubspec.yaml
@ -41,6 +41,20 @@ dependencies:
|
|||||||
dio: ^5.5.0+1
|
dio: ^5.5.0+1
|
||||||
http: ^1.2.2
|
http: ^1.2.2
|
||||||
shared_preferences: ^2.2.3
|
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:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
@ -6,6 +6,18 @@
|
|||||||
|
|
||||||
#include "generated_plugin_registrant.h"
|
#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) {
|
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
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
|
file_selector_windows
|
||||||
|
firebase_core
|
||||||
|
syncfusion_pdfviewer_windows
|
||||||
|
url_launcher_windows
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||||
|
Loading…
Reference in New Issue
Block a user