1)shipto and bill to Api integration done

2)Opening Inventory api integration done
This commit is contained in:
saritabirare 2024-10-30 13:15:56 +05:30
parent 09193d7423
commit 077aa1e5d5
17 changed files with 1877 additions and 64 deletions

View File

@ -0,0 +1,56 @@
import 'package:cheminova/controller/product_mannual_service.dart';
import 'package:cheminova/controller/product_stock_service.dart';
import 'package:cheminova/models/product_stock_model.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 ProductStockController extends GetxController {
var productStockList = <ProductStockModel>[].obs;
// Service to fetch data
final ProductStockService productStockService = ProductStockService();
// Loading state
var isLoading = false.obs;
// Method to fetch product manuals from the service
Future<void>fetchProductStock() async {
try {
// Set loading to true
isLoading.value = true;
SharedPreferences prefs = await SharedPreferences.getInstance();
String? token = prefs.getString('token');
var manuals = await productStockService.getProductStock(token!);
// If data is returned, update the list
if (manuals != null) {
productStockList.value = manuals;
} else {
productStockList.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 stock: $e");
} finally {
// Set loading to false
isLoading.value = false;
}
}
void updateProductInventory(int index, ProductStockModel newInventory) {
productStockList[index] = newInventory ;
productStockList.refresh(); // Refresh the list to reflect changes
}
@override
void onInit() {
// Fetch product manuals when the controller is initialized
fetchProductStock();
super.onInit();
}
}

View File

@ -0,0 +1,40 @@
import 'package:cheminova/utils/api_urls.dart';
import '../models/product_mannual_model.dart';
import '../models/product_stock_model.dart';
import '../utils/common_api_service.dart'; // Replace with your actual common API service import
class ProductStockService {
// Method to fetch product manuals using an authorization token
Future<List<ProductStockModel>?> getProductStock(String token) async {
try {
String url = ApiUrls.ProductStockUrl; // Base URL to fetch product manuals
final response = await commonApiService<List<ProductStockModel>>(
method: "GET",
url: url,
additionalHeaders: { // Pass the token here
'Authorization': 'Bearer $token',
},
fromJson: (json) {
if (json['stocks'] != null) {
// If the productManuals key is present, map the response to a list of ProductManualModel objects
final List<ProductStockModel> productstock = (json['stocks'] as List)
.map((manualJson) => ProductStockModel.fromJson(manualJson as Map<String, dynamic>))
.toList();
return productstock; // Return the list of product manuals
} else {
return [];
}
},
);
return response;
} catch (e) {
print(e.toString());
return null;
}
}
}

View File

@ -0,0 +1,40 @@
import '../models/shippingandBilling_address_model.dart';
import '../utils/api_urls.dart';
import '../utils/common_api_service.dart';
class ShiptoandbilltoService {
Future<List<UserShippingAddress>?> fetchshiptobillAddress(String token) async {
try {
String url = ApiUrls
.ShiptoandBilltoAddressUrl; // Base URL to fetch product manuals
final response = await commonApiService<List<UserShippingAddress>>(
method: "GET",
url: url,
additionalHeaders: { // Pass the token here
'Authorization': 'Bearer $token',
},
fromJson: (json) {
if (json['UserShippingAddress'] != null) {
// If the productManuals key is present, map the response to a list of ProductManualModel objects
final List<
UserShippingAddress> productManuals = (json['UserShippingAddress'] as List)
.map((manualJson) => UserShippingAddress.fromJson(manualJson))
.toList();
return productManuals; // Return the list of product manuals
} else {
return [];
}
},
);
return response;
} catch (e) {
print("fkfgghgh ,${e.toString()}");
//print(e.toString());
return null;
}
}
}

View File

@ -0,0 +1,101 @@
// import 'package:cheminova/controller/shiptoandbillto_service.dart';
// import 'package:cheminova/models/shiping_billing_address_model.dart';
// import 'package:get/get.dart';
// import 'package:shared_preferences/shared_preferences.dart';
//
// class AddressController extends GetxController {
// final ShiptoandbilltoService _productService = ShiptoandbilltoService();
//
// var addressList = <UserShippingAddress>[].obs; // Observable list of addresses
// var selectedShippingAddressId = ''.obs;
// var selectedBillingAddressId = ''.obs;
//
// @override
// void onInit() {
// super.onInit();
// _loadAddresses();
// }
//
// void _loadAddresses() async {
// try {
// SharedPreferences prefs = await SharedPreferences.getInstance();
// String? token = prefs.getString('token');
// final response = await _productService.fetchshiptobillAddress(token!);
// addressList.assignAll(response as Iterable<UserShippingAddress>);
//
// // Load previously selected addresses
// selectedShippingAddressId.value = prefs.getString('selectedShippingAddress') ?? '';
// selectedBillingAddressId.value = prefs.getString('selectedBillingAddress') ?? '';
//
// // Set the default selection to the first address if available
// if (addressList.isNotEmpty) {
// if (selectedShippingAddressId.value.isEmpty) {
// selectedShippingAddressId.value = addressList.first.id;
// }
// if (selectedBillingAddressId.value.isEmpty) {
// selectedBillingAddressId.value = addressList.first.id;
// }
// }
// } catch (e) {
// print("Exception: $e");
// }
// }
//
// void _saveSelectedAddress() async {
// SharedPreferences prefs = await SharedPreferences.getInstance();
// await prefs.setString('selectedShippingAddress', selectedShippingAddressId.value);
// await prefs.setString('selectedBillingAddress', selectedBillingAddressId.value);
// }
//
// void onShippingAddressChanged(String? value) {
// if (value != null) {
// selectedShippingAddressId.value = value;
// _saveSelectedAddress();
// }
// }
//
// void onBillingAddressChanged(String? value) {
// if (value != null) {
// selectedBillingAddressId.value = value;
// _saveSelectedAddress();
// }
// }
// }
import 'package:cheminova/controller/shiptoandbillto_service.dart';
import 'package:get/get_rx/src/rx_types/rx_types.dart';
import 'package:get/get_state_manager/src/simple/get_controllers.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../models/shippingandBilling_address_model.dart';
class AddressController extends GetxController {
RxList<UserShippingAddress> addressList = <UserShippingAddress>[].obs;
RxString selectedShippingAddressId = ''.obs;
RxString selectedBillingAddressId = ''.obs;
Rx<UserShippingAddress?> selectedShippingAddress = Rx<UserShippingAddress?>(null);
Rx<UserShippingAddress?> selectedBillingAddress = Rx<UserShippingAddress?>(null);
void fetchAddresses() async {
// Fetch the addresses from the API
SharedPreferences prefs = await SharedPreferences.getInstance();
String? token = prefs.getString('token');
var response = await ShiptoandbilltoService().fetchshiptobillAddress(token!);
if (response!= null) {
addressList.value = response;
}
}
void onShippingAddressChanged(String? value) {
selectedShippingAddressId.value = value ?? '';
selectedShippingAddress.value = addressList.firstWhere((address) => address.id == value);
}
void onBillingAddressChanged(String? value) {
selectedBillingAddressId.value = value ?? '';
selectedBillingAddress.value = addressList.firstWhere((address) => address.id == value,);
}
}

