1)Order Place api Integration
2)Confirm Order api Integration 3)get Oder api Integration
This commit is contained in:
parent
43413ac168
commit
215877afc4
@ -1,4 +1,5 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<application
|
||||
android:label="cheminova"
|
||||
android:name="${applicationName}"
|
||||
|
40
lib/controller/get_order_placed_controller.dart
Normal file
40
lib/controller/get_order_placed_controller.dart
Normal file
@ -0,0 +1,40 @@
|
||||
import 'package:cheminova/controller/get_place_order_service.dart';
|
||||
import 'package:cheminova/controller/product_service.dart';
|
||||
import 'package:cheminova/models/oder_place_model.dart';
|
||||
import 'package:cheminova/models/product_model1.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
|
||||
class GetPlacedOrderController extends GetxController {
|
||||
final GetOrderPlacedServcie _getOrderPlacedServcie = GetOrderPlacedServcie();
|
||||
var products = <PlacedOrderModel>[].obs;
|
||||
|
||||
int _currentPage = 1;
|
||||
bool isLoading = false;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
|
||||
}
|
||||
|
||||
Future<void> getOrder(String id) async {
|
||||
if (isLoading) return;
|
||||
isLoading = true;
|
||||
try {
|
||||
|
||||
final fetchedProducts = await _getOrderPlacedServcie.getPlacedOrder();
|
||||
|
||||
|
||||
if (fetchedProducts != null) {
|
||||
|
||||
products.addAll(fetchedProducts);
|
||||
}
|
||||
} catch (e) {
|
||||
print("Error fetching products: $e");
|
||||
} finally {
|
||||
isLoading = false;
|
||||
update();
|
||||
}
|
||||
}
|
||||
}
|
35
lib/controller/get_place_order_service.dart
Normal file
35
lib/controller/get_place_order_service.dart
Normal file
@ -0,0 +1,35 @@
|
||||
import 'package:cheminova/models/oder_place_model.dart';
|
||||
|
||||
import '../utils/common_api_service.dart';
|
||||
import '../utils/show_snackbar.dart';
|
||||
|
||||
class GetOrderPlacedServcie{
|
||||
Future<List<PlacedOrderModel>?> getPlacedOrder() async {
|
||||
try {
|
||||
String url;
|
||||
|
||||
url = "/api/get-placed-order-pd?id=66cc7869f02b935094127a27";
|
||||
|
||||
final response = await commonApiService<List<PlacedOrderModel>>(
|
||||
method: "GET",
|
||||
url: url,
|
||||
fromJson: (json) {
|
||||
if (json['plcaedOrders'] != null) {
|
||||
final List<PlacedOrderModel> products = (json['plcaedOrders'] as List)
|
||||
.map((productJson) => PlacedOrderModel.fromJson(productJson as Map<String, dynamic>))
|
||||
.toList();
|
||||
return products;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
);
|
||||
return response;
|
||||
} catch (e) {
|
||||
showSnackbar(e.toString());
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
import 'package:cheminova/controller/home_service.dart';
|
||||
import 'package:cheminova/models/user_model.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
class HomeController extends GetxController {
|
||||
final HomeService homeService = HomeService();
|
||||
|
||||
var user = Rxn<UserModel>();
|
||||
|
||||
@override
|
||||
@ -12,8 +14,10 @@ class HomeController extends GetxController {
|
||||
super.onInit();
|
||||
}
|
||||
|
||||
Future<void> getUser() async {
|
||||
user.value = await homeService.getUser();
|
||||
update();
|
||||
Future<void> getUser() async
|
||||
{
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
String? token = prefs.getString('token');
|
||||
user.value = (await homeService.getUser(token: token)) as UserModel? ;
|
||||
}
|
||||
}
|
||||
|
@ -3,12 +3,15 @@ import 'package:cheminova/utils/common_api_service.dart';
|
||||
import 'package:cheminova/utils/show_snackbar.dart';
|
||||
|
||||
class HomeService {
|
||||
Future<UserModel?> getUser() async {
|
||||
Future<Map<String, dynamic>?> getUser({String? token}) async {
|
||||
try {
|
||||
final response = await commonApiService<UserModel>(
|
||||
final response = await commonApiService<Map<String,dynamic>>(
|
||||
method: "GET",
|
||||
url: "/api/territorymanager/my-profile",
|
||||
fromJson: (json) => UserModel.fromJson(json),
|
||||
url: "api/v1/user/details",
|
||||
fromJson: (json) => json,
|
||||
additionalHeaders: { // Pass the token here
|
||||
'Authorization': 'Bearer $token',
|
||||
},
|
||||
);
|
||||
|
||||
return response;
|
||||
@ -17,4 +20,6 @@ class HomeService {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
129
lib/controller/place_order_controller.dart
Normal file
129
lib/controller/place_order_controller.dart
Normal file
@ -0,0 +1,129 @@
|
||||
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;
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// import 'package:cheminova/controller/place_order_service.dart';
|
||||
// import 'package:cheminova/models/category_model.dart';
|
||||
// import 'package:get/get.dart';
|
||||
// import 'package:shared_preferences/shared_preferences.dart';
|
||||
// import '../models/oder_place_model.dart';
|
||||
// import 'cart_controller.dart';
|
||||
//
|
||||
//
|
||||
// class OrderPlacedController extends GetxController {
|
||||
// final OrderPlacedService _orderPlacedService = OrderPlacedService();
|
||||
// final CartController _cartController = Get.find();
|
||||
// Rx<PlacedOrderModel?> placedOrder1 = Rx<PlacedOrderModel?>(null);
|
||||
// RxBool isLoading = false.obs;
|
||||
//
|
||||
// // Method to place an order with provided details
|
||||
// Future<void> placeOrder() async {
|
||||
// SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
// String? token = prefs.getString('token');
|
||||
//
|
||||
// // Prepare order details
|
||||
// final order = PlacedOrderModel(
|
||||
// paymentMode: 'cheque',
|
||||
// shipTo: '456, Park Street, Kolkata, West Bengal - 700016',
|
||||
// billTo: '456, Park Street, Kolkata, West Bengal - 700016',
|
||||
// subtotal: 4000,
|
||||
// gstTotal: 18,
|
||||
// grandTotal: 4720,
|
||||
// orderItems: [
|
||||
// OrderItem(
|
||||
// id: "66cc7869f02b935094127a27",
|
||||
// sku: "BJD",
|
||||
// name: "Zycor 60m.l",
|
||||
// price: 4000,
|
||||
// gst: 18,
|
||||
// hsnCode: 200,
|
||||
// description: "",
|
||||
// productStatus: "Active",
|
||||
// addedBy: "ChemiNova",
|
||||
// image: [],
|
||||
// createdAt: DateTime.parse("2024-08-26T12:43:21.103Z"),
|
||||
// updatedAt: DateTime.parse("2024-08-26T12:43:21.103Z"),
|
||||
// count: 1, category:Category(id: "66cc7868f02b935094127a21", categoryName: "Insectiside") ,
|
||||
// brand: Brand(id: "66cc77fbf02b9350941279f5", brandName: "Old"), v: 0,
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
//
|
||||
// try {
|
||||
// isLoading.value = true;
|
||||
// PlacedOrderModel? result = await _orderPlacedService.placeOrder(order, token);
|
||||
// if (result != null) {
|
||||
// placedOrder1.value = result;
|
||||
// Get.snackbar('Success', 'Order placed successfully.');
|
||||
// // _cartController.clearCart(); // Clear cart items after order
|
||||
// } else {
|
||||
// Get.snackbar('Error', 'Failed to place order.');
|
||||
// }
|
||||
// } catch (e) {
|
||||
// Get.snackbar('Error', e.toString());
|
||||
// } finally {
|
||||
// isLoading.value = false;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// String getShippingAddress() {
|
||||
// return placedOrder1.value?.shipTo ?? 'No shipping address';
|
||||
// }
|
||||
//
|
||||
// String getBillingAddress() {
|
||||
// return placedOrder1.value?.billTo ?? 'No billing address';
|
||||
// }
|
||||
//
|
||||
// String getPaymentMode() {
|
||||
// return placedOrder1.value?.paymentMode ?? 'No payment mode';
|
||||
// }
|
||||
// }
|
41
lib/controller/place_order_service.dart
Normal file
41
lib/controller/place_order_service.dart
Normal file
@ -0,0 +1,41 @@
|
||||
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://cheminova-api-2.onrender.com/api/order-place', // Ensure this is your correct endpoint
|
||||
data: jsonEncode(orderDetails.toJson()),
|
||||
options: Options(
|
||||
headers: {
|
||||
'Authorization': 'Bearer $token',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
),
|
||||
);
|
||||
logger.w("Status code,${response.statusCode}");
|
||||
if (response.statusCode != 201) {
|
||||
|
||||
throw Exception('Failed to place order');
|
||||
}
|
||||
}
|
||||
// on DioException catch (e) {
|
||||
// print("DioException: ${e.message}");
|
||||
// throw Exception('Failed to place order: ${e.message}');
|
||||
// }
|
||||
// catch (e) {
|
||||
// print("General Exception: ${e.toString()}");
|
||||
// throw Exception('Failed to place order: ${e.toString()}');
|
||||
// }
|
||||
}
|
||||
|
@ -1,10 +1,11 @@
|
||||
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 = <Map<String, dynamic>>[].obs;
|
||||
var products = <Product>[].obs;
|
||||
var categories = <String>[].obs; // Holds the list of categories
|
||||
var selectedCategory = Rxn<String>(); // Holds the selected category
|
||||
int _currentPage = 1;
|
||||
@ -28,7 +29,9 @@ class ProductController extends GetxController {
|
||||
);
|
||||
|
||||
if (fetchedProducts != null) {
|
||||
products.addAll(fetchedProducts as Iterable<Map<String, dynamic>>);
|
||||
// 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");
|
||||
|
@ -1,8 +1,9 @@
|
||||
import '../models/product_model1.dart';
|
||||
import '../utils/common_api_service.dart';
|
||||
import '../utils/show_snackbar.dart';
|
||||
|
||||
class ProductService {
|
||||
Future<List<Map<String, dynamic>>?> getProduct(int page, {String? category}) async {
|
||||
Future<List<Product>?> getProduct(int page, {String? category}) async {
|
||||
try {
|
||||
String url;
|
||||
if (category != null && category.isNotEmpty) {
|
||||
@ -11,13 +12,13 @@ class ProductService {
|
||||
url = "/api/product/getAll/user?page=$page"; // URL without category filter
|
||||
}
|
||||
|
||||
final response = await commonApiService<List<Map<String, dynamic>>>(
|
||||
final response = await commonApiService<List<Product>>(
|
||||
method: "GET",
|
||||
url: url,
|
||||
fromJson: (json) {
|
||||
if (json['products'] != null) {
|
||||
final List<Map<String, dynamic>> products = (json['products'] as List)
|
||||
.map((productJson) => productJson as Map<String, dynamic>)
|
||||
final List<Product> products = (json['products'] as List)
|
||||
.map((productJson) => Product.fromJson(productJson as Map<String, dynamic>))
|
||||
.toList();
|
||||
return products;
|
||||
} else {
|
||||
@ -27,11 +28,11 @@ class ProductService {
|
||||
);
|
||||
return response;
|
||||
} catch (e) {
|
||||
showSnackbar(e.toString());
|
||||
//print("Error: $e");
|
||||
}
|
||||
// showSnackbar(e.toString());
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Future<List<Map<String, dynamic>>?> getCategory() async {
|
||||
|
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,)';
|
||||
}
|
||||
}
|
183
lib/models/oder_place_model.dart
Normal file
183
lib/models/oder_place_model.dart
Normal file
@ -0,0 +1,183 @@
|
||||
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)';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// class Brand {
|
||||
// String id;
|
||||
// String brandName;
|
||||
//
|
||||
// Brand({
|
||||
// required this.id,
|
||||
// required this.brandName,
|
||||
// });
|
||||
//
|
||||
// factory Brand.fromJson(Map<String, dynamic> json) => Brand(
|
||||
// id: json["_id"],
|
||||
// brandName: json["brandName"],
|
||||
// );
|
||||
//
|
||||
// Map<String, dynamic> toJson() => {
|
||||
// "_id": id,
|
||||
// "brandName": brandName,
|
||||
// };
|
||||
// }
|
||||
//
|
||||
// class Category {
|
||||
// String id;
|
||||
// String categoryName;
|
||||
//
|
||||
// Category({
|
||||
// required this.id,
|
||||
// required this.categoryName,
|
||||
// });
|
||||
//
|
||||
// factory Category.fromJson(Map<String, dynamic> json) => Category(
|
||||
// id: json["_id"],
|
||||
// categoryName: json["categoryName"],
|
||||
// );
|
||||
//
|
||||
// Map<String, dynamic> toJson() => {
|
||||
// "_id": id,
|
||||
// "categoryName": categoryName,
|
||||
// };
|
||||
// }
|
130
lib/models/order_item_model.dart
Normal file
130
lib/models/order_item_model.dart
Normal file
@ -0,0 +1,130 @@
|
||||
// import 'brand_model.dart';
|
||||
// import 'category_model.dart';
|
||||
//
|
||||
// class OrderItem {
|
||||
// final String id;
|
||||
// final String sku;
|
||||
// final String name;
|
||||
// final Category category;
|
||||
// final Brand brand;
|
||||
// final double price;
|
||||
// final double gst;
|
||||
// final int hsnCode;
|
||||
// final String description;
|
||||
// final String productStatus;
|
||||
// final String addedBy;
|
||||
// final List<String> image;
|
||||
// final DateTime createdAt;
|
||||
// final DateTime updatedAt;
|
||||
// final int count;
|
||||
//
|
||||
// OrderItem({
|
||||
// required this.id,
|
||||
// required this.sku,
|
||||
// required this.name,
|
||||
// required this.category,
|
||||
// required this.brand,
|
||||
// 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,
|
||||
// });
|
||||
//
|
||||
// factory OrderItem.fromJson(Map<String, dynamic> json) {
|
||||
// return OrderItem(
|
||||
// id: json['_id'],
|
||||
// sku: json['SKU'],
|
||||
// name: json['name'],
|
||||
// category: Category.fromJson(json['category']),
|
||||
// brand: Brand.fromJson(json['brand']),
|
||||
// price: json['price'].toDouble(),
|
||||
// gst: json['GST'].toDouble(),
|
||||
// hsnCode: json['HSN_Code'],
|
||||
// description: json['description'],
|
||||
// productStatus: json['product_Status'],
|
||||
// addedBy: json['addedBy'],
|
||||
// image: List<String>.from(json['image'] ?? []),
|
||||
// createdAt: DateTime.parse(json['createdAt']),
|
||||
// updatedAt: DateTime.parse(json['updatedAt']),
|
||||
// count: json['count'],
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// Map<String, dynamic> toJson() {
|
||||
// return {
|
||||
// '_id': id,
|
||||
// 'SKU': sku,
|
||||
// 'name': name,
|
||||
// 'category': category,
|
||||
// 'brand': brand,
|
||||
// 'price': price,
|
||||
// 'GST': gst,
|
||||
// 'HSN_Code': hsnCode,
|
||||
// 'description': description,
|
||||
// 'product_Status': productStatus,
|
||||
// 'addedBy': addedBy,
|
||||
// 'image': image,
|
||||
// 'createdAt': createdAt.toIso8601String(),
|
||||
// 'updatedAt': updatedAt.toIso8601String(),
|
||||
// 'count': count,
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// //
|
||||
// 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'],
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// //
|
||||
// // class AddedBy {
|
||||
// // final String id;
|
||||
// // final String name;
|
||||
// //
|
||||
// // AddedBy({
|
||||
// // required this.id,
|
||||
// // required this.name,
|
||||
// // });
|
||||
// //
|
||||
// // factory AddedBy.fromJson(Map<String, dynamic> json) {
|
||||
// // return AddedBy(
|
||||
// // id: json['_id'],
|
||||
// // name: json['name'],
|
||||
// // );
|
||||
// // }
|
||||
// // }
|
@ -5,6 +5,8 @@ class ProductModel {
|
||||
final String image;
|
||||
final String description;
|
||||
final double price;
|
||||
String? category1;
|
||||
String? brandname;
|
||||
final ProductCategory category;
|
||||
final String id;
|
||||
int quantity;
|
||||
@ -15,7 +17,39 @@ class ProductModel {
|
||||
required this.description,
|
||||
required this.price,
|
||||
required this.category,
|
||||
this.category1,
|
||||
this.brandname,
|
||||
required this.id,
|
||||
this.quantity = 1,
|
||||
});
|
||||
|
||||
// Factory constructor
|
||||
factory ProductModel.fromJson(Map<String, dynamic> json) {
|
||||
return ProductModel(
|
||||
name: json['name']??"",
|
||||
image: json['image']??"",
|
||||
description: json['description']??"",
|
||||
price: json['price']??"",
|
||||
category: ProductCategory.values.firstWhere((e) => e.toString().split('.').last == json['category']),
|
||||
category1: json['category1']??"",
|
||||
brandname: json['brandname']??"",
|
||||
id: json['id'],
|
||||
quantity: json['quantity'] ?? 1,
|
||||
);
|
||||
}
|
||||
|
||||
// Optional: toJson method if you need to convert the model back to JSON
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'name': name,
|
||||
'image': image,
|
||||
'description': description,
|
||||
'price': price,
|
||||
'category': category.toString().split('.').last,
|
||||
'category1': category1,
|
||||
'brandname': brandname,
|
||||
'id': id,
|
||||
'quantity': quantity,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
116
lib/models/product_model1.dart
Normal file
116
lib/models/product_model1.dart
Normal file
@ -0,0 +1,116 @@
|
||||
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;
|
||||
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,
|
||||
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'],
|
||||
// );
|
||||
// }
|
||||
// }
|
@ -16,11 +16,11 @@ class UserModel {
|
||||
// Factory constructor to create an instance of UserModel from a JSON map
|
||||
factory UserModel.fromJson(Map<String, dynamic> json) {
|
||||
return UserModel(
|
||||
id: json['_id'] as String,
|
||||
name: json['name'] as String,
|
||||
uniqueId: json['uniqueId'] as String,
|
||||
email: json['email'] as String,
|
||||
isVerified: json['isVerified'] as bool,
|
||||
id: json['_id'] ??"",
|
||||
name: json['name'] ??"Sarita",
|
||||
uniqueId: json['uniqueId'] ??"1234",
|
||||
email: json['email'] ??"",
|
||||
isVerified: json['isVerified'] as bool? ??false,
|
||||
);
|
||||
}
|
||||
|
||||
@ -34,4 +34,10 @@ class UserModel {
|
||||
'isVerified': isVerified,
|
||||
};
|
||||
}
|
||||
|
||||
// Override toString() to provide a readable output
|
||||
@override
|
||||
String toString() {
|
||||
return 'UserModel{id: $id, name: $name, uniqueId: $uniqueId, email: $email, isVerified: $isVerified}';
|
||||
}
|
||||
}
|
||||
|
@ -132,6 +132,7 @@ class _ForgetPasswordScreenState extends State<ForgetPasswordScreen> {
|
||||
|
||||
onPressed: () => authController.forgotpass(),
|
||||
isLoading: authController.isLoading.value,
|
||||
|
||||
),
|
||||
],
|
||||
),
|
||||
|
@ -85,7 +85,7 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||
HomeCard(
|
||||
title: 'Order Management',
|
||||
onTap: () => Get.to(
|
||||
() => const OrderManagementScreen(),
|
||||
() => OrderManagementScreen(),
|
||||
),
|
||||
),
|
||||
HomeCard(
|
||||
|
@ -1,36 +1,174 @@
|
||||
import 'package:cheminova/models/product_model.dart';
|
||||
import 'package:cheminova/screens/order/order_confermation_screen.dart';
|
||||
import 'package:cheminova/widgets/input_field.dart';
|
||||
import 'package:cheminova/widgets/my_drawer.dart';
|
||||
import 'package:cheminova/widgets/product_card.dart';
|
||||
import 'dart:ffi';
|
||||
import 'package:cheminova/controller/get_order_placed_controller.dart';
|
||||
import 'package:cheminova/models/added_by_model.dart';
|
||||
import 'package:cheminova/models/category_model.dart';
|
||||
import 'package:cheminova/utils/show_snackbar.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import '../../controller/cart_controller.dart';
|
||||
import '../../controller/place_order_controller.dart';
|
||||
import '../../controller/place_order_service.dart';
|
||||
import '../../controller/product_controller.dart';
|
||||
import '../../controller/product_service.dart';
|
||||
import '../../models/brand_model.dart';
|
||||
import '../../models/oder_place_model.dart';
|
||||
import '../../models/product_model1.dart';
|
||||
import '../../widgets/my_drawer.dart';
|
||||
import '../../widgets/product_card.dart';
|
||||
import 'order_confermation_screen.dart';
|
||||
|
||||
class CheckoutScreen extends StatefulWidget {
|
||||
const CheckoutScreen({super.key});
|
||||
final Product? productModel;
|
||||
|
||||
PlacedOrderModel? placeOrder;
|
||||
|
||||
CheckoutScreen({super.key, this.productModel, this.placeOrder});
|
||||
|
||||
@override
|
||||
State<CheckoutScreen> createState() => _CheckoutScreenState();
|
||||
}
|
||||
|
||||
class _CheckoutScreenState extends State<CheckoutScreen> {
|
||||
final TextEditingController _addressController = TextEditingController();
|
||||
final TextEditingController _contactController = TextEditingController();
|
||||
final CartController _cartController = Get.put(CartController());
|
||||
final ProductService _productService = ProductService();
|
||||
final ProductController _productController = Get.put(ProductController());
|
||||
final OrderPlacedController _orderPlacedController =
|
||||
Get.put(OrderPlacedController());
|
||||
final GetPlacedOrderController _getPlacedOrderController = Get.put(GetPlacedOrderController());
|
||||
|
||||
final List<ProductModel> _checkoutList = [
|
||||
ProductModel(
|
||||
id: "1",
|
||||
image: 'assets/images/product.png',
|
||||
name: "Product 1",
|
||||
category: ProductCategory.food,
|
||||
description: 'Product 1 description',
|
||||
price: 100,
|
||||
),
|
||||
int currentPage = 1;
|
||||
String _groupValue = "cheque";
|
||||
|
||||
final List<String> _addressList = [
|
||||
'Home - 123 Street, City',
|
||||
'Office - 456 Avenue, City',
|
||||
'Warehouse - 789 Blvd, City',
|
||||
];
|
||||
|
||||
String _groupValue = "Credit Card";
|
||||
String? _selectedShippingAddress;
|
||||
String? _selectedBillingAddress;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
// _getOrder();
|
||||
_loadSelectedAddress();
|
||||
_loadSelectedPaymentMode();
|
||||
|
||||
if (_addressList.isNotEmpty) {
|
||||
_selectedShippingAddress = _addressList.first;
|
||||
_selectedBillingAddress = _addressList.first;
|
||||
}
|
||||
}
|
||||
|
||||
void _saveSelectedAddress() async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setString('selectedShippingAddress', _selectedShippingAddress!);
|
||||
await prefs.setString('selectedBillingAddress', _selectedBillingAddress!);
|
||||
}
|
||||
|
||||
void _onShippingAddressChanged(String? value) {
|
||||
setState(() {
|
||||
_selectedShippingAddress = value;
|
||||
});
|
||||
_saveSelectedAddress();
|
||||
}
|
||||
|
||||
void _onBillingAddressChanged(String? value) {
|
||||
setState(() {
|
||||
_selectedBillingAddress = value;
|
||||
});
|
||||
_saveSelectedAddress();
|
||||
}
|
||||
|
||||
void _loadSelectedAddress() async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
setState(() {
|
||||
_selectedShippingAddress =
|
||||
prefs.getString('selectedShippingAddress') ?? _addressList.first;
|
||||
_selectedBillingAddress =
|
||||
prefs.getString('selectedBillingAddress') ?? _addressList.first;
|
||||
});
|
||||
}
|
||||
|
||||
void _onPaymentModeChanged(String? value) {
|
||||
setState(() {
|
||||
_groupValue = value!;
|
||||
});
|
||||
_saveSelectedPaymentMode();
|
||||
}
|
||||
|
||||
void _saveSelectedPaymentMode() async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setString('selectedPaymentMode', _groupValue);
|
||||
}
|
||||
|
||||
void _loadSelectedPaymentMode() async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
setState(() {
|
||||
_groupValue = prefs.getString('selectedPaymentMode') ?? 'cheque';
|
||||
});
|
||||
}
|
||||
|
||||
// void _getOrder(){
|
||||
// final details = _getPlacedOrderController.getOrder(widget.productModel!.id);
|
||||
// print("dffgfg,$details");
|
||||
// }
|
||||
void _onPlaceOrder() async {
|
||||
try {
|
||||
// Map the cart items (Product) to OrderItem objects
|
||||
List<OrderItem> orderItems = _cartController.cartList.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("OderPlaced Successfully");
|
||||
Get.to(() => OrderConfermationScreen(
|
||||
placedOrder: _orderPlacedController.placedOrder1.value,
|
||||
));
|
||||
}
|
||||
} catch (e) {
|
||||
print("PlaceOrderScreen error: $e");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -63,9 +201,7 @@ class _CheckoutScreenState extends State<CheckoutScreen> {
|
||||
),
|
||||
),
|
||||
],
|
||||
title: const Text(
|
||||
"Checkout",
|
||||
),
|
||||
title: const Text("Checkout"),
|
||||
),
|
||||
drawer: const MyDrawer(),
|
||||
body: Stack(
|
||||
@ -78,9 +214,7 @@ class _CheckoutScreenState extends State<CheckoutScreen> {
|
||||
SafeArea(
|
||||
child: Column(
|
||||
children: [
|
||||
SizedBox(
|
||||
height: Get.height * 0.02,
|
||||
),
|
||||
SizedBox(height: Get.height * 0.02),
|
||||
Card(
|
||||
margin: EdgeInsets.symmetric(horizontal: Get.width * 0.05),
|
||||
shape: RoundedRectangleBorder(
|
||||
@ -106,15 +240,37 @@ class _CheckoutScreenState extends State<CheckoutScreen> {
|
||||
),
|
||||
),
|
||||
),
|
||||
InputField(
|
||||
hintText: 'Address:',
|
||||
labelText: 'Address:',
|
||||
controller: _addressController,
|
||||
SizedBox(height: 5,),
|
||||
DropdownButtonFormField<String>(
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Shipping Address:',
|
||||
hintText: 'Select Shipping Address',
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
InputField(
|
||||
hintText: 'Contact:',
|
||||
labelText: 'Contact:',
|
||||
controller: _contactController,
|
||||
value: _selectedShippingAddress,
|
||||
items: _addressList.map((String address) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: address,
|
||||
child: Text(address),
|
||||
);
|
||||
}).toList(),
|
||||
onChanged: _onShippingAddressChanged,
|
||||
),
|
||||
SizedBox(height: Get.height * 0.02),
|
||||
DropdownButtonFormField<String>(
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Billing Address:',
|
||||
hintText: 'Select Billing Address',
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
value: _selectedBillingAddress,
|
||||
items: _addressList.map((String address) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: address,
|
||||
child: Text(address),
|
||||
);
|
||||
}).toList(),
|
||||
onChanged: _onBillingAddressChanged,
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
@ -136,42 +292,30 @@ class _CheckoutScreenState extends State<CheckoutScreen> {
|
||||
SizedBox(
|
||||
height: Get.height * 0.035,
|
||||
child: RadioListTile(
|
||||
title: const Text("Credit Card"),
|
||||
title: const Text("cheque"),
|
||||
contentPadding: EdgeInsets.zero,
|
||||
value: "Credit Card",
|
||||
value: "cheque",
|
||||
groupValue: _groupValue,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_groupValue = value.toString();
|
||||
});
|
||||
},
|
||||
onChanged: _onPaymentModeChanged,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: Get.height * 0.035,
|
||||
child: RadioListTile(
|
||||
title: const Text("Net Banking"),
|
||||
title: const Text("online-transfer"),
|
||||
contentPadding: EdgeInsets.zero,
|
||||
value: "Net Banking",
|
||||
value: "online-transfer",
|
||||
groupValue: _groupValue,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_groupValue = value.toString();
|
||||
});
|
||||
},
|
||||
onChanged: _onPaymentModeChanged,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
child: RadioListTile(
|
||||
title: const Text("Cash on Delivery"),
|
||||
title: const Text("credit"),
|
||||
contentPadding: EdgeInsets.zero,
|
||||
value: "Cash on Delivery",
|
||||
value: "credit",
|
||||
groupValue: _groupValue,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_groupValue = value.toString();
|
||||
});
|
||||
},
|
||||
onChanged: _onPaymentModeChanged,
|
||||
),
|
||||
),
|
||||
],
|
||||
@ -198,58 +342,68 @@ class _CheckoutScreenState extends State<CheckoutScreen> {
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(Get.width * 0.02),
|
||||
child: ListView.builder(
|
||||
padding: EdgeInsets.zero,
|
||||
itemCount: 10,
|
||||
itemBuilder: (context, index) =>
|
||||
ProductCard(
|
||||
product: _checkoutList[0],
|
||||
itemCount: _cartController.cartList.length,
|
||||
itemBuilder: (context, index) {
|
||||
final cartItem =
|
||||
_cartController.cartList[index];
|
||||
return ProductCard(
|
||||
productModel:_cartController.cartList[index] ,
|
||||
isCheckout: true,
|
||||
),
|
||||
quantity: _cartController.cartList[0].quantity,
|
||||
|
||||
|
||||
// ListTile(
|
||||
// title: Text(cartItem.name ?? 'N/A'),
|
||||
// subtitle: Text(
|
||||
// 'Quantity: ${cartItem.quantity}'),
|
||||
// trailing: Text(
|
||||
// 'Price: \₹${cartItem.price.toStringAsFixed(2)}'),
|
||||
// );
|
||||
);},
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.all(Get.width * 0.04),
|
||||
child: Text(
|
||||
'Total Price: ₹ 1000.00',
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: Get.width * 0.05,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
),
|
||||
padding: EdgeInsets.all(Get.width * 0.02),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Subtotal: \₹${_cartController.subtotal.value.toStringAsFixed(2)}'),
|
||||
Text(
|
||||
'GST: \₹${_cartController.gstTotal.value.toStringAsFixed(2)}'),
|
||||
Text(
|
||||
'Grand Total: \₹${_cartController.grandTotal.value.toStringAsFixed(2)}'),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
height: Get.height * 0.025,
|
||||
),
|
||||
SizedBox(
|
||||
width: Get.width * 0.9,
|
||||
height: Get.height * 0.06,
|
||||
child: ElevatedButton(
|
||||
onPressed: () =>
|
||||
Get.to(() => const OrderConfermationScreen()),
|
||||
),
|
||||
SizedBox(height: 10.0,),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
ElevatedButton(
|
||||
onPressed: _onPlaceOrder,
|
||||
style: ElevatedButton.styleFrom(
|
||||
foregroundColor: Colors.white,
|
||||
backgroundColor: const Color(0xFF00784C),
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: Get.width * 0.20,
|
||||
vertical: Get.height * 0.02),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
"Place Order",
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: Get.width * 0.04,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
child: const Text("Place Order"),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
|
@ -1,4 +1,6 @@
|
||||
import 'package:cheminova/controller/get_order_placed_controller.dart';
|
||||
import 'package:cheminova/models/product_model.dart';
|
||||
import 'package:cheminova/utils/show_snackbar.dart';
|
||||
import 'package:cheminova/widgets/my_drawer.dart';
|
||||
import 'package:cheminova/widgets/product_card.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@ -6,8 +8,15 @@ import 'package:flutter_svg/svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
|
||||
import '../../controller/cart_controller.dart';
|
||||
import '../../controller/place_order_controller.dart';
|
||||
import '../../models/oder_place_model.dart';
|
||||
import '../../models/product_model1.dart';
|
||||
|
||||
class OrderConfermationScreen extends StatefulWidget {
|
||||
const OrderConfermationScreen({super.key});
|
||||
Product? productModel;
|
||||
PlacedOrderModel? placedOrder;
|
||||
OrderConfermationScreen({super.key,this.productModel,this.placedOrder});
|
||||
|
||||
@override
|
||||
State<OrderConfermationScreen> createState() =>
|
||||
@ -15,18 +24,28 @@ class OrderConfermationScreen extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _OrderConfermationScreenState extends State<OrderConfermationScreen> {
|
||||
final List<ProductModel> _checkoutList = [
|
||||
ProductModel(
|
||||
id: "1",
|
||||
image: 'assets/images/product.png',
|
||||
name: "Product 1",
|
||||
category: ProductCategory.food,
|
||||
description: 'Product 1 description',
|
||||
price: 100.00,
|
||||
),
|
||||
];
|
||||
final CartController _cartController = Get.put(CartController());
|
||||
final OrderPlacedController _placedController = Get.put(OrderPlacedController());
|
||||
final GetPlacedOrderController _getPlacedOrderController = Get.put(GetPlacedOrderController());
|
||||
// final List<ProductModel> _checkoutList = [
|
||||
// ProductModel(
|
||||
// id: "1",
|
||||
// image: 'assets/images/product.png',
|
||||
// name: "Product 1",
|
||||
// category: ProductCategory.food,
|
||||
// description: 'Product 1 description',
|
||||
// price: 100.00,
|
||||
// ),
|
||||
// ];
|
||||
|
||||
void _getOrder(){
|
||||
final details = _getPlacedOrderController.getOrder(_cartController.cartList[0].id);
|
||||
showSnackbar("Get Placed Order Sucessfully");
|
||||
print("dffgfg,$details");
|
||||
}
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final orderItems = _placedController.placedOrder1;
|
||||
return Scaffold(
|
||||
extendBodyBehindAppBar: true,
|
||||
appBar: AppBar(
|
||||
@ -94,7 +113,7 @@ class _OrderConfermationScreenState extends State<OrderConfermationScreen> {
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(
|
||||
"Order Number: 123456",
|
||||
"Order Number:1234",
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: Get.width * 0.04,
|
||||
fontWeight: FontWeight.w400,
|
||||
@ -124,24 +143,27 @@ class _OrderConfermationScreenState extends State<OrderConfermationScreen> {
|
||||
padding: EdgeInsets.all(Get.width * 0.02),
|
||||
child: ListView.builder(
|
||||
padding: EdgeInsets.zero,
|
||||
itemCount: 10,
|
||||
itemCount: _cartController.cartList.length,
|
||||
itemBuilder: (context, index) =>
|
||||
ProductCard(
|
||||
product: _checkoutList[0],
|
||||
productModel:_cartController.cartList[index],
|
||||
isCheckout: true,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.all(Get.width * 0.04),
|
||||
child: Text(
|
||||
'Total Price: ₹ 1000.00',
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: Get.width * 0.05,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: Colors.black,
|
||||
),
|
||||
padding: EdgeInsets.all(Get.width * 0.02),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
Text(
|
||||
'Subtotal: \₹${_cartController.subtotal.value.toStringAsFixed(2)}'),
|
||||
Text(
|
||||
'GST: \₹${_cartController.gstTotal.value.toStringAsFixed(2)}'),
|
||||
Text(
|
||||
'Grand Total: \₹${_cartController.grandTotal.value.toStringAsFixed(2)}'),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
@ -161,30 +183,30 @@ class _OrderConfermationScreenState extends State<OrderConfermationScreen> {
|
||||
Card(
|
||||
child: SizedBox(
|
||||
width: Get.width,
|
||||
height: Get.height * 0.2,
|
||||
height: Get.height * 0.1,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(
|
||||
"Address: Lorem Ipsum is simply dummy text of the printing and typesetting industry",
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: Get.width * 0.04,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(
|
||||
"Contact: +91 9123456789",
|
||||
"Address :${widget.placedOrder!.shipTo}",
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: Get.width * 0.04,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
// Padding(
|
||||
// padding: const EdgeInsets.all(8.0),
|
||||
// child: Text(
|
||||
// "Contact: +91 9123456789",
|
||||
// style: GoogleFonts.roboto(
|
||||
// fontSize: Get.width * 0.04,
|
||||
// fontWeight: FontWeight.w400,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -196,7 +218,7 @@ class _OrderConfermationScreenState extends State<OrderConfermationScreen> {
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(
|
||||
"Estimated Delivery Date: [Date]",
|
||||
"Estimated Delivery Date: 20 Sep 2024",
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: Get.width * 0.04,
|
||||
fontWeight: FontWeight.w400,
|
||||
@ -205,10 +227,30 @@ class _OrderConfermationScreenState extends State<OrderConfermationScreen> {
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
// Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.center,
|
||||
// children: [
|
||||
// ElevatedButton(
|
||||
// onPressed:_getOrder,
|
||||
// style: ElevatedButton.styleFrom(
|
||||
// foregroundColor: Colors.white,
|
||||
// backgroundColor: const Color(0xFF00784C),
|
||||
// padding: EdgeInsets.symmetric(
|
||||
// horizontal: Get.width * 0.20,
|
||||
// vertical: Get.height * 0.02),
|
||||
// shape: RoundedRectangleBorder(
|
||||
// borderRadius: BorderRadius.circular(10),
|
||||
// ),
|
||||
// ),
|
||||
// child: const Text("Confirm Order"),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -6,24 +6,19 @@ import 'package:flutter_svg/svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
|
||||
import '../../controller/cart_controller.dart';
|
||||
import '../../models/product_model1.dart';
|
||||
|
||||
class OrderFullfilmentScreen extends StatefulWidget {
|
||||
const OrderFullfilmentScreen({super.key});
|
||||
final Product? productModel;
|
||||
const OrderFullfilmentScreen({super.key,required this.productModel});
|
||||
|
||||
@override
|
||||
State<OrderFullfilmentScreen> createState() => _OrderFullfilmentScreenState();
|
||||
}
|
||||
|
||||
class _OrderFullfilmentScreenState extends State<OrderFullfilmentScreen> {
|
||||
final List<ProductModel> _checkoutList = [
|
||||
ProductModel(
|
||||
id: "1",
|
||||
image: 'assets/images/image_1.png',
|
||||
name: "Product 1",
|
||||
category: ProductCategory.food,
|
||||
description: 'Product 1 description',
|
||||
price: 100,
|
||||
),
|
||||
];
|
||||
final CartController _cartController = Get.put(CartController());
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
@ -153,7 +148,7 @@ class _OrderFullfilmentScreenState extends State<OrderFullfilmentScreen> {
|
||||
padding: EdgeInsets.zero,
|
||||
itemCount: 10,
|
||||
itemBuilder: (context, index) => ProductCard(
|
||||
product: _checkoutList[0],
|
||||
productModel:widget.productModel,
|
||||
isCheckout: true,
|
||||
),
|
||||
),
|
||||
|
@ -1,31 +1,38 @@
|
||||
import 'package:cheminova/models/product_model.dart';
|
||||
import 'package:cheminova/screens/order_management/order_fullfilment_screen.dart';
|
||||
import 'package:cheminova/widgets/product_card.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
|
||||
import '../../controller/cart_controller.dart';
|
||||
import '../../models/product_model1.dart';
|
||||
|
||||
class OrderManagementDetailScreen extends StatefulWidget {
|
||||
const OrderManagementDetailScreen({super.key});
|
||||
final Product? productModel;
|
||||
const OrderManagementDetailScreen({super.key,required this.productModel});
|
||||
|
||||
@override
|
||||
State<OrderManagementDetailScreen> createState() =>
|
||||
_OrderManagementDetailScreenState();
|
||||
}
|
||||
|
||||
|
||||
class _OrderManagementDetailScreenState
|
||||
extends State<OrderManagementDetailScreen> {
|
||||
final List<ProductModel> _checkoutList = [
|
||||
ProductModel(
|
||||
id: "1",
|
||||
image: 'assets/images/image_1.png',
|
||||
name: "Product 1",
|
||||
category: ProductCategory.food,
|
||||
description: 'Product 1 description',
|
||||
price: 100,
|
||||
),
|
||||
];
|
||||
final CartController _cartController = Get.put(CartController());
|
||||
// final List<ProductModel> _checkoutList = [
|
||||
// ProductModel(
|
||||
// id: "1",
|
||||
// image: 'assets/images/image_1.png',
|
||||
// name: "Product 1",
|
||||
// category: ProductCategory.food,
|
||||
// description: 'Product 1 description',
|
||||
// price: 100,
|
||||
// ),
|
||||
// ];
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
@ -155,7 +162,7 @@ class _OrderManagementDetailScreenState
|
||||
padding: EdgeInsets.zero,
|
||||
itemCount: 10,
|
||||
itemBuilder: (context, index) => ProductCard(
|
||||
product: _checkoutList[0],
|
||||
productModel: widget.productModel,
|
||||
isCheckout: true,
|
||||
),
|
||||
),
|
||||
@ -236,7 +243,9 @@ class _OrderManagementDetailScreenState
|
||||
height: Get.height * 0.06,
|
||||
child: ElevatedButton(
|
||||
onPressed: () => Get.to(
|
||||
() => const OrderFullfilmentScreen(),
|
||||
() => OrderFullfilmentScreen(
|
||||
productModel:widget.productModel ,
|
||||
),
|
||||
),
|
||||
style: ElevatedButton.styleFrom(
|
||||
foregroundColor: Colors.white,
|
||||
|
@ -6,8 +6,11 @@ import 'package:flutter_svg/svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
|
||||
import '../../models/product_model1.dart';
|
||||
|
||||
class OrderManagementScreen extends StatefulWidget {
|
||||
const OrderManagementScreen({super.key});
|
||||
Product? productModel;
|
||||
OrderManagementScreen({super.key,this.productModel});
|
||||
|
||||
@override
|
||||
State<OrderManagementScreen> createState() => _OrderManagementScreenState();
|
||||
@ -177,7 +180,9 @@ class _OrderManagementScreenState extends State<OrderManagementScreen> {
|
||||
child: ElevatedButton(
|
||||
onPressed: () => Get.to(
|
||||
() =>
|
||||
const OrderManagementDetailScreen(),
|
||||
OrderManagementDetailScreen(
|
||||
productModel:widget.productModel,
|
||||
),
|
||||
),
|
||||
style: ElevatedButton.styleFrom(
|
||||
foregroundColor: Colors.white,
|
||||
|
@ -1,3 +1,4 @@
|
||||
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';
|
||||
@ -5,27 +6,31 @@ import 'package:cheminova/widgets/product_card.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:get/get_core/get_core.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
|
||||
import '../../controller/cart_controller.dart';
|
||||
import '../../models/product_model1.dart';
|
||||
|
||||
class CartScreen extends StatefulWidget {
|
||||
const CartScreen({super.key});
|
||||
Product? productModel;
|
||||
PlacedOrderModel? placedOrder;
|
||||
CartScreen({super.key, this.productModel,this.placedOrder});
|
||||
|
||||
@override
|
||||
State<CartScreen> createState() => _CartScreenState();
|
||||
}
|
||||
|
||||
class _CartScreenState extends State<CartScreen> {
|
||||
final List<ProductModel> _cartList = [
|
||||
ProductModel(
|
||||
id: "1",
|
||||
image: 'assets/images/product.png',
|
||||
name: "Product 1",
|
||||
category: ProductCategory.food,
|
||||
description: 'Product 1 description',
|
||||
price: 100,
|
||||
),
|
||||
];
|
||||
final CartController _cartController = Get.find<CartController>();
|
||||
|
||||
// @override
|
||||
void initState() {
|
||||
super.initState();
|
||||
if (widget.productModel != null) {
|
||||
_cartController.addToCart(widget.productModel);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
@ -89,29 +94,59 @@ class _CartScreenState extends State<CartScreen> {
|
||||
children: [
|
||||
SizedBox(
|
||||
height: Get.height * 0.6,
|
||||
child: ListView.builder(
|
||||
child: Obx(() {
|
||||
return ListView.builder(
|
||||
padding: EdgeInsets.zero,
|
||||
itemCount: 10,
|
||||
itemCount: _cartController.cartList.length,
|
||||
itemBuilder: (context, index) => ProductCard(
|
||||
product: _cartList[0],
|
||||
productModel: _cartController.cartList[index],
|
||||
isInCart: true,
|
||||
placedOrder:widget.placedOrder,
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Text(
|
||||
"Total Price: ₹ Total",
|
||||
Obx(() {
|
||||
return Text(
|
||||
"Subtotal Price: ₹ ${_cartController.subtotal.value}",
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: 20,
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: Colors.white,
|
||||
),
|
||||
);
|
||||
|
||||
}),
|
||||
|
||||
|
||||
// const SizedBox(
|
||||
// height: 16,
|
||||
// ),
|
||||
Obx(() {
|
||||
return Text(
|
||||
"gstTotal Price: ₹ ${_cartController.gstTotal.value}",
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: Colors.white,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 16,
|
||||
);
|
||||
|
||||
}),
|
||||
Obx(() {
|
||||
return Text(
|
||||
"grandTotal Price: ₹ ${_cartController.grandTotal.value}",
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: Colors.white,
|
||||
),
|
||||
);
|
||||
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -123,7 +158,10 @@ class _CartScreenState extends State<CartScreen> {
|
||||
width: Get.width * 0.9,
|
||||
height: Get.height * 0.06,
|
||||
child: ElevatedButton(
|
||||
onPressed: () => Get.to(() => const CheckoutScreen()),
|
||||
onPressed: () => Get.to(() => CheckoutScreen(
|
||||
|
||||
productModel:widget.productModel
|
||||
)),
|
||||
style: ElevatedButton.styleFrom(
|
||||
foregroundColor: Colors.white,
|
||||
backgroundColor: const Color(0xFF00784C),
|
||||
|
@ -1,10 +1,14 @@
|
||||
import 'package:cheminova/models/product_model1.dart';
|
||||
import 'package:cheminova/screens/product/cart_screen.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import '../../controller/cart_controller.dart';
|
||||
import '../../widgets/my_drawer.dart';
|
||||
import '../../widgets/product_card.dart';
|
||||
import '../../controller/product_service.dart';
|
||||
import '../../models/product_model.dart'; // Import your ProductModel
|
||||
|
||||
class ProductCatalogScreen extends StatefulWidget {
|
||||
const ProductCatalogScreen({super.key});
|
||||
@ -16,24 +20,27 @@ class ProductCatalogScreen extends StatefulWidget {
|
||||
class _ProductCatalogScreenState extends State<ProductCatalogScreen> {
|
||||
final ProductService _productService = ProductService();
|
||||
final ScrollController _scrollController = ScrollController();
|
||||
List<Map<String, dynamic>> _products = [];
|
||||
final CartController cartController = Get.put(CartController());
|
||||
|
||||
List<Product> _products = []; // Use ProductModel here
|
||||
List<Map<String, dynamic>> _categories = [];
|
||||
|
||||
int _currentPage = 1;
|
||||
bool _isLoading = false;
|
||||
bool _hasMoreData = true;
|
||||
|
||||
String? _selectedCategory; // Default to null to handle 'All' explicitly
|
||||
String? _selectedCategory;
|
||||
String? _selectedPriceRange;
|
||||
String? _selectedAvailability;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_fetchCategories(); // Fetch categories first to set initial filter
|
||||
_fetchProducts(); // Fetch products after setting initial filters
|
||||
_fetchCategories();
|
||||
_fetchProducts();
|
||||
_scrollController.addListener(() {
|
||||
if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent &&
|
||||
if (_scrollController.position.pixels ==
|
||||
_scrollController.position.maxScrollExtent &&
|
||||
!_isLoading &&
|
||||
_hasMoreData) {
|
||||
_fetchMoreProducts();
|
||||
@ -46,13 +53,13 @@ class _ProductCatalogScreenState extends State<ProductCatalogScreen> {
|
||||
_isLoading = true;
|
||||
});
|
||||
|
||||
// Adjust the category parameter based on the selected category
|
||||
final category = _selectedCategory == 'All' ? null : _selectedCategory;
|
||||
|
||||
final products = await _productService.getProduct(_currentPage, category: category);
|
||||
final products = await _productService.getProduct(
|
||||
_currentPage, category: category);
|
||||
setState(() {
|
||||
if (products != null) {
|
||||
_products.addAll(products);
|
||||
_products.addAll(products); // Assuming products is a List<ProductModel>
|
||||
_hasMoreData = products.isNotEmpty;
|
||||
}
|
||||
_isLoading = false;
|
||||
@ -64,9 +71,8 @@ class _ProductCatalogScreenState extends State<ProductCatalogScreen> {
|
||||
if (categories != null) {
|
||||
setState(() {
|
||||
_categories = categories;
|
||||
// Add "All" option
|
||||
_categories.insert(1, {'categoryName': 'All'});
|
||||
_selectedCategory = 'All'; // Set initial selected category to "All"
|
||||
_selectedCategory = 'All';
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -131,11 +137,34 @@ class _ProductCatalogScreenState extends State<ProductCatalogScreen> {
|
||||
),
|
||||
actions: [
|
||||
GestureDetector(
|
||||
onTap: () => Get.back(),
|
||||
onTap: () => Get.to(CartScreen()),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: SvgPicture.asset(
|
||||
'assets/svg/back_arrow.svg',
|
||||
child: Stack(
|
||||
children: [
|
||||
Icon(Icons.shopping_cart, size: 30,),
|
||||
// Cart count display
|
||||
Positioned(
|
||||
right: 0,
|
||||
child: Obx(() =>
|
||||
cartController.cartCount.value > 0
|
||||
? Container(
|
||||
padding: EdgeInsets.all(4),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.red,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: Text(
|
||||
'${cartController.cartCount.value}',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
)
|
||||
: SizedBox.shrink()),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -157,7 +186,6 @@ class _ProductCatalogScreenState extends State<ProductCatalogScreen> {
|
||||
child: Column(
|
||||
children: [
|
||||
SizedBox(height: Get.height * 0.02),
|
||||
// Search Bar
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 18.0),
|
||||
child: TextField(
|
||||
@ -212,10 +240,8 @@ class _ProductCatalogScreenState extends State<ProductCatalogScreen> {
|
||||
shrinkWrap: true,
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemCount: 3,
|
||||
itemBuilder: (context, index) => Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 4),
|
||||
child: _buildFilterDropdown(index),
|
||||
),
|
||||
itemBuilder: (context, index) =>
|
||||
_buildFilterDropdown(index),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
@ -223,16 +249,20 @@ class _ProductCatalogScreenState extends State<ProductCatalogScreen> {
|
||||
child: ListView.builder(
|
||||
controller: _scrollController,
|
||||
padding: EdgeInsets.zero,
|
||||
itemCount: _products.length + (_isLoading ? 1 : 0),
|
||||
itemCount: _products.length +
|
||||
(_isLoading ? 1 : 0),
|
||||
itemBuilder: (context, index) {
|
||||
if (index >= _products.length) {
|
||||
print("Product length $_products");
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
return const Center(
|
||||
child: CircularProgressIndicator());
|
||||
}
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 8),
|
||||
child: ProductCard(
|
||||
productModel: _products[index],
|
||||
// Use ProductModel here
|
||||
),
|
||||
);
|
||||
},
|
||||
@ -254,57 +284,89 @@ class _ProductCatalogScreenState extends State<ProductCatalogScreen> {
|
||||
Widget _buildFilterDropdown(int index) {
|
||||
switch (index) {
|
||||
case 0:
|
||||
return DropdownButton<String>(
|
||||
return _buildStyledDropdown(
|
||||
value: _selectedCategory,
|
||||
hint: const Text("Category"),
|
||||
onChanged: (value) {
|
||||
if (value != null) {
|
||||
_onCategoryChanged(value);
|
||||
}
|
||||
},
|
||||
items: _categories.map<DropdownMenuItem<String>>((category) {
|
||||
onChanged: _onCategoryChanged,
|
||||
items: _categories.map((category) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: category['categoryName'],
|
||||
child: Text(category['categoryName']),
|
||||
);
|
||||
}).toList(),
|
||||
hint: "Category",
|
||||
);
|
||||
case 1:
|
||||
return DropdownButton<String>(
|
||||
value: _selectedPriceRange,
|
||||
hint: const Text("Price Range"),
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_selectedPriceRange = value;
|
||||
});
|
||||
},
|
||||
items: <String>['\$0-\$50', '\$51-\$100', '\$101-\$150']
|
||||
.map<DropdownMenuItem<String>>((String value) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: value,
|
||||
child: Text(value),
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
case 2:
|
||||
return DropdownButton<String>(
|
||||
value: _selectedAvailability,
|
||||
hint: const Text("Availability"),
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_selectedAvailability = value;
|
||||
});
|
||||
},
|
||||
items: <String>['In Stock', 'Out of Stock']
|
||||
.map<DropdownMenuItem<String>>((String value) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: value,
|
||||
child: Text(value),
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
// 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 Container();
|
||||
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,5 +1,7 @@
|
||||
import 'package:cheminova/models/product_model.dart';
|
||||
import 'package:cheminova/models/product_model1.dart';
|
||||
import 'package:cheminova/screens/order/checkout_screen.dart';
|
||||
import 'package:cheminova/utils/show_snackbar.dart';
|
||||
import 'package:cheminova/widgets/my_drawer.dart';
|
||||
import 'package:cheminova/widgets/product_card.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@ -7,10 +9,11 @@ import 'package:flutter_svg/svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
|
||||
import '../../controller/cart_controller.dart';
|
||||
import 'cart_screen.dart';
|
||||
|
||||
class ProductDetailScreen extends StatefulWidget {
|
||||
final Map<String, dynamic>? productModel;
|
||||
Product? productModel;
|
||||
ProductModel? product;
|
||||
|
||||
ProductDetailScreen({super.key, this.product, this.productModel});
|
||||
@ -20,6 +23,7 @@ class ProductDetailScreen extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _ProductDetailScreenState extends State<ProductDetailScreen> {
|
||||
final CartController _cartController = Get.put(CartController());
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
@ -109,7 +113,7 @@ class _ProductDetailScreenState extends State<ProductDetailScreen> {
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: Text(
|
||||
widget.productModel!['name'],
|
||||
widget.productModel!.name,
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w600,
|
||||
@ -120,7 +124,7 @@ class _ProductDetailScreenState extends State<ProductDetailScreen> {
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: Text(
|
||||
"₹ ${widget.productModel!['price'].toString()}",
|
||||
"₹ ${widget.productModel!.price.toString()}",
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.w800,
|
||||
@ -131,7 +135,7 @@ class _ProductDetailScreenState extends State<ProductDetailScreen> {
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: Text(
|
||||
widget.productModel!['category']['categoryName'],
|
||||
widget.productModel!.category!.categoryName,
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w400,
|
||||
@ -143,7 +147,7 @@ class _ProductDetailScreenState extends State<ProductDetailScreen> {
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: Text(
|
||||
widget.productModel!['description'],
|
||||
widget.productModel!.description,
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w400,
|
||||
@ -162,9 +166,8 @@ class _ProductDetailScreenState extends State<ProductDetailScreen> {
|
||||
child: ElevatedButton(
|
||||
onPressed: () {
|
||||
// Pass the product data to the CartScreen
|
||||
Get.to(() => CartScreen(
|
||||
// Pass the product in a list
|
||||
));
|
||||
_cartController.addToCart(widget.productModel!);
|
||||
showSnackbar("Product Added to cart");
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
foregroundColor: Colors.white,
|
||||
|
@ -85,7 +85,7 @@ Future<BodyType?> commonApiService<BodyType>({
|
||||
errorMessage = e.response?.data;
|
||||
}
|
||||
|
||||
showSnackbar(errorMessage);
|
||||
//showSnackbar(errorMessage);
|
||||
} catch (e) {
|
||||
print("exception $url $e");
|
||||
}
|
||||
|
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
|
||||
)
|
||||
);
|
@ -23,7 +23,8 @@ class _MyDrawerState extends State<MyDrawer> {
|
||||
SizedBox(
|
||||
height: 150,
|
||||
child: Obx(
|
||||
() => DrawerHeader(
|
||||
(){
|
||||
return DrawerHeader(
|
||||
decoration: const BoxDecoration(
|
||||
color: Colors.black87,
|
||||
),
|
||||
@ -47,7 +48,8 @@ class _MyDrawerState extends State<MyDrawer> {
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
|
@ -1,30 +1,52 @@
|
||||
import 'package:cheminova/controller/cart_controller.dart';
|
||||
import 'package:cheminova/models/oder_place_model.dart';
|
||||
import 'package:cheminova/models/product_model.dart';
|
||||
import 'package:cheminova/screens/product/product_detail_screen.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
|
||||
class ProductCard extends StatelessWidget {
|
||||
final Map<String, dynamic>? productModel;
|
||||
import '../models/product_model1.dart';
|
||||
import '../screens/product/cart_screen.dart';
|
||||
import '../utils/show_snackbar.dart';
|
||||
|
||||
class ProductCard extends StatefulWidget {
|
||||
final Product? productModel;
|
||||
PlacedOrderModel? placedOrder;
|
||||
ProductModel? product;
|
||||
final bool isInCart;
|
||||
final bool isCheckout;
|
||||
|
||||
final bool isConfirmation;
|
||||
int? quantity;
|
||||
ProductCard({
|
||||
super.key,
|
||||
this.product,
|
||||
this.quantity=1,
|
||||
this.productModel,
|
||||
this.placedOrder,
|
||||
this.isInCart = false,
|
||||
this.isCheckout = false,
|
||||
this.isConfirmation = false,
|
||||
});
|
||||
|
||||
@override
|
||||
State<ProductCard> createState() => _ProductCardState();
|
||||
}
|
||||
|
||||
|
||||
class _ProductCardState extends State<ProductCard> {
|
||||
@override
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final CartController _cartController = Get.put(CartController());
|
||||
bool showQuantity = widget.isInCart || widget.isCheckout || widget.isConfirmation;
|
||||
bool isProductInCart = _cartController.cartList.contains(widget.productModel);
|
||||
return GestureDetector(
|
||||
onTap: () => isInCart || isCheckout
|
||||
onTap: () => widget.isInCart || widget.isCheckout
|
||||
? null
|
||||
: Get.to(() =>
|
||||
ProductDetailScreen(productModel: productModel)),
|
||||
ProductDetailScreen(productModel: widget.productModel)),
|
||||
child: Card(
|
||||
child: Row(
|
||||
children: [
|
||||
@ -52,29 +74,38 @@ class ProductCard extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
productModel!['name'],
|
||||
widget.productModel!.name,
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
productModel!['category']['categoryName'],
|
||||
widget.productModel!.category!.categoryName,
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"₹ ${ productModel!['price'].toString()}0",
|
||||
"₹ ${ widget.productModel!.price.toString()}",
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: 22,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
),
|
||||
isCheckout
|
||||
showQuantity
|
||||
? Text(
|
||||
"Quantity: ${widget.productModel!.quantity.toString()}",
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
)
|
||||
: const SizedBox(),
|
||||
widget.isCheckout
|
||||
? const SizedBox()
|
||||
: isInCart
|
||||
: widget.isInCart
|
||||
? Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
@ -93,7 +124,13 @@ class ProductCard extends StatelessWidget {
|
||||
height: 24,
|
||||
width: 24,
|
||||
child: ElevatedButton(
|
||||
onPressed: () {},
|
||||
onPressed: () {
|
||||
_cartController.increaseQuantity(widget.productModel!);
|
||||
setState(() {
|
||||
widget.quantity = widget.productModel!.quantity;
|
||||
|
||||
});
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
padding: EdgeInsets.zero,
|
||||
shape: RoundedRectangleBorder(
|
||||
@ -111,7 +148,7 @@ class ProductCard extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
Text(
|
||||
productModel!['brand']['brandName'],
|
||||
"${widget.quantity}",
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 16,
|
||||
@ -121,7 +158,13 @@ class ProductCard extends StatelessWidget {
|
||||
height: 24,
|
||||
width: 24,
|
||||
child: ElevatedButton(
|
||||
onPressed: () {},
|
||||
onPressed: () {
|
||||
_cartController.decreaseQuantity(widget.productModel!);
|
||||
setState(() {
|
||||
widget.quantity = widget.productModel!.quantity;
|
||||
});
|
||||
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
padding: EdgeInsets.zero,
|
||||
shape: RoundedRectangleBorder(
|
||||
@ -141,8 +184,11 @@ class ProductCard extends StatelessWidget {
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(width: 20.0,),
|
||||
IconButton(
|
||||
onPressed: () {},
|
||||
onPressed: () {
|
||||
_cartController.removeFromCart(widget.productModel);
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.delete_outline_rounded,
|
||||
color: Colors.red,
|
||||
@ -152,7 +198,12 @@ class ProductCard extends StatelessWidget {
|
||||
)
|
||||
: ElevatedButton(
|
||||
onPressed: () {
|
||||
|
||||
if (isProductInCart) {
|
||||
showSnackbar("Product already added to cart");
|
||||
} else {
|
||||
_cartController.addToCart(widget.productModel!);
|
||||
showSnackbar("Product added to cart successfully");
|
||||
}
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
foregroundColor: Colors.white,
|
||||
|
@ -200,6 +200,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.0"
|
||||
logger:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: logger
|
||||
sha256: "697d067c60c20999686a0add96cf6aba723b3aa1f83ecf806a8097231529ec32"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.0"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -41,6 +41,7 @@ dependencies:
|
||||
dio: ^5.5.0+1
|
||||
http: ^1.2.2
|
||||
shared_preferences: ^2.2.3
|
||||
logger: ^2.4.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
Loading…
Reference in New Issue
Block a user