Compare commits

..

5 Commits
main ... rita

Author SHA1 Message Date
e985fd194b new changes done 2025-04-28 13:34:34 +05:30
2c0797b687 new changes done 2025-02-06 15:44:18 +05:30
d101e82096 1) opening inventory api integration done
2) Billto shipto address api integration done
2024-10-30 16:34:18 +05:30
a545efca3b 1)Url added 2024-10-24 09:34:44 +05:30
ef2799cbd4 1) Cancelled file changes done 2024-10-23 13:55:09 +05:30
86 changed files with 5535 additions and 2074 deletions

View File

@ -1,12 +1,12 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.cheminova">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>
<application <application
android:label="cheminova" android:label="Principal Distributor"
android:name="${applicationName}" android:name="${applicationName}"
android:icon="@mipmap/ic_launcher"> android:icon="@mipmap/launcher_icon">
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:exported="true" android:exported="true"

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -427,7 +427,7 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO; ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon;
CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++"; CLANG_CXX_LIBRARY = "libc++";
@ -484,7 +484,7 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO; ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon;
CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++"; CLANG_CXX_LIBRARY = "libc++";

View File

@ -1,122 +1 @@
{ {"images":[{"size":"20x20","idiom":"iphone","filename":"Icon-App-20x20@2x.png","scale":"2x"},{"size":"20x20","idiom":"iphone","filename":"Icon-App-20x20@3x.png","scale":"3x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@1x.png","scale":"1x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@2x.png","scale":"2x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@3x.png","scale":"3x"},{"size":"40x40","idiom":"iphone","filename":"Icon-App-40x40@2x.png","scale":"2x"},{"size":"40x40","idiom":"iphone","filename":"Icon-App-40x40@3x.png","scale":"3x"},{"size":"57x57","idiom":"iphone","filename":"Icon-App-57x57@1x.png","scale":"1x"},{"size":"57x57","idiom":"iphone","filename":"Icon-App-57x57@2x.png","scale":"2x"},{"size":"60x60","idiom":"iphone","filename":"Icon-App-60x60@2x.png","scale":"2x"},{"size":"60x60","idiom":"iphone","filename":"Icon-App-60x60@3x.png","scale":"3x"},{"size":"20x20","idiom":"ipad","filename":"Icon-App-20x20@1x.png","scale":"1x"},{"size":"20x20","idiom":"ipad","filename":"Icon-App-20x20@2x.png","scale":"2x"},{"size":"29x29","idiom":"ipad","filename":"Icon-App-29x29@1x.png","scale":"1x"},{"size":"29x29","idiom":"ipad","filename":"Icon-App-29x29@2x.png","scale":"2x"},{"size":"40x40","idiom":"ipad","filename":"Icon-App-40x40@1x.png","scale":"1x"},{"size":"40x40","idiom":"ipad","filename":"Icon-App-40x40@2x.png","scale":"2x"},{"size":"50x50","idiom":"ipad","filename":"Icon-App-50x50@1x.png","scale":"1x"},{"size":"50x50","idiom":"ipad","filename":"Icon-App-50x50@2x.png","scale":"2x"},{"size":"72x72","idiom":"ipad","filename":"Icon-App-72x72@1x.png","scale":"1x"},{"size":"72x72","idiom":"ipad","filename":"Icon-App-72x72@2x.png","scale":"2x"},{"size":"76x76","idiom":"ipad","filename":"Icon-App-76x76@1x.png","scale":"1x"},{"size":"76x76","idiom":"ipad","filename":"Icon-App-76x76@2x.png","scale":"2x"},{"size":"83.5x83.5","idiom":"ipad","filename":"Icon-App-83.5x83.5@2x.png","scale":"2x"},{"size":"1024x1024","idiom":"ios-marketing","filename":"Icon-App-1024x1024@1x.png","scale":"1x"}],"info":{"version":1,"author":"xcode"}}
"images" : [
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@3x.png",
"scale" : "3x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@3x.png",
"scale" : "3x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@3x.png",
"scale" : "3x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@2x.png",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@3x.png",
"scale" : "3x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@1x.png",
"scale" : "1x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@1x.png",
"scale" : "1x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@1x.png",
"scale" : "1x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@2x.png",
"scale" : "2x"
},
{
"size" : "83.5x83.5",
"idiom" : "ipad",
"filename" : "Icon-App-83.5x83.5@2x.png",
"scale" : "2x"
},
{
"size" : "1024x1024",
"idiom" : "ios-marketing",
"filename" : "Icon-App-1024x1024@1x.png",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 226 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 295 B

After

Width:  |  Height:  |  Size: 817 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 406 B

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 450 B

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 282 B

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 462 B

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 704 B

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 406 B

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 586 B

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 862 B

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 862 B

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 762 B

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -9,7 +9,7 @@
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string> <string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <string>com.example.cheminova</string>
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string> <string>6.0</string>
<key>CFBundleName</key> <key>CFBundleName</key>

View File

@ -16,7 +16,7 @@ class AnnouncementController extends GetxController {
SharedPreferences prefs = await SharedPreferences.getInstance(); SharedPreferences prefs = await SharedPreferences.getInstance();
String? token = prefs.getString('token'); String? token = prefs.getString('token');
final List<AnnouncementModel>? fetchedAnnouncements = final List<AnnouncementModel>? fetchedAnnouncements =
await _announcementService.fetchAnnouncements(token!); await _announcementService.fetchAnnouncements();
announcements.assignAll(fetchedAnnouncements as Iterable<AnnouncementModel>); announcements.assignAll(fetchedAnnouncements as Iterable<AnnouncementModel>);
} catch (e) { } catch (e) {
errorMessage.value = e.toString(); errorMessage.value = e.toString();

View File

@ -8,16 +8,16 @@ class AnnouncementService {
final Dio _dio = Dio(); final Dio _dio = Dio();
Future<List<AnnouncementModel>?> fetchAnnouncements(String token) async { Future<List<AnnouncementModel>?> fetchAnnouncements() async {
try { try {
String url = ApiUrls.AnnaouncementUrl; // Base URL to fetch product manuals String url = ApiUrls.AnnaouncementUrl; // Base URL to fetch product manuals
final response = await commonApiService<List<AnnouncementModel>>( final response = await commonApiService<List<AnnouncementModel>>(
method: "GET", method: "GET",
url: url, url: url,
additionalHeaders: { // Pass the token here // additionalHeaders: { // Pass the token here
'Authorization': 'Bearer $token', // 'Authorization': 'Bearer $token',
}, // },
fromJson: (json) { fromJson: (json) {
if (json['announcements'] != null) { if (json['announcements'] != null) {
// If the productManuals key is present, map the response to a list of ProductManualModel objects // If the productManuals key is present, map the response to a list of ProductManualModel objects

View File

@ -49,7 +49,7 @@ class CartController extends GetxController {
} }
// Update observable values // Update observable values
subtotal.value = subTotal; subtotal.value = subTotal;
gstTotal.value = gstTotalAmount; gstTotal.value = double.parse(gstTotalAmount.toStringAsFixed(2));
grandTotal.value = subtotal.value + gstTotal.value; grandTotal.value = subtotal.value + gstTotal.value;
} }
// Function to increase the quantity of a product in the cart // Function to increase the quantity of a product in the cart
@ -76,6 +76,15 @@ class CartController extends GetxController {
} }
} }
} }
void updateQuantity(Product product, int quantity) {
final existingProduct = cartList.firstWhereOrNull((p) => p.id == product.id);
if (existingProduct != null) {
existingProduct.quantity = quantity;
updateTotalPrice();// Notify listeners
}
}
// Function to remove a product from the cart // Function to remove a product from the cart
void removeFromCart(Product product) { void removeFromCart(Product product) {
// Remove the product from the cart list // Remove the product from the cart list

View File

@ -1,3 +1,5 @@
import 'dart:convert';
import 'package:cheminova/models/user_model.dart'; import 'package:cheminova/models/user_model.dart';
import 'package:cheminova/utils/api_urls.dart'; import 'package:cheminova/utils/api_urls.dart';
import 'package:cheminova/utils/common_api_service.dart'; import 'package:cheminova/utils/common_api_service.dart';
@ -33,35 +35,26 @@ class HomeService {
} }
// Function to send FCM token to the server // Function to send FCM token to the server
Future<Map<String, dynamic>?> fcmToken(Map<String, dynamic> data, Future<Map<String, dynamic>?> fcmToken(Map<String, dynamic> data, String? token) async {
String? token) async {
try { try {
final response = await commonApiService<String>( final response = await commonApiService<Map<String, dynamic>>(
// Making a POST request to send the FCM token
url: ApiUrls.fcmUrl, url: ApiUrls.fcmUrl,
method: 'POST', method: 'POST',
body: data, body: data,
// Body data to be sent in the request fromJson: (json) => json as Map<String, dynamic>, // Parse JSON response
fromJson: (json) => json as String,
// Just return the string response
additionalHeaders: { additionalHeaders: {
// Pass the token here
'Authorization': 'Bearer $token', 'Authorization': 'Bearer $token',
// Bearer token for authenticated requests
}, },
); );
if (response != null) { if (response != null) {
// Since the response is a string, wrap it in a Map to avoid type issues return response; // Return parsed response
return {
'message': response
}; // Return the response in a map with 'message' as the key
} }
return null; return null;
} catch (e) { } catch (e) {
showSnackbar(e.toString()); // Handle any errors showSnackbar(e.toString());
return null; return null;
} }
} }
} }

View File

@ -2,13 +2,21 @@ import 'package:cheminova/models/kyc_model.dart';
import 'package:cheminova/utils/api_urls.dart'; import 'package:cheminova/utils/api_urls.dart';
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import '../utils/app_interceptor.dart';
class KycService { class KycService {
// Function to fetch KYC data from the API // Function to fetch KYC data from the API
Future<List<dynamic>> getKycData(String token) async { Future<List<dynamic>> getKycData(String token) async {
try { try {
// Make a GET request to the KYC API endpoint with authorization token // Make a GET request to the KYC API endpoint with authorization token
var response = await Dio().get(
final dio = Dio();
dio.interceptors.add(AuthInterceptor());
var response = await dio.get(
ApiUrls.getKycUrl, ApiUrls.getKycUrl,
// 'https://api.cnapp.co.in/api/kyc/getAll', // 'https://api.cnapp.co.in/api/kyc/getAll',
options: Options( options: Options(
@ -31,6 +39,8 @@ class KycService {
} }
Future<bool> approveKycStatus(String token, String kycId,String status) async { Future<bool> approveKycStatus(String token, String kycId,String status) async {
final dio = Dio();
dio.interceptors.add(AuthInterceptor());
try { try {
// Prepare the payload for approval directly // Prepare the payload for approval directly
var payload = { var payload = {
@ -41,7 +51,7 @@ class KycService {
// print("Payload: $payload"); // print("Payload: $payload");
// Make a PATCH request to update the KYC status // Make a PATCH request to update the KYC status
var response = await Dio().patch( var response = await dio.patch(
'https://api.cnapp.co.in/api/kyc/update/$kycId', // URL with the KYC ID 'https://api.cnapp.co.in/api/kyc/update/$kycId', // URL with the KYC ID
data: payload, // Payload with the status data: payload, // Payload with the status
options: Options( options: Options(
@ -74,6 +84,8 @@ class KycService {
} }
Future<bool> rejectKycStatus( Future<bool> rejectKycStatus(
String token, String kycId, String? rejectionReason, String? user, String status) async { String token, String kycId, String? rejectionReason, String? user, String status) async {
final dio = Dio();
dio.interceptors.add(AuthInterceptor());
try { try {
// Prepare the payload for the PATCH request // Prepare the payload for the PATCH request
var data = { var data = {
@ -92,7 +104,7 @@ class KycService {
print("Payload: $data"); print("Payload: $data");
// Make a PATCH request to update the KYC status // Make a PATCH request to update the KYC status
var response = await Dio().patch( var response = await dio.patch(
'https://api.cnapp.co.in/api/kyc/update/$kycId', 'https://api.cnapp.co.in/api/kyc/update/$kycId',
data: data, data: data,
options: Options( options: Options(

View File

@ -2,15 +2,17 @@ import 'package:dio/dio.dart';
import 'package:cheminova/models/notification_model.dart'; import 'package:cheminova/models/notification_model.dart';
import '../utils/api_urls.dart'; import '../utils/api_urls.dart';
import '../utils/app_interceptor.dart';
class NotificationService { class NotificationService {
final Dio _dio = Dio(); // final Dio _dio = Dio();
Future<List<NotificationModel>?> fetchNotifications(String token, String date) async { Future<List<NotificationModel>?> fetchNotifications(String token, String date) async {
final String url = ApiUrls.getNotificationUrl; final String url = ApiUrls.getNotificationUrl;
final dio = Dio();
dio.interceptors.add(AuthInterceptor());
try { try {
final response = await _dio.get( final response = await dio.get(
url, url,
options: Options( options: Options(
headers: { headers: {

View File

@ -6,12 +6,18 @@ import 'package:cheminova/utils/api_urls.dart';
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import '../models/oder_place_model.dart'; import '../models/oder_place_model.dart';
import '../utils/app_interceptor.dart';
import '../utils/log_service.dart'; import '../utils/log_service.dart';
class OrderPlacedService { class OrderPlacedService {
final Dio dio = Dio(); //final Dio dio = Dio();
// OrderPlacedService() : _dio = Dio(BaseOptions(baseUrl: 'https://api.cnapp.co.in')) {
// _dio.interceptors.add(AuthInterceptor());
// _dio.interceptors.add(PrettyDioLogger());
// }
Future<void> placeOrder(PlacedOrderModel orderDetails, String token) async { Future<void> placeOrder(PlacedOrderModel orderDetails, String token) async {
final dio = Dio();
dio.interceptors.add(AuthInterceptor());
//try { //try {
// logger.w("orderjson ${jsonEncode(orderDetails.toJson())}"); // logger.w("orderjson ${jsonEncode(orderDetails.toJson())}");
final response = await dio.post( final response = await dio.post(

View File

@ -0,0 +1,49 @@
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;
}
}
@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

@ -48,7 +48,8 @@ class RDOrderPlacedController extends GetxController {
// Call the service to place the order // Call the service to place the order
await _rdOrderPlacedService.placRDeOrder(orderDetails, token!); await _rdOrderPlacedService.placRDeOrder(orderDetails, token!);
} catch (e) { } catch (e) {
print("Error placing order: $e"); // print("Error placing order: $e");
showSnackbar("stock not available");
} finally { } finally {
isLoading.value = false; isLoading.value = false;
} }

View File

@ -6,16 +6,23 @@ import 'package:cheminova/utils/show_snackbar.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import '../models/rd_order_item_model.dart'; import '../models/rd_order_item_model.dart';
import '../utils/app_interceptor.dart';
class RDOrderPlacedService { class RDOrderPlacedService {
final Dio _dio = Dio(); // Create Dio instance final Dio _dio = Dio(); // Create Dio instance
// RDOrderPlacedService() : _dio = Dio(BaseOptions(baseUrl: 'https://api.cnapp.co.in')) {
// _dio.interceptors.add(AuthInterceptor());
// _dio.interceptors.add(PrettyDioLogger());
// }
Future<void> placRDeOrder(PlacedOrdersProcessing orderDetails, Future<void> placRDeOrder(PlacedOrdersProcessing orderDetails,
String token) async { String token) async {
final dio = Dio();
dio.interceptors.add(AuthInterceptor());
//try { //try {
// logger.w("orderjson ${jsonEncode(orderDetails.toJson())}"); // logger.w("orderjson ${jsonEncode(orderDetails.toJson())}");
final response = await _dio.post( final response = await dio.post(
'https://api.cnapp.co.in/api/pd-process-order', 'https://api.cnapp.co.in/api/pd-process-order',
// Ensure this is your correct endpoint // Ensure this is your correct endpoint
data: jsonEncode(orderDetails.toJson()), data: jsonEncode(orderDetails.toJson()),

View File

@ -0,0 +1,32 @@
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,48 @@
import 'dart:convert';
import 'package:cheminova/models/product_stock_model.dart';
import 'package:dio/dio.dart';
import '../utils/api_urls.dart';
import '../utils/app_interceptor.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;
final dio = Dio();
dio.interceptors.add(AuthInterceptor());
// 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

@ -1,27 +1,74 @@
class Brand { class Brand {
final String id; final String id;
final String brandName; final String brandName;
List<BrandImage> images;
Brand({ Brand({
required this.id, required this.id,
required this.brandName, required this.brandName,
required this.images,
}); });
factory Brand.fromJson(Map<String, dynamic> json) { factory Brand.fromJson(Map<String, dynamic> json) {
return Brand( return Brand(
id: json['_id'], id: json['_id'],
brandName: json['brandName'], brandName: json['brandName'],
// images: json["image"] != null
// ? (json["image"] as List).map((e) => BrandImage.fromJson(e)).toList()
// : [],
images: json["image"] != null // Ensure you use the correct key
? (json["image"] as List)
.map((e) => BrandImage.fromJson(e))
.toList()
: [],
); );
} }
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
return { return {
'_id': id, '_id': id,
'brandName': brandName, 'brandName': brandName,
"image": images.map((e) => e.toJson()).toList(),
}; };
} }
@override @override
String toString() { String toString() {
return 'Brand(id: $id, brandName: $brandName,)'; return 'Brand(id: $id, brandName: $brandName,images: $images)';
}
}
class BrandImage {
String publicId;
String url;
String imageId;
BrandImage({
required this.publicId,
required this.url,
required this.imageId,
});
factory BrandImage.fromJson(Map<String, dynamic> json) {
return BrandImage(
publicId: json["public_id"] ?? "",
url: json["url"]?.toString() ?? "",
imageId: json["_id"] ?? "",
);
}
Map<String, dynamic> toJson() {
return {
"public_id": publicId,
"url": url,
"_id": imageId,
};
}
@override
String toString() {
return "BrandImage(publicId: $publicId, url: $url, imageId: $imageId)";
} }
} }

View File

@ -1,9 +1,15 @@
import 'package:cheminova/models/rd_order_item_model.dart';
import 'brand_model.dart';
class GetRdCancelledModel { class GetRdCancelledModel {
final String id; final String id;
final String paymentMode; final String paymentMode;
final String shipTo; final String shipTo;
final String billTo; final String billTo;
final List<OrderItem> orderItems; final List<RDOrderItem> orderItems;
final double subtotal; final double subtotal;
final double gstTotal; final double gstTotal;
final double grandTotal; final double grandTotal;
@ -51,8 +57,8 @@ class GetRdCancelledModel {
paymentMode: json['paymentMode'], paymentMode: json['paymentMode'],
shipTo: json['shipTo'], shipTo: json['shipTo'],
billTo: json['billTo'], billTo: json['billTo'],
orderItems: (json['orderItem'] as List<dynamic>) orderItems: (json['orderItem'] as List)
.map((item) => OrderItem.fromJson(item)) .map((item) => RDOrderItem.fromJson(item))
.toList(), .toList(),
subtotal: json['subtotal'].toDouble(), subtotal: json['subtotal'].toDouble(),
gstTotal: json['gstTotal'].toDouble(), gstTotal: json['gstTotal'].toDouble(),
@ -122,7 +128,7 @@ class OrderItem {
final double gst; final double gst;
final int hsnCode; final int hsnCode;
final String description; final String description;
final List<String> images; final List<BrandImage> images;
final int quantity; final int quantity;
final int remainingQuantity; final int remainingQuantity;
final String id; final String id;
@ -154,7 +160,9 @@ class OrderItem {
gst: json['GST'].toDouble(), gst: json['GST'].toDouble(),
hsnCode: json['HSN_Code'], hsnCode: json['HSN_Code'],
description: json['description'] ?? '', description: json['description'] ?? '',
images: List<String>.from(json['image']), images : (json["image"] as List)
.map((item) => BrandImage.fromJson(item))
.toList(),
quantity: json['quantity'], quantity: json['quantity'],
remainingQuantity: json['remainingQuantity'], remainingQuantity: json['remainingQuantity'],
id: json['_id'], id: json['_id'],

View File

@ -64,7 +64,7 @@ class OrderItem {
String description; String description;
String productStatus; String productStatus;
final String addedBy; final String addedBy;
List<String> image; List<BrandImage> image;
DateTime createdAt; DateTime createdAt;
DateTime updatedAt; DateTime updatedAt;
int count; int count;
@ -124,7 +124,9 @@ class OrderItem {
description: json['description'], description: json['description'],
productStatus: json['product_Status'], productStatus: json['product_Status'],
addedBy: json['addedBy']['name'], // Assuming addedBy has a 'name' key addedBy: json['addedBy']['name'], // Assuming addedBy has a 'name' key
image: List<String>.from(json['image']), image: json['image'] is List
? (json['image'] as List).map((e) => BrandImage.fromJson(e)).toList()
: [BrandImage.fromJson(json['image'])],
createdAt: DateTime.parse(json['createdAt']), createdAt: DateTime.parse(json['createdAt']),
updatedAt: DateTime.parse(json['updatedAt']), updatedAt: DateTime.parse(json['updatedAt']),
count: json['count'], count: json['count'],

View File

@ -1,3 +1,5 @@
import 'brand_model.dart';
class PlacedOrderList { class PlacedOrderList {
final String id; final String id;
final String paymentMode; final String paymentMode;
@ -95,6 +97,7 @@ class OrderItem1 {
final String brandName; final String brandName;
final double price; final double price;
final int quantity; final int quantity;
List<BrandImage>? image;
OrderItem1({ OrderItem1({
required this.sku, required this.sku,
@ -102,6 +105,7 @@ class OrderItem1 {
required this.categoryName, required this.categoryName,
required this.brandName, required this.brandName,
required this.price, required this.price,
this.image,
required this.quantity, required this.quantity,
}); });
@ -112,6 +116,9 @@ class OrderItem1 {
categoryName: json['categoryName'], categoryName: json['categoryName'],
brandName: json['brandName'], brandName: json['brandName'],
price: json['price'].toDouble(), price: json['price'].toDouble(),
image : (json["image"] as List)
.map((item) => BrandImage.fromJson(item))
.toList(),
quantity: json['quantity'], quantity: json['quantity'],
); );
} }
@ -124,13 +131,14 @@ class OrderItem1 {
'brandName': brandName, 'brandName': brandName,
'price': price, 'price': price,
'quantity': quantity, 'quantity': quantity,
'image':image
}; };
} }
@override @override
String toString() { String toString() {
return 'OrderItem(sku: $sku, name: $name, categoryName: $categoryName, ' return 'OrderItem(sku: $sku, name: $name, categoryName: $categoryName, '
'brandName: $brandName, price: $price, quantity: $quantity)'; 'brandName: $brandName, price: $price, quantity: $quantity,image:$image)';
} }
} }

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

@ -1,5 +1,7 @@
class RDOrderItem { import 'brand_model.dart';
class RDOrderItem {
final String productId; final String productId;
final String sku; final String sku;
final String name; final String name;
@ -9,7 +11,7 @@
final int gst; // Ensure GST is int final int gst; // Ensure GST is int
final int hsnCode; // Ensure HSN_Code is int final int hsnCode; // Ensure HSN_Code is int
final String description; final String description;
final List<String> image; final List<BrandImage> image;
int? quantity; int? quantity;
int? remainingQuantity; int? remainingQuantity;
int? processquantity; int? processquantity;
@ -43,10 +45,13 @@
hsnCode: json['HSN_Code'] ?? 0, hsnCode: json['HSN_Code'] ?? 0,
// Handle HSN_Code as int // Handle HSN_Code as int
description: json['description'] ?? '', description: json['description'] ?? '',
image: List<String>.from(json['image'] ?? []), //image: List<String>.from(json['image'] ?? []),
image : (json["image"] as List)
.map((item) => BrandImage.fromJson(item))
.toList(),
quantity: json['quantity'] ?? 0, quantity: json['quantity'] ?? 0,
// Handle quantity as int // Handle quantity as int
processquantity: json['processquantity']??1, processquantity: json['processQuantity']??1,
remainingQuantity: json['remainingQuantity'] ?? remainingQuantity: json['remainingQuantity'] ??
0, // Handle remainingQuantity as int 0, // Handle remainingQuantity as int
); );

View File

@ -1,3 +1,121 @@
// 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:intl/intl.dart';
//
// import '../../controller/annaucement_controller.dart';
// import '../../widgets/comman_background.dart';
// import '../../widgets/common_appbar.dart';
//
// class AnnouncementScreen extends StatefulWidget {
// AnnouncementScreen({super.key});
//
// @override
// State<AnnouncementScreen> createState() => _AnnouncementScreenState();
// }
//
// class _AnnouncementScreenState extends State<AnnouncementScreen> {
// // Initialize the controller
// final AnnouncementController _announcementController = Get.put(AnnouncementController());
//
//
// String formatDate(String apiDate) {
// // Parse the API date string into a DateTime object
// DateTime parsedDate = DateTime.parse(apiDate).toLocal(); // Convert to local time
//
// // Format the date and time according to your specified format
// String formattedDate = DateFormat('EEE MMM dd yyyy').format(parsedDate);
//
// return formattedDate; // Return the formatted date string
// }
//
//
// @override
// Widget build(BuildContext context) {
// // Fetch announcements when the screen is built
// _announcementController.fetchAnnouncements();
//
// return CommonBackground(
// child: Scaffold(
// backgroundColor: Colors.transparent,
// appBar: CommonAppBar(
// actions: [
// IconButton(
// onPressed: () {
// Navigator.pop(context);
// },
// icon: SvgPicture.asset('assets/svg/back_arrow.svg'),
// padding: const EdgeInsets.only(right: 20),
// ),
// ],
// title: const Text(
// 'Announcement',
// style: TextStyle(
// fontSize: 20,
// color: Colors.black,
// fontWeight: FontWeight.w400,
// fontFamily: 'Anek',
// ),
// ),
// backgroundColor: Colors.transparent,
// elevation: 0,
// ),
// drawer: MyDrawer(),
// body: Obx(() {
// // Show loading indicator while fetching announcements
// if (_announcementController.isLoading.value) {
// return Center(child: CircularProgressIndicator());
// }
// // Show error message if there was an error
// if (_announcementController.errorMessage.isNotEmpty) {
// return Center(
// child: Text('Error: ${_announcementController.errorMessage}'),
// );
// }
// // Display the list of announcements
// return ListView.builder(
// itemCount: _announcementController.announcements.length,
// itemBuilder: (context, index) {
// final announcementList = _announcementController.announcements[index];
// print("asdf,${announcementList}");
// return Column(
// children: [
// Card(
// child: ListTile(
// //leading:Text(_announcementController.announcements[index].id),
// title: Row(
//
// children: [
// Text("Message :",style: TextStyle(fontWeight: FontWeight.bold,fontSize: 14),),
// Text(announcementList.message.toString(),style: TextStyle(fontSize: 12),),
//
// ],
// ),
// subtitle: Row(
// children: [
// Text("UniqueID :" , style: TextStyle(fontWeight: FontWeight.bold),),
// Text(announcementList.uniqueId.toString()),
// ],
// ),
// trailing: Text(formatDate(announcementList.createdAt.toString()),style: TextStyle(fontSize: 10),),
// ),
//
// ),
//
// ],
// );
// },
// );
// }),
// ),
// );
// }
// }
import 'package:cheminova/widgets/my_drawer.dart'; import 'package:cheminova/widgets/my_drawer.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
@ -16,24 +134,15 @@ class AnnouncementScreen extends StatefulWidget {
} }
class _AnnouncementScreenState extends State<AnnouncementScreen> { class _AnnouncementScreenState extends State<AnnouncementScreen> {
// Initialize the controller
final AnnouncementController _announcementController = Get.put(AnnouncementController()); final AnnouncementController _announcementController = Get.put(AnnouncementController());
String formatDate(String apiDate) { String formatDate(String apiDate) {
// Parse the API date string into a DateTime object DateTime parsedDate = DateTime.parse(apiDate).toLocal();
DateTime parsedDate = DateTime.parse(apiDate).toLocal(); // Convert to local time return DateFormat('EEE MMM dd yyyy').format(parsedDate);
// Format the date and time according to your specified format
String formattedDate = DateFormat('EEE MMM dd yyyy').format(parsedDate);
return formattedDate; // Return the formatted date string
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
// Fetch announcements when the screen is built
_announcementController.fetchAnnouncements(); _announcementController.fetchAnnouncements();
return CommonBackground( return CommonBackground(
@ -63,47 +172,61 @@ class _AnnouncementScreenState extends State<AnnouncementScreen> {
), ),
drawer: MyDrawer(), drawer: MyDrawer(),
body: Obx(() { body: Obx(() {
// Show loading indicator while fetching announcements
if (_announcementController.isLoading.value) { if (_announcementController.isLoading.value) {
return Center(child: CircularProgressIndicator()); return Center(child: CircularProgressIndicator());
} }
// Show error message if there was an error
if (_announcementController.errorMessage.isNotEmpty) { if (_announcementController.errorMessage.isNotEmpty) {
return Center( return Center(
child: Text('Error: ${_announcementController.errorMessage}'), child: Text('Error: ${_announcementController.errorMessage}'),
); );
} }
// Display the list of announcements
return ListView.builder( return ListView.builder(
itemCount: _announcementController.announcements.length, itemCount: _announcementController.announcements.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
final announcementList = _announcementController.announcements[index]; final announcementList = _announcementController.announcements[index];
print("asdf,${announcementList}"); return Card(
return Column( margin: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
children: [
Card(
child: ListTile( child: ListTile(
//leading:Text(_announcementController.announcements[index].id), // leading: CircleAvatar(
title: Row( // backgroundColor: Colors.blue,
// child: Text(
// announcementList.uniqueId.toString().toUpperCase(),
// style: TextStyle(color: Colors.white),
// ),
// ),
title: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text("Message :",style: TextStyle(fontWeight: FontWeight.bold,fontSize: 14),), Text(
Text(announcementList.message.toString(),style: TextStyle(fontSize: 12),), "Message:",
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14),
),
Text(
announcementList.message.toString(),
style: TextStyle(fontSize: 12),
overflow: TextOverflow.ellipsis,
),
], ],
), ),
subtitle: Row( subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text("UniqueID :" , style: TextStyle(fontWeight: FontWeight.bold),), Text(
Text(announcementList.uniqueId.toString()), "UniqueID:",
style: TextStyle(fontWeight: FontWeight.bold),
),
Text(
announcementList.uniqueId.toString(),
style: TextStyle(fontSize: 12),
overflow: TextOverflow.ellipsis,
),
], ],
), ),
trailing: Text(formatDate(announcementList.createdAt.toString()),style: TextStyle(fontSize: 10),), trailing: Text(
formatDate(announcementList.createdAt.toString()),
style: TextStyle(fontSize: 10),
), ),
), ),
],
); );
}, },
); );

View File

@ -20,13 +20,13 @@ class _ChangePasswordScreenState extends State<ChangePasswordScreen> {
final authController = Get.put(AuthController()); final authController = Get.put(AuthController());
void dispose() { // void dispose() {
// Dispose of the text controllers when the screen is closed to free up resources // // Dispose of the text controllers when the screen is closed to free up resources
authController.currentpassController.dispose(); // authController.currentpassController.dispose();
authController.newpassController.dispose(); // authController.newpassController.dispose();
authController.confirmpassController.dispose(); // authController.confirmpassController.dispose();
super.dispose(); // super.dispose();
} // }
// Function to validate user input and initiate password change // Function to validate user input and initiate password change
void validateAndChangePassword() async { void validateAndChangePassword() async {

View File

@ -1,9 +1,12 @@
import 'dart:convert'; import 'dart:convert';
import 'package:cheminova/controller/home_controller.dart'; import 'package:cheminova/controller/home_controller.dart';
import 'package:cheminova/controller/home_service.dart';
import 'package:cheminova/screens/authentication/controller/auth_service.dart'; import 'package:cheminova/screens/authentication/controller/auth_service.dart';
import 'package:cheminova/screens/authentication/login_screen.dart';
import 'package:cheminova/screens/home_screen.dart'; import 'package:cheminova/screens/home_screen.dart';
import 'package:cheminova/utils/show_snackbar.dart'; import 'package:cheminova/utils/show_snackbar.dart';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
@ -15,7 +18,7 @@ import '../../../utils/secure__storage_service.dart';
class AuthController extends GetxController { class AuthController extends GetxController {
final authService = AuthService(); final authService = AuthService();
final Dio _dio = Dio();
final _storageService = SecureStorageService(); final _storageService = SecureStorageService();
@ -28,6 +31,7 @@ class AuthController extends GetxController {
final HomeController _homeController = Get.put(HomeController()); final HomeController _homeController = Get.put(HomeController());
RxBool isLoading = false.obs; RxBool isLoading = false.obs;
@override @override
void onInit(){ void onInit(){
super.onInit(); super.onInit();
@ -35,26 +39,106 @@ class AuthController extends GetxController {
NotificationServices().requestNotificationPermission(); NotificationServices().requestNotificationPermission();
} }
// Function to handle user login // Function to handle user login
// Future<void> login() async {
// isLoading.value = true;
// // Call the login service with email and password
// final response = await authService.login({
// 'email': emailController.text,
// 'password': passwordController.text,
// });
// isLoading.value = false;
// update();
// if (response != null) {
// _homeController.fcmToken();
// showSnackbar("Your Successfully logged In!");
//
// Get.offAll(() => const HomeScreen());
// }
// else if(response == null){
// showSnackbar("Please Enter Valid Email or Password");
// }
// }
Future<void> login() async { Future<void> login() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
isLoading.value = true; isLoading.value = true;
// Call the login service with email and password
// Perform login API request
final response = await authService.login({ final response = await authService.login({
'email': emailController.text, 'email': emailController.text,
'password': passwordController.text, 'password': passwordController.text,
}); });
isLoading.value = false; isLoading.value = false;
update(); update();
if (response != null) {
_homeController.fcmToken();
showSnackbar("Your Successfully logged In!");
if (response != null && response['token'] != null) {
// Save the JWT token to SharedPreferences
String token = response['token'];
await prefs.setString('token', token);
// Fetch the FCM token and send it to the server
final fcmToken = await NotificationServices().getDeviceToken();
print('fcmToken: $fcmToken');
await HomeService().fcmToken({'fcmToken': fcmToken}, token);
showSnackbar("You successfully logged in!");
// Proceed to the HomeScreen after successful login
checkToken(); // Ensure the token is valid and the user is authenticated
Get.offAll(() => const HomeScreen()); Get.offAll(() => const HomeScreen());
} } else {
else if(response == null){ showSnackbar("Please enter a valid email or password");
showSnackbar("Please Enter Valid Email or Password");
} }
} }
Future<void> checkToken() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String? token = prefs.getString('token');
if (token != null) {
// Token exists, proceed with the flow (maybe fetch user data or navigate to the home screen)
print('Token found: $token');
// You can also fetch the FCM token if necessary
final fcmToken = await NotificationServices().getDeviceToken();
print('fcmToken: $fcmToken');
// Optionally send the FCM token to the server if needed
// This might be where you're getting the error
await _homeController.fcmToken();
// Navigate to HomeScreen or perform other operations
Get.offAll(() => const HomeScreen());
} else {
// No token found, redirect to login screen
Get.offAll(() => const LoginScreen());
}
}
// Function to validate the token
// Future<bool> isTokenValid(String token) async {
// try {
// final response = await authService.validateToken(token);
// return response['isValid'] ?? false; // Adjust based on your API response
// } catch (e) {
// print("Token validation failed: $e");
// return false;
// }
// }
// Future<(bool, String)> login() async { // Future<(bool, String)> login() async {
// isLoading(true); // isLoading(true);
// try { // try {

View File

@ -1,10 +1,18 @@
import 'package:cheminova/utils/api_urls.dart'; import 'package:cheminova/utils/api_urls.dart';
import 'package:cheminova/utils/common_api_service.dart'; import 'package:cheminova/utils/common_api_service.dart';
import 'package:cheminova/utils/show_snackbar.dart'; import 'package:cheminova/utils/show_snackbar.dart';
import 'package:dio/dio.dart';
import 'package:pretty_dio_logger/pretty_dio_logger.dart';
import '../../../utils/app_interceptor.dart';
class AuthService { class AuthService {
final Dio _dio;
AuthService() : _dio = Dio(BaseOptions(baseUrl: 'https://api.cnapp.co.in')) {
_dio.interceptors.add(AuthInterceptor());
_dio.interceptors.add(PrettyDioLogger());
}
// Function to handle user login // Function to handle user login
Future<Map<String, dynamic>?> login(Map<String, dynamic> data) async { Future<Map<String, dynamic>?> login(Map<String, dynamic> data) async {
try { try {

View File

@ -24,9 +24,15 @@ class _ProfileScreenState extends State<ProfileScreen> {
// Initialize the HomeController using GetX // Initialize the HomeController using GetX
final homecontroller = Get.put(HomeController()); final homecontroller = Get.put(HomeController());
@override @override
void initState() {
// TODO: implement initState
super.initState();
homecontroller.getUser();
}
@override
Widget build(BuildContext context) { Widget build(BuildContext context) {
// Accessing the user details from the HomeController // Accessing the user details from the HomeController
final user = homecontroller!.user; final user = homecontroller.user;
return Stack( return Stack(
children: [ children: [
CommonBackground( CommonBackground(
@ -52,7 +58,10 @@ class _ProfileScreenState extends State<ProfileScreen> {
], ],
), ),
// Main content of the profile screen // Main content of the profile screen
body: SingleChildScrollView( body: user == null
? const Center(child: CircularProgressIndicator())
:
SingleChildScrollView(
child: Column( child: Column(
children: [ children: [
Container( Container(
@ -70,7 +79,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
children: [ children: [
const SizedBox(height: 20), const SizedBox(height: 20),
// Displaying individual profile items // Displaying individual profile items
_buildProfileItem('Name', user!.name), _buildProfileItem('Name', user.name),
_buildProfileItem('ID', user.uniqueId), _buildProfileItem('ID', user.uniqueId),
_buildProfileItem('Email ID', user.email), _buildProfileItem('Email ID', user.email),
_buildProfileItem('Mobile Number', user.phone), _buildProfileItem('Mobile Number', user.phone),

View File

@ -19,6 +19,7 @@ import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'kyc/kyc_retailer_info_screen.dart'; import 'kyc/kyc_retailer_info_screen.dart';
import 'opening Inventory/inventory_management_screen.dart';
class HomeScreen extends StatefulWidget { class HomeScreen extends StatefulWidget {
const HomeScreen({super.key}); const HomeScreen({super.key});
@ -183,7 +184,7 @@ class _HomeScreenState extends State<HomeScreen> {
mainAxisAlignment: MainAxisAlignment.spaceEvenly, mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [ children: [
HomeCard( HomeCard(
title: 'RD Orders', title: 'Retailer Orders',
onTap: () => Get.to( onTap: () => Get.to(
() => RdOrderScreen(), () => RdOrderScreen(),
), ),
@ -196,6 +197,27 @@ class _HomeScreenState extends State<HomeScreen> {
), ),
],
),
const SizedBox(height: 10),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
HomeCard(
title: 'Opening Inventory',
onTap: () => Get.to(
() => OpeningInventoryManagementScreen(),
),
),
// HomeCard(
// title: 'Announcement',
// onTap: () => Get.to(
// () => AnnouncementScreen(),
// ),
// ),
], ],
), ),
], ],

View File

@ -23,7 +23,8 @@ class _InventoryManagementScreenState extends State<InventoryManagementScreen> {
quantity: 100, quantity: 100,
description: 'Description 1', description: 'Description 1',
category: ProductCategory.food, category: ProductCategory.food,
image: 'assets/images/product.png', image: "assets/images/new_product.jpeg",
//'assets/images/product.png',
) )
]; ];
final List<String> _filterList = [ final List<String> _filterList = [

View File

@ -179,13 +179,18 @@ class _KycRetailerInfoScreenState extends State<KycRetailerInfoScreen> {
), ),
SizedBox( SizedBox(
height: Get.height * 0.6, height: Get.height * 0.6,
child: Obx(() { child:
Obx(() {
// Filter the list based on the selected status // Filter the list based on the selected status
List<KycModel> filteredOrders = List<KycModel> filteredOrders =
selectedStatus == "All" selectedStatus == "All"
? _kycController.kycList ? _kycController.kycList
: _kycController.kycList.where((kyc) => kyc.status == selectedStatus).toList(); : _kycController.kycList.where((kyc) => kyc.status == selectedStatus).toList();
filteredOrders.sort((a, b) {
DateTime dateA = DateTime.parse(filteredOrders[0].createdAt.toString()); // Assuming createdAt is a string
DateTime dateB = DateTime.parse(filteredOrders[0].createdAt.toString());
return dateB.compareTo(dateA); // Sort in descending order
});
return ListView.builder( return ListView.builder(
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
shrinkWrap: true, shrinkWrap: true,

View File

@ -0,0 +1,213 @@
// import 'dart:io';
//
// import 'package:cheminova/screens/kyc/retailer_screen.dart';
// import 'package:cheminova/screens/kyc/upload_document_screen.dart';
// import 'package:cheminova/screens/kyc/verify_document_screen.dart';
// import 'package:cheminova/widgets/my_drawer.dart';
// import 'package:flutter_svg/flutter_svg.dart';
// import 'package:image_picker/image_picker.dart';
// import 'package:flutter/material.dart';
//
// import '../../widgets/comman_background.dart';
// import '../../widgets/common_appbar.dart';
//
//
// class CollectKycScreen extends StatefulWidget {
// const CollectKycScreen({super.key});
//
// @override
// State<CollectKycScreen> createState() => CollectKycScreenState();
// }
//
// class CollectKycScreenState extends State<CollectKycScreen>
// with SingleTickerProviderStateMixin {
// late TabController _tabController;
// bool isLoading = false;
//
// final _pages = [
// // RetailerDetailsScreen(),
// const UploadDocumentScreen(),
// const VerifyDocumentsScreen()
// ];
//
// @override
// void initState() {
// _tabController = TabController(length: 3, vsync: this);
// super.initState();
// }
//
// final locationController = TextEditingController();
// final notesController = TextEditingController();
// final dealerController = TextEditingController();
// final productController = TextEditingController();
// final qualityController = TextEditingController();
// final marketNameController = TextEditingController();
// final districtController = TextEditingController();
// final stateController = TextEditingController();
// final pincodeController = TextEditingController();
// final aadharcardController = TextEditingController();
// final pancardController = TextEditingController();
//
// File? _selfieImage;
// File? _pesticideLicenseImage;
// File? _fertilizerLicenseImage;
//
// final ImagePicker _picker = ImagePicker();
//
// Future<void> _pickImage(ImageSource source, bool isSelfie) async {
// final pickedFile = await _picker.pickImage(source: source);
//
// setState(() {
// if (pickedFile != null) {
// if (isSelfie) {
// _selfieImage = File(pickedFile.path);
// }
// }
// });
// }
//
// Future<void> _pickLicenseImage(ImageSource source, bool isPesticide) async {
// final pickedFile = await _picker.pickImage(source: source);
//
// setState(() {
// if (pickedFile != null) {
// if (isPesticide) {
// _pesticideLicenseImage = File(pickedFile.path);
// } else {
// _fertilizerLicenseImage = File(pickedFile.path);
// }
// }
// });
// }
//
// void _showPicker(BuildContext context, bool isSelfie) {
// showModalBottomSheet(
// context: context,
// builder: (BuildContext bc) {
// return SafeArea(
// child: Wrap(
// children: <Widget>[
// ListTile(
// leading: const Icon(Icons.photo_library),
// title: const Text('Photo Library'),
// onTap: () {
// _pickImage(ImageSource.gallery, isSelfie);
// Navigator.of(context).pop();
// },
// ),
// ListTile(
// leading: const Icon(Icons.photo_camera),
// title: const Text('Camera'),
// onTap: () {
// _pickImage(ImageSource.camera, isSelfie);
// Navigator.of(context).pop();
// },
// ),
// ],
// ),
// );
// },
// );
// }
//
// void _showLicensePicker(BuildContext context, bool isPesticide) {
// showModalBottomSheet(
// context: context,
// builder: (BuildContext bc) {
// return SafeArea(
// child: Wrap(
// children: <Widget>[
// ListTile(
// leading: const Icon(Icons.photo_library),
// title: const Text('Photo Library'),
// onTap: () {
// _pickLicenseImage(ImageSource.gallery, isPesticide);
// Navigator.of(context).pop();
// },
// ),
// ListTile(
// leading: const Icon(Icons.photo_camera),
// title: const Text('Camera'),
// onTap: () {
// _pickLicenseImage(ImageSource.camera, isPesticide);
// Navigator.of(context).pop();
// },
// ),
// ],
// ),
// );
// },
// );
// }
//
// @override
// Widget build(BuildContext context) {
// return Stack(
// children: [
// CommonBackground(
// child: DefaultTabController(
// length: 3,
// child: Scaffold(
// backgroundColor: Colors.transparent,
// appBar: PreferredSize(
// preferredSize: const Size.fromHeight(100),
// child: CommonAppBar(
// actions: [
// IconButton(
// onPressed: () {
// Navigator.pop(context);
// },
// icon: SvgPicture.asset("assets/svg/back_arrow.svg"),
// //Image.asset('assets/Back_attendance.png'),
// padding: const EdgeInsets.only(right: 20),
// ),
// ],
// title: const Text(
// 'Collect KYC Data',
// style: TextStyle(
// fontSize: 20,
// color: Colors.black,
// fontWeight: FontWeight.w400,
// fontFamily: 'Anek',
// ),
// ),
// backgroundColor: Colors.transparent,
// elevation: 0,
// bottom: TabBar(
// controller: _tabController,
// padding: const EdgeInsets.symmetric(horizontal: 10),
// dividerColor: Colors.transparent,
// indicatorColor: Colors.yellow,
// labelColor: Colors.white,
// unselectedLabelColor: Colors.black,
// indicatorSize: TabBarIndicatorSize.tab,
// indicator: BoxDecoration(
// color: Colors.blue,
// borderRadius: BorderRadius.circular(10),
// ),
// tabs: const [
// Tab(text: 'Details'),
// Tab(text: 'Documents'),
// Tab(text: 'Verify'),
// ],
// ),
// ),
// ),
// drawer: const MyDrawer(),
// body: TabBarView(
// controller: _tabController,
// physics: const NeverScrollableScrollPhysics(),
// children: _pages,
// ),
// ),
// ),
// ),
// if (isLoading)
// Container(
// color: Colors.black.withOpacity(0.5),
// child: const Center(child: CircularProgressIndicator()),
// ),
// ],
// );
// }
// }

View File

@ -67,7 +67,8 @@ class NotificationScreen extends StatelessWidget {
), ),
), ),
drawer: MyDrawer(), drawer: MyDrawer(),
body: Obx(() { body:
Obx(() {
// Show a loading indicator while data is being fetched // Show a loading indicator while data is being fetched
if (notificationController.isLoading.value) { if (notificationController.isLoading.value) {
return const Center(child: CircularProgressIndicator()); return const Center(child: CircularProgressIndicator());

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,350 @@
import 'package:cheminova/controller/product_stock_service.dart';
import 'package:cheminova/controller/update_stock_controller.dart';
import 'package:cheminova/controller/update_stock_service.dart';
import 'package:cheminova/models/product_model.dart';
import 'package:cheminova/models/product_stock_model.dart';
import 'package:cheminova/screens/opening%20Inventory/inventory_management_screen.dart';
import 'package:cheminova/widgets/input_field.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:get/get.dart';
import 'package:google_fonts/google_fonts.dart';
import '../../utils/show_snackbar.dart';
// 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());
//
// 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;
// }
//
// // 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: 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("Stock updated successfully");
// } catch (e) {
// print("Error updating stock: $e");
// showSnackbar("Error updating stock. Please try again.");
// }
// }
//
//
// @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 Stock Quantity:",
// labelText: "Enter New Stock Quantity:",
// controller: _textController,
// ),
// // InputField(
// // hintText: "Reason for Update: Restock",
// // labelText: "Reason for Update: Restock",
// // 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 Stock 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

@ -14,9 +14,11 @@ import '../../controller/place_order_controller.dart';
import '../../controller/place_order_service.dart'; import '../../controller/place_order_service.dart';
import '../../controller/product_controller.dart'; import '../../controller/product_controller.dart';
import '../../controller/product_service.dart'; import '../../controller/product_service.dart';
import '../../controller/shiptobilltoController.dart';
import '../../models/brand_model.dart'; import '../../models/brand_model.dart';
import '../../models/oder_place_model.dart'; import '../../models/oder_place_model.dart';
import '../../models/product_model1.dart'; import '../../models/product_model1.dart';
import '../../models/shiping_billing_address_model.dart';
import '../../widgets/my_drawer.dart'; import '../../widgets/my_drawer.dart';
import '../../widgets/product_card.dart'; import '../../widgets/product_card.dart';
import 'order_confermation_screen.dart'; import 'order_confermation_screen.dart';
@ -39,6 +41,7 @@ class _CheckoutScreenState extends State<CheckoutScreen> {
final OrderPlacedController _orderPlacedController = final OrderPlacedController _orderPlacedController =
Get.put(OrderPlacedController()); Get.put(OrderPlacedController());
final GetPlacedOrderController _getPlacedOrderController = Get.put(GetPlacedOrderController()); final GetPlacedOrderController _getPlacedOrderController = Get.put(GetPlacedOrderController());
final AddressController _addressController = Get.put(AddressController()); // Initialize AddressController
int currentPage = 1; int currentPage = 1;
String _groupValue = "cheque"; String _groupValue = "cheque";
@ -52,17 +55,25 @@ class _CheckoutScreenState extends State<CheckoutScreen> {
String? _selectedShippingAddress; String? _selectedShippingAddress;
String? _selectedBillingAddress; String? _selectedBillingAddress;
String capitalizeFirstLetter(String text) {
if (text.isEmpty) return text;
return text[0].toUpperCase() + text.substring(1).toLowerCase();
}
@override @override
void initState() { void initState() {
super.initState(); super.initState();
// _getOrder(); // _getOrder();
_addressController.fetchAddresses();
_loadSelectedAddress(); _loadSelectedAddress();
_loadSelectedPaymentMode(); _loadSelectedPaymentMode();
// _loadSelectedAddress();
if (_addressList.isNotEmpty) { // _loadSelectedPaymentMode();
_selectedShippingAddress = _addressList.first; //
_selectedBillingAddress = _addressList.first; // if (_addressList.isNotEmpty) {
} // _selectedShippingAddress = _addressList.first;
// _selectedBillingAddress = _addressList.first;
// }
} }
void _saveSelectedAddress() async { void _saveSelectedAddress() async {
@ -85,16 +96,34 @@ class _CheckoutScreenState extends State<CheckoutScreen> {
_saveSelectedAddress(); _saveSelectedAddress();
} }
// void _loadSelectedAddress() async {
// SharedPreferences prefs = await SharedPreferences.getInstance();
// setState(() {
// _selectedShippingAddress =
// prefs.getString('selectedShippingAddress') ?? _addressList.first;
// _selectedBillingAddress =
// prefs.getString('selectedBillingAddress') ?? _addressList.first;
// });
// }
void _loadSelectedAddress() async { void _loadSelectedAddress() async {
SharedPreferences prefs = await SharedPreferences.getInstance(); SharedPreferences prefs = await SharedPreferences.getInstance();
_addressController
.fetchAddresses(); // Ensure address list is updated
setState(() { setState(() {
_selectedShippingAddress = _selectedShippingAddress =
prefs.getString('selectedShippingAddress') ?? _addressList.first; (prefs.getString('selectedShippingAddress') ??
(_addressController.addressList.isNotEmpty ? _addressController.addressList.first : null)) as String?;
_selectedBillingAddress = _selectedBillingAddress =
prefs.getString('selectedBillingAddress') ?? _addressList.first; (prefs.getString('selectedBillingAddress') ??
(_addressController.addressList.isNotEmpty ? _addressController.addressList.first : null)) as String?;
}); });
} }
void _onPaymentModeChanged(String? value) { void _onPaymentModeChanged(String? value) {
setState(() { setState(() {
_groupValue = value!; _groupValue = value!;
@ -127,7 +156,14 @@ class _CheckoutScreenState extends State<CheckoutScreen> {
hsnCode: product.hsnCode, hsnCode: product.hsnCode,
description: product.description, description: product.description,
productStatus: product.productStatus, productStatus: product.productStatus,
image: [],
// image:[],
image: product.brand.images.isNotEmpty
? product.brand.images.map((image) => BrandImage(
publicId: image.publicId, // or any other identifier
imageId: image.imageId, url: image.url,
)).toList()
:[],
createdAt: product.createdAt, createdAt: product.createdAt,
updatedAt: product.createdAt, updatedAt: product.createdAt,
count: product.quantity, count: product.quantity,
@ -135,16 +171,40 @@ class _CheckoutScreenState extends State<CheckoutScreen> {
//category:product.category, //category:product.category,
category:Category(id: product.category.id, categoryName: product.category.categoryName), category:Category(id: product.category.id, categoryName: product.category.categoryName),
// brand:product.brand, // brand:product.brand,
brand:Brand(id: product.brand.id, brandName: product.brand.brandName), brand:Brand(id: product.brand.id, brandName: product.brand.brandName,images: product.brand.images),
v: 0, addedBy: product.addedBy, v: 0, addedBy: product.addedBy,
); );
}).toList(); }).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: '',
)).toStringFullAddress();
String? billingAddress = _addressController.addressList.firstWhere(
(address) => address.id == _addressController.selectedBillingAddressId.value,
orElse: () => UserShippingAddress(
id: '',
street: '',
city: '',
state: '',
postalCode: '',
country: '', tradeName: '',
)).toStringFullAddress();
// Update the placedOrder1 value // Update the placedOrder1 value
_orderPlacedController.placedOrder1.value= PlacedOrderModel( _orderPlacedController.placedOrder1.value= PlacedOrderModel(
paymentMode: _groupValue, paymentMode: _groupValue,
shipTo: _selectedShippingAddress!, shipTo: shippingAddress, // Full shipping address
billTo: _selectedBillingAddress!, billTo: billingAddress, // Full billing address
orderItems: orderItems, orderItems: orderItems,
gstTotal: _cartController.gstTotal.value, gstTotal: _cartController.gstTotal.value,
grandTotal: _cartController.grandTotal.value, grandTotal: _cartController.grandTotal.value,
@ -157,11 +217,16 @@ class _CheckoutScreenState extends State<CheckoutScreen> {
showSnackbar("Order Placed Successfully"); showSnackbar("Order Placed Successfully");
Get.to(() => OrderConfermationScreen( Get.to(() => OrderConfermationScreen(
placedOrder: _orderPlacedController.placedOrder1.value, placedOrder: _orderPlacedController.placedOrder1.value,
)); ));
} }
} catch (e) { } catch (e) {
print("PlaceOrderScreen error: $e"); print("PlaceOrderScreen error: $e");
} }
} }
@ -219,15 +284,15 @@ class _CheckoutScreenState extends State<CheckoutScreen> {
side: const BorderSide(color: Color(0xFFFDFDFD)), side: const BorderSide(color: Color(0xFFFDFDFD)),
), ),
color: const Color(0xFFB4D1E5).withOpacity(0.9), color: const Color(0xFFB4D1E5).withOpacity(0.9),
child: Padding( child:
Padding(
padding: EdgeInsets.all(Get.width * 0.04), padding: EdgeInsets.all(Get.width * 0.04),
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Padding( Padding(
padding: EdgeInsets.symmetric( padding: EdgeInsets.symmetric(horizontal: Get.width * 0.04),
horizontal: Get.width * 0.04),
child: Text( child: Text(
'Shipping Information', 'Shipping Information',
style: GoogleFonts.roboto( style: GoogleFonts.roboto(
@ -237,38 +302,54 @@ class _CheckoutScreenState extends State<CheckoutScreen> {
), ),
), ),
), ),
SizedBox(height: 5,), SizedBox(height: 5),
DropdownButtonFormField<String>( Obx(() => Container(
child: DropdownButtonFormField<String>(
decoration: InputDecoration( decoration: InputDecoration(
labelText: 'Shipping Address:', labelText: 'Shipping Address:',
hintText: 'Select Shipping Address', hintText: 'Select Shipping Address',
border: OutlineInputBorder(), border: OutlineInputBorder(),
), ),
value: _selectedShippingAddress, value: _addressController.selectedShippingAddressId.value.isEmpty
items: _addressList.map((String address) { ? 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>( return DropdownMenuItem<String>(
value: address, value: address.id, // Set the value as the address ID
child: Text(address), child: Text("${address.street} ${address.city} ${address.state} \n ${address.postalCode} , ${address.country}"), // Display full address
); );
}).toList(), }).toList(),
onChanged: _onShippingAddressChanged, onChanged: (value) {
_addressController.onShippingAddressChanged(value); // Update the selected address
},
), ),
)),
SizedBox(height: Get.height * 0.02), SizedBox(height: Get.height * 0.02),
DropdownButtonFormField<String>(
// Billing Address Dropdown
Obx(() => Container(
child: DropdownButtonFormField<String>(
decoration: InputDecoration( decoration: InputDecoration(
labelText: 'Billing Address:', labelText: 'Billing Address:',
hintText: 'Select Billing Address', hintText: 'Select Billing Address',
border: OutlineInputBorder(), border: OutlineInputBorder(),
), ),
value: _selectedBillingAddress, value: _addressController.selectedBillingAddressId.value.isEmpty
items: _addressList.map((String address) { ? null // Show null if there's no selection yet
: _addressController.selectedBillingAddressId.value, // Set the selected ID
items: _addressController.addressList.map((UserShippingAddress address) {
return DropdownMenuItem<String>( return DropdownMenuItem<String>(
value: address, value: address.id, // Set the value as the address ID
child: Text(address), child: Text("${address.street} ${address.city} ${address.state} \n ${address.postalCode} ${address.country}"), // Display full address
); );
}).toList(), }).toList(),
onChanged: _onBillingAddressChanged, onChanged: (value) {
_addressController.onBillingAddressChanged(value); // Update the selected address
},
), ),
)),
Padding( Padding(
padding: EdgeInsets.symmetric( padding: EdgeInsets.symmetric(
horizontal: Get.width * 0.04), horizontal: Get.width * 0.04),

View File

@ -1,4 +1,5 @@
import 'package:cheminova/controller/get_order_placed_controller.dart'; import 'package:cheminova/controller/get_order_placed_controller.dart';
import 'package:cheminova/controller/shiptobilltoController.dart';
import 'package:cheminova/models/product_model.dart'; import 'package:cheminova/models/product_model.dart';
import 'package:cheminova/utils/show_snackbar.dart'; import 'package:cheminova/utils/show_snackbar.dart';
import 'package:cheminova/widgets/my_drawer.dart'; import 'package:cheminova/widgets/my_drawer.dart';
@ -12,14 +13,18 @@ import '../../controller/cart_controller.dart';
import '../../controller/place_order_controller.dart'; import '../../controller/place_order_controller.dart';
import '../../models/oder_place_model.dart'; import '../../models/oder_place_model.dart';
import '../../models/product_model1.dart'; import '../../models/product_model1.dart';
import '../../models/shiping_billing_address_model.dart';
class OrderConfermationScreen extends StatefulWidget { class OrderConfermationScreen extends StatefulWidget {
Product? productModel; // The selected product model Product? productModel; // The selected product model
PlacedOrderModel? placedOrder; // The order details after placement PlacedOrderModel? placedOrder; // The order details after placement
List<Product>? selectedProducts; // List of selected products for the order List<Product>? selectedProducts; // List of selected products for the order
// final UserShippingAddress? shippingAddress;
// final UserShippingAddress? billingAddress;
// Constructor to initialize the class with optional parameters // Constructor to initialize the class with optional parameters
OrderConfermationScreen({super.key,this.productModel,this.placedOrder,this.selectedProducts}); OrderConfermationScreen({super.key,this.productModel,this.placedOrder,this.selectedProducts,});
@override @override
State<OrderConfermationScreen> createState() => State<OrderConfermationScreen> createState() =>
@ -30,9 +35,11 @@ class _OrderConfermationScreenState extends State<OrderConfermationScreen> {
final CartController _cartController = Get.put(CartController()); // Instance of CartController final CartController _cartController = Get.put(CartController()); // Instance of CartController
// Instance of OrderPlacedController // Instance of OrderPlacedController
final OrderPlacedController _placedController = Get.put(OrderPlacedController()); final OrderPlacedController _placedController = Get.put(OrderPlacedController());
final AddressController _addressController = Get.put(AddressController());
// Instance of GetPlacedOrderController // Instance of GetPlacedOrderController
final GetPlacedOrderController _getPlacedOrderController = Get.put(GetPlacedOrderController()); final GetPlacedOrderController _getPlacedOrderController = Get.put(GetPlacedOrderController());
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final orderItems = _placedController.placedOrder1; // Fetching the placed order details final orderItems = _placedController.placedOrder1; // Fetching the placed order details
@ -78,6 +85,7 @@ class _OrderConfermationScreenState extends State<OrderConfermationScreen> {
fit: BoxFit.cover, fit: BoxFit.cover,
), ),
SafeArea( SafeArea(
child: SingleChildScrollView(
child: Column( child: Column(
children: [ children: [
SizedBox( SizedBox(
@ -197,7 +205,13 @@ class _OrderConfermationScreenState extends State<OrderConfermationScreen> {
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: TextField( child: TextField(
controller: TextEditingController( controller: TextEditingController(
text: widget.placedOrder!.shipTo, // Pre-filling the address text:widget.placedOrder!.shipTo
// _addressController.selectedShippingAddressId != null
// ? '${widget.placedOrder?.shipTo}
// '${_addressController.addressList[0].city}, '
// '${_addressController.addressList[0].state}, '
// '${_addressController.addressList[0].postalCode}'
// : 'No address selected', // Pre-filling with full address if available // Pre-filling the address
), ),
decoration: InputDecoration( decoration: InputDecoration(
hintText: "Address : ${widget.placedOrder!.shipTo}", hintText: "Address : ${widget.placedOrder!.shipTo}",
@ -238,6 +252,7 @@ class _OrderConfermationScreenState extends State<OrderConfermationScreen> {
], ],
), ),
), ),
),
], ],
), ),
); );

View File

@ -1,5 +1,7 @@
import 'package:auto_size_text/auto_size_text.dart'; import 'package:auto_size_text/auto_size_text.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:cheminova/controller/get_order_placed_controller.dart'; import 'package:cheminova/controller/get_order_placed_controller.dart';
import 'package:cheminova/controller/shiptobilltoController.dart';
import 'package:cheminova/models/oder_place_model.dart'; import 'package:cheminova/models/oder_place_model.dart';
import 'package:cheminova/models/order_item_model.dart'; import 'package:cheminova/models/order_item_model.dart';
import 'package:cheminova/models/place_order_list_model.dart'; import 'package:cheminova/models/place_order_list_model.dart';
@ -32,6 +34,7 @@ class _OrderManagementDetailScreenState
extends State<OrderManagementDetailScreen> { extends State<OrderManagementDetailScreen> {
// Controllers for managing cart and placed orders // Controllers for managing cart and placed orders
final CartController _cartController = Get.put(CartController()); final CartController _cartController = Get.put(CartController());
final AddressController _addressController = Get.put(AddressController());
final GetPlacedOrderController _getPlacedOrderController = Get.put(GetPlacedOrderController()); final GetPlacedOrderController _getPlacedOrderController = Get.put(GetPlacedOrderController());
// Function to format date from the API to a more readable format // Function to format date from the API to a more readable format
String formatDate(String apiDate) { String formatDate(String apiDate) {
@ -70,7 +73,7 @@ Future<void> adduni()async {
.map((item) => (item.quantity)) .map((item) => (item.quantity))
.join(', '); .join(', ');
} }
//String? imageurl;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -221,6 +224,7 @@ Future<void> adduni()async {
itemCount: widget.placedOrderList?.orderItem.length ?? 0, itemCount: widget.placedOrderList?.orderItem.length ?? 0,
itemBuilder: (context, index) { itemBuilder: (context, index) {
final orderItem = widget.placedOrderList!.orderItem[index]; final orderItem = widget.placedOrderList!.orderItem[index];
final imageUrl = orderItem.image?.isNotEmpty == true ? orderItem.image![0].url : null;
return orderItem != null return orderItem != null
? Card( ? Card(
margin: const EdgeInsets.symmetric(vertical: 5.0), margin: const EdgeInsets.symmetric(vertical: 5.0),
@ -231,8 +235,26 @@ Future<void> adduni()async {
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: Row( child: Row(
children: [ children: [
Image.asset( // Image.asset(
"assets/images/product.png", // Add the image URL here // "assets/images/new_product.jpeg",
// // "assets/images/product.png", // Add the image URL here
// height: 50,
// width: 50,
// fit: BoxFit.cover,
// ),
imageUrl != null && imageUrl.isNotEmpty && imageUrl.startsWith('http') // Check if it's a network URL/ Check if it's a network URL
? CachedNetworkImage(
imageUrl: imageUrl,
height: 50,
width: 50,
fit: BoxFit.cover,
placeholder: (context, url) => const CircularProgressIndicator(), // Optional placeholder
errorWidget: (context, url, error) => const Icon(Icons.error), // Optional error widget
)
: Image.asset(
// imageUrl!,
'assets/images/no_image_available.jpg', // Placeholder image when URL is empty
height: 50, height: 50,
width: 50, width: 50,
fit: BoxFit.cover, fit: BoxFit.cover,
@ -289,11 +311,12 @@ Future<void> adduni()async {
), ),
SizedBox( SizedBox(
width: Get.width, width: Get.width,
height: Get.height*0.06, height: Get.height * 0.10,
child: Padding( child: Padding(
padding: padding: const EdgeInsets.fromLTRB(8, 8, 8, 0),
const EdgeInsets.fromLTRB(8, 8, 8, 0), child: Wrap( // Use Wrap to allow wrapping
child: Row( crossAxisAlignment: WrapCrossAlignment.start,
direction: Axis.horizontal,
children: [ children: [
Text( Text(
"Address: ", "Address: ",
@ -302,13 +325,23 @@ Future<void> adduni()async {
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
), ),
AutoSizeText("${widget.placedOrderList!.shipTo}",maxLines: 4, Text(
overflow:TextOverflow.ellipsis,) "${widget.placedOrderList!.shipTo.toString()}",
// Text(
// "${widget.placedOrderList!.shipTo}",
maxLines: 4,
overflow: TextOverflow.ellipsis,
style: GoogleFonts.roboto(
fontSize: Get.width * 0.04,
),
),
], ],
), ),
), ),
), ),
], ],
), ),
), ),

View File

@ -1,3 +1,5 @@
import 'dart:async';
import 'package:cheminova/models/place_order_list_model.dart'; import 'package:cheminova/models/place_order_list_model.dart';
import 'package:cheminova/screens/order_management/order_management_detail_screen.dart'; import 'package:cheminova/screens/order_management/order_management_detail_screen.dart';
import 'package:cheminova/widgets/input_field.dart'; import 'package:cheminova/widgets/input_field.dart';
@ -57,6 +59,11 @@ class _OrderManagementScreenState extends State<OrderManagementScreen> {
return formattedDate; return formattedDate;
} }
Future<void> searchOrder(String query) async {
{
_getPlacedOrderController.searchOrder();
}
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
@ -108,7 +115,11 @@ class _OrderManagementScreenState extends State<OrderManagementScreen> {
InputField( InputField(
hintText: "Search Order", hintText: "Search Order",
labelText: "Search Order", labelText: "Search Order",
controller: _searchController, controller: _searchController,
onChanged: (value) {
searchOrder(value);// Call search function with input value
},
), ),
SizedBox(height: Get.height * 0.035), SizedBox(height: Get.height * 0.035),
Card( Card(

View File

@ -123,7 +123,8 @@ class _CartScreenState extends State<CartScreen> {
), ),
); );
} }
return Column( return SingleChildScrollView(
child: Column(
children: [ children: [
SizedBox( SizedBox(
height: Get.height * 0.02, height: Get.height * 0.02,
@ -141,21 +142,21 @@ class _CartScreenState extends State<CartScreen> {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
// "Select All" Checkbox // "Select All" Checkbox
Row( // Row(
children: [ // children: [
Checkbox( // Checkbox(
value: _selectAll, // value: _selectAll,
onChanged: _toggleSelectAll, // onChanged: _toggleSelectAll,
), // ),
Text( // Text(
"Select All", // Label for the select all checkbox // "Select All", // Label for the select all checkbox
style: GoogleFonts.roboto( // style: GoogleFonts.roboto(
fontSize: 16, // fontSize: 16,
fontWeight: FontWeight.w500, // fontWeight: FontWeight.w500,
), // ),
), // ),
], // ],
), // ),
SizedBox( SizedBox(
height: Get.height * 0.6, height: Get.height * 0.6,
child: ListView.builder( child: ListView.builder(
@ -164,17 +165,17 @@ class _CartScreenState extends State<CartScreen> {
itemBuilder: (context, index) { itemBuilder: (context, index) {
return Row( return Row(
children: [ children: [
Checkbox( // Checkbox(
value: _cartController.selectedProducts.contains( // value: _cartController.selectedProducts.contains(
_cartController.cartList[index]), // Checkbox for individual product selection // _cartController.cartList[index]), // Checkbox for individual product selection
onChanged: (value) { // onChanged: (value) {
_cartController.toggleProductSelection( // _cartController.toggleProductSelection(
_cartController.cartList[index], // _cartController.cartList[index],
value!, // value!,
); // );
_checkIfAllSelected(); // Check if all are selected after each toggle // _checkIfAllSelected(); // Check if all are selected after each toggle
}, // },
), // ),
Expanded( Expanded(
child: ProductCard( child: ProductCard(
productModel: productModel:
@ -263,6 +264,7 @@ class _CartScreenState extends State<CartScreen> {
), ),
), ),
], ],
),
); );
}), }),
), ),

View File

@ -248,6 +248,19 @@ class _ProductCatalogScreenState extends State<ProductCatalogScreen> {
_buildFilterDropdown(index), _buildFilterDropdown(index),
), ),
), ),
SizedBox(
// height: Get.height * 0.1,
child:_products.isEmpty // Check if no products found
? Center(
child: Padding(
padding: const EdgeInsets.all(40.0),
child: Text(
"No products found!",
style: TextStyle(fontSize: 16),
),
),
) : SizedBox(),
),
SizedBox( SizedBox(
height: Get.height * 0.6, height: Get.height * 0.6,
child: ListView.builder( child: ListView.builder(
@ -272,6 +285,7 @@ class _ProductCatalogScreenState extends State<ProductCatalogScreen> {
}, },
), ),
), ),
], ],
), ),
), ),

View File

@ -1,3 +1,4 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:cheminova/models/product_model.dart'; import 'package:cheminova/models/product_model.dart';
import 'package:cheminova/models/product_model1.dart'; import 'package:cheminova/models/product_model1.dart';
import 'package:cheminova/screens/order/checkout_screen.dart'; import 'package:cheminova/screens/order/checkout_screen.dart';
@ -24,6 +25,7 @@ class ProductDetailScreen extends StatefulWidget {
class _ProductDetailScreenState extends State<ProductDetailScreen> { class _ProductDetailScreenState extends State<ProductDetailScreen> {
final CartController _cartController = Get.put(CartController());// Initialize CartController final CartController _cartController = Get.put(CartController());// Initialize CartController
String? imageurl;
// Function to capitalize the first letter of a string // Function to capitalize the first letter of a string
String capitalizeFirstLetter(String text) { String capitalizeFirstLetter(String text) {
if (text.isEmpty) return text; if (text.isEmpty) return text;
@ -31,6 +33,9 @@ class _ProductDetailScreenState extends State<ProductDetailScreen> {
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
imageurl = widget.productModel!.brand.images.isNotEmpty
? widget.productModel!.brand.images[0].url
: 'assets/images/no_image_available.jpg'; // Use a fallback image URL or handle it accordingly
return Scaffold( return Scaffold(
extendBodyBehindAppBar: true, extendBodyBehindAppBar: true,
appBar: AppBar( appBar: AppBar(
@ -105,13 +110,21 @@ class _ProductDetailScreenState extends State<ProductDetailScreen> {
), ),
borderRadius: BorderRadius.circular(15), borderRadius: BorderRadius.circular(15),
), ),
child: ClipRRect( child:
ClipRRect(
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
child: Image.asset("assets/images/product.png", fit: BoxFit.cover,), child:
// Image.asset( imageurl!.startsWith('http') // Check if it's a network URL
// widget.product.image, ? CachedNetworkImage(
// fit: BoxFit.cover, imageUrl: imageurl!,
// ), fit: BoxFit.cover,
placeholder: (context, url) => const CircularProgressIndicator(), // Optional placeholder
errorWidget: (context, url, error) => const Icon(Icons.error), // Optional error widget
)
: Image.asset(
imageurl!,
fit: BoxFit.cover,
),
), ),
), ),
), ),

View File

@ -122,6 +122,11 @@ class _PartialPendingDialogScreenState extends State<PartialPendingDialogScreen>
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final order = widget.placedOrderList!.orderItem[0];
final subTotalProcesssItem = order.price! * order.remainingQuantity!.toInt();
final GstTotalAmounProcessItem = (order.price! * order.remainingQuantity!.toInt()) *(order.gst!/100 );
final grandTotalProcessItem = subTotalProcesssItem + GstTotalAmounProcessItem;
return Scaffold( return Scaffold(
extendBodyBehindAppBar: true, extendBodyBehindAppBar: true,
appBar: AppBar( appBar: AppBar(
@ -205,7 +210,7 @@ class _PartialPendingDialogScreenState extends State<PartialPendingDialogScreen>
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
), ),
Text("${widget.placedOrderList!.subtotal ?? 0}"), Text("${subTotalProcesssItem}"),
], ],
), ),
Row( Row(
@ -219,7 +224,7 @@ class _PartialPendingDialogScreenState extends State<PartialPendingDialogScreen>
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
), ),
Text("${widget.placedOrderList!.gstTotal ?? 0}"), Text("${GstTotalAmounProcessItem.toStringAsFixed(2)}"),
], ],
), ),
Row( Row(
@ -233,7 +238,7 @@ class _PartialPendingDialogScreenState extends State<PartialPendingDialogScreen>
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
), ),
Text("${widget.placedOrderList!.grandTotal ?? 0}"), Text("${grandTotalProcessItem}"),
], ],
), ),
], ],

View File

@ -359,8 +359,6 @@ class _PartialProcessingDialogScreenState extends State<PartialProcessingDialogS
await controller.placeRDOrder(); await controller.placeRDOrder();
showSnackbar("Partial order processed successfully."); showSnackbar("Partial order processed successfully.");
// Close the dialog before navigating to another screen
Navigator.of(context).pop();
// Navigate to the pending screen // Navigate to the pending screen
Get.to(RdOrderPendingScreen()); Get.to(RdOrderPendingScreen());
@ -370,7 +368,7 @@ class _PartialProcessingDialogScreenState extends State<PartialProcessingDialogS
TextButton( TextButton(
onPressed: () { onPressed: () {
//Get.back(); //Get.back();
Navigator.of(context).pop(); Navigator.pop(context);
}, },
child: const Text("Cancel"), child: const Text("Cancel"),
), ),
@ -382,6 +380,10 @@ class _PartialProcessingDialogScreenState extends State<PartialProcessingDialogS
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final order = widget.placedOrderList!.orderItem[0];
final subTotalProcesssItem = order.price! * order.remainingQuantity!.toInt();
final GstTotalAmounProcessItem = (order.price! * order.remainingQuantity!.toInt()) *(order.gst!/100 );
final grandTotalProcessItem = subTotalProcesssItem + GstTotalAmounProcessItem;
return Scaffold( return Scaffold(
extendBodyBehindAppBar: true, extendBodyBehindAppBar: true,
appBar: AppBar( appBar: AppBar(
@ -470,7 +472,7 @@ class _PartialProcessingDialogScreenState extends State<PartialProcessingDialogS
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
), ),
Text("${widget.placedOrderList!.subtotal ?? 0}"), Text("${subTotalProcesssItem}"),
], ],
), ),
Row( Row(
@ -484,7 +486,7 @@ class _PartialProcessingDialogScreenState extends State<PartialProcessingDialogS
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
), ),
Text("${widget.placedOrderList!.gstTotal ?? 0}"), Text("${widget.placedOrderList!.gstTotal.toStringAsFixed(2) ?? 0}"),
], ],
), ),
Row( Row(

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +1,16 @@
import 'package:cheminova/controller/get_rd_cancle_controller.dart';
import 'package:cheminova/controller/get_rd_pending_controller.dart';
import 'package:cheminova/controller/rd_get_order_controller.dart'; import 'package:cheminova/controller/rd_get_order_controller.dart';
import 'package:cheminova/controller/rd_processing_invoice_controller.dart';
import 'package:cheminova/models/get_rd_cancelled_model.dart'; import 'package:cheminova/models/get_rd_cancelled_model.dart';
import 'package:cheminova/models/get_rd_pennding_model.dart';
import 'package:cheminova/models/rd_get_order_model.dart'; import 'package:cheminova/models/rd_get_order_model.dart';
import 'package:cheminova/models/single_get_order_model.dart'; import 'package:cheminova/models/single_get_order_model.dart';
import 'package:cheminova/screens/rd%20orders/rd_cancelled_details_screen.dart'; import 'package:cheminova/screens/rd%20orders/rd_cancelled_details_screen.dart';
import 'package:cheminova/screens/rd%20orders/rd_dispatched_details_screen.dart';
import 'package:cheminova/screens/rd%20orders/rd_order_details_screen.dart'; import 'package:cheminova/screens/rd%20orders/rd_order_details_screen.dart';
import 'package:cheminova/screens/rd%20orders/rd_order_details_update.dart';
import 'package:cheminova/screens/rd%20orders/rd_pending_deatils.dart'; import 'package:cheminova/screens/rd%20orders/rd_pending_deatils.dart';
import 'package:cheminova/screens/rd%20orders/rd_processing_details.dart';
import 'package:cheminova/widgets/input_field.dart'; import 'package:cheminova/widgets/input_field.dart';
import 'package:cheminova/widgets/my_drawer.dart'; import 'package:cheminova/widgets/my_drawer.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -15,12 +18,15 @@ import 'package:flutter_svg/svg.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../../controller/get_rd_cancle_controller.dart'; import '../../controller/get_single_invoice_Service.dart';
import '../../controller/get_single_invoice_controller.dart';
import '../../controller/rd_get_single_service.dart';
import '../order_management/order_management_detail_screen.dart'; import '../order_management/order_management_detail_screen.dart';
class RdCancelledScreen extends StatefulWidget { class RdCancelledScreen extends StatefulWidget {
final PlacedOrdersResponse? getrdProduct; final GetRdCancelledModel? getrdProduct;
RdCancelledScreen({super.key, this.getrdProduct}); RdCancelledScreen({super.key, this.getrdProduct});
@ -37,7 +43,11 @@ class _RdCancelledScreenState extends State<RdCancelledScreen> {
"cancelled", "cancelled",
"delivered",]; "delivered",];
int _selectedIndex = 0; int _selectedIndex = 0;
final GetRDCancleController _getRdProductController = Get.put(GetRDCancleController()); final GetRDCancleController _getRDCancleController = Get.put(GetRDCancleController());
// final GetSingleInvoiceController _getSingleInvoiceController = Get.put(GetSingleInvoiceController());
// final GetRDProcessingInvoiceController _getRDProcessingInvoiceController = Get.put(GetRDProcessingInvoiceController());
// // final GetProductRDController _getRdProductController =
// // Get.put(GetProductRDController());
final GlobalKey<RefreshIndicatorState> _refreshIndicatorKey = GlobalKey<RefreshIndicatorState>(); final GlobalKey<RefreshIndicatorState> _refreshIndicatorKey = GlobalKey<RefreshIndicatorState>();
@override @override
@ -49,11 +59,12 @@ class _RdCancelledScreenState extends State<RdCancelledScreen> {
Future<void> _onRefresh() async { Future<void> _onRefresh() async {
await getOrder1(); await getOrder1();
await Future.delayed(Duration(seconds: 1)); await Future.delayed(Duration(seconds: 1));
} }
Future<void> getOrder1() async { Future<void> getOrder1() async {
await _getRdProductController.getRDCancleProduct(); await _getRDCancleController.getRDCancleProduct();
if (_getRdProductController.productRDList.isEmpty) { if (_getRDCancleController.productRDList.isEmpty) {
print("No orders found."); print("No orders found.");
} else { } else {
print("Orders fetched successfully"); print("Orders fetched successfully");
@ -70,11 +81,133 @@ class _RdCancelledScreenState extends State<RdCancelledScreen> {
DateTime parsedDate = DateTime.parse(apiDate).toLocal(); // Convert to local time DateTime parsedDate = DateTime.parse(apiDate).toLocal(); // Convert to local time
// Format the date and time according to your specified format // Format the date and time according to your specified format
String formattedDate = DateFormat('EEE MMM dd yyyy').format(parsedDate); String formattedDate = DateFormat('EEE MMM dd yyyy hh:mm a').format(parsedDate);
return formattedDate; // Return the formatted date string return formattedDate; // Return the formatted date string
} }
void onOrderTap(int index) async {
try {
// Fetch orders and ensure you wait for it to complete
await _getRDCancleController.getRDCancleProduct();
// Log the count of fetched orders
print('Fetched orders count: ${_getRDCancleController.productRDList.length}');
// Check if the productRDList is populated
if (_getRDCancleController.productRDList.isNotEmpty) {
// Ensure the index is valid
if (index >= 0 && index < _getRDCancleController.productRDList.length) {
// Get the order ID from the list based on the index
final orderId = _getRDCancleController.productRDList[index].id;
// final invoiceId = _getRDCancleController.productRDList[index].invoices;
print("orderId canceeled,$orderId");
// Retrieve the token from SharedPreferences
SharedPreferences prefs = await SharedPreferences.getInstance();
String? token = prefs.getString('token');
// Check if the token is not null
if (token != null) {
// Fetch the single order using the order ID
final SingleGetOrderModel? singleOrder = await GetSingleProductService().getSingleOrder(token, orderId);
// Check if the single order was fetched successfully
if (singleOrder != null) {
// Navigate to the details screen with the fetched order
Get.to(() => RdOrderCancelledScreenDetailScreen(
placedOrderList: singleOrder, // Pass the single order instance
//orderId: orderId,
));
} else {
// Handle the case where the single order could not be fetched
Get.snackbar("Error", "Unable to fetch order details.");
}
} else {
// Handle the case where the token is null
Get.snackbar("Error", "User not authenticated.");
}
} else {
// Handle the case when the index is out of bounds
Get.snackbar("Error", "Invalid order selection.");
}
} else {
// Handle the case when the list is empty
Get.snackbar("Error", "No orders available to display.");
}
} catch (e) {
// Log any errors that occur during the process
print('Error in onOrderTap: $e');
Get.snackbar("Error", "An unexpected error occurred.");
}
}
// void onOrderTap(int index) async {
// try {
// // Fetch orders and wait for it to complete
// await _getRDCancleController.getRDCancleProduct();
//
// // Debugging: Check if data is actually fetched
// print('Fetched orders count: ${_getRDCancleController.productRDList.length}');
//
// // Ensure the list is not empty after fetching
// if (_getRDCancleController.productRDList.isEmpty) {
// Get.snackbar("Error", "No orders available to display.");
// return;
// }
//
// // Ensure index is within range
// if (index < 0 || index >= _getRDCancleController.productRDList.length) {
// Get.snackbar("Error", "Invalid order selection.");
// return;
// }
//
// // Retrieve order details
// final order = _getRDCancleController.productRDList[index].id;
// // final invoice = _getRDCancleController.productRDList[index].invoices[index];
// // Ensure invoices are available
// if (order.isEmpty) {
// Get.snackbar("Error", "No invoice found for this order.");
// return;
// }
//
// final orderId = order;
// //final invoiceId = invoice;
//
// print("Cancelled Order ID: $orderId");
//
// // Retrieve token
// SharedPreferences prefs = await SharedPreferences.getInstance();
// String? token = prefs.getString('token');
//
// if (token == null) {
// Get.snackbar("Error", "User not authenticated.");
// return;
// }
//
// // Fetch single order details
// final SingleGetOrderModel? singleOrder =
// await GetSingleProductService().getSingleOrder(token, orderId);
//
// if (singleOrder == null) {
// Get.snackbar("Error", "Unable to fetch order details.");
// return;
// }
//
// // Navigate to details screen
// await Get.to(() => RdOrderCancelledScreenDetailScreen(
// placedOrderList: singleOrder, // Pass fetched order
// orderId: orderId,
// ));
// } catch (e) {
// print('Error in onOrderTap: $e');
// Get.snackbar("Error", "An unexpected error occurred.");
// }
// }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
@ -103,7 +236,7 @@ class _RdCancelledScreenState extends State<RdCancelledScreen> {
), ),
), ),
], ],
title: const Text("RD Cancelled Order"), title: const Text("Retailer Cancelled Order"),
), ),
drawer: MyDrawer(), drawer: MyDrawer(),
body: Stack( body: Stack(
@ -128,6 +261,7 @@ class _RdCancelledScreenState extends State<RdCancelledScreen> {
controller: _searchController, controller: _searchController,
), ),
SizedBox(height: Get.height * 0.035), SizedBox(height: Get.height * 0.035),
SizedBox(height: Get.height * 0.035),
Card( Card(
margin: const EdgeInsets.symmetric(horizontal: 18), margin: const EdgeInsets.symmetric(horizontal: 18),
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
@ -140,63 +274,11 @@ class _RdCancelledScreenState extends State<RdCancelledScreen> {
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ 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: GestureDetector(
// onTap: () {
// setState(() {
// _selectedIndex = index; // Update selected index
// });
// // Navigate to different screens based on selected tab
// switch (_filterList[index]) {
// case "new":
// // Get.to(YourScreen1()); // Navigate to "new" orders screen
// break;
// case "pending":
// // Get.to(YourScreen2()); // Navigate to "pending" orders screen
// break;
// case "processing":
// // Get.to(YourScreen3()); // Navigate to "processing" orders screen
// break;
// // Add more cases for other statuses
// case "dispatched":
// // Get.to(YourScreen4()); // Navigate to dispatched orders
// break;
// case "cancelled":
// // Get.to(YourScreen5()); // Navigate to cancelled orders
// break;
// case "delivered":
// //Get.to(YourScreen6()); // Navigate to delivered orders
// break;
// default:
// // Get.to(YourScreen1()); // Default screen
// }
// },
// child: Chip(
// label: Text(capitalizeFirstLetter( _filterList[index])
// ,
// style: GoogleFonts.roboto(
// fontSize: 14,
// fontWeight: FontWeight.w500,
// color: _selectedIndex == index ? Colors.white : Colors.black, // Change color when selected
// ),
// ),
// backgroundColor: _selectedIndex == index ? Colors.blue : Colors.grey[300], // Change color when selected
// ),
// ),
// ),
// ),
// ),
SizedBox( SizedBox(
height: Get.height * 0.6, height: Get.height * 0.6,
child: Obx(() { child: Obx(() {
if (_getRdProductController.productRDList.isEmpty) { if (_getRDCancleController.productRDList.isEmpty) {
return Center( return Center(
child: Text( child: Text(
'No Orders Found', 'No Orders Found',
@ -208,7 +290,7 @@ class _RdCancelledScreenState extends State<RdCancelledScreen> {
final Set<String> uniqueOrderIds = {}; final Set<String> uniqueOrderIds = {};
final List<GetRdCancelledModel> uniqueOrders = []; final List<GetRdCancelledModel> uniqueOrders = [];
for (var order in _getRdProductController.productRDList) { for (var order in _getRDCancleController.productRDList) {
if (uniqueOrderIds.add(order.id)) { if (uniqueOrderIds.add(order.id)) {
uniqueOrders.add(order); uniqueOrders.add(order);
} }
@ -282,7 +364,16 @@ class _RdCancelledScreenState extends State<RdCancelledScreen> {
], ],
), ),
), ),
Padding(
padding: const EdgeInsets.fromLTRB(16, 8, 8, 0),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text("Order Value: ", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.bold)),
Text("${order.grandTotal}")
],
),
),
Padding( Padding(
padding: const EdgeInsets.fromLTRB(16, 8, 8, 0), padding: const EdgeInsets.fromLTRB(16, 8, 8, 0),
@ -310,10 +401,12 @@ class _RdCancelledScreenState extends State<RdCancelledScreen> {
child: Padding( child: Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: ElevatedButton( child: ElevatedButton(
onPressed: ()=> onPressed: (){
Get.to(() => onOrderTap(index);
RdCancelledDetailScreen( },
placedOrderList: uniqueOrders[index])), // Navigate to detail screen // Get.to(() =>
// RdOrderPendingScreenDetailScreen(
// placedOrderList: uniqueOrders[index])), // Navigate to detail screen
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
foregroundColor: Colors.white, foregroundColor: Colors.white,
backgroundColor: const Color(0xFF004791), backgroundColor: const Color(0xFF004791),
@ -348,3 +441,5 @@ class _RdCancelledScreenState extends State<RdCancelledScreen> {
} }
} }

View File

@ -150,7 +150,7 @@ class _RdDeliveredDetailsScreenState
), ),
], ],
title: const Text( title: const Text(
"RD Delivered Order Details", "Retailer Delivered Order Details",
), ),
), ),
body: Stack( body: Stack(
@ -298,7 +298,7 @@ class _RdDeliveredDetailsScreenState
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
), ),
Text("${widget.placedOrderList!.gstTotal}"), Text("${widget.placedOrderList!.gstTotal.toStringAsFixed(2)}"),
], ],
), ),
), ),

View File

@ -163,7 +163,7 @@ class _RdDeliveredScreenState extends State<RdDeliveredScreen> {
), ),
), ),
], ],
title: const Text("RD Delivered Order"), title: const Text("Retailer Delivered Order"),
), ),
drawer: MyDrawer(), drawer: MyDrawer(),
body: Stack( body: Stack(

View File

@ -198,7 +198,10 @@ class _RdDispatchedDetailsDetailScreenState
SnackBar(content: Text('Please select a delivery date.')), SnackBar(content: Text('Please select a delivery date.')),
); );
} }
Navigator.of(context).pop(); // Close the dialog after submission Navigator.push(context, MaterialPageRoute(builder: (context){
return RdDeliveredScreen();
}));
// Navigator.of(context).pop(); // Close the dialog after submission
}, },
child: Text('Confirm'), child: Text('Confirm'),
), ),
@ -312,7 +315,7 @@ class _RdDispatchedDetailsDetailScreenState
), ),
], ],
title: const Text( title: const Text(
"RD Dispatched Order Details", "Retailer Dispatched Order Details",
), ),
), ),
body: Stack( body: Stack(
@ -459,7 +462,7 @@ class _RdDispatchedDetailsDetailScreenState
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
), ),
Text("${widget.placedOrderList!.gstTotal}"), Text("${widget.placedOrderList!.gstTotal.toStringAsFixed(2)}"),
], ],
), ),
), ),

View File

@ -172,7 +172,7 @@ class _RdDispatchedScreenState extends State<RdDispatchedScreen> {
), ),
), ),
], ],
title: const Text("RD Dispatched Order"), title: const Text("Retailer Dispatched Order"),
), ),
drawer: MyDrawer(), drawer: MyDrawer(),
body: Stack( body: Stack(

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,5 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:cheminova/controller/rd_single_order_controller.dart'; import 'package:cheminova/controller/rd_single_order_controller.dart';
import 'package:cheminova/models/rd_order_item_model.dart'; import 'package:cheminova/models/rd_order_item_model.dart';
@ -26,12 +27,14 @@ class RdOrderDetailUpdateScreen extends StatefulWidget {
//final Product? productModel; //final Product? productModel;
// PlacedOrderList and PlacedOrderModel are optional parameters passed to this screen // PlacedOrderList and PlacedOrderModel are optional parameters passed to this screen
SingleGetOrderModel? placedOrderList; SingleGetOrderModel? placedOrderList;
final String orderId; //final String orderId;
//final int orderIndex; // New parameter to receive the index //final int orderIndex; // New parameter to receive the index
// PlacedOrderModel? placedOrderModel; // PlacedOrderModel? placedOrderModel;
// Constructor for initializing the screen with placed order details // Constructor for initializing the screen with placed order details
RdOrderDetailUpdateScreen({super.key,this.placedOrderList,required this.orderId}); RdOrderDetailUpdateScreen({super.key,this.placedOrderList,
//required this.orderId
});
@override @override
State<RdOrderDetailUpdateScreen> createState() => State<RdOrderDetailUpdateScreen> createState() =>
@ -46,6 +49,7 @@ class _RdOrderDetailUpdateScreenState
final RdSingleOrderController _getPlacedOrderController = Get.put(RdSingleOrderController()); final RdSingleOrderController _getPlacedOrderController = Get.put(RdSingleOrderController());
final GetProductRDController _getProductRDController = Get.put(GetProductRDController()); final GetProductRDController _getProductRDController = Get.put(GetProductRDController());
final RDOrderPlacedController controller = Get.put(RDOrderPlacedController()); final RDOrderPlacedController controller = Get.put(RDOrderPlacedController());
bool isDialogClosed = false; // Flag to track if dialog is already closed
String? orderId; String? orderId;
@ -226,6 +230,9 @@ class _RdOrderDetailUpdateScreenState
actions: [ actions: [
TextButton( TextButton(
onPressed: () async { onPressed: () async {
if (isDialogClosed) return; // Prevent reopening the dialog
isDialogClosed = true; // Mark dialog as closed
if (selectedStatus == "cancelled") { if (selectedStatus == "cancelled") {
// Ensure the reason is provided for cancellation // Ensure the reason is provided for cancellation
if (reasonController.text.isEmpty) { if (reasonController.text.isEmpty) {
@ -245,9 +252,9 @@ class _RdOrderDetailUpdateScreenState
}); });
// Close the dialog after a short delay // Close the dialog after a short delay
Future.delayed(Duration(seconds: 1), () { // Future.delayed(Duration(seconds: 1), () {
// Navigator.of(context).pop(); // Close the dialog // // Navigator.of(context).pop(); // Close the dialog
}); // });
return; // Exit here to prevent further processing return; // Exit here to prevent further processing
} }
@ -262,31 +269,33 @@ class _RdOrderDetailUpdateScreenState
Map<String, RDOrderItem> orderItemMap = {}; Map<String, RDOrderItem> orderItemMap = {};
// Populate the map with items and their quantities // Populate the map with items and their quantities
for (var item in _getProductRDController.productRDList) { for (var item in widget.placedOrderList!.orderItem) {
var productId = item.orderItem[0].productId; var productId = item.productId;
if (orderItemMap.containsKey(productId)) { if (orderItemMap.containsKey(productId)) {
// If the product already exists, aggregate the quantity // If the product already exists, aggregate the quantity
var existingItem = orderItemMap[productId]!; var existingItem = orderItemMap[productId]!;
existingItem.quantity = (existingItem.quantity ?? 0) + (item.orderItem[0].quantity ?? 0); // var existingItem = orderItemMap[productId]!;
existingItem.remainingQuantity = (existingItem.remainingQuantity ?? 0) + (item.orderItem[0].remainingQuantity ?? 0); existingItem.quantity = ((existingItem.quantity ?? 0) + (item.quantity ?? 0));
existingItem.processquantity = (existingItem.processquantity ?? 0) + (item.orderItem[0].processquantity ?? 0); // existingItem.quantity = (existingItem.quantity ?? 0) + (item.orderItem[0].quantity ?? 0);
// existingItem.remainingQuantity = (existingItem.remainingQuantity ?? 0) + (item.orderItem[0].remainingQuantity ?? 0);
// existingItem.processquantity = (existingItem.processquantity ?? 0) + (item.orderItem[0].processquantity ?? 0);
} else { } else {
// If it's a new product, add it to the map // If it's a new product, add it to the map
orderItemMap[productId] = RDOrderItem( orderItemMap[productId] = RDOrderItem(
productId: productId, productId: productId,
sku: item.orderItem[0].sku, sku: item.sku,
name: item.orderItem[0].name, name: item.name,
categoryName: item.orderItem[0].categoryName, categoryName: item.categoryName,
brandName: item.orderItem[0].brandName, brandName: item.brandName,
price: item.orderItem[0].price, price: item.price,
gst: item.orderItem[0].gst.toInt(), gst: item.gst.toInt(),
hsnCode: item.orderItem[0].hsnCode, hsnCode: item.hsnCode,
description: item.orderItem[0].description, description: item.description,
image: [], // Handle images appropriately image: [], // Handle images appropriately
quantity: item.orderItem[0].quantity ?? 0, quantity: item.quantity ?? 0,
remainingQuantity: item.orderItem[0].remainingQuantity ?? 0, remainingQuantity: item.remainingQuantity ?? 0,
processquantity: item.orderItem[0].processquantity ?? 0, processquantity: item.remainingQuantity ?? 0,
); );
} }
} }
@ -309,7 +318,7 @@ class _RdOrderDetailUpdateScreenState
showSnackbar("Order processed and invoice created successfully"); showSnackbar("Order processed and invoice created successfully");
Get.to(RdOrderProcessingScreen()); Get.to(RdOrderProcessingScreen());
Navigator.of(context).pop(); // Navigator.of(context).pop();
// Close the dialog after a short delay // Close the dialog after a short delay
// Close the dialog // Close the dialog
@ -440,7 +449,7 @@ class _RdOrderDetailUpdateScreenState
_buildRow("Order Date:", formatDate("${widget.placedOrderList!.createdAt}"), Get.width * 0.04), _buildRow("Order Date:", formatDate("${widget.placedOrderList!.createdAt}"), Get.width * 0.04),
_buildRow("Total Items:", "${widget.placedOrderList!.orderItem!.length}", Get.width * 0.04), _buildRow("Total Items:", "${widget.placedOrderList!.orderItem!.length}", Get.width * 0.04),
_buildRow("Sub Total:", "${widget.placedOrderList!.subtotal}", Get.width * 0.04), _buildRow("Sub Total:", "${widget.placedOrderList!.subtotal}", Get.width * 0.04),
_buildRow("GST:", "${widget.placedOrderList!.gstTotal}", Get.width * 0.04), _buildRow("GST:", "${widget.placedOrderList!.gstTotal.toStringAsFixed(2)}", Get.width * 0.04),
_buildRow("Total Amount:", "${widget.placedOrderList!.grandTotal}", Get.width * 0.04), _buildRow("Total Amount:", "${widget.placedOrderList!.grandTotal}", Get.width * 0.04),
], ],
), ),
@ -458,6 +467,7 @@ class _RdOrderDetailUpdateScreenState
itemCount: widget.placedOrderList!.orderItem!.length ?? 0, itemCount: widget.placedOrderList!.orderItem!.length ?? 0,
itemBuilder: (context, index) { itemBuilder: (context, index) {
final orderItem = widget.placedOrderList!.orderItem![index]; final orderItem = widget.placedOrderList!.orderItem![index];
final imageUrl = orderItem.image?.isNotEmpty == true ? orderItem.image![0].url : null;
final subTotalProcesssItem = orderItem.price! * orderItem.quantity!.toInt(); final subTotalProcesssItem = orderItem.price! * orderItem.quantity!.toInt();
final GstTotalAmounProcessItem = (orderItem.price! * orderItem.quantity!.toInt()) *(orderItem.gst!/100 ); final GstTotalAmounProcessItem = (orderItem.price! * orderItem.quantity!.toInt()) *(orderItem.gst!/100 );
final grandTotalProcessItem = subTotalProcesssItem + GstTotalAmounProcessItem; final grandTotalProcessItem = subTotalProcesssItem + GstTotalAmounProcessItem;
@ -471,8 +481,27 @@ class _RdOrderDetailUpdateScreenState
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: Row( child: Row(
children: [ children: [
Image.asset( // Image.asset(
"assets/images/product.png", // "assets/images/new_product.jpeg",
// // "assets/images/product.png",
// height: 50,
// width: 50,
// fit: BoxFit.cover,
// ),
imageUrl != null && imageUrl.isNotEmpty && imageUrl.startsWith('http') // Check if it's a network URL/ Check if it's a network URL
? CachedNetworkImage(
imageUrl: imageUrl,
height: 50,
width: 50,
fit: BoxFit.cover,
placeholder: (context, url) => const CircularProgressIndicator(), // Optional placeholder
errorWidget: (context, url, error) => const Icon(Icons.error), // Optional error widget
)
: Image.asset(
//imageUrl!,
'assets/images/no_image_available.jpg', // Placeholder image when URL is empty
height: 50, height: 50,
width: 50, width: 50,
fit: BoxFit.cover, fit: BoxFit.cover,
@ -498,7 +527,7 @@ class _RdOrderDetailUpdateScreenState
Text("Price: ${orderItem.price}"), Text("Price: ${orderItem.price}"),
Text("Subtotal : ${subTotalProcesssItem}"), Text("Subtotal : ${subTotalProcesssItem}"),
Text("GST : ${orderItem.gst}%"), Text("GST : ${orderItem.gst}%"),
Text("GST Amount (₹) : ${GstTotalAmounProcessItem}"), Text("GST Amount (₹) : ${GstTotalAmounProcessItem.toStringAsFixed(2)}"),
Text("Total Amount : ${grandTotalProcessItem}"), Text("Total Amount : ${grandTotalProcessItem}"),
], ],
), ),

View File

@ -165,7 +165,7 @@ class _RdOrderScreenState extends State<RdOrderScreen> {
// Navigate to the details screen with the fetched order // Navigate to the details screen with the fetched order
Get.to(() => RdOrderDetailUpdateScreen( Get.to(() => RdOrderDetailUpdateScreen(
placedOrderList: singleOrder, placedOrderList: singleOrder,
orderId: orderId, // orderId: orderId,
)); ));
} else { } else {
// Handle the case where the single order could not be fetched // Handle the case where the single order could not be fetched
@ -224,7 +224,7 @@ class _RdOrderScreenState extends State<RdOrderScreen> {
), ),
), ),
], ],
title: const Text("RD Order"), title: const Text("Retailer Order"),
), ),
drawer: MyDrawer(), drawer: MyDrawer(),
body: Stack( body: Stack(

View File

@ -1,4 +1,5 @@
import 'package:auto_size_text/auto_size_text.dart'; import 'package:auto_size_text/auto_size_text.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:cheminova/controller/get_order_placed_controller.dart'; import 'package:cheminova/controller/get_order_placed_controller.dart';
import 'package:cheminova/controller/get_rd_pending_controller.dart'; import 'package:cheminova/controller/get_rd_pending_controller.dart';
import 'package:cheminova/controller/rd_get_order_controller.dart'; import 'package:cheminova/controller/rd_get_order_controller.dart';
@ -24,6 +25,7 @@ import 'package:shared_preferences/shared_preferences.dart';
import '../../controller/cart_controller.dart'; import '../../controller/cart_controller.dart';
import '../../controller/get_single_invoice_controller.dart'; import '../../controller/get_single_invoice_controller.dart';
import '../../controller/rd_processing_order_controller.dart'; import '../../controller/rd_processing_order_controller.dart';
import '../../controller/rd_single_order_controller.dart';
import '../../models/get_invoice_model.dart'; import '../../models/get_invoice_model.dart';
import '../../models/product_model1.dart'; import '../../models/product_model1.dart';
import '../../models/rd_order_item_model.dart'; import '../../models/rd_order_item_model.dart';
@ -35,12 +37,14 @@ class RdOrderPendingScreenDetailScreen extends StatefulWidget {
// PlacedOrderList and PlacedOrderModel are optional parameters passed to this screen // PlacedOrderList and PlacedOrderModel are optional parameters passed to this screen
final SingleGetOrderModel? placedOrderList; final SingleGetOrderModel? placedOrderList;
// GetRdPendingModel? productpendingModel; // GetRdPendingModel? productpendingModel;
final String orderId; //final String orderId;
// GetInvoiceModel? placeInvoiceList; // GetInvoiceModel? placeInvoiceList;
// PlacedOrderModel? placedOrderModel; // PlacedOrderModel? placedOrderModel;
// Constructor for initializing the screen with placed order details // Constructor for initializing the screen with placed order details
RdOrderPendingScreenDetailScreen({super.key,this.placedOrderList,required this.orderId}); RdOrderPendingScreenDetailScreen({super.key,this.placedOrderList,
// required this.orderId
});
@override @override
State<RdOrderPendingScreenDetailScreen> createState() => State<RdOrderPendingScreenDetailScreen> createState() =>
@ -52,11 +56,12 @@ class _RdOrderPendingScreenDetailScreenState
extends State<RdOrderPendingScreenDetailScreen> { extends State<RdOrderPendingScreenDetailScreen> {
// Controllers for managing cart and placed orders // Controllers for managing cart and placed orders
final CartController _cartController = Get.put(CartController()); final CartController _cartController = Get.put(CartController());
final RdSingleOrderController _getPlacedOrderController = Get.put(RdSingleOrderController());
final GetRdPendingController _getRdPendingController = Get.put(GetRdPendingController()); final GetRdPendingController _getRdPendingController = Get.put(GetRdPendingController());
final GetSingleInvoiceController _getSingleInvoiceController = Get.put(GetSingleInvoiceController()); final GetSingleInvoiceController _getSingleInvoiceController = Get.put(GetSingleInvoiceController());
final GetProductRDController _getProductRDController = Get.put(GetProductRDController()); final GetProductRDController _getProductRDController = Get.put(GetProductRDController());
final RDOrderPlacedController controller = Get.put(RDOrderPlacedController()); final RDOrderPlacedController controller = Get.put(RDOrderPlacedController());
bool isDialogClosed = false; // Flag to track if dialog is already closed
final List<String> statusOptions = [ final List<String> statusOptions = [
"new", "new",
"pending", "pending",
@ -201,6 +206,9 @@ class _RdOrderPendingScreenDetailScreenState
actions: [ actions: [
TextButton( TextButton(
onPressed: () async { onPressed: () async {
if (isDialogClosed) return; // Prevent reopening the dialog
isDialogClosed = true; // Mark dialog as closed
{ {
if (selectedStatus == "cancelled") { if (selectedStatus == "cancelled") {
// Ensure the reason is provided for cancellation // Ensure the reason is provided for cancellation
@ -235,35 +243,47 @@ class _RdOrderPendingScreenDetailScreenState
Map<String, RDOrderItem> orderItemMap = {}; Map<String, RDOrderItem> orderItemMap = {};
// Populate the map with items and their quantities // Populate the map with items and their quantities
for (var item in _getProductRDController.productRDList) { for (var item in widget.placedOrderList!.orderItem) {
var productId = item.orderItem[0].productId; var productId = item.productId;
if (item.remainingQuantity != null && item.remainingQuantity! > 0) {
if (orderItemMap.containsKey(productId)) { if (orderItemMap.containsKey(productId)) {
// If the product already exists, aggregate the quantity // If the product already exists, aggregate the remaining quantity
var existingItem = orderItemMap[productId]!; var existingItem = orderItemMap[productId]!;
existingItem.quantity = (existingItem.quantity ?? 0) + (item.orderItem[0].quantity ?? 0); existingItem.quantity = (existingItem.quantity ?? 0) + (item.quantity ?? 0);
existingItem.remainingQuantity = (existingItem.remainingQuantity ?? 0) + (item.orderItem[0].remainingQuantity ?? 0); existingItem.remainingQuantity = (existingItem.remainingQuantity ?? 0) + (item.remainingQuantity ?? 0);
existingItem.processquantity = (existingItem.processquantity ?? 0) + (item.orderItem[0].processquantity ?? 0); existingItem.processquantity = existingItem.remainingQuantity; // Process all remaining stock
} else { }
// if (orderItemMap.containsKey(productId)) {
// // If the product already exists, aggregate the quantity
// var existingItem = orderItemMap[productId]!;
// // var existingItem = orderItemMap[productId]!;
// existingItem.quantity = ((existingItem.quantity ?? 0) + (item.quantity ?? 0));
// existingItem.quantity = (existingItem.quantity ?? 0) + (item.orderItem[0].quantity ?? 0);
// existingItem.remainingQuantity = (existingItem.remainingQuantity ?? 0) + (item.orderItem[0].remainingQuantity ?? 0);
// existingItem.processquantity = (existingItem.processquantity ?? 0) + (item.orderItem[0].processquantity ?? 0);
else {
// If it's a new product, add it to the map // If it's a new product, add it to the map
orderItemMap[productId] = RDOrderItem( orderItemMap[productId] = RDOrderItem(
productId: productId, productId: productId,
sku: item.orderItem[0].sku, sku: item.sku,
name: item.orderItem[0].name, name: item.name,
categoryName: item.orderItem[0].categoryName, categoryName: item.categoryName,
brandName: item.orderItem[0].brandName, brandName: item.brandName,
price: item.orderItem[0].price, price: item.price,
gst: item.orderItem[0].gst.toInt(), gst: item.gst.toInt(),
hsnCode: item.orderItem[0].hsnCode, hsnCode: item.hsnCode,
description: item.orderItem[0].description, description: item.description,
image: [], // Handle images appropriately image: [], // Handle images appropriately
quantity: item.orderItem[0].quantity ?? 0, quantity: item.quantity ?? 0,
remainingQuantity: item.orderItem[0].remainingQuantity ?? 0, remainingQuantity: item.remainingQuantity ?? 0,
processquantity: item.orderItem[0].processquantity ?? 0, processquantity: item.remainingQuantity ?? 0,
); );
} }
} }
}
// Convert the map to a list // Convert the map to a list
List<RDOrderItem> orderItems = orderItemMap.values.toList(); List<RDOrderItem> orderItems = orderItemMap.values.toList();
@ -372,7 +392,7 @@ class _RdOrderPendingScreenDetailScreenState
), ),
], ],
title: const Text( title: const Text(
"RDPending Order Details", "RetailerPending Order Details",
), ),
), ),
body: Stack( body: Stack(
@ -509,7 +529,7 @@ class _RdOrderPendingScreenDetailScreenState
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
), ),
Text("${invoice.gstTotal}"), Text("${invoice.gstTotal.toStringAsFixed(2)}"),
], ],
), ),
@ -593,6 +613,7 @@ class _RdOrderPendingScreenDetailScreenState
itemCount: order.orderItem!.length ?? 0, itemCount: order.orderItem!.length ?? 0,
itemBuilder: (context, index) { itemBuilder: (context, index) {
final orderItem =order.orderItem![index]; final orderItem =order.orderItem![index];
final imageUrl = orderItem.image?.isNotEmpty == true ? orderItem.image![0].url : null;
final subTotal = orderItem.price * orderItem.quantity!.toInt(); final subTotal = orderItem.price * orderItem.quantity!.toInt();
final GstTotalAmount = (orderItem.price * orderItem.quantity!.toInt()) *(orderItem.gst/100 ); final GstTotalAmount = (orderItem.price * orderItem.quantity!.toInt()) *(orderItem.gst/100 );
final grandTotal = subTotal + GstTotalAmount; final grandTotal = subTotal + GstTotalAmount;
@ -606,8 +627,26 @@ class _RdOrderPendingScreenDetailScreenState
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: Row( child: Row(
children: [ children: [
Image.asset( // Image.asset(
"assets/images/product.png", // "assets/images/new_product.jpeg",
// // "assets/images/product.png",
// height: 50,
// width: 50,
// fit: BoxFit.cover,
// ),
imageUrl != null && imageUrl.isNotEmpty && imageUrl.startsWith('http') // Check if it's a network URL/ Check if it's a network URL
? CachedNetworkImage(
imageUrl: imageUrl,
height: 50,
width: 50,
fit: BoxFit.cover,
placeholder: (context, url) => const CircularProgressIndicator(), // Optional placeholder
errorWidget: (context, url, error) => const Icon(Icons.error), // Optional error widget
)
: Image.asset(
//imageUrl!,
'assets/images/no_image_available.jpg', // Placeholder image when URL is empty
height: 50, height: 50,
width: 50, width: 50,
fit: BoxFit.cover, fit: BoxFit.cover,
@ -635,7 +674,7 @@ class _RdOrderPendingScreenDetailScreenState
Text("Price: ${orderItem.price}"), Text("Price: ${orderItem.price}"),
Text("Subtotal: ${subTotal}"), Text("Subtotal: ${subTotal}"),
Text("GSt: ${orderItem.gst}%"), Text("GSt: ${orderItem.gst}%"),
Text("GST Amount (₹): ${GstTotalAmount}"), Text("GST Amount (₹): ${GstTotalAmount.toStringAsFixed(2)}"),
Text("Total Amount (₹): ${grandTotal}"), Text("Total Amount (₹): ${grandTotal}"),
], ],
), ),
@ -689,6 +728,7 @@ class _RdOrderPendingScreenDetailScreenState
.toList(); .toList();
final orderItem = filteredItems[index]; final orderItem = filteredItems[index];
final imageUrl = orderItem.image?.isNotEmpty == true ? orderItem.image![0].url : null;
final subTotalProcesssItem = orderItem.price! * orderItem.remainingQuantity!.toInt(); final subTotalProcesssItem = orderItem.price! * orderItem.remainingQuantity!.toInt();
final GstTotalAmounProcessItem = (orderItem.price! * orderItem.remainingQuantity!.toInt()) *(orderItem.gst!/100 ); final GstTotalAmounProcessItem = (orderItem.price! * orderItem.remainingQuantity!.toInt()) *(orderItem.gst!/100 );
final grandTotalProcessItem = subTotalProcesssItem + GstTotalAmounProcessItem; final grandTotalProcessItem = subTotalProcesssItem + GstTotalAmounProcessItem;
@ -702,8 +742,27 @@ class _RdOrderPendingScreenDetailScreenState
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: Row( child: Row(
children: [ children: [
Image.asset( /* Image.asset(
"assets/images/product.png", "assets/images/new_product.jpeg",
// "assets/images/product.png",
height: 50,
width: 50,
fit: BoxFit.cover,
),*/
imageUrl != null && imageUrl.isNotEmpty && imageUrl.startsWith('http') // Check if it's a network URL/ Check if it's a network URL
? CachedNetworkImage(
imageUrl: imageUrl,
height: 50,
width: 50,
fit: BoxFit.cover,
placeholder: (context, url) => const CircularProgressIndicator(), // Optional placeholder
errorWidget: (context, url, error) => const Icon(Icons.error), // Optional error widget
)
: Image.asset(
//imageUrl!,
'assets/images/no_image_available.jpg', // Placeholder image when URL is empty
height: 50, height: 50,
width: 50, width: 50,
fit: BoxFit.cover, fit: BoxFit.cover,
@ -724,7 +783,7 @@ class _RdOrderPendingScreenDetailScreenState
Text("Price: ${orderItem.price}"), Text("Price: ${orderItem.price}"),
Text("Subtotal: ${subTotalProcesssItem}"), Text("Subtotal: ${subTotalProcesssItem}"),
Text("Gst: ${orderItem.gst}%"), Text("Gst: ${orderItem.gst}%"),
Text("GST Total: ${GstTotalAmounProcessItem}"), Text("GST Total: ${GstTotalAmounProcessItem.toStringAsFixed(2)}"),
Text("Total Amount: ${grandTotalProcessItem}"), Text("Total Amount: ${grandTotalProcessItem}"),
], ],
), ),

View File

@ -114,7 +114,7 @@ class _RdOrderPendingScreenState extends State<RdOrderPendingScreen> {
// Navigate to the details screen with the fetched order // Navigate to the details screen with the fetched order
Get.to(() => RdOrderPendingScreenDetailScreen( Get.to(() => RdOrderPendingScreenDetailScreen(
placedOrderList: singleOrder, // Pass the single order instance placedOrderList: singleOrder, // Pass the single order instance
orderId: orderId, // orderId: orderId,
)); ));
} else { } else {
@ -171,7 +171,7 @@ class _RdOrderPendingScreenState extends State<RdOrderPendingScreen> {
), ),
), ),
], ],
title: const Text("RD Pending Order"), title: const Text("Retailer Pending Order"),
), ),
drawer: MyDrawer(), drawer: MyDrawer(),
body: Stack( body: Stack(

View File

@ -123,8 +123,10 @@ class _RdOrderProcessingDetailScreenState extends State<RdOrderProcessingDetailS
// Call the API to submit data // Call the API to submit data
_getDispatchController.RDProcessingToDispatchProduct(widget.placeInvoiceList!.id.toString(), courierName, courierTrackingId); _getDispatchController.RDProcessingToDispatchProduct(widget.placeInvoiceList!.id.toString(), courierName, courierTrackingId);
showSnackbar("Order Status updated Order Dispatched"); showSnackbar("Order Status updated Order Dispatched");
Navigator.push(context, MaterialPageRoute(builder: (context){
Navigator.of(context).pop(); // Close the dialog after submission return RdDispatchedScreen();
}));
//Navigator.of(context).pop(); // Close the dialog after submission
}, },
child: Text('Submit'), child: Text('Submit'),
), ),
@ -332,7 +334,7 @@ class _RdOrderProcessingDetailScreenState extends State<RdOrderProcessingDetailS
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
), ),
Text("${widget.placeInvoiceList!.gstTotal}"), Text("${widget.placeInvoiceList!.gstTotal?.toStringAsFixed(2)}"),
], ],
), ),
), ),

View File

@ -172,7 +172,7 @@ class _RdOrderProcessingScreenState extends State<RdOrderProcessingScreen> {
), ),
), ),
], ],
title: const Text("RD Processing Order"), title: const Text("Retailer Processing Order"),
), ),
drawer: MyDrawer(), drawer: MyDrawer(),
body: Stack( body: Stack(

View File

@ -5,6 +5,8 @@ import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
import 'authentication/controller/auth_controller.dart';
class SplashScreen extends StatefulWidget { class SplashScreen extends StatefulWidget {
const SplashScreen({super.key}); const SplashScreen({super.key});
@ -16,8 +18,9 @@ class _SplashScreenState extends State<SplashScreen> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
Timer(const Duration(seconds: 2), () { Future.delayed(Duration(seconds: 2), () {
Get.offAll(() => const LoginScreen()); final authController = Get.put(AuthController());
authController.checkToken();
}); });
} }

View File

@ -80,6 +80,14 @@ class ApiUrls {
//============================== Annaouncement Details ==============================// //============================== Annaouncement Details ==============================//
static const String AnnaouncementUrl = '/api/announcement/PDs'; static const String AnnaouncementUrl = '/api/announcement/PDs';
//============================== Annaouncement Details ==============================// //============================== shipto Billto Details ==============================//
static const String ShiptoandBilltoAddressUrl = '/api/shipping/address/user/address'; static const String ShiptoandBilltoAddressUrl = '/api/shipping/address/user/address';
//============================== Product stock Details ==============================//
static const String ProductStockUrl = '/api/pd/stock';
//============================== Product Update stock Details ==============================//
static const String ProductUpdateStockUrl = '${baseUrl}/api/pd/stock-update';
} }

View File

@ -0,0 +1,31 @@
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
class AuthInterceptor extends Interceptor {
@override
void onRequest(
RequestOptions options, RequestInterceptorHandler handler) async {
final prefs = await SharedPreferences.getInstance();
final token = prefs.getString('token');
if (token != null) {
debugPrint('token-->\n $token\n');
options.headers['Authorization'] = 'Bearer $token';
}
handler.next(options);
}
@override
void onResponse(Response response, ResponseInterceptorHandler handler) {
// Handle the response if needed
handler.next(response);
}
@override
void onError(DioException err, ErrorInterceptorHandler handler) async {
if (err.response?.statusCode == 401) {}
return handler.next(err);
}
}

View File

@ -5,7 +5,18 @@ import 'package:cheminova/utils/constants.dart';
import 'package:cheminova/utils/show_snackbar.dart'; import 'package:cheminova/utils/show_snackbar.dart';
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'app_interceptor.dart';
Dio createDio() {
final dio = Dio();
dio.interceptors.add((AuthInterceptor()));
return dio;
}
// Generic API service function that handles API requests with optional file uploads // Generic API service function that handles API requests with optional file uploads
Future<BodyType?> commonApiService<BodyType>({ Future<BodyType?> commonApiService<BodyType>({
required String url, required String url,
required String method, required String method,
@ -18,7 +29,7 @@ Future<BodyType?> commonApiService<BodyType>({
}) async { }) async {
try { try {
// Initialize Dio for making HTTP requests // Initialize Dio for making HTTP requests
Dio dio = Dio(); Dio dio = createDio();
final Response response; final Response response;
print("body : $body"); print("body : $body");

View File

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

View File

@ -1,3 +1,212 @@
// import 'package:cheminova/controller/home_controller.dart';
// import 'package:cheminova/models/user_model.dart';
// import 'package:cheminova/screens/authentication/change_password_screen.dart';
// import 'package:cheminova/screens/authentication/login_screen.dart';
// import 'package:cheminova/screens/authentication/profile_screen.dart';
// import 'package:cheminova/screens/home_screen.dart';
// import 'package:flutter/material.dart';
// import 'package:get/get.dart';
//
// class MyDrawer extends StatefulWidget {
// final UserModel? userModel;
//
// MyDrawer({super.key, this.userModel});
//
// @override
// State<MyDrawer> createState() => _MyDrawerState();
// }
//
// class _MyDrawerState extends State<MyDrawer> {
// final homecontroller = Get.put(HomeController()); // Initialize HomeController
// @override
// Widget build(BuildContext context) {
// final user = homecontroller.user; // Get the current user from HomeController
// return Drawer(
// child: ListView(
// padding: EdgeInsets.zero,
// children: <Widget>[
// SizedBox(
// height: 150,
// // Drawer header displaying user information
// child: DrawerHeader(
// decoration: const BoxDecoration(
// color: Colors.black87,
// ),
// child: Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// mainAxisAlignment: MainAxisAlignment.start,
// children: [
// Text(
// user?.name ?? "username",
// style: const TextStyle(
// color: Colors.white,
// fontSize: 18,
// ),
// ),
// Text(
// user?.uniqueId ?? 'Employee ID',
// style: const TextStyle(
// color: Colors.white,
// fontSize: 20,
// ),
// ),
// ],
// ),
// ),
// ),
// // Navigation tile for Home
// ListTile(
// leading: const Icon(Icons.home),
// title: const Text('Home'),
// onTap: () {
// Navigator.pushAndRemoveUntil(
// context,
// MaterialPageRoute(builder: (context) => const HomeScreen()),
// (route) => false, // Remove all previous routes
// );
// },
// ),
// // Navigation tile for Profile
// ListTile(
// leading: const Icon(Icons.account_circle),
// title: const Text('Profile'),
// onTap: () {
// Navigator.push(
// context,
// MaterialPageRoute(builder: (context) => ProfileScreen()),
// );
// },
// ),
// // Navigation tile for Change Password
// ListTile(
// leading: const Icon(Icons.settings),
// title: const Text('Change Password'),
// onTap: () {
// Navigator.push(
// context,
// MaterialPageRoute(builder: (context) => ChangePasswordScreen()),
// );
// },
// ),
// // Navigation tile for Logout
// ListTile(
// leading: const Icon(Icons.exit_to_app),
// title: const Text('Logout'),
// onTap: () {
// logoutBox(context);
// },
// ),
//
//
//
//
// SizedBox(
// height: 700,
// child: Padding(
// padding: const EdgeInsets.all(8.0),
// child: Center(
// child: Text(
// 'Version 2.0.0',
// style: TextStyle(color: Colors.grey[600], fontSize: 12),
// ),
// ),
// ),
// ),
// ],
// ),
// );
// }
// }
// // Function to display logout confirmation dialog
// Future logoutBox(BuildContext context) {
// Size size = MediaQuery.of(context).size;
// return showDialog(
// context: context,
// builder: (BuildContext context) {
// return AlertDialog(
// shape: RoundedRectangleBorder(
// borderRadius: BorderRadius.circular(6.0),
// ),
// backgroundColor: Colors.white,
// alignment: Alignment.center,
// title: const Text('Are you sure you want to log out?'),
// titleTextStyle: const TextStyle(
// fontSize: 20, fontWeight: FontWeight.w400, color: Colors.black),
// actionsAlignment: MainAxisAlignment.center,
// actionsPadding: const EdgeInsets.only(left: 10, right: 10, bottom: 20),
// actions: [
// Row(
// children: [
// Expanded(
// child: SizedBox(
// height: (size.height / 50.52) * 2,
// child: ElevatedButton(
// style: ButtonStyle(
// elevation: MaterialStateProperty.all(0),
// backgroundColor: MaterialStateProperty.all<Color>(
// Colors.black),
// shape: MaterialStateProperty.all<RoundedRectangleBorder>(
// RoundedRectangleBorder(
// borderRadius: BorderRadius.circular(6.0),
// )),
// ),
// onPressed: () async {
// Navigator.pop(context);
// },
// child: const Text(
// "No",
// style: TextStyle(
// fontSize: 17,
// color: Colors.white,
// fontWeight: FontWeight.w500),
// ),
// ),
// ),
// ),
// const SizedBox(width: 5),
// Expanded(
// child: SizedBox(
// height: (size.height / 50.52) * 2,
// child: ElevatedButton(
// style: ButtonStyle(
// elevation: MaterialStateProperty.all(0),
// backgroundColor:
// MaterialStateProperty.all<Color>(Colors.white),
// shape:
// MaterialStateProperty.all<RoundedRectangleBorder>(
// RoundedRectangleBorder(
// borderRadius: BorderRadius.circular(6.0),
// side: const BorderSide(
// color: Colors.purple, width: 1))),
// ),
// onPressed: () async {
// Navigator.pushAndRemoveUntil(
// context,
// MaterialPageRoute(
// builder: (context) => LoginScreen()),
// (route) => false,
// );
// },
// child: const Text(
// "Yes",
// style: TextStyle(
// fontSize: 17,
// color: Colors.purple,
// fontWeight: FontWeight.w500),
// ),
// ),
// ),
// ),
// ],
// )
// ],
// );
// },
// );
// }
import 'package:cheminova/controller/home_controller.dart'; import 'package:cheminova/controller/home_controller.dart';
import 'package:cheminova/models/user_model.dart'; import 'package:cheminova/models/user_model.dart';
import 'package:cheminova/screens/authentication/change_password_screen.dart'; import 'package:cheminova/screens/authentication/change_password_screen.dart';
@ -6,6 +215,7 @@ import 'package:cheminova/screens/authentication/profile_screen.dart';
import 'package:cheminova/screens/home_screen.dart'; import 'package:cheminova/screens/home_screen.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:package_info_plus/package_info_plus.dart';
class MyDrawer extends StatefulWidget { class MyDrawer extends StatefulWidget {
final UserModel? userModel; final UserModel? userModel;
@ -18,17 +228,34 @@ class MyDrawer extends StatefulWidget {
class _MyDrawerState extends State<MyDrawer> { class _MyDrawerState extends State<MyDrawer> {
final homecontroller = Get.put(HomeController()); // Initialize HomeController final homecontroller = Get.put(HomeController()); // Initialize HomeController
String _appVersion = '';
@override
void initState() {
super.initState();
_getAppVersion();
}
Future<void> _getAppVersion() async {
PackageInfo packageInfo = await PackageInfo.fromPlatform(
);
setState(() {
_appVersion = packageInfo.version; // 1.0.0
});
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final user = homecontroller.user; // Get the current user from HomeController final user = homecontroller.user; // Get the current user from HomeController
return Drawer( return Drawer(
child: ListView( child: Column(
padding: EdgeInsets.zero,
children: <Widget>[ children: <Widget>[
SizedBox( SizedBox(
height: 150, height: 150,
width: double.infinity,
// Drawer header displaying user information // Drawer header displaying user information
child: DrawerHeader( child: DrawerHeader(
//padding: EdgeInsets.zero,
decoration: const BoxDecoration( decoration: const BoxDecoration(
color: Colors.black87, color: Colors.black87,
), ),
@ -36,15 +263,16 @@ class _MyDrawerState extends State<MyDrawer> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
children: [ children: [
Text( Text(
user!.name ?? "username", user?.name ?? "username",
style: const TextStyle( style: const TextStyle(
color: Colors.white, color: Colors.white,
fontSize: 18, fontSize: 18,
), ),
), ),
Text( Text(
user!.uniqueId ?? 'Employee ID', user?.uniqueId ?? 'Employee ID',
style: const TextStyle( style: const TextStyle(
color: Colors.white, color: Colors.white,
fontSize: 20, fontSize: 20,
@ -96,11 +324,23 @@ class _MyDrawerState extends State<MyDrawer> {
logoutBox(context); logoutBox(context);
}, },
), ),
// Spacer to push the version text to the bottom
const Spacer(),
Padding(
padding: const EdgeInsets.all(8.0),
child: Center(
child: Text(
'Version: $_appVersion',
style: TextStyle(color: Colors.grey[600], fontSize: 12),
),
),
),
], ],
), ),
); );
} }
} }
// Function to display logout confirmation dialog // Function to display logout confirmation dialog
Future logoutBox(BuildContext context) { Future logoutBox(BuildContext context) {
Size size = MediaQuery.of(context).size; Size size = MediaQuery.of(context).size;
@ -188,3 +428,4 @@ Future logoutBox(BuildContext context) {
}, },
); );
} }

View File

@ -1,8 +1,10 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:cheminova/controller/cart_controller.dart'; import 'package:cheminova/controller/cart_controller.dart';
import 'package:cheminova/models/oder_place_model.dart'; import 'package:cheminova/models/oder_place_model.dart';
import 'package:cheminova/models/order_item_model.dart'; import 'package:cheminova/models/order_item_model.dart';
import 'package:cheminova/models/place_order_list_model.dart'; import 'package:cheminova/models/place_order_list_model.dart';
import 'package:cheminova/models/product_model.dart'; import 'package:cheminova/models/product_model.dart';
import 'package:cheminova/models/rd_get_order_model.dart';
import 'package:cheminova/screens/product/product_detail_screen.dart'; import 'package:cheminova/screens/product/product_detail_screen.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
@ -16,6 +18,7 @@ class ProductCard extends StatefulWidget {
PlacedOrderModel? placedOrder; PlacedOrderModel? placedOrder;
PlacedOrderList? placedOrderList; PlacedOrderList? placedOrderList;
PlaceOrderItem1? placeorderItem; PlaceOrderItem1? placeorderItem;
PlacedOrdersResponse ? placeRDOrder;
ProductModel? product; ProductModel? product;
final bool isInCart; final bool isInCart;
final bool isCheckout; final bool isCheckout;
@ -30,6 +33,7 @@ class ProductCard extends StatefulWidget {
this.placedOrder, this.placedOrder,
this.placedOrderList, this.placedOrderList,
this.placeorderItem, this.placeorderItem,
this.placeRDOrder,
this.isInCart = false, this.isInCart = false,
this.isCheckout = false, this.isCheckout = false,
this.isConfirmation = false, this.isConfirmation = false,
@ -44,6 +48,7 @@ class _ProductCardState extends State<ProductCard> {
if (text.isEmpty) return text; if (text.isEmpty) return text;
return text[0].toUpperCase() + text.substring(1).toLowerCase(); return text[0].toUpperCase() + text.substring(1).toLowerCase();
} }
String? imageurl;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -53,13 +58,20 @@ class _ProductCardState extends State<ProductCard> {
// Get the current quantity of the product, either from the cart or the default value // Get the current quantity of the product, either from the cart or the default value
int currentQuantity = isProductInCart int currentQuantity = isProductInCart
? _cartController.cartList.firstWhere((p) => p.id == widget.productModel!.id).quantity ? _cartController.cartList.firstWhere((p) => p.id == widget.productModel!.id).quantity
: widget.productModel!.quantity; : widget.productModel!.quantity ??1;
TextEditingController quantityController =
TextEditingController(text: currentQuantity.toString());
imageurl = widget.productModel!.brand.images.isNotEmpty
? widget.productModel!.brand.images[0].url
: 'assets/images/no_image_available.jpg'; // Use a fallback image URL or handle it accordingly
return GestureDetector( return GestureDetector(
// Navigate to the ProductDetailScreen on tap unless the product is in cart or checkout // Navigate to the ProductDetailScreen on tap unless the product is in cart or checkout
onTap: () => widget.isInCart || widget.isCheckout onTap: () => widget.isInCart || widget.isCheckout
? null ? null
: Get.to(() => ProductDetailScreen(productModel: widget.productModel)), : Get.to(() => ProductDetailScreen(productModel: widget.productModel)),
child: SizedBox(
// height: Get.height * 0.21,
// width: Get.width *0.20,
child: Card( child: Card(
child: Row( child: Row(
children: [ children: [
@ -67,21 +79,26 @@ class _ProductCardState extends State<ProductCard> {
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: ClipRRect( child: ClipRRect(
borderRadius: BorderRadius.circular(15.0), borderRadius: BorderRadius.circular(15.0),
child: Container( child:
height: Get.height * 0.15, Container(
width: Get.width * 0.31, height: Get.height * 0.18,
width: Get.width * 0.32,
decoration: BoxDecoration( decoration: BoxDecoration(
image: DecorationImage( image: DecorationImage(
image: AssetImage("assets/images/product.png"), image: imageurl!.startsWith('http')
? CachedNetworkImageProvider(imageurl!) as ImageProvider
: AssetImage(imageurl!),
fit: BoxFit.cover, fit: BoxFit.cover,
), ),
), ),
), ),
), ),
), ),
Expanded( Expanded(
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 3.0), padding: const EdgeInsets.symmetric(horizontal: 0.0),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -102,106 +119,22 @@ class _ProductCardState extends State<ProductCard> {
), ),
), ),
// Display the price of the product // Display the price of the product
if (!widget.isCheckout)
widget.isInCart
?
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text( Text(
"${widget.productModel!.price.toString()}", "${widget.productModel!.price.toString()}",
style: GoogleFonts.roboto( style: GoogleFonts.roboto(
fontSize: 22, fontSize: 20,
fontWeight: FontWeight.w700, fontWeight: FontWeight.w700,
), ),
), ),
if (showQuantity) // SizedBox(
Text( // width: 60,
"Quantity: ${currentQuantity}", // ),
style: GoogleFonts.roboto(
fontSize: 15,
fontWeight: FontWeight.w700,
),
),
// Display quantity adjustment buttons and remove button if the product is in cart
if (!widget.isCheckout)
widget.isInCart
? Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
height: Get.height * 0.04,
width: Get.width * 0.21,
decoration: BoxDecoration(
color: const Color(0xFF004791),
borderRadius: BorderRadius.circular(10),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
SizedBox(
height: 24,
width: 24,
child: ElevatedButton(
onPressed: () {
_cartController.decreaseQuantity(widget.productModel!);
setState(() {
currentQuantity = _cartController
.cartList
.firstWhere((p) => p.id == widget.productModel!.id)
.quantity;
});
},
style: ElevatedButton.styleFrom(
padding: EdgeInsets.zero,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
),
child: Text(
'-',
style: GoogleFonts.roboto(
fontSize: 16,
fontWeight: FontWeight.w800,
),
),
),
),
Text(
"${currentQuantity}",
style: const TextStyle(
color: Colors.white,
fontSize: 16,
),
),
SizedBox(
height: 22,
width: 22,
child: ElevatedButton(
onPressed: () {
_cartController.increaseQuantity(widget.productModel!);
setState(() {
currentQuantity = _cartController
.cartList
.firstWhere((p) => p.id == widget.productModel!.id)
.quantity;
});
},
style: ElevatedButton.styleFrom(
padding: EdgeInsets.zero,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
),
child: Text(
'+',
style: GoogleFonts.roboto(
fontSize: 16,
fontWeight: FontWeight.w800,
),
),
),
),
],
),
),
SizedBox(
width: 2.0,
),
IconButton( IconButton(
onPressed: () { onPressed: () {
_cartController.removeFromCart(widget.productModel!); _cartController.removeFromCart(widget.productModel!);
@ -216,6 +149,225 @@ class _ProductCardState extends State<ProductCard> {
), ),
), ),
], ],
)
:SizedBox(),
if (showQuantity)
SizedBox(
height: Get.height * 0.04,
child: Text(
"Quantity: ${currentQuantity}",
style: GoogleFonts.roboto(
color: Color(0xFF004791),
fontSize: 15,
fontWeight: FontWeight.w700,
),
),
),
// Display quantity adjustment buttons and remove button if the product is in cart
if (!widget.isCheckout)
widget.isInCart
?
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
height: Get.height * 0.05,
width: Get.width * 0.40,
decoration: BoxDecoration(
color: const Color(0xFF004791),
borderRadius: BorderRadius.circular(10),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
SizedBox(
height: 25,
width: 25,
child: ElevatedButton(
onPressed: () {
_cartController.decreaseQuantity(widget.productModel!);
setState(() {
currentQuantity = _cartController
.cartList
.firstWhere((p) => p.id == widget.productModel!.id)
.quantity;
});
},
style: ElevatedButton.styleFrom(
padding: EdgeInsets.zero,
backgroundColor:Color(0xFF004791),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
),
child: Text(
'-',
style: GoogleFonts.roboto(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
),
),
// Text(
// "${currentQuantity}",
// style: const TextStyle(
// color: Colors.white,
// fontSize: 16,
// ),
// Expanded(
// child: TextFormField(
// // decoration:InputDecoration(
// // border: InputBorder.none,
// // ),
//
// controller: quantityController,
// style: TextStyle(color: Color(0xFF004791),fontWeight: FontWeight.bold),
// keyboardType: TextInputType.number,
//
// textAlign: TextAlign.center,
// onFieldSubmitted: (value) {
// int enteredQuantity = int.tryParse(value) ?? currentQuantity;
// if (enteredQuantity <= 0) {
// showSnackbar("Quantity must be at least 1");
// enteredQuantity = 1;
// }
// setState(() {
// currentQuantity = enteredQuantity;
// _cartController.updateQuantity(
// widget.productModel!, currentQuantity);
// });
// },
// decoration: const InputDecoration(
//
// contentPadding: EdgeInsets.only(left: 8.0,right: 8.0,bottom: 8.0),
// border: OutlineInputBorder(
// //
// ),
// ),
// ),
// ),
SizedBox(width: 5,),
Expanded(
child: TextFormField(
controller: quantityController,
style: const TextStyle(
color: Color(0xFF004791),
fontWeight: FontWeight.bold,
fontSize: 16,
),
keyboardType: TextInputType.number,
textAlign: TextAlign.center,
onFieldSubmitted: (value) {
int enteredQuantity = int.tryParse(value) ?? currentQuantity;
if (enteredQuantity <= 0) {
showSnackbar("Quantity must be at least 1");
enteredQuantity = 1;
}
setState(() {
currentQuantity = enteredQuantity;
_cartController.updateQuantity(widget.productModel!, currentQuantity);
});
},
decoration: InputDecoration(
labelText: "Enter Quantity",
labelStyle: const TextStyle(
color: Color(0xFF004791),
fontWeight: FontWeight.w600,
fontSize: 14,
),
hintText: "",
hintStyle: const TextStyle(
color: Colors.grey,
fontWeight: FontWeight.w400,
fontSize: 14,
),
filled: true,
fillColor: Colors.white,
contentPadding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 16.0),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: const BorderSide(
color: Color(0xFF004791),
width: 1.5,
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: const BorderSide(
color: Color(0xFF004791),
width: 2,
),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: const BorderSide(
color: Colors.red,
width: 1.5,
),
),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: const BorderSide(
color: Colors.red,
width: 2,
),
),
),
),
),
SizedBox(width: 5,),
SizedBox(
height: 25,
width: 25,
child: ElevatedButton(
onPressed: () {
_cartController.increaseQuantity(widget.productModel!);
setState(() {
currentQuantity = _cartController
.cartList
.firstWhere((p) => p.id == widget.productModel!.id)
.quantity;
});
},
style: ElevatedButton.styleFrom(
backgroundColor: Color(0xFF004791),
padding: EdgeInsets.zero,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
),
child: Text(
'+',
style: GoogleFonts.roboto(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
),
),
],
),
),
SizedBox(
width: 1.0,
),
// IconButton(
// onPressed: () {
// _cartController.removeFromCart(widget.productModel!);
// showSnackbar("Product has been removed successfully!");
// setState(() {
// currentQuantity = 1;
// });
// },
// icon: const Icon(
// Icons.delete_outline_rounded,
// color: Colors.red,
// ),
// ),
],
) )
: ElevatedButton( : ElevatedButton(
onPressed: () { onPressed: () {
@ -249,6 +401,211 @@ class _ProductCardState extends State<ProductCard> {
], ],
), ),
), ),
),
); );
} }
} }
//
// class ProductCard extends StatefulWidget {
// final Product? productModel;
// PlacedOrderModel? placedOrder;
// PlacedOrderList? placedOrderList;
// PlaceOrderItem1? placeorderItem;
// PlacedOrdersResponse ? placeRDOrder;
// 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.placedOrderList,
// this.placeorderItem,
// this.placeRDOrder,
// this.isInCart = false,
// this.isCheckout = false,
// this.isConfirmation = false,
// });
//
// @override
// State<ProductCard> createState() => _ProductCardState();
// }
//
// class _ProductCardState extends State<ProductCard> {
// final CartController _cartController = Get.put(CartController());
//
// String capitalizeFirstLetter(String text) {
// if (text.isEmpty) return text;
// return text[0].toUpperCase() + text.substring(1).toLowerCase();
// }
//
// @override
// Widget build(BuildContext context) {
// bool showQuantity = widget.isInCart || widget.isCheckout || widget.isConfirmation;
// bool isProductInCart = _cartController.cartList.any((p) => p.id == widget.productModel!.id);
//
// // Get the current quantity of the product
// int currentQuantity = isProductInCart
// ? _cartController.cartList.firstWhere((p) => p.id == widget.productModel!.id).quantity
// : widget.productModel!.quantity ?? 1;
//
// TextEditingController quantityController =
// TextEditingController(text: currentQuantity.toString());
//
// return GestureDetector(
// onTap: () => widget.isInCart || widget.isCheckout
// ? null
// : Get.to(() => ProductDetailScreen(productModel: widget.productModel)),
// child: Card(
// child: Row(
// children: [
// Padding(
// padding: const EdgeInsets.all(8.0),
// child: ClipRRect(
// borderRadius: BorderRadius.circular(15.0),
// child: Container(
// height: Get.height * 0.15,
// width: Get.width * 0.31,
// decoration: const BoxDecoration(
// image: DecorationImage(
// image: AssetImage("assets/images/product.png"),
// fit: BoxFit.cover,
// ),
// ),
// ),
// ),
// ),
// Expanded(
// child: Padding(
// padding: const EdgeInsets.symmetric(horizontal: 3.0),
// child: Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// Text(
// capitalizeFirstLetter(widget.productModel!.name),
// style: GoogleFonts.roboto(
// fontSize: 16,
// fontWeight: FontWeight.w500,
// ),
// ),
// Text(
// capitalizeFirstLetter(widget.productModel!.category!.categoryName),
// style: GoogleFonts.roboto(
// fontSize: 14,
// fontWeight: FontWeight.w400,
// ),
// ),
// Text(
// "${widget.productModel!.price.toString()}",
// style: GoogleFonts.roboto(
// fontSize: 22,
// fontWeight: FontWeight.w700,
// ),
// ),
// if (showQuantity)
// Row(
// children: [
// SizedBox(
// width: 50,
// child: TextFormField(
// controller: quantityController,
// keyboardType: TextInputType.number,
// textAlign: TextAlign.center,
// onFieldSubmitted: (value) {
// int enteredQuantity = int.tryParse(value) ?? currentQuantity;
// if (enteredQuantity <= 0) {
// showSnackbar("Quantity must be at least 1");
// enteredQuantity = 1;
// }
// setState(() {
// currentQuantity = enteredQuantity;
// _cartController.updateQuantity(
// widget.productModel!, currentQuantity);
// });
// },
// decoration: const InputDecoration(
// contentPadding: EdgeInsets.all(8),
// border: OutlineInputBorder(),
// ),
// ),
// ),
// IconButton(
// onPressed: () {
// _cartController.decreaseQuantity(widget.productModel!);
// setState(() {
// currentQuantity = _cartController
// .cartList
// .firstWhere((p) => p.id == widget.productModel!.id)
// .quantity;
// quantityController.text = currentQuantity.toString();
// });
// },
// icon: const Icon(Icons.remove),
// ),
// IconButton(
// onPressed: () {
// _cartController.increaseQuantity(widget.productModel!);
// setState(() {
// currentQuantity = _cartController
// .cartList
// .firstWhere((p) => p.id == widget.productModel!.id)
// .quantity;
// quantityController.text = currentQuantity.toString();
// });
// },
// icon: const Icon(Icons.add),
// ),
// ],
// ),
// if (!widget.isCheckout)
// widget.isInCart
// ? Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// children: [
// ElevatedButton(
// onPressed: () {
// _cartController.removeFromCart(widget.productModel!);
// showSnackbar("Product removed successfully!");
// setState(() {
// currentQuantity = 1;
// quantityController.text = currentQuantity.toString();
// });
// },
// style: ElevatedButton.styleFrom(
// backgroundColor: Colors.red,
// ),
// child: const Text("Remove"),
// ),
// ],
// )
// : ElevatedButton(
// onPressed: () {
// if (isProductInCart) {
// showSnackbar("Product already added to cart");
// } else {
// _cartController.addToCart(widget.productModel!);
// showSnackbar("Product added to cart successfully!");
// }
// },
// child: const Text("Add To Cart"),
// ),
// ],
// ),
// ),
// ),
// ],
// ),
// ),
// );
// }
// }

View File

@ -1,3 +1,4 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:cheminova/controller/cart_controller.dart'; import 'package:cheminova/controller/cart_controller.dart';
import 'package:cheminova/controller/rd_get_order_controller.dart'; import 'package:cheminova/controller/rd_get_order_controller.dart';
import 'package:cheminova/models/rd_get_order_model.dart'; import 'package:cheminova/models/rd_get_order_model.dart';
@ -5,6 +6,8 @@ import 'package:cheminova/models/rd_order_item_model.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
import '../utils/show_snackbar.dart';
class ProductCard1 extends StatefulWidget { class ProductCard1 extends StatefulWidget {
final RDOrderItem productModel; // The specific product to be displayed final RDOrderItem productModel; // The specific product to be displayed
int? quantity; int? quantity;
@ -24,16 +27,20 @@ class _ProductCard1State extends State<ProductCard1> {
if (text.isEmpty) return text; if (text.isEmpty) return text;
return text[0].toUpperCase() + text.substring(1).toLowerCase(); return text[0].toUpperCase() + text.substring(1).toLowerCase();
} }
String? imageurl;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final CartController _cartController = Get.put(CartController()); final CartController _cartController = Get.put(CartController());
TextEditingController quantityController =
TextEditingController();
// Current quantity the user wants to process // Current quantity the user wants to process
int processQuantity = widget.productModel.processquantity ?? 1; int processQuantity = widget.productModel.processquantity ?? 1;
// Total available quantity // Total available quantity
int availableQuantity = widget.productModel.remainingQuantity ?? 1; int availableQuantity = widget.productModel.remainingQuantity ?? 1;
imageurl = widget.productModel.image.isNotEmpty
? widget.productModel.image[0].url
: 'assets/images/no_image_available.jpg';
return Card( return Card(
child: Row( child: Row(
@ -45,9 +52,12 @@ class _ProductCard1State extends State<ProductCard1> {
child: Container( child: Container(
height: Get.height * 0.15, height: Get.height * 0.15,
width: Get.width * 0.31, width: Get.width * 0.31,
decoration: const BoxDecoration( decoration: BoxDecoration(
image: DecorationImage( image: DecorationImage(
image: AssetImage("assets/images/product.png"), image:
imageurl!.startsWith('http')
? CachedNetworkImageProvider(imageurl!) as ImageProvider
: AssetImage(imageurl!),
fit: BoxFit.cover, fit: BoxFit.cover,
), ),
), ),
@ -94,7 +104,7 @@ class _ProductCard1State extends State<ProductCard1> {
), ),
), ),
Text( Text(
" ${widget.productModel.quantity}", " ${widget.productModel.remainingQuantity}",
style: GoogleFonts.roboto( style: GoogleFonts.roboto(
fontSize: 15, fontSize: 15,
), ),
@ -158,6 +168,39 @@ class _ProductCard1State extends State<ProductCard1> {
fontSize: 16, fontSize: 16,
), ),
), ),
// Expanded(
// child: TextFormField(
// // decoration:InputDecoration(
// // border: InputBorder.none,
// // ),
//
// controller: quantityController,
// style: TextStyle(color: Colors.white,fontWeight: FontWeight.bold),
// keyboardType: TextInputType.number,
//
// textAlign: TextAlign.center,
// onFieldSubmitted: (value) {
// int enteredQuantity = int.tryParse(value) ?? processQuantity;
// if (enteredQuantity <= 0) {
// showSnackbar("Quantity must be at least 1");
// enteredQuantity = 1;
// }
// // setState(() {
// // // widget.productModel.processquantity = enteredQuantity;
// // // // _cartController.updateQuantity(
// // // // widget.productModel.processquantity!, processQuantity);
// // processQuantity = enteredQuantity;
// // widget.productModel.processquantity = processQuantity;
// // });
// },
// decoration: const InputDecoration(
//
// contentPadding: EdgeInsets.only(left: 8.0,right: 8.0,bottom: 8.0),
// // border: OutlineInputBorder(),
// ),
// ),
// ),
// Increase quantity button // Increase quantity button
SizedBox( SizedBox(
height: 22, height: 22,

View File

@ -12,8 +12,10 @@ import firebase_core
import firebase_crashlytics import firebase_crashlytics
import firebase_messaging import firebase_messaging
import flutter_local_notifications import flutter_local_notifications
import package_info_plus
import path_provider_foundation import path_provider_foundation
import shared_preferences_foundation import shared_preferences_foundation
import sqflite
import syncfusion_pdfviewer_macos import syncfusion_pdfviewer_macos
import url_launcher_macos import url_launcher_macos
@ -25,8 +27,10 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FLTFirebaseCrashlyticsPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCrashlyticsPlugin")) FLTFirebaseCrashlyticsPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCrashlyticsPlugin"))
FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin")) FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin"))
FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin")) FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin"))
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
SyncfusionFlutterPdfViewerPlugin.register(with: registry.registrar(forPlugin: "SyncfusionFlutterPdfViewerPlugin")) SyncfusionFlutterPdfViewerPlugin.register(with: registry.registrar(forPlugin: "SyncfusionFlutterPdfViewerPlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
} }

View File

@ -9,6 +9,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.44" version: "1.3.44"
archive:
dependency: transitive
description:
name: archive
sha256: "6199c74e3db4fbfbd04f66d739e72fe11c8a8957d5f219f1f4482dbde6420b5a"
url: "https://pub.dev"
source: hosted
version: "4.0.2"
args: args:
dependency: transitive dependency: transitive
description: description:
@ -41,6 +49,30 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.1" version: "2.1.1"
cached_network_image:
dependency: "direct main"
description:
name: cached_network_image
sha256: "7c1183e361e5c8b0a0f21a28401eecdbde252441106a9816400dd4c2b2424916"
url: "https://pub.dev"
source: hosted
version: "3.4.1"
cached_network_image_platform_interface:
dependency: transitive
description:
name: cached_network_image_platform_interface
sha256: "35814b016e37fbdc91f7ae18c8caf49ba5c88501813f73ce8a07027a395e2829"
url: "https://pub.dev"
source: hosted
version: "4.1.1"
cached_network_image_web:
dependency: transitive
description:
name: cached_network_image_web
sha256: "980842f4e8e2535b8dbd3d5ca0b1f0ba66bf61d14cc3a17a9b4788a3685ba062"
url: "https://pub.dev"
source: hosted
version: "1.3.1"
characters: characters:
dependency: transitive dependency: transitive
description: description:
@ -49,6 +81,22 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.0" version: "1.3.0"
checked_yaml:
dependency: transitive
description:
name: checked_yaml
sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff
url: "https://pub.dev"
source: hosted
version: "2.0.3"
cli_util:
dependency: transitive
description:
name: cli_util
sha256: ff6785f7e9e3c38ac98b2fb035701789de90154024a75b6cb926445e83197d1c
url: "https://pub.dev"
source: hosted
version: "0.4.2"
clock: clock:
dependency: transitive dependency: transitive
description: description:
@ -302,14 +350,22 @@ packages:
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
flutter_lints: flutter_cache_manager:
dependency: "direct dev" dependency: transitive
description: description:
name: flutter_lints name: flutter_cache_manager
sha256: "9e8c3858111da373efc5aa341de011d9bd23e2c5c5e0c62bccf32438e192d7b1" sha256: "400b6592f16a4409a7f2bb929a9a7e38c72cceb8ffb99ee57bbf2cb2cecf8386"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.2" version: "3.4.1"
flutter_launcher_icons:
dependency: "direct dev"
description:
name: flutter_launcher_icons
sha256: bfa04787c85d80ecb3f8777bde5fc10c3de809240c48fa061a2c2bf15ea5211c
url: "https://pub.dev"
source: hosted
version: "0.14.3"
flutter_local_notifications: flutter_local_notifications:
dependency: "direct main" dependency: "direct main"
description: description:
@ -424,6 +480,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.0.2" version: "4.0.2"
image:
dependency: transitive
description:
name: image
sha256: "8346ad4b5173924b5ddddab782fc7d8a6300178c8b1dc427775405a01701c4a6"
url: "https://pub.dev"
source: hosted
version: "4.5.2"
image_picker: image_picker:
dependency: "direct main" dependency: "direct main"
description: description:
@ -504,6 +568,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.7.1" version: "0.7.1"
json_annotation:
dependency: transitive
description:
name: json_annotation
sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1"
url: "https://pub.dev"
source: hosted
version: "4.9.0"
leak_tracker: leak_tracker:
dependency: transitive dependency: transitive
description: description:
@ -528,14 +600,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.1" version: "3.0.1"
lints:
dependency: transitive
description:
name: lints
sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290
url: "https://pub.dev"
source: hosted
version: "3.0.0"
logger: logger:
dependency: "direct main" dependency: "direct main"
description: description:
@ -576,6 +640,30 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.6" version: "1.0.6"
octo_image:
dependency: transitive
description:
name: octo_image
sha256: "34faa6639a78c7e3cbe79be6f9f96535867e879748ade7d17c9b1ae7536293bd"
url: "https://pub.dev"
source: hosted
version: "2.1.0"
package_info_plus:
dependency: "direct main"
description:
name: package_info_plus
sha256: "739e0a5c3c4055152520fa321d0645ee98e932718b4c8efeeb51451968fe0790"
url: "https://pub.dev"
source: hosted
version: "8.1.3"
package_info_plus_platform_interface:
dependency: transitive
description:
name: package_info_plus_platform_interface
sha256: a5ef9986efc7bf772f2696183a3992615baa76c1ffb1189318dd8803778fb05b
url: "https://pub.dev"
source: hosted
version: "3.0.2"
path: path:
dependency: transitive dependency: transitive
description: description:
@ -672,6 +760,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.8" version: "2.1.8"
posix:
dependency: transitive
description:
name: posix
sha256: a0117dc2167805aa9125b82eee515cc891819bac2f538c83646d355b16f58b9a
url: "https://pub.dev"
source: hosted
version: "6.0.1"
pretty_dio_logger: pretty_dio_logger:
dependency: "direct main" dependency: "direct main"
description: description:
@ -680,6 +776,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.4.0" version: "1.4.0"
rxdart:
dependency: transitive
description:
name: rxdart
sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962"
url: "https://pub.dev"
source: hosted
version: "0.28.0"
shared_preferences: shared_preferences:
dependency: "direct main" dependency: "direct main"
description: description:
@ -757,6 +861,22 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "7.0.0" version: "7.0.0"
sqflite:
dependency: transitive
description:
name: sqflite
sha256: a43e5a27235518c03ca238e7b4732cf35eabe863a369ceba6cbefa537a66f16d
url: "https://pub.dev"
source: hosted
version: "2.3.3+1"
sqflite_common:
dependency: transitive
description:
name: sqflite_common
sha256: "3da423ce7baf868be70e2c0976c28a1bb2f73644268b7ffa7d2e08eab71f16a4"
url: "https://pub.dev"
source: hosted
version: "2.5.4"
stack_trace: stack_trace:
dependency: transitive dependency: transitive
description: description:
@ -845,6 +965,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "26.2.14" version: "26.2.14"
synchronized:
dependency: transitive
description:
name: synchronized
sha256: "539ef412b170d65ecdafd780f924e5be3f60032a1128df156adad6c5b373d558"
url: "https://pub.dev"
source: hosted
version: "3.1.0+1"
term_glyph: term_glyph:
dependency: transitive dependency: transitive
description: description:
@ -1029,6 +1157,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.5.0" version: "6.5.0"
yaml:
dependency: transitive
description:
name: yaml
sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce
url: "https://pub.dev"
source: hosted
version: "3.1.3"
sdks: sdks:
dart: ">=3.4.1 <4.0.0" dart: ">=3.4.1 <4.0.0"
flutter: ">=3.22.0" flutter: ">=3.22.0"

View File

@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts # In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix. # of the product and file versions while build-number is used as the build suffix.
version: 1.0.0+1 version: 2.0.2+1
environment: environment:
sdk: ">=3.4.1 <4.0.0" sdk: ">=3.4.1 <4.0.0"
@ -56,17 +56,28 @@ dependencies:
firebase_analytics: ^11.2.1 firebase_analytics: ^11.2.1
flutter_secure_storage: ^4.2.1 flutter_secure_storage: ^4.2.1
pretty_dio_logger: ^1.4.0 pretty_dio_logger: ^1.4.0
package_info_plus: ^8.1.3
cached_network_image: ^3.4.1
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter
flutter_launcher_icons: ^0.14.3
flutter_launcher_icons:
android: "launcher_icon"
ios: true
image_path: "assets/images/app-icon-principal-distributor.png"
# The "flutter_lints" package below contains a set of recommended lints to # The "flutter_lints" package below contains a set of recommended lints to
# encourage good coding practices. The lint set provided by the package is # encourage good coding practices. The lint set provided by the package is
# activated in the `analysis_options.yaml` file located at the root of your # activated in the `analysis_options.yaml` file located at the root of your
# package. See that file for information about deactivating specific lint # package. See that file for information about deactivating specific lint
# rules and activating additional ones. # rules and activating additional ones.
flutter_lints: ^3.0.0 flutter_lints: ^3.0.0
# For information on the generic Dart part of this file, see the # For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec # following page: https://dart.dev/tools/pub/pubspec