View File

@ -0,0 +1,33 @@
import 'package:cheminova/controller/product_stock_service.dart';
import 'package:cheminova/controller/update_stock_service.dart';
import 'package:cheminova/models/product_stock_model.dart';
import 'package:get/get.dart';
import 'package:shared_preferences/shared_preferences.dart';
class UpdateStockController extends GetxController{
Future<void> updateProductStock(List<ProductStockModel> reason) async {
try {
SharedPreferences prefs = await SharedPreferences.getInstance();
String? token = prefs.getString('token'); // Get the token
if (token == null || token.isEmpty) {
throw Exception("Token is missing. Please login again.");
}
// Show loading indicator
// Call the service function and pass the token, orderId, and reason
await UpdateStockService().UpdateStockProduct(token, reason);
// Optionally refresh the data or show success message
print("UpdateStockService process complete.");
} catch (e) {
print("Error: $e");
} finally {
}
}
}

View File

@ -0,0 +1,46 @@
import 'dart:convert';
import 'package:cheminova/models/product_stock_model.dart';
import 'package:dio/dio.dart';
import '../utils/api_urls.dart';
import '../utils/common_api_service.dart';
import '../utils/show_snackbar.dart';
class UpdateStockService{
// Function to handle password change functionality
Future<void> UpdateStockProduct(String token, List<ProductStockModel> stock) async {
try {
// Correct API URL with orderId passed in the URL
final String url = ApiUrls.ProductUpdateStockUrl;
// Make the PUT request
final response = await Dio().put(
url, // Use the correct URL here
data: {
"products": stock, // Send the cancellation reason as JSON
},
options: Options(
headers: {
'Authorization': 'Bearer $token', // Pass the token in the Authorization header
'Content-Type': 'application/json', // Set content-type to application/json
},
),
);
// Check the response status
if (response.statusCode == 200) {
print(response.data);
print("Stock Update successfully");
} else {
throw Exception('Failed to Stock Update');
}
} catch (e) {
// Handle error
print('Error Stock Update: $e');
}
}
}

View File

@ -0,0 +1,41 @@
class ProductStockModel {
final String productid;
final String name;
final String sku;
final int stock;
final int openingInventory;
ProductStockModel({
required this.productid,
required this.name,
required this.sku,
required this.stock,
required this.openingInventory,
});
factory ProductStockModel.fromJson(Map<String, dynamic> json) {
return ProductStockModel(
productid: json['productid']??"2323",
name: json['name']??"rert",
sku: json['SKU']??"",
stock: json['Stock']??"",
openingInventory: json['openingInventory']??""
);
}
// Convert a ProductStock instance to a JSON map
Map<String, dynamic> toJson() {
return {
'productid': productid,
'name': name,
'SKU': sku,
'Stock': stock,
'openingInventory':openingInventory
};
}
@override
String toString() {
return 'ProductStock(productid: $productid, name: $name, sku: $sku, stock: $stock,openingInventory:$openingInventory)';
}
}

View File

@ -0,0 +1,56 @@
class UserShippingAddress {
final String id;
final String name;
final String phoneNumber;
final String street;
final String district;
final String city;
final String state;
final String postalCode;
final String country;
final String tradeName;
final bool isDefault;
final String user;
DateTime? createdAt;
DateTime? updatedAt;
UserShippingAddress({
required this.id,
required this.name,
required this.phoneNumber,
required this.street,
required this.district,
required this.city,
required this.state,
required this.postalCode,
required this.country,
required this.tradeName,
required this.isDefault,
required this.user,
this.createdAt,
this.updatedAt,
});
factory UserShippingAddress.fromJson(Map<String, dynamic> json) {
return UserShippingAddress(
id: json['_id'] ?? '',
name: json['Name'] ?? '',
phoneNumber: json['phoneNumber'] ?? '',
street: json['street'] ?? '',
district: json['district'] ?? '',
city: json['city'] ?? '',
state: json['state'] ?? '',
postalCode: json['postalCode'] ?? '',
country: json['country'] ?? '',
tradeName: json['tradeName'] ?? '',
isDefault: json['isDefault'] ?? false,
user: json['user'] ?? '',
createdAt: DateTime.parse(json['createdAt']),
updatedAt: DateTime.parse(json['updatedAt']),
);
}
String toStringFullAddress() {
return "$street, $city, $state, $postalCode, $country";
}
}

View File

@ -1,6 +1,7 @@
import 'package:cheminova/controller/home_controller.dart';
import 'package:cheminova/screens/announment/announment_screen.dart';
import 'package:cheminova/screens/inventory/inventory_management_screen.dart';
import 'package:cheminova/screens/opening%20Inventory/inventory_management_screen.dart';
import 'package:cheminova/screens/order/order_tracking_screen.dart';
import 'package:cheminova/screens/order_management/order_management_screen.dart';
import 'package:cheminova/screens/product/product_catalog_screen.dart';
@ -139,6 +140,12 @@ class _HomeScreenState extends State<HomeScreen> {
() => AnnouncementScreen(), // Navigates to RetailDistributerOnBoardingScreen.
),
),
HomeCard(
title: 'Opening Inventory',
onTap: () => Get.to(
() => OpeningInventoryManagementScreen(), // Navigates to RetailDistributerOnBoardingScreen.
),
),
],
),
],

View File

