Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
e985fd194b | |||
2c0797b687 | |||
d101e82096 | |||
a545efca3b | |||
ef2799cbd4 |
@ -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"
|
||||||
|
BIN
assets/images/app-icon-principal-distributor.png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
assets/images/new_product.jpeg
Normal file
After Width: | Height: | Size: 5.0 KiB |
BIN
assets/images/no_image_available.jpg
Normal file
After Width: | Height: | Size: 12 KiB |
@ -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++";
|
||||||
|
@ -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"
|
|
||||||
}
|
|
||||||
}
|
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 226 KiB |
Before Width: | Height: | Size: 295 B After Width: | Height: | Size: 817 B |
Before Width: | Height: | Size: 406 B After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 450 B After Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 282 B After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 462 B After Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 704 B After Width: | Height: | Size: 7.5 KiB |
Before Width: | Height: | Size: 406 B After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 586 B After Width: | Height: | Size: 6.6 KiB |
Before Width: | Height: | Size: 862 B After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 862 B After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 762 B After Width: | Height: | Size: 6.0 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 19 KiB |
@ -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>
|
||||||
|
@ -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();
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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(
|
||||||
|
@ -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: {
|
||||||
|
@ -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(
|
||||||
|
49
lib/controller/product_stock_controller.dart
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
40
lib/controller/product_stock_service.dart
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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()),
|
||||||
|
32
lib/controller/update_stock_controller.dart
Normal 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 {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
48
lib/controller/update_stock_service.dart
Normal 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');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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)";
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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'],
|
||||||
|
@ -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'],
|
||||||
|
@ -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)';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
41
lib/models/product_stock_model.dart
Normal 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)';
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
||||||
);
|
);
|
||||||
|
@ -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: [
|
child: ListTile(
|
||||||
Card(
|
// leading: CircleAvatar(
|
||||||
child: ListTile(
|
// backgroundColor: Colors.blue,
|
||||||
//leading:Text(_announcementController.announcements[index].id),
|
// child: Text(
|
||||||
title: Row(
|
// announcementList.uniqueId.toString().toUpperCase(),
|
||||||
|
// style: TextStyle(color: Colors.white),
|
||||||
children: [
|
// ),
|
||||||
Text("Message :",style: TextStyle(fontWeight: FontWeight.bold,fontSize: 14),),
|
// ),
|
||||||
Text(announcementList.message.toString(),style: TextStyle(fontSize: 12),),
|
title: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
],
|
children: [
|
||||||
|
Text(
|
||||||
|
"Message:",
|
||||||
|
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14),
|
||||||
),
|
),
|
||||||
subtitle: Row(
|
Text(
|
||||||
children: [
|
announcementList.message.toString(),
|
||||||
Text("UniqueID :" , style: TextStyle(fontWeight: FontWeight.bold),),
|
style: TextStyle(fontSize: 12),
|
||||||
Text(announcementList.uniqueId.toString()),
|
overflow: TextOverflow.ellipsis,
|
||||||
],
|
|
||||||
),
|
),
|
||||||
trailing: Text(formatDate(announcementList.createdAt.toString()),style: TextStyle(fontSize: 10),),
|
],
|
||||||
),
|
|
||||||
|
|
||||||
),
|
),
|
||||||
|
subtitle: Column(
|
||||||
],
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"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),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -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 {
|
||||||
|
@ -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 {
|
||||||
|
@ -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 {
|
||||||
|
@ -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),
|
||||||
|
@ -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(),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
|
||||||
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -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 = [
|
||||||
|
@ -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,
|
||||||
|
213
lib/screens/kyc/kyc_screen.dart
Normal 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()),
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// }
|
@ -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());
|
||||||
|
290
lib/screens/opening Inventory/inventory_management_screen.dart
Normal 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)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
350
lib/screens/opening Inventory/update_stock_screen.dart
Normal 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,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -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(
|
||||||
decoration: InputDecoration(
|
|
||||||
labelText: 'Shipping Address:',
|
child: DropdownButtonFormField<String>(
|
||||||
hintText: 'Select Shipping Address',
|
decoration: InputDecoration(
|
||||||
border: OutlineInputBorder(),
|
labelText: 'Shipping Address:',
|
||||||
|
hintText: 'Select Shipping Address',
|
||||||
|
border: OutlineInputBorder(),
|
||||||
|
),
|
||||||
|
value: _addressController.selectedShippingAddressId.value.isEmpty
|
||||||
|
? null // Show null if there's no selection yet
|
||||||
|
: _addressController.selectedShippingAddressId.value, // Set the selected ID
|
||||||
|
items: _addressController.addressList.map((UserShippingAddress address) {
|
||||||
|
return DropdownMenuItem<String>(
|
||||||
|
value: address.id, // Set the value as the address ID
|
||||||
|
child: Text("${address.street} ${address.city} ${address.state} \n ${address.postalCode} , ${address.country}"), // Display full address
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
onChanged: (value) {
|
||||||
|
_addressController.onShippingAddressChanged(value); // Update the selected address
|
||||||
|
},
|
||||||
),
|
),
|
||||||
value: _selectedShippingAddress,
|
)),
|
||||||
items: _addressList.map((String address) {
|
|
||||||
return DropdownMenuItem<String>(
|
|
||||||
value: address,
|
|
||||||
child: Text(address),
|
|
||||||
);
|
|
||||||
}).toList(),
|
|
||||||
onChanged: _onShippingAddressChanged,
|
|
||||||
),
|
|
||||||
SizedBox(height: Get.height * 0.02),
|
SizedBox(height: Get.height * 0.02),
|
||||||
DropdownButtonFormField<String>(
|
|
||||||
decoration: InputDecoration(
|
// Billing Address Dropdown
|
||||||
labelText: 'Billing Address:',
|
Obx(() => Container(
|
||||||
hintText: 'Select Billing Address',
|
|
||||||
border: OutlineInputBorder(),
|
child: DropdownButtonFormField<String>(
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: 'Billing Address:',
|
||||||
|
hintText: 'Select Billing Address',
|
||||||
|
border: OutlineInputBorder(),
|
||||||
|
),
|
||||||
|
value: _addressController.selectedBillingAddressId.value.isEmpty
|
||||||
|
? 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>(
|
||||||
|
value: address.id, // Set the value as the address ID
|
||||||
|
child: Text("${address.street} ${address.city} ${address.state} \n ${address.postalCode} ${address.country}"), // Display full address
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
onChanged: (value) {
|
||||||
|
_addressController.onBillingAddressChanged(value); // Update the selected address
|
||||||
|
},
|
||||||
),
|
),
|
||||||
value: _selectedBillingAddress,
|
)),
|
||||||
items: _addressList.map((String address) {
|
|
||||||
return DropdownMenuItem<String>(
|
|
||||||
value: address,
|
|
||||||
child: Text(address),
|
|
||||||
);
|
|
||||||
}).toList(),
|
|
||||||
onChanged: _onBillingAddressChanged,
|
|
||||||
),
|
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.symmetric(
|
padding: EdgeInsets.symmetric(
|
||||||
horizontal: Get.width * 0.04),
|
horizontal: Get.width * 0.04),
|
||||||
|
@ -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,164 +85,172 @@ class _OrderConfermationScreenState extends State<OrderConfermationScreen> {
|
|||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
),
|
),
|
||||||
SafeArea(
|
SafeArea(
|
||||||
child: Column(
|
child: SingleChildScrollView(
|
||||||
children: [
|
child: Column(
|
||||||
SizedBox(
|
children: [
|
||||||
height: Get.height * 0.02, // Spacing from the top
|
SizedBox(
|
||||||
),
|
height: Get.height * 0.02, // Spacing from the top
|
||||||
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),
|
Card(
|
||||||
child: Padding(
|
margin: const EdgeInsets.symmetric(horizontal: 18),
|
||||||
padding: EdgeInsets.all(Get.width * 0.04),
|
shape: RoundedRectangleBorder(
|
||||||
child: Column(
|
borderRadius: BorderRadius.circular(19),
|
||||||
mainAxisSize: MainAxisSize.min,
|
side: const BorderSide(color: Color(0xFFFDFDFD)),
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
),
|
||||||
children: [
|
color: const Color(0xFFB4D1E5).withOpacity(0.9),
|
||||||
Card(
|
child: Padding(
|
||||||
child: SizedBox(
|
padding: EdgeInsets.all(Get.width * 0.04),
|
||||||
width: Get.width,
|
child: Column(
|
||||||
height: Get.height * 0.05,
|
mainAxisSize: MainAxisSize.min,
|
||||||
child: Padding(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
padding: const EdgeInsets.all(8.0),
|
children: [
|
||||||
child: Text(
|
Card(
|
||||||
"Order Number:1234",
|
child: SizedBox(
|
||||||
style: GoogleFonts.roboto(
|
width: Get.width,
|
||||||
fontSize: Get.width * 0.04,
|
height: Get.height * 0.05,
|
||||||
fontWeight: FontWeight.w400,
|
child: Padding(
|
||||||
),
|
padding: const EdgeInsets.all(8.0),
|
||||||
),
|
child: Text(
|
||||||
),
|
"Order Number:1234",
|
||||||
),
|
style: GoogleFonts.roboto(
|
||||||
),
|
fontSize: Get.width * 0.04,
|
||||||
Padding(
|
fontWeight: FontWeight.w400,
|
||||||
padding: EdgeInsets.all(Get.width * 0.02),
|
|
||||||
child: Text(
|
|
||||||
'Order Summary',
|
|
||||||
style: GoogleFonts.roboto(
|
|
||||||
fontSize: Get.width * 0.04,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: Colors.black,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Card(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
SizedBox(
|
|
||||||
height: Get.height * 0.22,
|
|
||||||
child: Padding(
|
|
||||||
padding: EdgeInsets.all(Get.width * 0.02),
|
|
||||||
child: ListView.builder(
|
|
||||||
padding: EdgeInsets.zero,
|
|
||||||
itemCount: _cartController.selectedProducts.length,
|
|
||||||
itemBuilder: (context, index) =>
|
|
||||||
ProductCard(
|
|
||||||
productModel:_cartController.selectedProducts[index],
|
|
||||||
isCheckout: true,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Padding(
|
|
||||||
padding: EdgeInsets.all(Get.width * 0.02),
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Text('Subtotal',style: TextStyle(fontWeight: FontWeight.bold)),
|
|
||||||
Text('₹${_cartController.subtotal.value.toStringAsFixed(2)}'),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Text('GST',style: TextStyle(fontWeight: FontWeight.bold)),
|
|
||||||
Text('₹${_cartController.gstTotal.value.toStringAsFixed(2)}'),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Text('Total Amount',style: TextStyle(fontWeight: FontWeight.bold)),
|
|
||||||
Text('₹${_cartController.grandTotal.value.toStringAsFixed(2)}'),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: EdgeInsets.all(Get.width * 0.02),
|
|
||||||
child: Text(
|
|
||||||
'Shipping Information',
|
|
||||||
style: GoogleFonts.roboto(
|
|
||||||
fontSize: Get.width * 0.04,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
color: Colors.black,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
Padding(
|
||||||
Card(
|
padding: EdgeInsets.all(Get.width * 0.02),
|
||||||
child: SizedBox(
|
child: Text(
|
||||||
width: Get.width,
|
'Order Summary',
|
||||||
height: Get.height * 0.1,
|
style: GoogleFonts.roboto(
|
||||||
|
fontSize: Get.width * 0.04,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Card(
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
SizedBox(
|
||||||
padding: const EdgeInsets.all(8.0),
|
height: Get.height * 0.22,
|
||||||
child: TextField(
|
child: Padding(
|
||||||
controller: TextEditingController(
|
padding: EdgeInsets.all(Get.width * 0.02),
|
||||||
text: widget.placedOrder!.shipTo, // Pre-filling the address
|
child: ListView.builder(
|
||||||
),
|
padding: EdgeInsets.zero,
|
||||||
decoration: InputDecoration(
|
itemCount: _cartController.selectedProducts.length,
|
||||||
hintText: "Address : ${widget.placedOrder!.shipTo}",
|
itemBuilder: (context, index) =>
|
||||||
hintStyle: GoogleFonts.roboto(
|
ProductCard(
|
||||||
fontSize: Get.width * 0.04,
|
productModel:_cartController.selectedProducts[index],
|
||||||
fontWeight: FontWeight.w400,
|
isCheckout: true,
|
||||||
),
|
),
|
||||||
border: OutlineInputBorder(),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.all(Get.width * 0.02),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text('Subtotal',style: TextStyle(fontWeight: FontWeight.bold)),
|
||||||
|
Text('₹${_cartController.subtotal.value.toStringAsFixed(2)}'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text('GST',style: TextStyle(fontWeight: FontWeight.bold)),
|
||||||
|
Text('₹${_cartController.gstTotal.value.toStringAsFixed(2)}'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text('Total Amount',style: TextStyle(fontWeight: FontWeight.bold)),
|
||||||
|
Text('₹${_cartController.grandTotal.value.toStringAsFixed(2)}'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
]),
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
Padding(
|
||||||
Card(
|
padding: EdgeInsets.all(Get.width * 0.02),
|
||||||
child: SizedBox(
|
child: Text(
|
||||||
width: Get.width,
|
'Shipping Information',
|
||||||
height: Get.height * 0.05,
|
style: GoogleFonts.roboto(
|
||||||
child: Padding(
|
fontSize: Get.width * 0.04,
|
||||||
padding: const EdgeInsets.all(8.0),
|
fontWeight: FontWeight.w500,
|
||||||
child: Text(
|
color: Colors.black,
|
||||||
"Estimated Delivery Date: ${widget.placedOrder!.orderItems[0].createdAt}",
|
),
|
||||||
style: GoogleFonts.roboto(
|
),
|
||||||
fontSize: Get.width * 0.04,
|
),
|
||||||
fontWeight: FontWeight.w400,
|
Card(
|
||||||
|
child: SizedBox(
|
||||||
|
width: Get.width,
|
||||||
|
height: Get.height * 0.1,
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: TextField(
|
||||||
|
controller: TextEditingController(
|
||||||
|
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(
|
||||||
|
hintText: "Address : ${widget.placedOrder!.shipTo}",
|
||||||
|
hintStyle: GoogleFonts.roboto(
|
||||||
|
fontSize: Get.width * 0.04,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
border: OutlineInputBorder(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Card(
|
||||||
|
child: SizedBox(
|
||||||
|
width: Get.width,
|
||||||
|
height: Get.height * 0.05,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: Text(
|
||||||
|
"Estimated Delivery Date: ${widget.placedOrder!.orderItems[0].createdAt}",
|
||||||
|
style: GoogleFonts.roboto(
|
||||||
|
fontSize: Get.width * 0.04,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
|
|
||||||
],
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
|
|
||||||
],
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -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,
|
||||||
|
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -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(
|
||||||
|
@ -123,146 +123,148 @@ class _CartScreenState extends State<CartScreen> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return Column(
|
return SingleChildScrollView(
|
||||||
children: [
|
child: Column(
|
||||||
SizedBox(
|
children: [
|
||||||
height: Get.height * 0.02,
|
SizedBox(
|
||||||
),
|
height: Get.height * 0.02,
|
||||||
Card(
|
|
||||||
margin: const EdgeInsets.symmetric(horizontal: 18),
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(19),
|
|
||||||
side: const BorderSide(color: Color(0xFFFDFDFD)),
|
|
||||||
),
|
),
|
||||||
color: const Color(0xFFB4D1E5).withOpacity(0.9),
|
Card(
|
||||||
child: Padding(
|
margin: const EdgeInsets.symmetric(horizontal: 18),
|
||||||
padding: const EdgeInsets.all(12.0),
|
shape: RoundedRectangleBorder(
|
||||||
child: Column(
|
borderRadius: BorderRadius.circular(19),
|
||||||
mainAxisSize: MainAxisSize.min,
|
side: const BorderSide(color: Color(0xFFFDFDFD)),
|
||||||
children: [
|
),
|
||||||
// "Select All" Checkbox
|
color: const Color(0xFFB4D1E5).withOpacity(0.9),
|
||||||
Row(
|
child: Padding(
|
||||||
children: [
|
padding: const EdgeInsets.all(12.0),
|
||||||
Checkbox(
|
child: Column(
|
||||||
value: _selectAll,
|
mainAxisSize: MainAxisSize.min,
|
||||||
onChanged: _toggleSelectAll,
|
children: [
|
||||||
),
|
// "Select All" Checkbox
|
||||||
Text(
|
// Row(
|
||||||
"Select All", // Label for the select all checkbox
|
// children: [
|
||||||
style: GoogleFonts.roboto(
|
// Checkbox(
|
||||||
fontSize: 16,
|
// value: _selectAll,
|
||||||
fontWeight: FontWeight.w500,
|
// onChanged: _toggleSelectAll,
|
||||||
),
|
// ),
|
||||||
),
|
// Text(
|
||||||
],
|
// "Select All", // Label for the select all checkbox
|
||||||
),
|
// style: GoogleFonts.roboto(
|
||||||
SizedBox(
|
// fontSize: 16,
|
||||||
height: Get.height * 0.6,
|
// fontWeight: FontWeight.w500,
|
||||||
child: ListView.builder(
|
// ),
|
||||||
padding: EdgeInsets.zero,
|
// ),
|
||||||
itemCount: _cartController.cartList.length,
|
// ],
|
||||||
itemBuilder: (context, index) {
|
// ),
|
||||||
return Row(
|
SizedBox(
|
||||||
children: [
|
height: Get.height * 0.6,
|
||||||
Checkbox(
|
child: ListView.builder(
|
||||||
value: _cartController.selectedProducts.contains(
|
padding: EdgeInsets.zero,
|
||||||
_cartController.cartList[index]), // Checkbox for individual product selection
|
itemCount: _cartController.cartList.length,
|
||||||
onChanged: (value) {
|
itemBuilder: (context, index) {
|
||||||
_cartController.toggleProductSelection(
|
return Row(
|
||||||
|
children: [
|
||||||
|
// Checkbox(
|
||||||
|
// value: _cartController.selectedProducts.contains(
|
||||||
|
// _cartController.cartList[index]), // Checkbox for individual product selection
|
||||||
|
// onChanged: (value) {
|
||||||
|
// _cartController.toggleProductSelection(
|
||||||
|
// _cartController.cartList[index],
|
||||||
|
// value!,
|
||||||
|
// );
|
||||||
|
// _checkIfAllSelected(); // Check if all are selected after each toggle
|
||||||
|
// },
|
||||||
|
// ),
|
||||||
|
Expanded(
|
||||||
|
child: ProductCard(
|
||||||
|
productModel:
|
||||||
_cartController.cartList[index],
|
_cartController.cartList[index],
|
||||||
value!,
|
isInCart: true,
|
||||||
);
|
placedOrder: widget.placedOrder,
|
||||||
_checkIfAllSelected(); // Check if all are selected after each toggle
|
),
|
||||||
},
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: ProductCard(
|
|
||||||
productModel:
|
|
||||||
_cartController.cartList[index],
|
|
||||||
isInCart: true,
|
|
||||||
placedOrder: widget.placedOrder,
|
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
);
|
||||||
);
|
},
|
||||||
},
|
),
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(height: 10),
|
||||||
const SizedBox(height: 10),
|
Row(
|
||||||
Row(
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
children: [
|
||||||
children: [
|
Text(
|
||||||
Text(
|
"Subtotal ",
|
||||||
"Subtotal ",
|
style: GoogleFonts.roboto(
|
||||||
style: GoogleFonts.roboto(
|
fontSize: 15,
|
||||||
fontSize: 15,
|
color: Colors.black,
|
||||||
color: Colors.black,
|
fontWeight: FontWeight.bold,
|
||||||
fontWeight: FontWeight.bold,
|
),
|
||||||
),
|
),
|
||||||
),
|
Obx(() =>
|
||||||
Obx(() =>
|
Text("₹ ${_cartController.subtotal.value}")),
|
||||||
Text("₹ ${_cartController.subtotal.value}")),
|
],
|
||||||
],
|
),
|
||||||
),
|
Row(
|
||||||
Row(
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
children: [
|
||||||
children: [
|
Text(
|
||||||
Text(
|
"GST ",
|
||||||
"GST ",
|
style: GoogleFonts.roboto(
|
||||||
style: GoogleFonts.roboto(
|
fontSize: 15,
|
||||||
fontSize: 15,
|
color: Colors.black,
|
||||||
color: Colors.black,
|
fontWeight: FontWeight.bold,
|
||||||
fontWeight: FontWeight.bold,
|
),
|
||||||
),
|
),
|
||||||
),
|
Obx(() =>
|
||||||
Obx(() =>
|
Text("₹ ${_cartController.gstTotal.value}")),
|
||||||
Text("₹ ${_cartController.gstTotal.value}")),
|
],
|
||||||
],
|
),
|
||||||
),
|
Row(
|
||||||
Row(
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
children: [
|
||||||
children: [
|
Text(
|
||||||
Text(
|
"Total Amount ",
|
||||||
"Total Amount ",
|
style: GoogleFonts.roboto(
|
||||||
style: GoogleFonts.roboto(
|
fontSize: 15,
|
||||||
fontSize: 15,
|
color: Colors.black,
|
||||||
color: Colors.black,
|
fontWeight: FontWeight.bold,
|
||||||
fontWeight: FontWeight.bold,
|
),
|
||||||
),
|
),
|
||||||
),
|
Obx(() => Text(
|
||||||
Obx(() => Text(
|
"₹ ${_cartController.grandTotal.value}")),
|
||||||
"₹ ${_cartController.grandTotal.value}")),
|
],
|
||||||
],
|
),
|
||||||
),
|
],
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(height: Get.height * 0.020),
|
|
||||||
SizedBox(
|
|
||||||
width: Get.width * 0.9,
|
|
||||||
height: Get.height * 0.06,
|
|
||||||
child: ElevatedButton(
|
|
||||||
onPressed: () => Get.to(() => CheckoutScreen(
|
|
||||||
selectedProducts: _cartController.selectedProducts, // Pass selected products to checkout
|
|
||||||
)),
|
|
||||||
style: ElevatedButton.styleFrom(
|
|
||||||
foregroundColor: Colors.white,
|
|
||||||
backgroundColor: const Color(0xFF00784C),
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(10),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: Text(
|
|
||||||
"Proceed to Checkout",
|
|
||||||
style: GoogleFonts.roboto(
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
SizedBox(height: Get.height * 0.020),
|
||||||
],
|
SizedBox(
|
||||||
|
width: Get.width * 0.9,
|
||||||
|
height: Get.height * 0.06,
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: () => Get.to(() => CheckoutScreen(
|
||||||
|
selectedProducts: _cartController.selectedProducts, // Pass selected products to checkout
|
||||||
|
)),
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
foregroundColor: Colors.white,
|
||||||
|
backgroundColor: const Color(0xFF00784C),
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
"Proceed to Checkout",
|
||||||
|
style: GoogleFonts.roboto(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
|
@ -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> {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -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,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -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}"),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -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(
|
||||||
|
@ -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> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -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)}"),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -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(
|
||||||
|
@ -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)}"),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -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(
|
||||||
|
@ -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}"),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -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(
|
||||||
|
@ -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 (orderItemMap.containsKey(productId)) {
|
|
||||||
// If the product already exists, aggregate the quantity
|
if (item.remainingQuantity != null && item.remainingQuantity! > 0) {
|
||||||
var existingItem = orderItemMap[productId]!;
|
if (orderItemMap.containsKey(productId)) {
|
||||||
existingItem.quantity = (existingItem.quantity ?? 0) + (item.orderItem[0].quantity ?? 0);
|
// If the product already exists, aggregate the remaining quantity
|
||||||
existingItem.remainingQuantity = (existingItem.remainingQuantity ?? 0) + (item.orderItem[0].remainingQuantity ?? 0);
|
var existingItem = orderItemMap[productId]!;
|
||||||
existingItem.processquantity = (existingItem.processquantity ?? 0) + (item.orderItem[0].processquantity ?? 0);
|
existingItem.quantity = (existingItem.quantity ?? 0) + (item.quantity ?? 0);
|
||||||
} else {
|
existingItem.remainingQuantity = (existingItem.remainingQuantity ?? 0) + (item.remainingQuantity ?? 0);
|
||||||
|
existingItem.processquantity = existingItem.remainingQuantity; // Process all remaining stock
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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}"),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -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(
|
||||||
|
@ -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)}"),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -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(
|
||||||
|
@ -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();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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';
|
||||||
|
|
||||||
}
|
}
|
||||||
|
31
lib/utils/app_interceptor.dart
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
@ -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");
|
||||||
|
@ -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
|
||||||
});
|
});
|
||||||
|
@ -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) {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,155 +58,83 @@ 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: Card(
|
child: SizedBox(
|
||||||
child: Row(
|
// height: Get.height * 0.21,
|
||||||
children: [
|
// width: Get.width *0.20,
|
||||||
Padding(
|
child: Card(
|
||||||
padding: const EdgeInsets.all(8.0),
|
child: Row(
|
||||||
child: ClipRRect(
|
children: [
|
||||||
borderRadius: BorderRadius.circular(15.0),
|
Padding(
|
||||||
child: Container(
|
padding: const EdgeInsets.all(8.0),
|
||||||
height: Get.height * 0.15,
|
child: ClipRRect(
|
||||||
width: Get.width * 0.31,
|
borderRadius: BorderRadius.circular(15.0),
|
||||||
decoration: BoxDecoration(
|
child:
|
||||||
image: DecorationImage(
|
Container(
|
||||||
image: AssetImage("assets/images/product.png"),
|
height: Get.height * 0.18,
|
||||||
fit: BoxFit.cover,
|
width: Get.width * 0.32,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
image: DecorationImage(
|
||||||
|
image: imageurl!.startsWith('http')
|
||||||
|
? CachedNetworkImageProvider(imageurl!) as ImageProvider
|
||||||
|
: AssetImage(imageurl!),
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
),
|
Expanded(
|
||||||
Expanded(
|
child: Padding(
|
||||||
child: Padding(
|
padding: const EdgeInsets.symmetric(horizontal: 0.0),
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 3.0),
|
child: Column(
|
||||||
child: Column(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
children: [
|
||||||
children: [
|
// Display the product name with the first letter capitalized
|
||||||
// Display the product name with the first letter capitalized
|
|
||||||
Text(
|
|
||||||
capitalizeFirstLetter(widget.productModel!.name),
|
|
||||||
style: GoogleFonts.roboto(
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
// Display the category name of the product
|
|
||||||
Text(
|
|
||||||
capitalizeFirstLetter(widget.productModel!.category!.categoryName),
|
|
||||||
style: GoogleFonts.roboto(
|
|
||||||
fontSize: 14,
|
|
||||||
fontWeight: FontWeight.w400,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
// Display the price of the product
|
|
||||||
Text(
|
|
||||||
"₹ ${widget.productModel!.price.toString()}",
|
|
||||||
style: GoogleFonts.roboto(
|
|
||||||
fontSize: 22,
|
|
||||||
fontWeight: FontWeight.w700,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (showQuantity)
|
|
||||||
Text(
|
Text(
|
||||||
"Quantity: ${currentQuantity}",
|
capitalizeFirstLetter(widget.productModel!.name),
|
||||||
style: GoogleFonts.roboto(
|
style: GoogleFonts.roboto(
|
||||||
fontSize: 15,
|
fontSize: 16,
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w500,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// Display quantity adjustment buttons and remove button if the product is in cart
|
// Display the category name of the product
|
||||||
if (!widget.isCheckout)
|
Text(
|
||||||
widget.isInCart
|
capitalizeFirstLetter(widget.productModel!.category!.categoryName),
|
||||||
? Row(
|
style: GoogleFonts.roboto(
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// Display the price of the product
|
||||||
|
if (!widget.isCheckout)
|
||||||
|
widget.isInCart
|
||||||
|
?
|
||||||
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Text(
|
||||||
height: Get.height * 0.04,
|
"₹ ${widget.productModel!.price.toString()}",
|
||||||
width: Get.width * 0.21,
|
style: GoogleFonts.roboto(
|
||||||
decoration: BoxDecoration(
|
fontSize: 20,
|
||||||
color: const Color(0xFF004791),
|
fontWeight: FontWeight.w700,
|
||||||
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(
|
// SizedBox(
|
||||||
width: 2.0,
|
// width: 60,
|
||||||
),
|
// ),
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
_cartController.removeFromCart(widget.productModel!);
|
_cartController.removeFromCart(widget.productModel!);
|
||||||
@ -217,38 +150,462 @@ class _ProductCardState extends State<ProductCard> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
: ElevatedButton(
|
:SizedBox(),
|
||||||
onPressed: () {
|
if (showQuantity)
|
||||||
if (isProductInCart) {
|
SizedBox(
|
||||||
showSnackbar("Product already added to cart");
|
height: Get.height * 0.04,
|
||||||
} else {
|
child: Text(
|
||||||
_cartController.addToCart(widget.productModel!);
|
"Quantity: ${currentQuantity}",
|
||||||
showSnackbar("Product successfully added to your cart");
|
style: GoogleFonts.roboto(
|
||||||
}
|
color: Color(0xFF004791),
|
||||||
},
|
fontSize: 15,
|
||||||
style: ElevatedButton.styleFrom(
|
fontWeight: FontWeight.w700,
|
||||||
foregroundColor: Colors.white,
|
),
|
||||||
backgroundColor: const Color(0xFF00784C),
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 8),
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(30),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: Text(
|
// Display quantity adjustment buttons and remove button if the product is in cart
|
||||||
"Add To Cart",
|
if (!widget.isCheckout)
|
||||||
style: GoogleFonts.roboto(
|
widget.isInCart
|
||||||
fontSize: 14,
|
?
|
||||||
fontWeight: FontWeight.w600,
|
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(
|
||||||
|
onPressed: () {
|
||||||
|
if (isProductInCart) {
|
||||||
|
showSnackbar("Product already added to cart");
|
||||||
|
} else {
|
||||||
|
_cartController.addToCart(widget.productModel!);
|
||||||
|
showSnackbar("Product successfully added to your cart");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
foregroundColor: Colors.white,
|
||||||
|
backgroundColor: const Color(0xFF00784C),
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 8),
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(30),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
"Add To Cart",
|
||||||
|
style: GoogleFonts.roboto(
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// 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"),
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
@ -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,
|
||||||
|
@ -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"))
|
||||||
}
|
}
|
||||||
|
162
pubspec.lock
@ -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"
|
||||||
|
15
pubspec.yaml
@ -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
|
||||||
|