@ -0,0 +1,290 @@
import 'dart:async';
import 'package:cheminova/controller/product_stock_controller.dart';
import 'package:cheminova/models/place_order_list_model.dart';
import 'package:cheminova/models/product_stock_model.dart';
import 'package:cheminova/screens/opening%20Inventory/update_stock_screen.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';
class OpeningInventoryManagementScreen extends StatefulWidget {
final ProductStockModel? productModel;
// PlacedOrderList? placeOrder;
OpeningInventoryManagementScreen({super.key, this.productModel,});
@override
State<OpeningInventoryManagementScreen> createState() => _OpeningInventoryManagementScreenState();
}
class _OpeningInventoryManagementScreenState extends State<OpeningInventoryManagementScreen> {
final _searchController = TextEditingController();
//final List<String> _filterList = ["Order Status", "Date Range"];
final ProductStockController _getProductStockController = Get.put(ProductStockController());
final CartController _cartController = Get.put(CartController());
final GlobalKey<RefreshIndicatorState> _refreshIndicatorKey =
GlobalKey<RefreshIndicatorState>();
@override
void initState() {
super.initState();
getOrder1(); // Fetch orders when the screen initializes
}
Future<void> _onRefresh() async {
await getOrder1();
await Future.delayed(Duration(seconds: 1));
}
// Fetches orders from the API
Future<void> getOrder1() async {
await _getProductStockController.fetchProductStock();
print("Opening order Inventory fetched successfully");
}
// Capitalizes the first letter of the string
String capitalizeFirstLetter(String text) {
if (text.isEmpty) return text;
return text[0].toUpperCase() + text.substring(1).toLowerCase();
}
// Formats the date received from the API
String formatDate(String apiDate) {
DateTime parsedDate = DateTime.parse(apiDate);
String formattedDate = DateFormat('dd-MMM-yyyy').format(parsedDate);
return formattedDate;
}
@override
Widget build(BuildContext context) {
return Scaffold(
extendBodyBehindAppBar: true,
appBar: AppBar(
centerTitle: true,
backgroundColor: Colors.transparent,
elevation: 0,
leading: Builder(
builder: (context) {
return GestureDetector(
onTap: () => Scaffold.of(context).openDrawer(),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: SvgPicture.asset('assets/svg/menu.svg'),
),
);
},
),
actions: [
GestureDetector(
onTap: () => Get.back(),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: SvgPicture.asset('assets/svg/back_arrow.svg'),
),
),
],
title: const Text("Opening Inventory "),
),
drawer: MyDrawer(),
body: Stack(
fit: StackFit.expand,
children: [
Image.asset('assets/images/image_1.png', fit: BoxFit.cover),
SafeArea(
child: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
child: RefreshIndicator(
key: _refreshIndicatorKey,
onRefresh: _onRefresh,
color: Colors.black,
backgroundColor: Colors.white,
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
children: [
InputField(
hintText: "Search Order",
labelText: "Search Order",
controller: _searchController,
onChanged: (value) {
//searchOrder(value);// Call search function with input value
},
),
SizedBox(height: Get.height * 0.035),
Card(
margin: const EdgeInsets.symmetric(horizontal: 18),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(19),
side: const BorderSide(color: Color(0xFFFDFDFD)),
),
color: const Color(0xFFB4D1E5).withOpacity(0.9),
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// SizedBox(
// height: Get.height * 0.05,
// child: ListView.builder(
// shrinkWrap: true,
// scrollDirection: Axis.horizontal,
// itemCount: _filterList.length,
// itemBuilder: (context, index) => Padding(
// padding: const EdgeInsets.symmetric(horizontal: 4),
// child: Chip(
// label: Text(
// _filterList[index],
// style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.w500),
// ),
// ),
// ),
// ),
// ),
SizedBox(
height: Get.height * 0.6,
child: Obx(() {
// Use a set to keep track of unique order IDs
final Set<String> uniqueOrderIds = {};
final List<ProductStockModel> uniqueOrders = [];
// Loop through the fetched orders to filter unique orders
for (var order in _getProductStockController.productStockList) {
if (uniqueOrderIds.add(order.productid)) {
uniqueOrders.add(order);
}
}
// Displaying unique orders in a ListView
return ListView.builder(
padding: EdgeInsets.zero,
shrinkWrap: true,
itemCount: uniqueOrders.length,
itemBuilder: (context, index) {
final order = uniqueOrders[index];
// Combine product names into a single string
// final productNames = order.name
// .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.start,
children: [
Text("Product ID: ", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.bold)),
Text("${order.productid}")
],
),
),
Padding(
padding: const EdgeInsets.fromLTRB(16, 8, 8, 0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start, // Aligns the Column to the top of the Text
children: [
Text(
"Product Names: ",
style: GoogleFonts.roboto(
fontSize: 14,
fontWeight: FontWeight.bold,
),
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start, // Aligns text to the right within the Column
children: [
Text(
'${order.name}', // 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("SKU: ", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.bold)),
Text("${order.sku}")
],
),
),
Padding(
padding: const EdgeInsets.fromLTRB(16, 8, 8, 0),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text("Opening Inventory: ", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.bold)),
Text("${order.openingInventory}")
],
),
),
SizedBox(
width: Get.width * 0.5,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: ElevatedButton(
onPressed: (){
Get.to(InventoryUpdateStockScreen(products: _getProductStockController.productStockList, selectedProductId: _getProductStockController.productStockList[index].productid,));
},
// Navigate to detail screen
style: ElevatedButton.styleFrom(
foregroundColor: Colors.white,
backgroundColor: const Color(0xFF004791),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10)),
),
child: Text("Update Inventory", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.w400)),
),
),
)
],
),
),
);
},
);
}),
)
],
),
),
),
],
),
),
),
),
),
],
),
);
}
}

View File

@ -0,0 +1,226 @@
import 'package:cheminova/models/product_model.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:get/get.dart';
import 'package:google_fonts/google_fonts.dart';
class OpeningInventoryProductDetailScreen extends StatefulWidget {
final ProductModel product;
const OpeningInventoryProductDetailScreen({
super.key,
required this.product,
});
@override
State<OpeningInventoryProductDetailScreen> createState() =>
_OpeningInventoryProductDetailScreenState();
}
class _OpeningInventoryProductDetailScreenState
extends State<OpeningInventoryProductDetailScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
extendBodyBehindAppBar: true,
appBar: AppBar(
centerTitle: true,
backgroundColor: Colors.transparent,
elevation: 0,
leading: GestureDetector(
onTap: () {},
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(
"Inventory Product Detail",
),
),
body: Stack(
fit: StackFit.expand,
children: [
Image.asset(
'assets/images/image_1.png',
fit: BoxFit.cover,
),
SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
SizedBox(
height: Get.height * 0.02,
),
Card(
margin: const EdgeInsets.symmetric(horizontal: 16),
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,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
width: Get.width,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: Get.height * 0.4,
width: Get.width * 0.7,
decoration: BoxDecoration(
border: Border.all(
width: 4,
color: Colors.white,
),
borderRadius: BorderRadius.circular(15),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Image.asset(
widget.product.image,
fit: BoxFit.cover,
),
),
),
),
),
Card(
child: Column(
children: [
SizedBox(
width: Get.width,
child: Padding(
padding:
const EdgeInsets.fromLTRB(8, 8, 8, 0),
child: Text(
"Product Name: ${widget.product.name}",
style: GoogleFonts.roboto(
fontSize: Get.width * 0.04,
fontWeight: FontWeight.w600,
),
),
),
),
SizedBox(
width: Get.width,
child: Padding(
padding:
const EdgeInsets.fromLTRB(8, 8, 8, 8),
child: Text(
"Descrition: ${widget.product.description}",
style: GoogleFonts.roboto(
fontSize: Get.width * 0.04,
fontWeight: FontWeight.w400,
),
),
),
),
],
),
),
Card(
child: Column(
children: [
SizedBox(
width: Get.width,
child: Padding(
padding:
const EdgeInsets.fromLTRB(8, 8, 8, 0),
child: Text(
"Stock Information",
style: GoogleFonts.roboto(
fontSize: Get.width * 0.04,
fontWeight: FontWeight.w600,
),
),
),
),
SizedBox(
width: Get.width,
child: Padding(
padding:
const EdgeInsets.fromLTRB(8, 8, 8, 0),
child: Text(
"Current Stock: ${widget.product.quantity}",
style: GoogleFonts.roboto(
fontSize: Get.width * 0.04,
fontWeight: FontWeight.w400,
),
),
),
),
SizedBox(
width: Get.width,
child: Padding(
padding:
const EdgeInsets.fromLTRB(8, 8, 8, 0),
child: Text(
"Minimum Stock Level: 20",
style: GoogleFonts.roboto(
fontSize: Get.width * 0.04,
fontWeight: FontWeight.w400,
),
),
),
),
SizedBox(
width: Get.width,
child: Padding(
padding:
const EdgeInsets.fromLTRB(8, 8, 8, 0),
child: Text(
"Last Restock Date: MM/DD/YYYY",
style: GoogleFonts.roboto(
fontSize: Get.width * 0.04,
fontWeight: FontWeight.w400,
),
),
),
),
SizedBox(
width: Get.width,
child: Padding(
padding:
const EdgeInsets.fromLTRB(8, 8, 8, 8),
child: Text(
"Supplier: ABC Supplier",
style: GoogleFonts.roboto(
fontSize: Get.width * 0.04,
fontWeight: FontWeight.w400,
),
),
),
),
],
),
),
],
),
),
),
],
),
),
],
),
);
}
}

View File

@ -0,0 +1,367 @@
//
// import 'package:flutter_svg/svg.dart';
// import 'package:get/get.dart';
// import 'package:get/get_core/src/get_main.dart';
// import 'package:google_fonts/google_fonts.dart';
//
// import '../../controller/update_stock_controller.dart';
// import '../../models/product_stock_model.dart';
// import 'package:flutter/material.dart';
//
// import '../../utils/show_snackbar.dart';
// import '../../widgets/input_field.dart';
// import 'inventory_management_screen.dart';
// class InventoryUpdateStockScreen extends StatefulWidget {
// final ProductStockModel product;
//
// const InventoryUpdateStockScreen({
// super.key,
// required this.product,
// });
//
// @override
// State<InventoryUpdateStockScreen> createState() => _InventoryUpdateStockScreenState();
// }
//
// class _InventoryUpdateStockScreenState extends State<InventoryUpdateStockScreen> {
// final _textController = TextEditingController();
// final UpdateStockController _updateStockController = Get.put(UpdateStockController());
//
// // Map to store the updated stock quantities for each product
// final Map<String, int> _updatedStockMap = {};
//
// @override
// void initState() {
// super.initState();
// // Set the initial value of the text controller if there's an updated stock for the current product
// _textController.text = _updatedStockMap[widget.product.productid]?.toString() ?? widget.product.stock.toString();
// }
//
// void _onUpdateStock() async {
// try {
// // Parse the new stock quantity from the text controller
// int? newStockQuantity = int.tryParse(_textController.text.trim());
//
// // Check if the parsed quantity is valid
// if (newStockQuantity == null || newStockQuantity < 0) {
// showSnackbar("Please enter a valid stock quantity.");
// return;
// }
//
// // Update the map with the new stock quantity for the current product
// setState(() {
// _updatedStockMap[widget.product.productid] = newStockQuantity;
// });
//
// // Create a list of ProductStockModel instances with updated stock
// List<ProductStockModel> productStockList = [
// ProductStockModel(
// productid: widget.product.productid,
// name: widget.product.name,
// sku: widget.product.sku,
// stock: widget.product.stock,
// openingInventory: newStockQuantity, // Update stock with new quantity
// ),
// ];
//
// // Call the updateStock function
// final update = await _updateStockController.updateProductStock(productStockList);
//
// // Optionally, show a confirmation message or navigate to another screen
// showSnackbar("Opening Inventory updated successfully");
// Get.to(OpeningInventoryManagementScreen());
// } catch (e) {
// print("Error updating stock: $e");
// showSnackbar("Error updating stock. Please try again.");
// }
// }
//
// @override
// void didUpdateWidget(covariant InventoryUpdateStockScreen oldWidget) {
// super.didUpdateWidget(oldWidget);
// // Update the text controller with the new product's stock or the previously updated value
// _textController.text = _updatedStockMap[widget.product.productid]?.toString() ?? widget.product.stock.toString();
// }
//
// @override
// Widget build(BuildContext context) {
// return Scaffold(
// extendBodyBehindAppBar: true,
// appBar: AppBar(
// centerTitle: true,
// backgroundColor: Colors.transparent,
// elevation: 0,
// leading: GestureDetector(
// onTap: () {},
// 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(
// "Update Inventory",
// ),
// ),
// body: Stack(
// fit: StackFit.expand,
// children: [
// Image.asset(
// 'assets/images/image_1.png',
// fit: BoxFit.cover,
// ),
// SafeArea(
// child: Column(
// mainAxisAlignment: MainAxisAlignment.start,
// children: [
// SizedBox(
// height: Get.height * 0.02,
// ),
// Card(
// margin: const EdgeInsets.symmetric(horizontal: 16),
// 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,
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// Card(
// child: SizedBox(
// width: Get.width,
// child: Padding(
// padding: const EdgeInsets.all(12),
// child: Row(
// children: [
// Text(
// "Product Name: ",
// style: GoogleFonts.roboto(
// fontSize: Get.width * 0.04,
// fontWeight: FontWeight.w700,
// ),
// ),
// Text("${widget.product.name}"),
// ],
// ),
// ),
// ),
// ),
// InputField(
// hintText: "Enter New Opening Inventory Quantity:",
// labelText: "Enter New Opening Inventory Quantity:",
// controller: _textController,
// ),
// ],
// ),
// ),
// ),
// SizedBox(height: Get.height * 0.04),
// SizedBox(
// width: Get.width * 0.9,
// height: Get.height * 0.06,
// child: ElevatedButton(
// onPressed: () {
// _onUpdateStock();
// },
// style: ElevatedButton.styleFrom(
// foregroundColor: Colors.white,
// backgroundColor: const Color(0xFF00784C),
// shape: RoundedRectangleBorder(
// borderRadius: BorderRadius.circular(10),
// ),
// ),
// child: Text(
// "Update Inventory Quantity",
// style: GoogleFonts.roboto(
// fontSize: Get.width * 0.05,
// fontWeight: FontWeight.w600,
// ),
// ),
// ),
// ),
// ],
// ),
// ),
// ],
// ),
// );
// }
// }
//
import 'package:flutter_svg/svg.dart';
import 'package:get/get.dart';
import 'package:google_fonts/google_fonts.dart';
import '../../controller/update_stock_controller.dart';
import '../../models/product_stock_model.dart';
import 'package:flutter/material.dart';
import '../../utils/show_snackbar.dart';
import '../../widgets/input_field.dart';
import 'inventory_management_screen.dart';
class InventoryUpdateStockScreen extends StatefulWidget {
final List<ProductStockModel> products;
final String selectedProductId;
const InventoryUpdateStockScreen({
super.key,
required this.products,
required this.selectedProductId,
});
@override
State<InventoryUpdateStockScreen> createState() => _InventoryUpdateStockScreenState();
}
class _InventoryUpdateStockScreenState extends State<InventoryUpdateStockScreen> {
late TextEditingController _textController;
final UpdateStockController _updateStockController = Get.put(UpdateStockController());
@override
void initState() {
super.initState();
// Initialize text controller with the stock of the selected product
final selectedProduct = widget.products.firstWhere((product) => product.productid == widget.selectedProductId);
_textController = TextEditingController(text: selectedProduct.stock.toString());
}
void _onUpdateStock() async {
try {
int? newStockQuantity = int.tryParse(_textController.text.trim());
if (newStockQuantity == null || newStockQuantity < 0) {
showSnackbar("Please enter a valid stock quantity.");
return;
}
// Update only the stock for the selected product while keeping others the same
List<ProductStockModel> updatedProductStockList = widget.products.map((product) {
if (product.productid == widget.selectedProductId) {
return ProductStockModel(
productid: product.productid,
name: product.name,
sku: product.sku,
stock: newStockQuantity,
openingInventory: newStockQuantity,
);
} else {
return product;
}
}).toList();
// Call the updateStock function with the updated list
final update = await _updateStockController.updateProductStock(updatedProductStockList);
showSnackbar("Opening Inventory for ${widget.selectedProductId} updated successfully");
Get.to(OpeningInventoryManagementScreen());
} catch (e) {
print("Error updating stock: $e");
showSnackbar("Error updating stock. Please try again.");
}
}
@override
Widget build(BuildContext context) {
final selectedProduct = widget.products.firstWhere((product) => product.productid == widget.selectedProductId);
return Scaffold(
extendBodyBehindAppBar: true,
appBar: AppBar(
centerTitle: true,
backgroundColor: Colors.transparent,
elevation: 0,
leading: GestureDetector(
onTap: () {},
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(
"Update Inventory",
),
),
body: Stack(
fit: StackFit.expand,
children: [
Image.asset(
'assets/images/image_1.png',
fit: BoxFit.cover,
),
SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
SizedBox(height: Get.height * 0.02),
Text(
"Product Name: ${selectedProduct.name}",
style: GoogleFonts.roboto(
fontSize: Get.width * 0.04,
fontWeight: FontWeight.w700,
),
),
InputField(
hintText: "Enter New Opening Inventory Quantity:",
labelText: "Enter New Opening Inventory Quantity:",
controller: _textController,
),
SizedBox(height: 8),
ElevatedButton(
onPressed: _onUpdateStock,
style: ElevatedButton.styleFrom(
foregroundColor: Colors.white,
backgroundColor: const Color(0xFF00784C),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
),
child: Text(
"Update Inventory Quantity",
style: GoogleFonts.roboto(
fontSize: Get.width * 0.05,
fontWeight: FontWeight.w600,
),
),
),
],
),
),
],
),
);
}
}

View File

@ -1,3 +1,434 @@
// 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 {
// final Product? productModel;
//
// PlacedOrderModel? placeOrder;
// List<Product>? selectedProducts;
// CheckoutScreen({super.key, this.productModel, this.placeOrder,this.selectedProducts});
//
// @override
// State<CheckoutScreen> createState() => _CheckoutScreenState();
// }
//
// class _CheckoutScreenState extends State<CheckoutScreen> {
// final 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());
//
// int currentPage = 1;
// String _groupValue = "cheque";
//
// final List<String> _addressList = [
// 'Home - 123 Street, City',
// 'Office - 456 Avenue, City',
// 'Warehouse - 789 Blvd, City',
// ];
//
// String? _selectedShippingAddress;
// String? _selectedBillingAddress;
//
// @override
// void initState() {
// super.initState();
// // _getOrder();
// _loadSelectedAddress();
// _loadSelectedPaymentMode();
//
// if (_addressList.isNotEmpty) {
// _selectedShippingAddress = _addressList.first;
// _selectedBillingAddress = _addressList.first;
// }
// }
//
// void _saveSelectedAddress() async {
// SharedPreferences prefs = await SharedPreferences.getInstance();
// await prefs.setString('selectedShippingAddress', _selectedShippingAddress!);
// await prefs.setString('selectedBillingAddress', _selectedBillingAddress!);
// }
//
// void _onShippingAddressChanged(String? value) {
// setState(() {
// _selectedShippingAddress = value;
// });
// _saveSelectedAddress();
// }
//
// void _onBillingAddressChanged(String? value) {
// setState(() {
// _selectedBillingAddress = value;
// });
// _saveSelectedAddress();
// }
//
// void _loadSelectedAddress() async {
// SharedPreferences prefs = await SharedPreferences.getInstance();
// setState(() {
// _selectedShippingAddress =
// prefs.getString('selectedShippingAddress') ?? _addressList.first;
// _selectedBillingAddress =
// prefs.getString('selectedBillingAddress') ?? _addressList.first;
// });
// }
//
// void _onPaymentModeChanged(String? value) {
// setState(() {
// _groupValue = value!;
// });
// _saveSelectedPaymentMode();
// }
//
// void _saveSelectedPaymentMode() async {
// SharedPreferences prefs = await SharedPreferences.getInstance();
// await prefs.setString('selectedPaymentMode', _groupValue);
// }
//
// void _loadSelectedPaymentMode() async {
// SharedPreferences prefs = await SharedPreferences.getInstance();
// setState(() {
// _groupValue = prefs.getString('selectedPaymentMode') ?? 'cheque';
// });
// }
//
// // void _getOrder(){
// // final details = _getPlacedOrderController.getOrder(widget.productModel!.id);
// // print("dffgfg,$details");
// // }
// void _onPlaceOrder() async {
// try {
// // Map the cart items (Product) to OrderItem objects
// List<OrderItem> orderItems = _cartController.selectedProducts.map<OrderItem>((product) {
// return OrderItem(
// id: product.id,
// name: product.name,
// price: product.price.toDouble(),
// sku: product.sku,
// gst: product.gst.toDouble(),
// hsnCode: product.hsnCode,
// description: product.description,
// productStatus: product.productStatus,
// image: [],
// createdAt: product.createdAt,
// updatedAt: product.createdAt,
// count: product.quantity,
//
// //category:product.category,
// category:Category(id: product.category.id, categoryName: product.category.categoryName),
// // brand:product.brand,
// brand:Brand(id: product.brand.id, brandName: product.brand.brandName),
// v: 0, addedBy: product.addedBy,
// );
// }).toList();
//
// // Update the placedOrder1 value
// _orderPlacedController.placedOrder1.value= PlacedOrderModel(
// paymentMode: _groupValue,
// shipTo: _selectedShippingAddress!,
// billTo: _selectedBillingAddress!,
// orderItems: orderItems,
// gstTotal: _cartController.gstTotal.value,
// grandTotal: _cartController.grandTotal.value,
// subtotal: _cartController.subtotal.value,
// );
//
// await _orderPlacedController.placeOrder();
//
// if (_orderPlacedController.isLoading.value) {
// showSnackbar("Order Placed Successfully");
// Get.to(() => OrderConfermationScreen(
// placedOrder: _orderPlacedController.placedOrder1.value,
// ));
// }
// } catch (e) {
// print("PlaceOrderScreen error: $e");
// }
// }
//
//
//
//
// @override
// Widget build(BuildContext context) {
// 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: EdgeInsets.all(Get.width * 0.02),
// child: SvgPicture.asset(
// 'assets/svg/back_arrow.svg',
// ),
// ),
// ),
// ],
// title: const Text("Checkout"),
// ),
// drawer: const MyDrawer(),
// body: Stack(
// fit: StackFit.expand,
// children: [
// Image.asset(
// 'assets/images/image_1.png',
// fit: BoxFit.cover,
// ),
// SafeArea(
// child: Column(
// children: [
// SizedBox(height: Get.height * 0.02),
// Card(
// margin: EdgeInsets.symmetric(horizontal: Get.width * 0.05),
// shape: RoundedRectangleBorder(
// borderRadius: BorderRadius.circular(19),
// side: const BorderSide(color: Color(0xFFFDFDFD)),
// ),
// color: const Color(0xFFB4D1E5).withOpacity(0.9),
// child: Padding(
// padding: EdgeInsets.all(Get.width * 0.04),
// child: Column(
// mainAxisSize: MainAxisSize.min,
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// Padding(
// padding: EdgeInsets.symmetric(
// horizontal: Get.width * 0.04),
// child: Text(
// 'Shipping Information',
// style: GoogleFonts.roboto(
// fontSize: Get.width * 0.04,
// fontWeight: FontWeight.w500,
// color: Colors.black,
// ),
// ),
// ),
// SizedBox(height: 5,),
// DropdownButtonFormField<String>(
// decoration: InputDecoration(
// 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,
// ),
// 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(
// horizontal: Get.width * 0.04),
// child: Text(
// 'Payment Information',
// style: GoogleFonts.roboto(
// fontSize: Get.width * 0.04,
// fontWeight: FontWeight.w500,
// color: Colors.black,
// ),
// ),
// ),
// Card(
// child: ListView(
// padding: EdgeInsets.zero,
// shrinkWrap: true,
// children: [
// SizedBox(
// height: Get.height * 0.035,
// child: RadioListTile(
// title: const Text("Cheque"),
// contentPadding: EdgeInsets.zero,
// value: "cheque",
// groupValue: _groupValue,
// onChanged: _onPaymentModeChanged,
// ),
// ),
// SizedBox(
// height: Get.height * 0.035,
// child: RadioListTile(
// title: const Text("Online transfer"),
// contentPadding: EdgeInsets.zero,
// value: "online-transfer",
// groupValue: _groupValue,
// onChanged: _onPaymentModeChanged,
// ),
// ),
// SizedBox(
// child: RadioListTile(
// title: const Text("Credit"),
// contentPadding: EdgeInsets.zero,
// value: "credit",
// groupValue: _groupValue,
// onChanged: _onPaymentModeChanged,
// ),
// ),
// ],
// ),
// ),
// Padding(
// padding: EdgeInsets.symmetric(
// horizontal: Get.width * 0.04),
// child: Text(
// 'Order Summary',
// style: GoogleFonts.roboto(
// fontSize: Get.width * 0.04,
// fontWeight: FontWeight.w500,
// color: Colors.black,
// ),
// ),
// ),
// Card(
// child: Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// SizedBox(
// height: Get.height * 0.22,
// child: Padding(
// padding: EdgeInsets.all(Get.width * 0.02),
// child: ListView.builder(
// itemCount: _cartController.selectedProducts.length,
// itemBuilder: (context, index) {
// final cartItem =
// _cartController.cartList[index];
// return ProductCard(
// productModel:_cartController.selectedProducts[index] ,
// isCheckout: true,
// quantity: _cartController.cartList[0].quantity,
//
//
// // ListTile(
// // title: Text(cartItem.name ?? 'N/A'),
// // subtitle: Text(
// // 'Quantity: ${cartItem.quantity}'),
// // trailing: Text(
// // 'Price: \${cartItem.price.toStringAsFixed(2)}'),
// // );
// );},
// ),
// ),
// ),
// Padding(
// padding: EdgeInsets.all(Get.width * 0.02),
// child: Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// children: [
// Text('Subtotal',style: TextStyle(fontWeight: FontWeight.bold)),
// Text('${_cartController.subtotal.value.toStringAsFixed(2)}'),
// ],
// ),
// Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// children: [
// Text('GST',style: TextStyle(fontWeight: FontWeight.bold)),
// Text('${_cartController.gstTotal.value.toStringAsFixed(2)}'),
// ],
// ),
// Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// children: [
// Text('Total Amount',style: TextStyle(fontWeight: FontWeight.bold)),
// Text('${_cartController.grandTotal.value.toStringAsFixed(2)}'),
// ],
// ),
// ],
// ),
// ),
// ],
// ),
// ),
//
// ],
// ),
// ),
// ),
// 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: const Text("Place Order"),
// ),
// ],
// ),
// ],
// ),
// ),
// ],
// ),
// );
// }
// }
import 'dart:ffi';
import 'package:cheminova/controller/get_order_placed_controller.dart';
import 'package:cheminova/models/added_by_model.dart';
@ -14,9 +445,12 @@ import '../../controller/place_order_controller.dart';
import '../../controller/place_order_service.dart';
import '../../controller/product_controller.dart';
import '../../controller/product_service.dart';
import '../../controller/shiptobilltoController.dart';
import '../../models/brand_model.dart';
import '../../models/oder_place_model.dart';
import '../../models/product_model1.dart';
import '../../models/shippingandBilling_address_model.dart';
import '../../widgets/my_drawer.dart';
import '../../widgets/product_card.dart';
import 'order_confermation_screen.dart';
@ -25,7 +459,7 @@ class CheckoutScreen extends StatefulWidget {
final Product? productModel;
PlacedOrderModel? placeOrder;
List<Product>? selectedProducts;
List<Product>? selectedProducts;
CheckoutScreen({super.key, this.productModel, this.placeOrder,this.selectedProducts});
@override
@ -39,6 +473,7 @@ class _CheckoutScreenState extends State<CheckoutScreen> {
final OrderPlacedController _orderPlacedController =
Get.put(OrderPlacedController());
final GetPlacedOrderController _getPlacedOrderController = Get.put(GetPlacedOrderController());
final AddressController _addressController = Get.put(AddressController()); // Initialize AddressController
int currentPage = 1;
String _groupValue = "cheque";
@ -52,17 +487,25 @@ class _CheckoutScreenState extends State<CheckoutScreen> {
String? _selectedShippingAddress;
String? _selectedBillingAddress;
String capitalizeFirstLetter(String text) {
if (text.isEmpty) return text;
return text[0].toUpperCase() + text.substring(1).toLowerCase();
}
@override
void initState() {
super.initState();
// _getOrder();
_addressController.fetchAddresses();
_loadSelectedAddress();
_loadSelectedPaymentMode();
if (_addressList.isNotEmpty) {
_selectedShippingAddress = _addressList.first;
_selectedBillingAddress = _addressList.first;
}
// _loadSelectedAddress();
// _loadSelectedPaymentMode();
//
// if (_addressList.isNotEmpty) {
// _selectedShippingAddress = _addressList.first;
// _selectedBillingAddress = _addressList.first;
// }
}
void _saveSelectedAddress() async {
@ -114,10 +557,6 @@ class _CheckoutScreenState extends State<CheckoutScreen> {
});
}
// void _getOrder(){
// final details = _getPlacedOrderController.getOrder(widget.productModel!.id);
// print("dffgfg,$details");
// }
void _onPlaceOrder() async {
try {
// Map the cart items (Product) to OrderItem objects
@ -144,11 +583,35 @@ class _CheckoutScreenState extends State<CheckoutScreen> {
);
}).toList();
// Get the full address for shipping and billing
String? shippingAddress = _addressController.addressList.firstWhere(
(address) => address.id == _addressController.selectedShippingAddressId.value,
orElse: () => UserShippingAddress(
id: '',
street: '',
city: '',
state: '',
postalCode: '',
country: '', tradeName: '', name: '', phoneNumber: '', district: '', isDefault: false, user: '',
)).toStringFullAddress();
String? billingAddress = _addressController.addressList.firstWhere(
(address) => address.id == _addressController.selectedBillingAddressId.value,
orElse: () => UserShippingAddress(
id: '',
street: '',
city: '',
state: '',
postalCode: '',
country: '', tradeName: '', name: '', phoneNumber: '', district: '', isDefault: false, user: '', createdAt: null,
)).toStringFullAddress();
// Update the placedOrder1 value
_orderPlacedController.placedOrder1.value= PlacedOrderModel(
paymentMode: _groupValue,
shipTo: _selectedShippingAddress!,
billTo: _selectedBillingAddress!,
shipTo: shippingAddress, // Full shipping address
billTo: billingAddress, // Full billing address
orderItems: orderItems,
gstTotal: _cartController.gstTotal.value,
grandTotal: _cartController.grandTotal.value,
@ -161,11 +624,16 @@ class _CheckoutScreenState extends State<CheckoutScreen> {
showSnackbar("Order Placed Successfully");
Get.to(() => OrderConfermationScreen(
placedOrder: _orderPlacedController.placedOrder1.value,
));
}
} catch (e) {
print("PlaceOrderScreen error: $e");
}
}
@ -204,7 +672,7 @@ class _CheckoutScreenState extends State<CheckoutScreen> {
],
title: const Text("Checkout"),
),
drawer: const MyDrawer(),
drawer: MyDrawer(),
body: Stack(
fit: StackFit.expand,
children: [
@ -223,15 +691,15 @@ class _CheckoutScreenState extends State<CheckoutScreen> {
side: const BorderSide(color: Color(0xFFFDFDFD)),
),
color: const Color(0xFFB4D1E5).withOpacity(0.9),
child: Padding(
child:
Padding(
padding: EdgeInsets.all(Get.width * 0.04),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.symmetric(
horizontal: Get.width * 0.04),
padding: EdgeInsets.symmetric(horizontal: Get.width * 0.04),
child: Text(
'Shipping Information',
style: GoogleFonts.roboto(
@ -241,38 +709,58 @@ class _CheckoutScreenState extends State<CheckoutScreen> {
),
),
),
SizedBox(height: 5,),
DropdownButtonFormField<String>(
decoration: InputDecoration(
labelText: 'Shipping Address:',
hintText: 'Select Shipping Address',
border: OutlineInputBorder(),
SizedBox(height: 5),
Obx(() => Container(
child: DropdownButtonFormField<String>(
decoration: InputDecoration(
labelText: 'Shipping Address:',
hintText: 'Select Shipping Address',
border: OutlineInputBorder(),
),
value: _addressController.selectedShippingAddressId.value.isEmpty
? null // Show null if there's no selection yet
: _addressController.selectedShippingAddressId.value, // Set the selected ID
items: _addressController.addressList.map((UserShippingAddress address) {
return DropdownMenuItem<String>(
value: address.id, // Set the value as the address ID
child: Text("${address.street} ${address.city}\n ${address.state} \n ${address.postalCode} , ${address.country}",style: TextStyle(fontSize: 15),), // Display full address
);
}).toList(),
onChanged: (value) {
_addressController.onShippingAddressChanged(value); // Update the selected address
},
),
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(),
// Billing Address Dropdown
Obx(() => Container(
child: DropdownButtonFormField<String>(
decoration: InputDecoration(
labelText: 'Billing Address:',
hintText: 'Select Billing Address',
border: OutlineInputBorder(),
),
value: _addressController.selectedBillingAddressId.value.isEmpty
? null
: _addressController.selectedBillingAddressId.value,
items: _addressController.addressList
.where((address) => address.isDefault == true) // Filter only default addresses
.map((UserShippingAddress address) {
return DropdownMenuItem<String>(
value: address.id,
child: Text(
"${address.street} ${address.city}${address.state}\n${address.postalCode}, ${address.country}",
style: TextStyle(fontSize: 15),
),
);
}).toList(),
onChanged: (value) {
_addressController.onBillingAddressChanged(value);
},
),
value: _selectedBillingAddress,
items: _addressList.map((String address) {
return DropdownMenuItem<String>(
value: address,
child: Text(address),
);
}).toList(),
onChanged: _onBillingAddressChanged,
),
)),
Padding(
padding: EdgeInsets.symmetric(
horizontal: Get.width * 0.04),
@ -370,7 +858,7 @@ class _CheckoutScreenState extends State<CheckoutScreen> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('Subtotal',style: TextStyle(fontWeight: FontWeight.bold)),
Text('${_cartController.subtotal.value.toStringAsFixed(2)}'),

View File

@ -282,11 +282,12 @@ Future<void> adduni()async {
),
SizedBox(
width: Get.width,
height: Get.height*0.06,
height: Get.height * 0.10,
child: Padding(
padding:
const EdgeInsets.fromLTRB(8, 8, 8, 0),
child: Row(
padding: const EdgeInsets.fromLTRB(8, 8, 8, 0),
child: Wrap( // Use Wrap to allow wrapping
crossAxisAlignment: WrapCrossAlignment.start,
direction: Axis.horizontal,
children: [
Text(
"Address: ",
@ -295,8 +296,17 @@ Future<void> adduni()async {
fontWeight: FontWeight.bold,
),
),
AutoSizeText("${widget.placedOrderList!.shipTo}",maxLines: 4,
overflow:TextOverflow.ellipsis,)
Text(
"${widget.placedOrderList!.shipTo.toString()}",
// Text(
// "${widget.placedOrderList!.shipTo}",
maxLines: 4,
overflow: TextOverflow.ellipsis,
style: GoogleFonts.roboto(
fontSize: Get.width * 0.04,
),
),
],
),
),

View File

@ -16,4 +16,14 @@ class ApiUrls {
static const String inventoryManangementOrdersStock ='${baseUrl}/api/stock';
static const String announcementUrl ='${baseUrl}/api/announcement/RDs?page%3D1=rowsPerPage=5';
//============================== Product stock Details ==============================//
static const String ProductStockUrl = '/api/rd/stock';
//============================== Product Update stock Details ==============================//
static const String ProductUpdateStockUrl = '${baseUrl}/api/rd/stock-update';
//============================== shipto Billto Details ==============================//
static const String ShiptoandBilltoAddressUrl = '/api/rd/shipping/address';
}

View File

@ -7,6 +7,7 @@ class InputField extends StatefulWidget {
final TextEditingController controller;
final bool obscureText;
final TextInputType? keyboardType;
final void Function(String)? onChanged;
final String? Function(String?)? validator;// Add this line for validation
InputField({
@ -15,6 +16,7 @@ class InputField extends StatefulWidget {
required this.labelText,
required this.controller,
this.obscureText = false,
this.onChanged,
this.keyboardType = TextInputType.text,
this.validator, // Add this
});

View File

@ -500,18 +500,18 @@ packages:
dependency: transitive
description:
name: leak_tracker
sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05"
sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a"
url: "https://pub.dev"
source: hosted
version: "10.0.5"
version: "10.0.4"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806"
sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8"
url: "https://pub.dev"
source: hosted
version: "3.0.5"
version: "3.0.3"
leak_tracker_testing:
dependency: transitive
description:
@ -548,18 +548,18 @@ packages:
dependency: transitive
description:
name: material_color_utilities
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a"
url: "https://pub.dev"
source: hosted
version: "0.11.1"
version: "0.8.0"
meta:
dependency: transitive
description:
name: meta
sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7
sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
url: "https://pub.dev"
source: hosted
version: "1.15.0"
version: "1.12.0"
mime:
dependency: transitive
description:
@ -849,10 +849,10 @@ packages:
dependency: transitive
description:
name: test_api
sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb"
sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f"
url: "https://pub.dev"
source: hosted
version: "0.7.2"
version: "0.7.0"
timezone:
dependency: transitive
description:
@ -977,10 +977,10 @@ packages:
dependency: transitive
description:
name: vm_service
sha256: f652077d0bdf60abe4c1f6377448e8655008eef28f128bc023f7b5e8dfeb48fc
sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec"
url: "https://pub.dev"
source: hosted
version: "14.2.4"
version: "14.2.1"
web:
dependency: transitive
description: