diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..59d6d4a --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,25 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Wosull", + "request": "launch", + "type": "dart" + }, + { + "name": "Wosull (profile mode)", + "request": "launch", + "type": "dart", + "flutterMode": "profile" + }, + { + "name": "Wosull (release mode)", + "request": "launch", + "type": "dart", + "flutterMode": "release" + } + ] +} \ No newline at end of file diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 9386822..eb531c5 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,10 +1,11 @@ - - - - + + + + + + + + + diff --git a/fonts/DejaVuSansMono.ttf b/fonts/DejaVuSansMono.ttf new file mode 100644 index 0000000..8b7bb2a Binary files /dev/null and b/fonts/DejaVuSansMono.ttf differ diff --git a/images/active_cart.svg b/images/active_cart.svg new file mode 100644 index 0000000..1613056 --- /dev/null +++ b/images/active_cart.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/images/active_cashier.svg b/images/active_cashier.svg new file mode 100644 index 0000000..983a4fa --- /dev/null +++ b/images/active_cashier.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/images/active_hold.svg b/images/active_hold.svg new file mode 100644 index 0000000..06dcf78 --- /dev/null +++ b/images/active_hold.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/images/cart.svg b/images/cart.svg new file mode 100644 index 0000000..9834b5f --- /dev/null +++ b/images/cart.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/cart_icon_svg.svg b/images/cart_icon_svg.svg new file mode 100644 index 0000000..9834b5f --- /dev/null +++ b/images/cart_icon_svg.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/cashier.svg b/images/cashier.svg new file mode 100644 index 0000000..0eb6f93 --- /dev/null +++ b/images/cashier.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/hold_order.svg b/images/hold_order.svg new file mode 100644 index 0000000..a095258 --- /dev/null +++ b/images/hold_order.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/home.svg b/images/home.svg new file mode 100644 index 0000000..f30051e --- /dev/null +++ b/images/home.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/home_active.svg b/images/home_active.svg new file mode 100644 index 0000000..98cdf82 --- /dev/null +++ b/images/home_active.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 3ec9ff2..cbfff2c 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1,4 +1,7 @@ PODS: + - connectivity_plus (0.0.1): + - Flutter + - ReachabilitySwift - DKImagePickerController/Core (4.3.4): - DKImagePickerController/ImageDataManager - DKImagePickerController/Resource @@ -33,17 +36,20 @@ PODS: - file_picker (0.0.1): - DKImagePickerController/PhotoGallery - Flutter + - file_saver (0.0.1): + - Flutter - Flutter (1.0.0) - fluttertoast (0.0.2): - Flutter - Toast - - FMDB (2.7.5): - - FMDB/standard (= 2.7.5) - - FMDB/standard (2.7.5) - image_picker_ios (0.0.1): - Flutter - modal_progress_hud_nsn (0.4.0): - Flutter + - ObjectBox (1.8.1) + - objectbox_flutter_libs (0.0.1): + - Flutter + - ObjectBox (= 1.8.1) - package_info_plus (0.4.5): - Flutter - path_provider_foundation (0.0.1): @@ -51,42 +57,47 @@ PODS: - FlutterMacOS - permission_handler_apple (9.1.1): - Flutter + - ReachabilitySwift (5.0.0) - SDWebImage (5.16.0): - SDWebImage/Core (= 5.16.0) - SDWebImage/Core (5.16.0) - shared_preferences_foundation (0.0.1): - Flutter - FlutterMacOS - - sqflite (0.0.3): - - Flutter - - FMDB (>= 2.7.5) - SwiftyGif (5.4.4) - Toast (4.0.0) DEPENDENCIES: + - connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`) - file_picker (from `.symlinks/plugins/file_picker/ios`) + - file_saver (from `.symlinks/plugins/file_saver/ios`) - Flutter (from `Flutter`) - fluttertoast (from `.symlinks/plugins/fluttertoast/ios`) - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`) - modal_progress_hud_nsn (from `.symlinks/plugins/modal_progress_hud_nsn/ios`) + - objectbox_flutter_libs (from `.symlinks/plugins/objectbox_flutter_libs/ios`) - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`) - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) - - sqflite (from `.symlinks/plugins/sqflite/ios`) SPEC REPOS: trunk: - DKImagePickerController - DKPhotoGallery - - FMDB + - ObjectBox + - ReachabilitySwift - SDWebImage - SwiftyGif - Toast EXTERNAL SOURCES: + connectivity_plus: + :path: ".symlinks/plugins/connectivity_plus/ios" file_picker: :path: ".symlinks/plugins/file_picker/ios" + file_saver: + :path: ".symlinks/plugins/file_saver/ios" Flutter: :path: Flutter fluttertoast: @@ -95,6 +106,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/image_picker_ios/ios" modal_progress_hud_nsn: :path: ".symlinks/plugins/modal_progress_hud_nsn/ios" + objectbox_flutter_libs: + :path: ".symlinks/plugins/objectbox_flutter_libs/ios" package_info_plus: :path: ".symlinks/plugins/package_info_plus/ios" path_provider_foundation: @@ -103,24 +116,25 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/permission_handler_apple/ios" shared_preferences_foundation: :path: ".symlinks/plugins/shared_preferences_foundation/darwin" - sqflite: - :path: ".symlinks/plugins/sqflite/ios" SPEC CHECKSUMS: + connectivity_plus: 07c49e96d7fc92bc9920617b83238c4d178b446a DKImagePickerController: b512c28220a2b8ac7419f21c491fc8534b7601ac DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179 file_picker: ce3938a0df3cc1ef404671531facef740d03f920 + file_saver: 503e386464dbe118f630e17b4c2e1190fa0cf808 Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 fluttertoast: fafc4fa4d01a6a9e4f772ecd190ffa525e9e2d9c - FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a image_picker_ios: 4a8aadfbb6dc30ad5141a2ce3832af9214a705b5 modal_progress_hud_nsn: b66f99f02da7de83484e50dfe1fe2d71ac406e67 + ObjectBox: a7900d5335218cd437cbc080b7ccc38a5211f7b4 + objectbox_flutter_libs: 61d74196d924fbc773da5f5757d1e9fab7b3cc78 package_info_plus: fd030dabf36271f146f1f3beacd48f564b0f17f7 path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943 permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6 + ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825 SDWebImage: 2aea163b50bfcb569a2726b6a754c54a4506fcf6 shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126 - sqflite: 31f7eba61e3074736dff8807a9b41581e4f7f15a SwiftyGif: 93a1cc87bf3a51916001cf8f3d63835fb64c819f Toast: 91b396c56ee72a5790816f40d3a94dd357abc196 diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index f3cc074..86fc99f 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -4,10 +4,18 @@ CADisableMinimumFrameDurationOnPhone + LSSupportsOpeningDocumentsInPlace + + UIFileSharingEnabled + CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleDisplayName Wosul + LSSupportsOpeningDocumentsInPlace + + UIFileSharingEnabled + CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier diff --git a/lib/application/MyApp.dart b/lib/application/MyApp.dart index b41d9f9..2ac1abd 100644 --- a/lib/application/MyApp.dart +++ b/lib/application/MyApp.dart @@ -4,28 +4,51 @@ import 'package:provider/provider.dart'; import 'package:sizer/sizer.dart'; import 'package:wosull/application/language/AppLocale.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/application/views/authModule/checkinViews/viewModel/CheckInViewModel.dart'; import 'package:wosull/application/views/authModule/loginViews/LoginVC.dart'; -import 'package:wosull/application/views/authModule/viewModel/CheckInViewModel.dart'; -import 'package:wosull/application/views/authModule/viewModel/LoginViewModel.dart'; +import 'package:wosull/application/views/authModule/loginViews/viewModel/LoginViewModel.dart'; +import 'package:wosull/application/views/authModule/registerViews/viewModel/AuthViewModel.dart'; import 'package:wosull/application/views/create_order_module/viewModels/CartViewModel.dart'; +import 'package:wosull/application/views/create_order_module/viewModels/CounterCloseViewMdoel.dart'; import 'package:wosull/application/views/create_order_module/viewModels/CreateOrderViewModel.dart'; +import 'package:wosull/application/views/create_order_module/viewModels/DineInViewModel.dart'; +import 'package:wosull/application/views/create_order_module/viewModels/ItemModifiersViewModel.dart'; +import 'package:wosull/application/views/create_order_module/viewModels/PaymentOptionViewModel.dart'; +import 'package:wosull/application/views/create_order_module/viewModels/PrintInvoiceViewModel.dart'; import 'package:wosull/application/views/create_order_module/viewModels/RegisterCashOutViewModel.dart'; import 'package:wosull/application/views/dashboard/viewModel/DashboardViewModel.dart'; +import 'package:wosull/application/views/discountModule/viewModels/NewDiscountViewModel.dart'; +import 'package:wosull/application/views/dowloadReports/viewModel/DownloadBestSellerReportViewModel.dart'; import 'package:wosull/application/views/home/HomePage.dart'; import 'package:wosull/application/views/inventorymodule/categoryviews/viewModels/AddCategoryViewModel.dart'; +import 'package:wosull/application/views/inventorymodule/comboviews/viewModels/AddComboGroupViewModel.dart'; +import 'package:wosull/application/views/inventorymodule/comboviews/viewModels/AddNewComboViewModel.dart'; import 'package:wosull/application/views/inventorymodule/deliveryPartnerViews/viewModels/DeliveryPartnerPriceViewModel.dart'; +import 'package:wosull/application/views/inventorymodule/deliveryPartnerViews/viewModels/NewDeliveryPartnerViewModel.dart'; +import 'package:wosull/application/views/inventorymodule/ingredientsViews/viewModels/AddIngredientViewModel.dart'; import 'package:wosull/application/views/inventorymodule/measurementviews/viewModels/AddMeasurementUnitVM.dart'; import 'package:wosull/application/views/inventorymodule/measurementviews/viewModels/AddMeasurementViewModel.dart'; import 'package:wosull/application/views/inventorymodule/modifierviews/viewModels/NewModifierVM.dart'; -import 'package:wosull/application/views/inventorymodule/productviews/viewModels/AddIngredientViewModel.dart'; import 'package:wosull/application/views/inventorymodule/productviews/viewModels/AddProductViewModel.dart'; +import 'package:wosull/application/views/inventorymodule/stockReturn/viewmodels/NewStockReturnViewModel.dart'; import 'package:wosull/application/views/inventorymodule/subCategoryViews/viewModels/AddSubCategoryViewModel.dart'; import 'package:wosull/application/views/kitchenmodule/views/table/viewModels/NewTableViewModel.dart'; +import 'package:wosull/application/views/salesandordermodule/views/invoiceModule/viewModels/InvoiceViewModel.dart'; +import 'package:wosull/application/views/salesandordermodule/views/invoiceModule/viewModels/MakePaymentViewModel.dart'; +import 'package:wosull/application/views/salesandordermodule/views/invoiceModule/viewModels/NewInvoiceViewModel.dart'; +import 'package:wosull/application/views/salesandordermodule/views/invoiceModule/viewModels/ReturnDamageInvoiceViewModel.dart'; import 'package:wosull/application/views/salesandordermodule/views/ordersModule/viewModel/OrderViewModel.dart'; +import 'package:wosull/application/views/salesandordermodule/views/quotataionModule/viewModels/NewQuotationViewModel.dart'; +import 'package:wosull/application/views/settings/viewModels/POSCompleteViewModel.dart'; +import 'package:wosull/application/views/settings/views/paymentMethods/viewModel/NewPaymentMethodViewModel.dart'; import 'package:wosull/application/views/transactions/viewmodels/TransactionQuotationViewModel.dart'; +import 'package:wosull/application/views/transactions/widgets/EditOrderViewModel.dart'; +import 'views/billingCounterDashboard/viewModels/BillingCounterViewModel.dart'; import 'views/create_order_module/viewModels/SelectComboVM.dart'; import 'views/home/HomePageViewModel.dart'; +import 'views/inventorymodule/comboviews/viewModels/AddComboSizeViewModel.dart'; +import 'views/inventorymodule/modiferOption/viewModels/NewModifierOptionViewModel.dart'; import 'views/inventorymodule/stockTransferViews/viewModels/NewStockTransferVM.dart'; import 'views/transactions/viewmodels/ReturnPOSOrderVM.dart'; @@ -38,6 +61,52 @@ class MyApp extends StatelessWidget { Widget build(BuildContext context) { return MultiProvider( providers: [ + ChangeNotifierProvider( + create: (context) => DineInViewModel()), + ChangeNotifierProvider( + create: (context) => ItemModifiersViewModel()), + ChangeNotifierProvider( + create: (context) => AuthViewModel()), + ChangeNotifierProvider( + create: (context) => POSCompleteViewModel()), + ChangeNotifierProvider( + create: (context) => DownloadBestSellerReportViewModel()), + ChangeNotifierProvider( + create: (context) => NewPaymentMethodViewModel()), + ChangeNotifierProvider( + create: (context) => MakePaymentViewModel()), + ChangeNotifierProvider( + create: (context) => ReturnDamageInvoiceViewModel()), + ChangeNotifierProvider( + create: (context) => CounterCloseViewModel()), + ChangeNotifierProvider( + create: (context) => NewQuotationViewModel()), + ChangeNotifierProvider( + create: (context) => NewStockReturnViewModel()), + ChangeNotifierProvider( + create: (context) => NewModifierOptionViewModel()), + ChangeNotifierProvider( + create: (context) => InvoiceViewModel()), + ChangeNotifierProvider( + create: (context) => NewInvoiceViewModel()), + ChangeNotifierProvider( + create: (context) => EditOrderViewModel()), + ChangeNotifierProvider( + create: (context) => NewDiscountViewModel()), + ChangeNotifierProvider( + create: (context) => NewDeliveryPartnerViewModel()), + ChangeNotifierProvider( + create: (context) => AddNewComboViewModel()), + ChangeNotifierProvider( + create: (context) => AddComboGroupViewModel()), + ChangeNotifierProvider( + create: (context) => AddComboSizeViewModel()), + ChangeNotifierProvider( + create: (context) => BillingCounterViewModel()), + ChangeNotifierProvider( + create: (context) => PaymentOptionViewModel()), + ChangeNotifierProvider( + create: (context) => PrintInvoiceViewModel()), ChangeNotifierProvider( create: (context) => CartViewModel()), ChangeNotifierProvider( @@ -91,7 +160,9 @@ class MyApp extends StatelessWidget { home: Directionality( // add this textDirection: TextDirection.ltr, // set this property - child: sharedPrefs.isLoggedIn ? const HomePage() : LoginVC(), + child: sharedPrefs.isLoggedIn + ? const HomePage() + : const LoginVC(), ), // home: , localizationsDelegates: AppLocalizations.localizationsDelegates, diff --git a/lib/application/ViewModel/InventoryViewModel.dart b/lib/application/ViewModel/InventoryViewModel.dart deleted file mode 100644 index add1d11..0000000 --- a/lib/application/ViewModel/InventoryViewModel.dart +++ /dev/null @@ -1,106 +0,0 @@ -import 'dart:convert'; - -import 'package:http/http.dart' as http; -import 'package:wosull/application/model/SimpleResponsModel.dart'; -import 'package:wosull/application/model/StockTransfer/ProductItemCategoryModel.dart'; -import 'package:wosull/application/model/store/GetSpecificStores.dart'; -import 'package:wosull/application/repo/AuthRepository.dart'; -import 'package:wosull/application/utils/Constants.dart'; - -class InventoryViewModel { - Future getSpecificStoresById(Map value) async { - try { - dynamic response = await AuthRepository() - .postResponseAuth(Constants.GET_SPECIFIC_STORES, value); - return GetSpecificStores.fromJson(response); - } catch (e) { - return GetSpecificStores(success: false, stores: [], message: ''); - } - } - - Future addMeasurement(Map data) async { - try { - dynamic response = await AuthRepository() - .postResponseAuth(Constants.ADD_UPDATE_MEASUREMENT, data); - return SimpleResponseModel.fromJson(response); - } catch (e) { - return SimpleResponseModel(); - } - } - - Future getProductSearchStores( - Map data) async { - try { - dynamic response = await AuthRepository() - .postResponseAuth(Constants.SEARCH_ITEM_STORE, data); - return ProductItemCategoryModel.fromJson(response); - } catch (e) { - return ProductItemCategoryModel(); - } - } - - Future getResponse(String url) async { - Map headers = { - "Content-Type": "application/json", - "Authorization": Constants.auth - }; - final res = await http - .get(Uri.parse('${Constants.baseURL}$url'), headers: headers) - .timeout(const Duration(seconds: 60)); - - final data = await jsonDecode(res.body); - return data; - } - - Future getResponseAuth(String url, - [Map? queryParameter]) async { - try { - dynamic response = - await AuthRepository().getResponseAuth(url, queryParameter); - return response; - } catch (e) { - return e; - } - } - - Future updateStoreItem(Map data) async { - try { - dynamic response = await AuthRepository() - .postResponseAuth(Constants.UPDATE_STORE_ITEM, data); - return SimpleResponseModel.fromJson(response); - } catch (e) { - dynamic response = e; - return SimpleResponseModel.fromJson(response); - } - } - - Future addStockTransfer( - Map data) async { - try { - dynamic response = await AuthRepository() - .postResponseAuth(Constants.ADD_STOCK_TRANSFER, data); - return SimpleResponseModel.fromJson(response); - } catch (e) { - return SimpleResponseModel(); - } - } - - Future getData(String url, Map data) async { - try { - dynamic response = await AuthRepository().postResponseAuth(url, data); - return response; - } catch (e) { - return e; - } - } - - Future getResponsePatch( - String url, Map data) async { - try { - dynamic response = await AuthRepository().patchResponseAuth(url, data); - return SimpleResponseModel.fromJson(response); - } catch (e) { - return SimpleResponseModel(success: false, message: e.toString()); - } - } -} diff --git a/lib/application/interfaces/DrawerWidgetSelect.dart b/lib/application/interfaces/DrawerWidgetSelect.dart index 639025a..1750402 100644 --- a/lib/application/interfaces/DrawerWidgetSelect.dart +++ b/lib/application/interfaces/DrawerWidgetSelect.dart @@ -1,7 +1,7 @@ import 'package:wosull/application/model/cart/GetHoldOrderModel.dart'; import 'package:wosull/application/model/customers/GetStoreCustomer.dart'; import 'package:wosull/application/model/invoice/StoreInvoice.dart'; -import 'package:wosull/application/model/reports/CashierOrderHistory.dart'; +import 'package:wosull/application/model/reports/CashierOrder.dart'; import 'package:wosull/application/model/reports/TopOrderItemsModel.dart'; import 'package:wosull/application/model/suppliers/GetStoreSupplierModel.dart'; diff --git a/lib/application/localdb/SharedPrefs.dart b/lib/application/localdb/SharedPrefs.dart index f4cb191..a7f59ca 100644 --- a/lib/application/localdb/SharedPrefs.dart +++ b/lib/application/localdb/SharedPrefs.dart @@ -16,7 +16,13 @@ class SharedPrefs { String get token => _sharedPrefs.getString('token') ?? - 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjYzZTcyOGNlYTFlZDA2ZmY1ODUwYTdkOSIsImVtYWlsIjoic2F5ZWRfcmVzdEBnbWFpbC5jb20iLCJyb2xlIjoic3RvcmUiLCJpYXQiOjE2ODcxNjA5MjUsImV4cCI6MTY5NDkzNjkyNX0.MYYfG9EJrFaffcAoSYfxK7qGkurqcmQXbXb1tDyybQw'; + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjY0Zjk3Yjk0ZTJkYjI0Mjk5NzlkMzI3ZCIsImVtYWlsIjoib2ZmbGluZUBnbWFpbC5jb20iLCJyb2xlIjoic3RvcmUiLCJpYXQiOjE2OTQ1MDUyNDEsImV4cCI6MTcwMjI4MTI0MX0.DbrP2oHNBHN3bJB_nZrPe1dhPwHm8fqT_SpOKJRF3C8'; + + set limit(String limit) { + _sharedPrefs.setString('limit', limit); + } + + int get pageLimit => int.parse(_sharedPrefs.getString('limit') ?? '10'); set token(String value) { _sharedPrefs.setString('token', value); @@ -119,6 +125,13 @@ class SharedPrefs { set billingCounterId(String value) { _sharedPrefs.setString(Constants.billingCounterId, value); } + + String get businessRegisterId => + _sharedPrefs.getString(Constants.businessRegisterId) ?? ''; + + set businessRegisterId(String value) { + _sharedPrefs.setString(Constants.businessRegisterId, value); + } } final sharedPrefs = SharedPrefs(); diff --git a/lib/application/model/BusinessRegister/BusinessRegister.dart b/lib/application/model/BusinessRegister/BusinessRegister.dart new file mode 100644 index 0000000..6bae733 --- /dev/null +++ b/lib/application/model/BusinessRegister/BusinessRegister.dart @@ -0,0 +1,39 @@ +import 'package:wosull/helpers/Utils.dart'; + +class BusinessRegister { + final String id; + final double openedAmount; + final double closingCashAmount; + final double expectedCashAmount; + final double varianceCash; + final double closingCreditAmount; + final double expectedCreditAmount; + final double varianceCredit; + + BusinessRegister({ + required this.id, + required this.openedAmount, + required this.closingCashAmount, + required this.expectedCashAmount, + required this.varianceCash, + required this.closingCreditAmount, + required this.expectedCreditAmount, + required this.varianceCredit, + }); + + factory BusinessRegister.fromJson(Map json) { + return BusinessRegister( + id: json['_id'] ?? '', + openedAmount: Utils.checkDouble(json['opened_amount'] ?? '')!, + closingCashAmount: + Utils.checkDouble(json['closing_cash_amount'] ?? '')!, + expectedCashAmount: + Utils.checkDouble(json['expected_cash_amount'] ?? '')!, + varianceCash: Utils.checkDouble(json['variance_cash'] ?? '')!, + closingCreditAmount: + Utils.checkDouble(json['closing_credit_amount'] ?? '')!, + expectedCreditAmount: + Utils.checkDouble(json['expected_credit_amount'] ?? '')!, + varianceCredit: Utils.checkDouble(json['variance_credit'] ?? '')!); + } +} diff --git a/lib/application/model/BusinessRegister/BusinessRegisterResponse.dart b/lib/application/model/BusinessRegister/BusinessRegisterResponse.dart new file mode 100644 index 0000000..7c46b43 --- /dev/null +++ b/lib/application/model/BusinessRegister/BusinessRegisterResponse.dart @@ -0,0 +1,17 @@ +import 'package:wosull/application/model/BusinessRegister/BusinessRegister.dart'; + +class BusinessRegisterResponse { + final bool success; + final BusinessRegister businessRegister; + + BusinessRegisterResponse({ + required this.success, + required this.businessRegister, + }); + + factory BusinessRegisterResponse.fromJson(Map json) { + return BusinessRegisterResponse( + success: json['success'] ?? false, + businessRegister: BusinessRegister.fromJson(json['business_register'])); + } +} diff --git a/lib/application/model/Combo/AddNewComboModel.dart b/lib/application/model/Combo/AddNewComboModel.dart index 050dfc4..b5a04a5 100644 --- a/lib/application/model/Combo/AddNewComboModel.dart +++ b/lib/application/model/Combo/AddNewComboModel.dart @@ -9,7 +9,7 @@ class AddNewComboModel { List comboProducts = []; Map toJson() { - final Map data = Map(); + final Map data = {}; data['store_id'] = sharedPrefs.storeId; data['category_id'] = categoryId; data['combo_name'] = comboName; diff --git a/lib/application/model/Combo/ComboProduct.dart b/lib/application/model/Combo/ComboProduct.dart index d4af667..354faa9 100644 --- a/lib/application/model/Combo/ComboProduct.dart +++ b/lib/application/model/Combo/ComboProduct.dart @@ -1,4 +1,3 @@ - class ComboProducts { String? size; String? group; @@ -8,12 +7,17 @@ class ComboProducts { String? quantity; var price; - - ComboProducts({this.size, this.group, this.subGroup, this.product, - this.measurementId, this.quantity, this.price}); + ComboProducts( + {this.size, + this.group, + this.subGroup, + this.product, + this.measurementId, + this.quantity, + this.price}); Map toJson() { - final Map data = Map(); + final Map data = {}; data['size'] = size; data['group'] = group; data['subGroup'] = subGroup; @@ -23,4 +27,4 @@ class ComboProducts { data['price'] = price; return data; } -} \ No newline at end of file +} diff --git a/lib/application/model/inventory/SearchComboItemModel.dart b/lib/application/model/Combo/SearchComboItemModel.dart similarity index 95% rename from lib/application/model/inventory/SearchComboItemModel.dart rename to lib/application/model/Combo/SearchComboItemModel.dart index edb4739..8a12a11 100644 --- a/lib/application/model/inventory/SearchComboItemModel.dart +++ b/lib/application/model/Combo/SearchComboItemModel.dart @@ -1,4 +1,4 @@ -import '../Combo/GetComboModel.dart'; +import 'GetComboModel.dart'; class SearchComboItemModel { bool? success; diff --git a/lib/application/model/CreateAndUpdateOrder.dart b/lib/application/model/CreateAndUpdateOrder.dart index 23a8056..c4e948f 100644 --- a/lib/application/model/CreateAndUpdateOrder.dart +++ b/lib/application/model/CreateAndUpdateOrder.dart @@ -1,11 +1,12 @@ import 'package:flutter/foundation.dart'; import 'package:objectbox/objectbox.dart'; import 'package:wosull/application/model/Combo/GetComboModel.dart'; +import 'package:wosull/application/model/Modifiers/ModifierOption.dart'; import 'package:wosull/application/model/createOrder/OrderDetails.dart'; +import 'package:wosull/application/utils/Constants.dart'; import 'package:wosull/helpers/Utils.dart'; import '../localdb/SharedPrefs.dart'; -import 'Modifiers/GetModifiersModel.dart'; import 'store/StoreItemsResponse.dart'; @Entity() @@ -22,15 +23,21 @@ class CreateAndUpdateOrder { String? cartUniqueToken; String? destinationAddresses = "Business Bay"; double? minOrderPrice = 0.0; + + @Transient() var orderDetails = ToMany(); // List? orderDetails; + + String? orderDetailsOffline = ''; + String? storeId; String? orderId; String? cartId; - String? orderType = 'TAKE AWAY'; + String? orderType = Constants.takeawayService; String selectedTableName = ""; //for offline String createdAt = ''; + @Unique(onConflict: ConflictStrategy.replace) int cartUniqueId = 0; String? orderStatus; bool paymentStatus = false; @@ -38,12 +45,38 @@ class CreateAndUpdateOrder { double? amount; double? totalAmount; double? totalDiscount; + String? discountId; int? cardNumber; double? changeBalanceAmount; int? timer = 10; int? orderNumber; String? deliveryNotes; + Map toOfflineJson() { + final Map data = {}; + data['selectedTableName'] = selectedTableName; + data['orderStatus'] = orderStatus; + data['paymentStatus'] = paymentStatus; + data['paymentMode'] = paymentMode; + data['amount'] = amount; + data['totalAmount'] = totalAmount; + data['totalDiscount'] = totalDiscount; + data['deliveryNotes'] = deliveryNotes; + data['timer'] = timer; + data['changeBalanceAmount'] = changeBalanceAmount; + data['cardNumber'] = cardNumber; + data['discountId'] = discountId; + data['cart_unique_id'] = sharedPrefs.getCartUniqueId; + data['cart_unique_token'] = sharedPrefs.cartUniqueToken; + data['delivery_partner_id'] = deliveryPartnerId; + data['destination_addresses'] = 'Business Bay'; + data['min_order_price'] = minOrderPrice ?? 0; + data['order_details'] = orderDetailsOffline; + data['order_type'] = orderType ?? ''; + data['store_id'] = sharedPrefs.storeId; + return data; + } + CreateAndUpdateOrder( {this.totalCartPrice = 0.0, this.totalItemTax, @@ -72,17 +105,12 @@ class CreateAndUpdateOrder { Map toJson() { final Map data = {}; - // data['total_cart_price'] = totalCartPrice; - // data['total_item_tax'] = totalItemTax; - // if (sharedPrefs.cartID.isNotEmpty) { - // data['cartId'] = sharedPrefs.cartID; - // } data['cart_unique_id'] = sharedPrefs.getCartUniqueId; data['cart_unique_token'] = sharedPrefs.cartUniqueToken; data['delivery_partner_id'] = deliveryPartnerId; data['destination_addresses'] = 'Business Bay'; data['min_order_price'] = minOrderPrice ?? 0; - data['order_details'] = orderDetails!.map((v) => v.toJson()).toList(); + data['order_details'] = orderDetails.map((v) => v.toJson()).toList(); data['order_type'] = orderType ?? ''; data['store_id'] = sharedPrefs.storeId; return data; @@ -90,13 +118,11 @@ class CreateAndUpdateOrder { void addItem(StoreItems items, String selectedProductId) { int orderIndex = -1; - if (cartOrder.orderDetails != null) { - orderIndex = getIndex(selectedProductId); - } + orderIndex = getIndex(selectedProductId); items.totalItemPrice = getSingleItemPrice(items); // single item price if (orderIndex >= 0) { - cartOrder.orderDetails![orderIndex].items!.add(items); - cartOrder.orderDetails![orderIndex].productId = selectedProductId; + cartOrder.orderDetails[orderIndex].items.add(items); + cartOrder.orderDetails[orderIndex].productId = selectedProductId; addUpdateCartPrice(orderIndex); } else { addNewItemInOrderDetails(items, selectedProductId); @@ -108,19 +134,19 @@ class CreateAndUpdateOrder { } void addUpdateCartPrice(int orderIndex) { - cartOrder.orderDetails![orderIndex].totalItemPrice = - getTotalItemPrice(cartOrder.orderDetails![orderIndex]); - cartOrder.orderDetails![orderIndex].totalItemTax = 0.0; + cartOrder.orderDetails[orderIndex].totalItemPrice = + getTotalItemPrice(cartOrder.orderDetails[orderIndex]); + cartOrder.orderDetails[orderIndex].totalItemTax = 0.0; cartOrder.totalCartPrice = getTotalCartPrice(); } void addNote(StoreItems items, String selectedProductId, String note) { int orderIndex = getIndex(selectedProductId); try { - int itemIndex = getItemIndexInOrderDetails(orderIndex, items.id); + int itemIndex = getItemIndexInOrderDetails(orderIndex, items.itemId); int quantity = getQuantityForAdd(orderIndex, itemIndex); - cartOrder.orderDetails![orderIndex].items![itemIndex] + cartOrder.orderDetails[orderIndex].items[itemIndex] .noteForItem![quantity - 1] = note; } catch (e) { if (kDebugMode) { @@ -131,23 +157,23 @@ class CreateAndUpdateOrder { int getItemIndexWithId(StoreItems items, String selectedProductId) { int parent = getIndex(selectedProductId); - return getItemIndexInOrderDetails(parent, items.id); + return getItemIndexInOrderDetails(parent, items.itemId); } int getQuantityForAdd(int parent, int child) { - return cartOrder.orderDetails![parent].items![child].quantity; + return cartOrder.orderDetails[parent].items[child].quantity ?? 1; } int getItemIndexInOrderDetails(int parent, String id) { - return cartOrder.orderDetails![parent].items! - .indexWhere((element) => element.id == id); + return cartOrder.orderDetails[parent].items + .indexWhere((element) => element.itemId == id); } void removeModifierOnDecrease(StoreItems items, String selectedProductId) { int orderIndex = getIndex(selectedProductId); try { - int itemIndex = getItemIndexInOrderDetails(orderIndex, items.id); - cartOrder.orderDetails![orderIndex].items![itemIndex].selectedModifiers + int itemIndex = getItemIndexInOrderDetails(orderIndex, items.itemId); + cartOrder.orderDetails[orderIndex].items[itemIndex].selectedModifiers .removeWhere((element) => element.qtyIdx == items.quantity); } catch (e) { if (kDebugMode) { @@ -159,8 +185,8 @@ class CreateAndUpdateOrder { void removeModifier(StoreItems items, String selectedProductId) { int orderIndex = getIndex(selectedProductId); try { - int itemIndex = getItemIndexInOrderDetails(orderIndex, items.id); - cartOrder.orderDetails![orderIndex].items![itemIndex].selectedModifiers + int itemIndex = getItemIndexInOrderDetails(orderIndex, items.itemId); + cartOrder.orderDetails[orderIndex].items[itemIndex].selectedModifiers .removeWhere((element) => element.qtyIdx == items.quantity); } catch (e) { if (kDebugMode) { @@ -174,8 +200,8 @@ class CreateAndUpdateOrder { int orderIndex = getIndex(selectedProductId); try { items.totalItemPrice = getSingleItemPrice(items); // single item price - int itemIndex = getItemIndexInOrderDetails(orderIndex, items.id); - cartOrder.orderDetails![orderIndex].items![itemIndex] = items; + int itemIndex = getItemIndexInOrderDetails(orderIndex, items.itemId); + cartOrder.orderDetails[orderIndex].items[itemIndex] = items; addUpdateCartPrice(orderIndex); } catch (e) { if (kDebugMode) { @@ -187,12 +213,12 @@ class CreateAndUpdateOrder { void removeItem(StoreItems items, String selectedProductId) { int orderIndex = getIndex(selectedProductId); if (orderIndex >= 0) { - cartOrder.orderDetails![orderIndex].items! - .removeWhere((element) => element.id == items.id); - cartOrder.orderDetails![orderIndex].productId = selectedProductId; + cartOrder.orderDetails[orderIndex].items + .removeWhere((element) => element.itemId == items.itemId); + cartOrder.orderDetails[orderIndex].productId = selectedProductId; addUpdateCartPrice(orderIndex); - if (cartOrder.orderDetails![orderIndex].items!.isEmpty) { - cartOrder.orderDetails!.removeAt(orderIndex); + if (cartOrder.orderDetails[orderIndex].items.isEmpty) { + cartOrder.orderDetails.removeAt(orderIndex); } } } @@ -200,10 +226,10 @@ class CreateAndUpdateOrder { void addNewItemInOrderDetails(StoreItems items, String selectedProductId) { final orderDetails = OrderDetails(items: ToMany(items: [])); // orderDetails.items = []; - orderDetails.items!.add(items); + orderDetails.items.add(items); + // orderDetails.obid = orderDetails.obid + 100; orderDetails.productId = selectedProductId; orderDetails.totalItemTax = 0.0; - cartOrder.orderDetails ??= ToMany(items: []); cartOrder.orderDetails.add(orderDetails); int orderIndex = getIndex(selectedProductId); addUpdateCartPrice(orderIndex); @@ -213,11 +239,11 @@ class CreateAndUpdateOrder { StoreItems items, String selectedProductId) { int orderIndex = getIndex(selectedProductId); if (orderIndex >= 0) { - int itemIndex = cartOrder.orderDetails![orderIndex].items! - .indexWhere((element) => element.id == items.id); + int itemIndex = cartOrder.orderDetails[orderIndex].items + .indexWhere((element) => element.itemId == items.itemId); return cartOrder - .orderDetails![orderIndex].items![itemIndex].selectedModifiers; + .orderDetails[orderIndex].items[itemIndex].selectedModifiers; } return []; } @@ -225,11 +251,10 @@ class CreateAndUpdateOrder { List getCombos(StoreItems items, String selectedProductId) { int orderIndex = getIndex(selectedProductId); if (orderIndex >= 0) { - int itemIndex = cartOrder.orderDetails![orderIndex].items! - .indexWhere((element) => element.id == items.id); + int itemIndex = cartOrder.orderDetails[orderIndex].items + .indexWhere((element) => element.itemId == items.itemId); - return cartOrder - .orderDetails![orderIndex].items![itemIndex].selectedCombos; + return cartOrder.orderDetails[orderIndex].items[itemIndex].selectedCombos; } return []; } @@ -237,19 +262,19 @@ class CreateAndUpdateOrder { List getNotes(StoreItems items, String selectedProductId) { int orderIndex = getIndex(selectedProductId); if (orderIndex >= 0) { - int itemIndex = cartOrder.orderDetails![orderIndex].items! - .indexWhere((element) => element.id == items.id); + int itemIndex = cartOrder.orderDetails[orderIndex].items + .indexWhere((element) => element.itemId == items.itemId); - return cartOrder.orderDetails![orderIndex].items![itemIndex].noteForItem!; + return cartOrder.orderDetails[orderIndex].items[itemIndex].noteForItem!; } return []; } -//will get all items price in single order + //will get all items price in single order double getTotalItemPrice(OrderDetails orderDetails) { double totalPrice = 0.0; - for (var item in orderDetails.items!) { - totalPrice += item.totalItemPrice; + for (var item in orderDetails.items) { + totalPrice += item.totalItemPrice ?? 0.0; } return totalPrice; @@ -257,21 +282,10 @@ class CreateAndUpdateOrder { //set single item price with modifier double getSingleItemPrice(StoreItems item) { - double totalPrice = item.price * item.quantity; // item price only + double totalPrice = item.price * item.quantity!; // item price only //will add modifier price - print('Total ' + totalPrice.toString()); - - // if (item.isCombo) { - // for (int i = 0; i < item.selectedCombos!.length; i++) { - // print('combo price ' + item.selectedCombos![i].price!.toString()); - // final itemPrice = item.selectedCombos![i].price!; - // totalPrice += itemPrice; - // } - // } - if (item.selectedModifiers.isNotEmpty) { for (int i = 0; i < item.selectedModifiers.length; i++) { - print('modi price ' + item.selectedModifiers[i].price.toString()); final itemPrice = item.selectedModifiers[i].price; totalPrice += itemPrice; } @@ -283,17 +297,15 @@ class CreateAndUpdateOrder { //get total cart price double getTotalCartPrice() { double totalPrice = 0.0; - if (cartOrder.orderDetails != null) { - for (int i = 0; i < cartOrder.orderDetails!.length; i++) { - final itemPrice = cartOrder.orderDetails![i].totalItemPrice!; - totalPrice += itemPrice; - } + for (int i = 0; i < cartOrder.orderDetails.length; i++) { + final itemPrice = cartOrder.orderDetails[i].totalItemPrice!; + totalPrice += itemPrice; } return totalPrice; } int getIndex(String id) { - return cartOrder.orderDetails! + return cartOrder.orderDetails .indexWhere((element) => element.productId! == id); } @@ -321,9 +333,10 @@ class CreateAndUpdateOrder { var quantity = 1; if (orderIndex >= 0) { try { - quantity = cartOrder.orderDetails![orderIndex].items! - .singleWhere((element) => element.id == itemId) - .quantity; + quantity = cartOrder.orderDetails[orderIndex].items + .singleWhere((element) => element.itemId == itemId) + .quantity ?? + 1; } catch (e) { quantity = 1; } @@ -342,16 +355,14 @@ class CreateAndUpdateOrder { cartOrder.orderType = 'TAKE AWAY'; cartOrder.totalCartPrice = 0.0; cartOrder.totalItemTax = 0.0; - if (cartOrder.orderDetails != null) { - cartOrder.orderDetails!.clear(); - } + cartOrder.orderDetails.clear(); } bool isThere(String id) { // int index = -1; if (cartOrder.orderDetails != null) { - return cartOrder.orderDetails! - .any((element) => element.items!.any((element) => element.id == id)); + return cartOrder.orderDetails.any( + (element) => element.items.any((element) => element.itemId == id)); } else { return false; } diff --git a/lib/application/model/DeliveryPartner/GetDeliveryPartner.dart b/lib/application/model/DeliveryPartner/GetDeliveryPartner.dart index 10e4bef..02a41a6 100644 --- a/lib/application/model/DeliveryPartner/GetDeliveryPartner.dart +++ b/lib/application/model/DeliveryPartner/GetDeliveryPartner.dart @@ -46,27 +46,28 @@ class DeliveryPartner { String createdAt; String updatedAt; List? stores = []; + int? totalItemCount; - DeliveryPartner({ - this.id = '', - this.status = '', - this.nameArabic = '', - this.stores, - this.name = '', - this.createdAt = '', - this.updatedAt = '', - }); + DeliveryPartner( + {this.id = '', + this.status = '', + this.nameArabic = '', + this.stores, + this.name = '', + this.createdAt = '', + this.updatedAt = '', + this.totalItemCount}); factory DeliveryPartner.fromJson(Map json) { return DeliveryPartner( - stores: json['store_id'] != null ? json['store_id'].cast() : [], - id: json['_id'] ?? '', - name: json['name'] ?? '', - nameArabic: json['arabic_name'] ?? '', - status: json['status'] ?? '', - createdAt: json['createdAt'] ?? '', - updatedAt: json['updatedAt'] ?? '', - ); + stores: json['store_id'] != null ? json['store_id'].cast() : [], + id: json['_id'] ?? '', + name: json['name'] ?? '', + nameArabic: json['arabic_name'] ?? '', + status: json['status'] ?? '', + createdAt: json['createdAt'] ?? '', + updatedAt: json['updatedAt'] ?? '', + totalItemCount: json['total_item_count'] ?? 0); } bool getStatus() { diff --git a/lib/application/model/inventory/GetMeasurementCategory.dart b/lib/application/model/Measurement/GetMeasurementCategory.dart similarity index 100% rename from lib/application/model/inventory/GetMeasurementCategory.dart rename to lib/application/model/Measurement/GetMeasurementCategory.dart diff --git a/lib/application/model/Measurement/GetStoreMeasurementModel.dart b/lib/application/model/Measurement/GetStoreMeasurementModel.dart new file mode 100644 index 0000000..122660c --- /dev/null +++ b/lib/application/model/Measurement/GetStoreMeasurementModel.dart @@ -0,0 +1,18 @@ +import 'package:wosull/application/model/Measurement/InventoryMeasurementModel.dart'; + +class GetStoreMeasurementModel { + bool? success; + List? measurements; + + GetStoreMeasurementModel({this.success, this.measurements}); + + factory GetStoreMeasurementModel.fromJson(Map json) { + return GetStoreMeasurementModel( + success: json['success'] ?? false, + measurements: json['measurement'] != null + ? List.from(json['measurement']) + .map((i) => Measurement.fromJson(i)) + .toList() + : []); + } +} diff --git a/lib/application/model/inventory/InventoryMeasurementModel.dart b/lib/application/model/Measurement/InventoryMeasurementModel.dart similarity index 71% rename from lib/application/model/inventory/InventoryMeasurementModel.dart rename to lib/application/model/Measurement/InventoryMeasurementModel.dart index 961091e..27a3393 100644 --- a/lib/application/model/inventory/InventoryMeasurementModel.dart +++ b/lib/application/model/Measurement/InventoryMeasurementModel.dart @@ -13,7 +13,6 @@ class InventoryMeasurementModel { } } - class InvoiceMeasurementModel { bool? success; List? measurements; @@ -23,9 +22,11 @@ class InvoiceMeasurementModel { factory InvoiceMeasurementModel.fromJson(Map json) { return InvoiceMeasurementModel( success: json['success'] ?? false, - measurements: json['measurement'] != null ? List.from(json['measurement']) - .map((i) => Measurement.fromJson(i)) - .toList() : []); + measurements: json['measurment'] != null + ? List.from(json['measurment']) + .map((i) => Measurement.fromJson(i)) + .toList() + : []); } } @@ -38,9 +39,11 @@ class ProductMeasurementModel { factory ProductMeasurementModel.fromJson(Map json) { return ProductMeasurementModel( success: json['success'] ?? false, - measurements: json['measurment'] != null ? List.from(json['measurment']) - .map((i) => Measurement.fromJson(i)) - .toList() : []); + measurements: json['measurment'] != null + ? List.from(json['measurment']) + .map((i) => Measurement.fromJson(i)) + .toList() + : []); } } @@ -52,7 +55,6 @@ class Measurement { String? createdAt; String? updatedAt; - bool getStatus() { return status == "Inactive" ? false : true; } @@ -68,10 +70,10 @@ class Measurement { factory Measurement.fromJson(Map data) { return Measurement( id: data['_id'] ?? "", - name: data['name'] ?? "", - measurement: data['measurement_unit'] ?? "", - status: data[ 'status'] ?? "", - createdAt: data['created_at'] ?? "", - updatedAt: data['updated_at'] ?? ""); + name: data['name'] ?? "", + measurement: data['measurement_unit'] ?? "", + status: data['status'] ?? "", + createdAt: data['created_at'] ?? "", + updatedAt: data['updated_at'] ?? ""); } } diff --git a/lib/application/model/inventory/MeasurementUnitModel.dart b/lib/application/model/Measurement/MeasurementUnitModel.dart similarity index 100% rename from lib/application/model/inventory/MeasurementUnitModel.dart rename to lib/application/model/Measurement/MeasurementUnitModel.dart diff --git a/lib/application/model/Measurement/MeasuringUnit.dart b/lib/application/model/Measurement/MeasuringUnit.dart new file mode 100644 index 0000000..48158e5 --- /dev/null +++ b/lib/application/model/Measurement/MeasuringUnit.dart @@ -0,0 +1,18 @@ +import 'package:wosull/application/model/Measurement/MeasurementUnitModel.dart'; + +class MeasuringUnit { + bool success; + List measurementUnits; + + MeasuringUnit({this.success = false, this.measurementUnits = const []}); + + factory MeasuringUnit.fromJson(Map json) { + return MeasuringUnit( + success: json['success'] ?? false, + measurementUnits: json['measuring_unit'] != null + ? List.from(json['measuring_unit']) + .map((i) => MeasurementUnit.fromJson(i)) + .toList() + : []); + } +} diff --git a/lib/application/model/Modifiers/GetModifiersModel.dart b/lib/application/model/Modifiers/GetModifiersModel.dart index 52c6098..c318fdc 100644 --- a/lib/application/model/Modifiers/GetModifiersModel.dart +++ b/lib/application/model/Modifiers/GetModifiersModel.dart @@ -1,7 +1,4 @@ -import 'package:objectbox/objectbox.dart'; -import 'package:wosull/application/localdb/SharedPrefs.dart'; - -import '../../../helpers/Utils.dart'; +import 'package:wosull/application/model/Modifiers/Modifier.dart'; class GetModifiersModel { bool? success; @@ -19,129 +16,3 @@ class GetModifiersModel { : []); } } - -@Entity() -class Modifier { - @Id() - int obid = 0; - - String id; - String name; - String arabicName; - String description; - double price; - String status = "Inactive"; - bool isMultiple; - var options = ToMany(); - var selected = ToMany(); - String createdOn; - String updatedOn; - bool isSelected; - int selectedModifierIndex = 0; - - Modifier( - {this.id = '', - this.name = '', - this.arabicName = '', - this.description = '', - this.price = 0.0, - required this.options, - required this.selected, - this.status = '', - this.isSelected = false, - this.isMultiple = false, - this.createdOn = '', - this.updatedOn = ''}); - - factory Modifier.fromJson(Map json) { - return Modifier( - id: json['_id'] ?? "", - name: json['name'] ?? "", - arabicName: - json['arabicName'] != null ? json['arabicName'] as String : '', - description: json['description'] ?? "", - price: Utils.checkDouble(json['price'])!, - options: ToMany( - items: json['options'] != null - ? List.from(json['options']) - .map((i) => ModifierOption.fromJson(i)) - .toList() - : []), - selected: ToMany( - items: json['selected'] != null - ? List.from(json['selected']) - .map((i) => ModifierOption.fromJson(i)) - .toList() - : []), - status: json['status'] != null ? json['status'] ?? 'Inactive' : '', - isMultiple: json['is_multiple'] ?? false, - createdOn: - json['created_at'] != null ? json['created_at'] as String : '', - updatedOn: - json['updated_at'] != null ? json['updated_at'] as String : ''); - } - - Map toJson() { - final Map data = {}; - data['name'] = name; - data['arabicName'] = arabicName; - data['store_id'] = sharedPrefs.storeId; - data['status'] = status; - data['is_multiple'] = isMultiple; - data['options'] = options; - data['selected'] = selected; - data['modifier_id'] = id; - if (selectedModifierIndex > 0) { - data['selectedModifierIndex'] = selectedModifierIndex; - } - - return data; - } - - bool getStatus() { - return status == "Inactive" ? false : true; - } -} - -@Entity() -class ModifierOption { - @Id() - int obid = 0; - - String name; - String arabicName; - double price; - bool isSelected = false; - String modifierName; - int qtyIdx; - - ModifierOption( - {this.name = '', - this.arabicName = '', - this.price = 0, - this.isSelected = false, - this.modifierName = '', - this.qtyIdx = 1}); - - factory ModifierOption.fromJson(Map json) { - return ModifierOption( - name: json['name'] ?? "", - arabicName: json['arabic_name'] ?? "", - price: Utils.checkDouble(json['price'] ?? 0.0)!, - isSelected: json['is_selected'] ?? false, - modifierName: json['modifier'] ?? "", - qtyIdx: json['qtyIdx'] ?? 1, - ); - } - - Map toJson() { - final Map data = {}; - data['name'] = name; - data['arabic_name'] = arabicName; - data['price'] = price; - data['is_selected'] = isSelected; - data['modifier'] = modifierName; - data['qtyIdx'] = qtyIdx; - return data; - } -} diff --git a/lib/application/model/Modifiers/Modifier.dart b/lib/application/model/Modifiers/Modifier.dart new file mode 100644 index 0000000..cd336b8 --- /dev/null +++ b/lib/application/model/Modifiers/Modifier.dart @@ -0,0 +1,85 @@ +import 'package:objectbox/objectbox.dart'; +import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/application/model/Modifiers/ModifierOption.dart'; +import 'package:wosull/helpers/Utils.dart'; + +@Entity() +class Modifier { + @Id() + int obid = 0; + + String id; + String name; + String arabicName; + String description; + double price; + String status = "Active"; + bool isMultiple; + var options = ToMany(); + var selected = ToMany(); + String createdOn; + String updatedOn; + bool isSelected; + int selectedModifierIndex = 0; + + Modifier( + {this.id = '', + this.name = '', + this.arabicName = '', + this.description = '', + this.price = 0.0, + required this.options, + required this.selected, + this.status = 'Active', + this.isSelected = false, + this.isMultiple = false, + this.createdOn = '', + this.updatedOn = ''}); + + factory Modifier.fromJson(Map json) { + return Modifier( + id: json['_id'] ?? "", + name: json['name'] ?? "", + arabicName: json['arabicName'] ?? '', + description: json['description'] ?? "", + price: Utils.checkDouble(json['price'])!, + options: ToMany( + items: json['options'] != null + ? List.from(json['options']) + .map((i) => ModifierOption.fromJson(i)) + .toList() + : []), + selected: ToMany( + items: json['selected'] != null + ? List.from(json['selected']) + .map((i) => ModifierOption.fromJson(i)) + .toList() + : []), + status: json['status'] ?? 'Inactive', + isMultiple: json['is_multiple'] ?? false, + createdOn: json['created_at'] ?? '', + updatedOn: json['updated_at'] ?? ''); + } + + Map toJson() { + final Map data = {}; + data['name'] = name; + data['arabicName'] = arabicName; + data['store_id'] = sharedPrefs.storeId; + data['status'] = status; + data['is_multiple'] = isMultiple; + data['modifier_id'] = id; + //data['options'] = options; + // data['selected'] = selected; + + // if (selectedModifierIndex > 0) { + // data['selectedModifierIndex'] = selectedModifierIndex; + // } + + return data; + } + + bool getStatus() { + return status == "Inactive" ? false : true; + } +} diff --git a/lib/application/model/Modifiers/ModifierOption.dart b/lib/application/model/Modifiers/ModifierOption.dart new file mode 100644 index 0000000..2cad390 --- /dev/null +++ b/lib/application/model/Modifiers/ModifierOption.dart @@ -0,0 +1,60 @@ +import 'package:objectbox/objectbox.dart'; +import 'package:wosull/application/model/ingredients/AddIngredient.dart'; +import 'package:wosull/helpers/Utils.dart'; + +@Entity() +class ModifierOption { + @Id() + int obid = 0; + + String id; + String modifierId; + String name; + String arabicName; + double price; + var ingredients = ToMany(); + bool isSelected = false; + String modifierName; + int qtyIdx; + + ModifierOption( + {this.name = '', + this.id = '', + this.modifierId = '', + this.arabicName = '', + this.price = 0, + required this.ingredients, + this.isSelected = false, + this.modifierName = '', + this.qtyIdx = 1}); + + factory ModifierOption.fromJson(Map json) { + return ModifierOption( + id: json['_id'] ?? '', + modifierId: json['modifier_id'] ?? '', + name: json['name'] ?? '', + arabicName: json['arabic_name'] ?? '', + price: Utils.checkDouble(json['price'] ?? 0.0)!, + isSelected: json['is_selected'] ?? false, + modifierName: json['modifier'] ?? '', + qtyIdx: json['qtyIdx'] ?? 1, + ingredients: ToMany( + items: json['ingredients'] != null + ? List.from(json['ingredients']) + .map((i) => AddIngredient.fromJson(i)) + .toList() + : []), + ); + } + + Map toJson() { + final Map data = {}; + data['name'] = name; + data['arabic_name'] = arabicName; + data['price'] = price; + data['is_selected'] = isSelected; + data['modifier'] = modifierName; + data['qtyIdx'] = qtyIdx; + return data; + } +} diff --git a/lib/application/model/Products/AddProduct.dart b/lib/application/model/Products/AddProduct.dart new file mode 100644 index 0000000..247ec7e --- /dev/null +++ b/lib/application/model/Products/AddProduct.dart @@ -0,0 +1,218 @@ +import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/application/model/DeliveryPartner/ItemsDeliveryPartner.dart'; +import 'package:wosull/application/model/Modifiers/ModifierOption.dart'; +import 'package:wosull/application/model/Products/ProductId.dart'; +import 'package:wosull/application/model/ingredients/AddIngredient.dart'; + +import '../../../helpers/Utils.dart'; + +class AddProduct { + String itemId = ""; + + String name; + + List? noteForItem = []; + String storeId; + bool isUnlimitedQuantity; + String itemNameArabic; + ProductId? productId; + String productIdSt = ''; + + String product_product_id = ''; + double? price; + int? uniqueId; + String uniqueIdForStoreData; + + int? quantity; + String imageUrl = ""; + String updatedAt; + bool isItemInStock = false; + String description; + String descriptionArabic; + double? purchasePrice; + int? stockAlertQuantity; + double? itemPriceWithOutOffer; + int? totalAddedQuantity; + int? totalUsedQuantity; + double? salePriceExclusiveTax; + + double? totalItemPrice; + String supplier; + String discount; + String measurementCategory; + String measurement; + String measurementUnit; + String brand; + String deliveryPartner; + String manufactureDate; + String expireDate; + bool status; + bool isCombo = false; + bool isCheckedForReturn = false; + + List selectedModifiers = []; + List ingredients = []; + List modifiers = []; + List deliveryPartners = []; + + AddProduct( + {this.name = '', + this.itemId = '', + required this.deliveryPartners, + this.isUnlimitedQuantity = false, + this.storeId = '', + this.deliveryPartner = '', + this.itemNameArabic = '', + this.productId, + this.price, + this.uniqueId, + this.measurementUnit = '', + this.uniqueIdForStoreData = '', + this.quantity, + this.imageUrl = '', + this.updatedAt = '', + this.totalItemPrice, + this.isItemInStock = false, + this.description = '', + this.descriptionArabic = '', + this.purchasePrice, + this.stockAlertQuantity, + this.itemPriceWithOutOffer, + this.totalAddedQuantity, + this.noteForItem, + this.totalUsedQuantity, + this.salePriceExclusiveTax, + required this.modifiers, + required this.ingredients, + required this.selectedModifiers, + this.supplier = '', + this.discount = '', + this.measurementCategory = '', + this.measurement = '', + this.brand = '', + this.isCombo = false, + this.manufactureDate = '', + this.expireDate = '', + this.status = false}); + + factory AddProduct.fromJson(Map json) { + return AddProduct( + status: json['status'] ?? false, + name: json['name'] as String, + itemNameArabic: json['item_name_arabic'] ?? "", + itemId: json['_id'] ?? "", + deliveryPartner: json['delivery_partner'] ?? "", + isUnlimitedQuantity: json['unlimited_quantity'] ?? false, + storeId: json['store_id'] ?? "", + productId: ProductId.fromJson(json['product_id']), + price: Utils.checkDouble(json['price'])!, + uniqueId: json['unique_id'] ?? 0, + totalItemPrice: Utils.checkDouble(json['totalItemPrice'])!, + description: json['details'] ?? "", + totalAddedQuantity: json['total_quantity'] ?? 0, + stockAlertQuantity: json['stock_alert_quantity'] ?? 0, + discount: json['discount'] ?? "", + supplier: json['supplier'] ?? "", + purchasePrice: Utils.checkDouble(json['purchase_cost'])!, + measurement: json['measurement'] ?? "", + manufactureDate: json['manufacturer_date'] ?? "", + expireDate: json['expiry_date'] ?? "", + isCombo: json['isCombo'] ?? false, + salePriceExclusiveTax: + Utils.checkDouble(json['sale_price_exclusive_tax'])!, + descriptionArabic: json['item_description_arabic'] ?? "", + uniqueIdForStoreData: json['unique_id_for_store_data'] ?? "0", + quantity: json['quantity'] ?? 0, + measurementUnit: json['measurement_unit'] ?? '', + selectedModifiers: json['selectedModifiers'] != null + ? List.from(json['selectedModifiers']) + .map((i) => ModifierOption.fromJson(i)) + .toList() + : [], + imageUrl: json['image_url'] != null + ? Utils.checkList(json['image_url'])! + : "", + updatedAt: json['updated_at'] ?? '', + isItemInStock: json['is_item_in_stock'] ?? false, + deliveryPartners: json['delivery_partners'] != null + ? List.from(json['delivery_partners']) + .map((i) => ItemsDeliveryPartner.fromJson(i)) + .toList() + : [], + modifiers: + json['modifiers'] != null ? Utils.getList(json['modifiers'])! : [], + ingredients: json['ingrediants'] != null + ? List.from(json['ingrediants']) + .map((i) => AddIngredient.fromJson(i)) + .toList() + : []); + } + + Map toJsonProduct() { + final Map data = {}; + data['product_id'] = productIdSt; + data['store_id'] = sharedPrefs.storeId; + data['name'] = name; + data['unlimited_quantity'] = isUnlimitedQuantity; + data['unique_id_for_store_data'] = uniqueIdForStoreData; + data['is_item_in_stock'] = isItemInStock; + data['item_name_arabic'] = itemNameArabic; + data['item_description_arabic'] = descriptionArabic; + data['details'] = description; + data['total_quantity'] = totalAddedQuantity; + data['sale_price_exclusive_tax'] = salePriceExclusiveTax; + data['stock_alert_quantity'] = stockAlertQuantity; + data['is_visible_in_store'] = true; + data['price'] = price; + if (supplier.isNotEmpty) { + data['supplier'] = supplier; + } + if (discount.isNotEmpty) { + data['discount'] = discount ?? ""; + } + data['purchase_cost'] = purchasePrice; + //data['totalItemPrice'] = totalItemPrice ?? 0.0; + data['delivery_partners'] = deliveryPartners; + data['measurement'] = measurement ?? ""; + data['manufacturer_date'] = manufactureDate; + data['expiry_date'] = expireDate; + data['ingrediants'] = ingredients; + data['modifiers'] = modifiers; + return data; + } + + Map toJsonUpdateProduct() { + final Map data = {}; + data['product_id'] = productId!.toJson(); + data['store_id'] = sharedPrefs.storeId; + data['name'] = name; + data['unlimited_quantity'] = isUnlimitedQuantity ?? false; + data['productId'] = product_product_id ?? "0"; + data['_id'] = itemId; + data['unique_id_for_store_data'] = uniqueIdForStoreData; + data['is_item_in_stock'] = isItemInStock; + data['item_name_arabic'] = itemNameArabic; + data['item_description_arabic'] = descriptionArabic; + data['details'] = description; + data['total_quantity'] = totalAddedQuantity; + data['sale_price_exclusive_tax'] = salePriceExclusiveTax; + data['stock_alert_quantity'] = stockAlertQuantity; + data['is_visible_in_store'] = true; + data['price'] = price; + data['purchase_cost'] = purchasePrice; + data['quantity'] = quantity ?? 1; + if (supplier.isNotEmpty) { + data['supplier'] = supplier ?? ""; + } + if (discount.isNotEmpty) { + data['discount'] = discount ?? ""; + } + data['delivery_partners'] = deliveryPartners; + data['measurement'] = measurement ?? ""; + data['manufacturer_date'] = manufactureDate ?? ""; + data['expiry_date'] = expireDate ?? ""; + data['ingrediants'] = ingredients; + data['modifiers'] = modifiers; + return data; + } +} diff --git a/lib/application/model/Products/GetProductResponse.dart b/lib/application/model/Products/GetProductResponse.dart new file mode 100644 index 0000000..8fd12d9 --- /dev/null +++ b/lib/application/model/Products/GetProductResponse.dart @@ -0,0 +1,28 @@ +import 'package:wosull/application/model/store/StoreItemsResponse.dart'; + +class GetProductResponse { + bool success; + int count; + int message; + int pages; + List storeItems; + + GetProductResponse( + {this.success = false, + this.count = 0, + this.message = 0, + this.pages = 0, + this.storeItems = const []}); + + factory GetProductResponse.fromJson(Map json) { + return GetProductResponse( + success: json['success'] ?? false, + count: json['count'] ?? 0, + pages: json['pages'] ?? 0, + storeItems: json['items'] != null + ? List.from(json['items']) + .map((i) => StoreItems.fromJson(i)) + .toList() + : []); + } +} diff --git a/lib/application/model/Products/ItemProductModel.dart b/lib/application/model/Products/ItemProductModel.dart index 4036e80..e50f8dd 100644 --- a/lib/application/model/Products/ItemProductModel.dart +++ b/lib/application/model/Products/ItemProductModel.dart @@ -2,15 +2,17 @@ import '../inventory/ItemSubCategoryResponse.dart'; class ItemProductModel { bool success; - ItemSubCategory product; + List product; ItemProductModel({required this.success, required this.product}); factory ItemProductModel.fromJson(Map json) { return ItemProductModel( success: json['success'] ?? false, - product: json['success'] == true - ? ItemSubCategory.fromJson(json['product']) - : ItemSubCategory()); + product: json['product'] != null + ? List.from(json['product']) + .map((i) => ItemSubCategory.fromJson(i)) + .toList() + : []); } } diff --git a/lib/application/model/Products/ProductById.dart b/lib/application/model/Products/ProductById.dart new file mode 100644 index 0000000..bb9fa6a --- /dev/null +++ b/lib/application/model/Products/ProductById.dart @@ -0,0 +1,14 @@ +import 'package:wosull/application/model/Products/AddProduct.dart'; + +class ProductById { + bool success; + AddProduct item; + + ProductById({required this.success, required this.item}); + + factory ProductById.fromJson(Map json) { + return ProductById( + success: json['success'] ?? false, + item: AddProduct.fromJson(json['product'])); + } +} diff --git a/lib/application/model/Products/ProductId.dart b/lib/application/model/Products/ProductId.dart new file mode 100644 index 0000000..bbf1c81 --- /dev/null +++ b/lib/application/model/Products/ProductId.dart @@ -0,0 +1,24 @@ +import 'package:objectbox/objectbox.dart'; + +@Entity() +class ProductId { + @Id() + int obid = 0; + + String? productId; + String? categoryId; + + ProductId({this.productId, this.categoryId}); + + factory ProductId.fromJson(Map json) { + return ProductId( + productId: json['_id'] ?? '', categoryId: json['category_id'] ?? ''); + } + + Map toJson() { + final Map data = {}; + data['category_id'] = categoryId; + data['_id'] = productId; + return data; + } +} diff --git a/lib/application/model/Products/SearchProductResponse.dart b/lib/application/model/Products/SearchProductResponse.dart new file mode 100644 index 0000000..58a11b9 --- /dev/null +++ b/lib/application/model/Products/SearchProductResponse.dart @@ -0,0 +1,18 @@ +import 'package:wosull/application/model/store/StoreItemsResponse.dart'; + +class SearchItemsResponse { + bool? success; + List? storeItems; + + SearchItemsResponse({this.success, this.storeItems}); + + factory SearchItemsResponse.fromJson(Map json) { + return SearchItemsResponse( + success: json['success'] ?? false, + storeItems: json['item'] != null + ? List.from(json['item']) + .map((i) => StoreItems.fromJson(i)) + .toList() + : []); + } +} diff --git a/lib/application/model/ReturnStock/ReturnStock.dart b/lib/application/model/ReturnStock/ReturnStock.dart new file mode 100644 index 0000000..05331f1 --- /dev/null +++ b/lib/application/model/ReturnStock/ReturnStock.dart @@ -0,0 +1,126 @@ +import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/application/model/ReturnStock/ReturnStockCharges.dart'; +import 'package:wosull/application/model/store/StoreInvoicesModel.dart'; +import 'package:wosull/helpers/Utils.dart'; + +class ReturnStock { + String? id; + String? storeId; + Supplier? supplierId; + String? stockReference; + String? currency; + String? taxOption; + String? stockReturnDate; + List? products; + List? charges; + String? discountType; + String? notes; + double? shippingCharges; + double? packingCharges; + double? totalDiscountAmount; + double? totalVat; + double? totalAmount; + double? totalExcludingVat; + double? totalTaxableAmount; + bool? isDeleted; + String? createdAt; + String? updatedAt; + int? uniqueId; + + ReturnStock({ + this.id, + this.storeId, + this.supplierId, + this.stockReference, + this.currency, + this.taxOption, + this.stockReturnDate, + this.products, + this.charges, + this.discountType, + this.notes, + this.shippingCharges, + this.packingCharges, + this.totalDiscountAmount, + this.totalVat, + this.totalAmount, + this.totalExcludingVat, + this.totalTaxableAmount, + this.isDeleted, + this.createdAt, + this.updatedAt, + this.uniqueId, + }); + + factory ReturnStock.fromJson(Map json) { + return ReturnStock( + id: json['_id'] ?? '', + storeId: json['store_id'] ?? '', + supplierId: json['supplier_id'] != null + ? Supplier.fromJson(json['supplier_id']) + : Supplier(id: '', name: ''), + stockReference: json['stock_reference'] ?? '', + currency: json['currency'] ?? '', + taxOption: json['tax_option'] ?? '', + stockReturnDate: json['stock_return_date'] ?? '', + products: json['products'] != null + ? List.from(json['products']) + .map((i) => StoreInvoiceProduct.fromJson(i)) + .toList() + : [], + charges: json['charges'] != null + ? List.from(json['charges']) + .map((i) => ReturnStockCharges.fromJson(i)) + .toList() + : [], + discountType: json['discount_type'] ?? '', + notes: json['notes'] ?? '', + shippingCharges: Utils.checkDouble(json['shipping_charges'])!, + packingCharges: Utils.checkDouble(json['packing_charges'])!, + totalDiscountAmount: Utils.checkDouble(json['total_discount_amount'])!, + totalVat: Utils.checkDouble(json['total_vat'])!, + totalAmount: Utils.checkDouble(json['total_amount'])!, + totalExcludingVat: Utils.checkDouble(json['total_excluding_vat'])!, + totalTaxableAmount: Utils.checkDouble(json['total_taxable_amount'])!, + isDeleted: json['is_deleted'] ?? false, + createdAt: json['createdAt'] ?? '', + updatedAt: json['updatedAt'] ?? '', + uniqueId: json['unique_id'] ?? 0); + } + + Map toJson() { + final Map data = {}; + data['store_id'] = sharedPrefs.storeId; + data['supplier_id'] = supplierId!.id ?? ''; + data['stock_return_date'] = stockReturnDate; + data['currency'] = currency; + data['notes'] = notes; + data['return_stock_id'] = id ?? ''; + data['tax_option'] = taxOption; + data['total_amount'] = totalAmount; + data['total_discount_amount'] = totalDiscountAmount; + data['products'] = products!.map((v) => v.toJson()).toList(); + data['charges'] = charges!.map((v) => v.toJson()).toList(); + data['total_excluding_vat'] = getExcludingVat(); + data['total_taxable_amount'] = getTotalTaxableAmount(); + data['total_vat'] = totalVat; + + return data; + } + + double getExcludingVat() { + var price = 0.0; + for (var product in products!) { + price += (product.totalQuantity! * product.price!); + } + return price; + } + + double getTotalTaxableAmount() { + var price = 0.0; + for (var product in products!) { + price += (product.totalQuantity! * product.price!); + } + return price; + } +} diff --git a/lib/application/model/ReturnStock/ReturnStockCharges.dart b/lib/application/model/ReturnStock/ReturnStockCharges.dart new file mode 100644 index 0000000..f19572c --- /dev/null +++ b/lib/application/model/ReturnStock/ReturnStockCharges.dart @@ -0,0 +1,21 @@ +class ReturnStockCharges { + String amount; + String name; + + ReturnStockCharges({ + required this.amount, + required this.name, + }); + + factory ReturnStockCharges.fromJson(Map json) { + return ReturnStockCharges( + amount: json['amount'] ?? '', name: json['name'] ?? ''); + } + + Map toJson() { + final Map data = {}; + data['amount'] = amount; + data['name'] = name; + return data; + } +} diff --git a/lib/application/model/ReturnStock/ReturnStockResponse.dart b/lib/application/model/ReturnStock/ReturnStockResponse.dart new file mode 100644 index 0000000..e6c7d97 --- /dev/null +++ b/lib/application/model/ReturnStock/ReturnStockResponse.dart @@ -0,0 +1,21 @@ +import 'package:wosull/application/model/ReturnStock/ReturnStock.dart'; + +class ReturnStockResponse { + bool success; + List returnStock; + + ReturnStockResponse({ + required this.success, + required this.returnStock, + }); + + factory ReturnStockResponse.fromJson(Map json) { + return ReturnStockResponse( + success: json['success'] ?? false, + returnStock: json['returnStock'] != null + ? List.from(json['returnStock']) + .map((i) => ReturnStock.fromJson(i)) + .toList() + : []); + } +} diff --git a/lib/application/model/StockTransfer/ProductItemCategoryModel.dart b/lib/application/model/StockTransfer/ProductItemCategoryModel.dart index 33adcb1..f252b68 100644 --- a/lib/application/model/StockTransfer/ProductItemCategoryModel.dart +++ b/lib/application/model/StockTransfer/ProductItemCategoryModel.dart @@ -1,21 +1,23 @@ +import 'package:wosull/application/model/Modifiers/Modifier.dart'; +import 'package:wosull/application/model/ingredients/AddIngredient.dart'; import 'package:wosull/helpers/Utils.dart'; import '../Combo/GetComboModel.dart'; -import '../Modifiers/GetModifiersModel.dart'; -import '../inventory/AddIngredientModel.dart'; class ProductItemCategoryModel { - bool? success; - List? categories; + bool success; + List categories; - ProductItemCategoryModel({this.success, this.categories}); + ProductItemCategoryModel({required this.success, required this.categories}); factory ProductItemCategoryModel.fromJson(Map json) { return ProductItemCategoryModel( success: json['success'] as bool, - categories: List.from(json['item']) - .map((i) => ProductItem.fromJson(i)) - .toList()); + categories: json['item'] != null + ? List.from(json['item']) + .map((i) => ProductItem.fromJson(i)) + .toList() + : []); } } @@ -57,11 +59,11 @@ class ProductItem { .map((i) => ComboProduct.fromJson(i)) .toList() : [], - modifiers: data['modifiers'] != null - ? List.from(data['modifiers']) - .map((i) => Modifier.fromJson(i)) - .toList() - : [], + // modifiers: data['modifiers'] != null + // ? List.from(data['modifiers']) + // .map((i) => Modifier.fromJson(i)) + // .toList() + // : [], ingredients: data['ingrediants'] != null ? List.from(data['ingrediants']) .map((i) => AddIngredient.fromJson(i)) diff --git a/lib/application/model/StockTransfer/SearchStockTransferResponse.dart b/lib/application/model/StockTransfer/SearchStockTransferResponse.dart new file mode 100644 index 0000000..372c4d5 --- /dev/null +++ b/lib/application/model/StockTransfer/SearchStockTransferResponse.dart @@ -0,0 +1,17 @@ +import 'package:wosull/application/model/StockTransfer/StockTransferDetailsModel.dart'; + +class SearchStockTransferResponse { + bool success; + List stockTransfers; + + SearchStockTransferResponse( + {this.success = false, this.stockTransfers = const []}); + + factory SearchStockTransferResponse.fromJson(Map json) { + return SearchStockTransferResponse( + success: json['success'] ?? false, + stockTransfers: List.from(json['stocktransfer'] ?? []) + .map((i) => StockTransfer.fromJson(i)) + .toList()); + } +} diff --git a/lib/application/model/StockTransfer/StockTransferDetailsModel.dart b/lib/application/model/StockTransfer/StockTransferDetailsModel.dart index 6f0c66a..949415a 100644 --- a/lib/application/model/StockTransfer/StockTransferDetailsModel.dart +++ b/lib/application/model/StockTransfer/StockTransferDetailsModel.dart @@ -53,7 +53,9 @@ class StockTransfer { uniqueId: json['unique_id'] ?? 0, isDeleted: json['is_deleted'] ?? false, fromStore: WosulStore.fromJson(json['from_store']), - toStore: WosulStore.fromJson(json['to_store'])); + toStore: json['to_store'] != null + ? WosulStore.fromJson(json['to_store']) + : WosulStore(id: '', name: '')); } bool getStatus() { diff --git a/lib/application/model/StockTransfer/ViewStockTransferModel.dart b/lib/application/model/StockTransfer/ViewStockTransferModel.dart index 632dcb4..5a87a7e 100644 --- a/lib/application/model/StockTransfer/ViewStockTransferModel.dart +++ b/lib/application/model/StockTransfer/ViewStockTransferModel.dart @@ -49,7 +49,9 @@ class ViewStockTransfer { uniqueId: json['unique_id'] as int, isDeleted: json['is_deleted'] as bool, fromStore: WosulStore.fromJson(json['from_store']), - toStore: WosulStore.fromJson(json['to_store'])); + toStore: json['to_store'] != null + ? WosulStore.fromJson(json['to_store']) + : WosulStore(id: '', name: '')); } } diff --git a/lib/application/model/auth/AccessToken.dart b/lib/application/model/auth/AccessToken.dart new file mode 100644 index 0000000..eae6489 --- /dev/null +++ b/lib/application/model/auth/AccessToken.dart @@ -0,0 +1,11 @@ +class AccessToken { + String? accessToken; + + AccessToken({this.accessToken}); + + factory AccessToken.fromJson(Map json) { + return AccessToken( + accessToken: json['token'] ?? '', + ); + } +} diff --git a/lib/application/model/auth/AccessTokenModel.dart b/lib/application/model/auth/AccessTokenModel.dart new file mode 100644 index 0000000..5d9dad3 --- /dev/null +++ b/lib/application/model/auth/AccessTokenModel.dart @@ -0,0 +1,16 @@ +import 'package:wosull/application/model/auth/AccessToken.dart'; + +class AccessTokenModel { + bool? success; + AccessToken? access; + + AccessTokenModel({this.success = false, this.access}); + + factory AccessTokenModel.fromJson(Map json) { + return AccessTokenModel( + success: json['success'] ?? false, + access: json['access_token'] != null + ? AccessToken.fromJson(json['access_token']) + : AccessToken()); + } +} diff --git a/lib/application/model/billingCounter/BillingCounterDashboard.dart b/lib/application/model/billingCounter/BillingCounterDashboard.dart new file mode 100644 index 0000000..362d9b0 --- /dev/null +++ b/lib/application/model/billingCounter/BillingCounterDashboard.dart @@ -0,0 +1,21 @@ +import 'package:wosull/application/model/billingCounter/CounterDashboard.dart'; + +class BillingCounterDashboard { + bool success; + List billingCounter; + + BillingCounterDashboard({ + required this.success, + required this.billingCounter, + }); + + factory BillingCounterDashboard.fromJson(Map json) { + return BillingCounterDashboard( + success: json['success'] ?? false, + billingCounter: json['billing_counter'] != null + ? List.from(json['billing_counter']) + .map((i) => CounterDashboard.fromJson(i)) + .toList() + : []); + } +} diff --git a/lib/application/model/billingCounter/BillingPaymentModes.dart b/lib/application/model/billingCounter/BillingPaymentModes.dart new file mode 100644 index 0000000..b1abf32 --- /dev/null +++ b/lib/application/model/billingCounter/BillingPaymentModes.dart @@ -0,0 +1,46 @@ +import 'package:wosull/application/model/billingCounter/PaymentModes.dart'; + +class BillingPaymentModes { + PaymentModes? cash; + PaymentModes? mada; + PaymentModes? stcPay; + PaymentModes? visa; + PaymentModes? surePay; + PaymentModes? expressPay; + PaymentModes? nearPay; + + BillingPaymentModes( + {this.cash, + this.mada, + this.stcPay, + this.visa, + this.surePay, + this.expressPay, + this.nearPay}); + + factory BillingPaymentModes.fromJson(Map json) { + return BillingPaymentModes( + cash: json['Cash'] != null + ? PaymentModes.fromJson(json['Cash']) + : PaymentModes(), + mada: json['Mada'] != null + ? PaymentModes.fromJson(json['Mada']) + : PaymentModes(), + stcPay: json['Stc_Pay'] != null + ? PaymentModes.fromJson(json['Stc_Pay']) + : PaymentModes(), + visa: json['Visa'] != null + ? PaymentModes.fromJson(json['Visa']) + : PaymentModes(), + surePay: json['Sure_Pay'] != null + ? PaymentModes.fromJson(json['Sure_Pay']) + : PaymentModes(), + expressPay: json['Express_Pay'] != null + ? PaymentModes.fromJson(json['Express_Pay']) + : PaymentModes(), + nearPay: json['Near_Pay'] != null + ? PaymentModes.fromJson(json['Near_Pay']) + : PaymentModes(), + ); + } +} diff --git a/lib/application/model/billingCounter/CounterDashboard.dart b/lib/application/model/billingCounter/CounterDashboard.dart new file mode 100644 index 0000000..8dace3f --- /dev/null +++ b/lib/application/model/billingCounter/CounterDashboard.dart @@ -0,0 +1,25 @@ +import 'package:wosull/application/model/billingCounter/BillingPaymentModes.dart'; +import 'package:wosull/application/model/billingCounter/GetBillingCounter.dart'; +import 'package:wosull/helpers/Utils.dart'; + +class CounterDashboard { + BillingCounter? counterDetails; + BillingPaymentModes? paymentModes; + int? orderCount; + double? orderValues; + + CounterDashboard( + {this.counterDetails, + this.paymentModes, + this.orderCount, + this.orderValues}); + + factory CounterDashboard.fromJson(Map json) { + return CounterDashboard( + counterDetails: BillingCounter.fromJson(json['_id']), + paymentModes: BillingPaymentModes.fromJson(json['payment_mode']), + orderCount: json['order_count'] ?? 0, + orderValues: Utils.checkDouble(json['order_value']), + ); + } +} diff --git a/lib/application/model/billingCounter/GetBillingCounter.dart b/lib/application/model/billingCounter/GetBillingCounter.dart index 2fd2a1e..3220e3f 100644 --- a/lib/application/model/billingCounter/GetBillingCounter.dart +++ b/lib/application/model/billingCounter/GetBillingCounter.dart @@ -24,14 +24,18 @@ class BillingCounter { String id; String counterName; String counterCode; + String storeName; String status; double cashIn; double cashOut; + String checkInTime; double availableCash; bool isAvailable; BillingCounter( {this.id = '', + this.checkInTime = '', + this.storeName = '', this.cashIn = 0.0, this.cashOut = 0.0, this.availableCash = 0.0, @@ -49,6 +53,8 @@ class BillingCounter { counterName: json['counter_name'] ?? "", counterCode: json['counter_code'] ?? "", status: json['status'] ?? "", + checkInTime: json['check_in_time'] ?? '', + storeName: json['store_name'] ?? "", isAvailable: json['is_available'] ?? false, ); } diff --git a/lib/application/model/billingCounter/PaymentModes.dart b/lib/application/model/billingCounter/PaymentModes.dart new file mode 100644 index 0000000..2ef75d6 --- /dev/null +++ b/lib/application/model/billingCounter/PaymentModes.dart @@ -0,0 +1,13 @@ +import 'package:wosull/helpers/Utils.dart'; + +class PaymentModes { + double? amount; + int? count; + + PaymentModes({this.amount, this.count}); + + factory PaymentModes.fromJson(Map json) { + return PaymentModes( + amount: Utils.checkDouble(json['amount']), count: json['count'] ?? 0); + } +} diff --git a/lib/application/model/cart/GetHoldOrderModel.dart b/lib/application/model/cart/GetHoldOrderModel.dart index 9e98553..d4778ce 100644 --- a/lib/application/model/cart/GetHoldOrderModel.dart +++ b/lib/application/model/cart/GetHoldOrderModel.dart @@ -36,6 +36,22 @@ class GetOrderByStatusModel { } } +class SearchCashier { + bool? success; + List? orderModel; + + SearchCashier({this.success, this.orderModel}); + + factory SearchCashier.fromJson(Map json) { + return SearchCashier( + success: json['success'], + orderModel: List.from(json['cashier']) + .map((i) => ReturnOrderModel.fromJson(i)) + .toList(), + ); + } +} + class GetReturnOrderModel { bool? success; List? orderModel; @@ -44,6 +60,22 @@ class GetReturnOrderModel { factory GetReturnOrderModel.fromJson(Map json) { return GetReturnOrderModel( + success: json['success'], + orderModel: List.from(json['cashier_order']) + .map((i) => ReturnOrderModel.fromJson(i)) + .toList(), + ); + } +} + +class GetReturnAndDamageModel { + bool? success; + List? orderModel; + + GetReturnAndDamageModel({this.success, this.orderModel}); + + factory GetReturnAndDamageModel.fromJson(Map json) { + return GetReturnAndDamageModel( success: json['success'], orderModel: List.from(json['return_order']) .map((i) => ReturnOrderModel.fromJson(i)) @@ -168,6 +200,9 @@ class ReturnOrderModel { int? uniqueId; String? createdAt; String? updatedAt; + int? reference; + String? transactionId; + int? orderNumber; ReturnOrderModel( {this.id, @@ -175,6 +210,8 @@ class ReturnOrderModel { this.storeId, this.orderType, this.status, + this.orderNumber, + this.reference, this.paymentMode, this.paymentStatus, this.amount, @@ -184,6 +221,7 @@ class ReturnOrderModel { this.changeBalanceAmount, this.timer, this.table, + this.transactionId, this.deliveryNotes, this.createdAt, this.updatedAt, @@ -207,6 +245,9 @@ class ReturnOrderModel { changeBalanceAmount: Utils.checkDouble(json['change_balance_amount'])!, timer: json['timer'] ?? 0, table: json['table'] ?? "", + orderNumber: json['order_number'] ?? 0, + transactionId: json['transaction_id'] ?? "", + reference: json['reference'] ?? 0, createdAt: json['createdAt'] ?? "", updatedAt: json['updatedAt'] ?? "", deliveryNotes: json['delivery_notes'] ?? "", diff --git a/lib/application/model/converters/DataTimeFormat.dart b/lib/application/model/converters/DataTimeFormat.dart index dc7caff..f6c13c7 100644 --- a/lib/application/model/converters/DataTimeFormat.dart +++ b/lib/application/model/converters/DataTimeFormat.dart @@ -3,7 +3,7 @@ import 'package:intl/intl.dart'; class DataTimeFormat { static String getFormatDate(String date) { if (date.isEmpty) { - return ""; + return "dd/mm/yyyy"; } var dateValue = DateFormat("yyyy-MM-ddTHH:mm:ssZ").parseUTC(date).toLocal(); @@ -11,6 +11,18 @@ class DataTimeFormat { return formattedDate; } + static String getFormatDateWithTime() { + String formattedDate = + DateFormat("dd-MM-yyyy, hh:mm a").format(DateTime.now()); + return formattedDate; + } + + static String getCurrentTimeDate() { + String formattedDate = + DateFormat("yyyy-MM-ddTHH:mm:ssZ").format(DateTime.now()); + return formattedDate; + } + static bool subtractTime(String date, int timer) { var endTime = DateFormat("yyyy-MM-ddTHH:mm:ssZ").parseUTC(date).toLocal(); return DateTime.now().isAfter(endTime.add(Duration(minutes: timer))); @@ -23,7 +35,11 @@ class DataTimeFormat { } static String getFormatDateString(String date) { + if (date.isEmpty) { + return ""; + } var dateValue = DateFormat("yyyy-MM-ddTHH:mm:ssZ").parseUTC(date).toLocal(); + String formattedDate = DateFormat("yyyy-MM-dd").format(dateValue); return formattedDate; } @@ -32,7 +48,27 @@ class DataTimeFormat { return DateFormat("yyyy-MM-dd").format(picked); } + static String formatDateMMDDYYYY(DateTime picked) { + return DateFormat("dd/MM/yyyy").format(picked); + } + static String formatDateFromPicketINVOICE(DateTime picked) { return DateFormat("yyyy-MM-ddTHH:mm:ssZ").format(picked); } + + static String getDay(String s) { + var dateValue = DateFormat("yyyy-MM-ddTHH:mm:ssZ").parseUTC(s).toLocal(); + return DateFormat('EEEE').format(dateValue); + } + + static String getTimeFormat(String s) { + var dateValue = DateFormat("yyyy-MM-ddTHH:mm:ssZ").parseUTC(s).toLocal(); + return DateFormat('jm').format(dateValue); + } + + static bool isDateExpired(String date) { + final now = DateTime.now(); + var endTime = DateFormat("yyyy-MM-ddTHH:mm:ssZ").parseUTC(date).toLocal(); + return endTime.isBefore(now); + } } diff --git a/lib/application/model/createOrder/CashierCart.dart b/lib/application/model/createOrder/CashierCart.dart index 42ed0d8..c6703ac 100644 --- a/lib/application/model/createOrder/CashierCart.dart +++ b/lib/application/model/createOrder/CashierCart.dart @@ -1,8 +1,10 @@ +import 'package:wosull/application/model/Modifiers/Modifier.dart'; +import 'package:wosull/application/model/Modifiers/ModifierOption.dart'; +import 'package:wosull/application/model/ingredients/AddIngredient.dart'; + import '../../../helpers/Utils.dart'; import '../../localdb/SharedPrefs.dart'; import '../Combo/GetComboModel.dart'; -import '../Modifiers/GetModifiersModel.dart'; -import '../inventory/AddIngredientModel.dart'; import '../store/StoreItemsResponse.dart'; class CashierCart { diff --git a/lib/application/model/createOrder/OrderDetails.dart b/lib/application/model/createOrder/OrderDetails.dart index a6772b9..9e1cfb7 100644 --- a/lib/application/model/createOrder/OrderDetails.dart +++ b/lib/application/model/createOrder/OrderDetails.dart @@ -1,20 +1,24 @@ +import 'dart:convert'; + import 'package:objectbox/objectbox.dart'; import 'package:wosull/application/model/store/StoreItemsResponse.dart'; import 'package:wosull/helpers/Utils.dart'; @Entity() class OrderDetails { - @Id() - int obid = 0; + @Id(assignable: true) + int id = 0; String? productId; double? totalItemTax; double? totalItemPrice; double? totalItemPriceWithoutModifier; + var items = ToMany(); OrderDetails( {this.productId, + this.id = 0, this.totalItemTax, this.totalItemPrice, required this.items, @@ -22,6 +26,7 @@ class OrderDetails { factory OrderDetails.fromJson(Map json) { return OrderDetails( + id: 0, productId: json['product_id'], totalItemTax: Utils.checkDouble(json['total_item_tax'])!, totalItemPrice: Utils.checkDouble(json['total_item_price'])!, @@ -43,9 +48,18 @@ class OrderDetails { data['total_item_price'] = totalItemPrice ?? 0; data['total_item_price_without_modifier'] = totalItemPriceWithoutModifier ?? 0; - if (items != null) { - data['items'] = items!.map((v) => v.toJson()).toList(); - } + data['items'] = items.map((v) => v.toJson()).toList(); + return data; + } + + Map toJsonOffline() { + final Map data = {}; + data['product_id'] = productId; + data['total_item_tax'] = totalItemTax ?? 0; + data['total_item_price'] = totalItemPrice ?? 0; + data['total_item_price_without_modifier'] = + totalItemPriceWithoutModifier ?? 0; + data['items'] = jsonEncode(items); return data; } } diff --git a/lib/application/model/dashboard/AdminDashboardModel.dart b/lib/application/model/dashboard/AdminDashboardModel.dart index fbb09d6..6ac6813 100644 --- a/lib/application/model/dashboard/AdminDashboardModel.dart +++ b/lib/application/model/dashboard/AdminDashboardModel.dart @@ -10,6 +10,10 @@ class AdminDashboardModel { int? totalSupplier = 0; int? totalCancelledOrders = 0; int? totalCompleteOrders = 0; + int? totalDamagedOrders = 0; + int? totalReturnOrders = 0; + int? totalPartiallyReturnOrders = 0; + int? totalPartiallyDamagedOrders = 0; AdminDashboardModel( {this.success, @@ -19,6 +23,10 @@ class AdminDashboardModel { this.totalCustomer, this.totalBranches, this.totalSupplier, + this.totalDamagedOrders, + this.totalReturnOrders, + this.totalPartiallyReturnOrders, + this.totalPartiallyDamagedOrders, this.totalCancelledOrders, this.totalCompleteOrders}); @@ -31,6 +39,10 @@ class AdminDashboardModel { totalCustomer: data['total_customers'] ?? 0, totalSupplier: data['total_suppliers'] ?? 0, totalBranches: data['total_branches'] ?? 0, + totalDamagedOrders: data['total_damaged_orders'] ?? 0, + totalReturnOrders: data['total_returned_orders'] ?? 0, + totalPartiallyReturnOrders: data['total_partially_return_orders'] ?? 0, + totalPartiallyDamagedOrders: data['total_partially_damage_orders'] ?? 0, totalCancelledOrders: data['total_cancelled_orders'] ?? 0, totalCompleteOrders: data['total_completed_orders'] ?? 0); } diff --git a/lib/application/model/dashboard/graph/AllInvoiceStatus.dart b/lib/application/model/dashboard/graph/AllInvoiceStatus.dart index f840ef4..f5d6f01 100644 --- a/lib/application/model/dashboard/graph/AllInvoiceStatus.dart +++ b/lib/application/model/dashboard/graph/AllInvoiceStatus.dart @@ -13,10 +13,10 @@ class AllInvoiceStatus { this.cancelledInvoices}); AllInvoiceStatus.fromJson(Map json) { - openInvoices = json['open_invoices']; - paidInvoices = json['paid_invoices']; - partiallyPaidInvoices = json['partially_paid_invoices']; - returnInvoices = json['return_invoices']; - cancelledInvoices = json['cancelled_invoices']; + openInvoices = json['open_invoices'] ?? 0; + paidInvoices = json['paid_invoices'] ?? 0; + partiallyPaidInvoices = json['partially_paid_invoices'] ?? 0; + returnInvoices = json['return_invoices'] ?? 0; + cancelledInvoices = json['cancelled_invoices'] ?? 0; } } diff --git a/lib/application/model/dashboard/graph/AllPosStatus.dart b/lib/application/model/dashboard/graph/AllPosStatus.dart index cce54aa..6e95bd8 100644 --- a/lib/application/model/dashboard/graph/AllPosStatus.dart +++ b/lib/application/model/dashboard/graph/AllPosStatus.dart @@ -11,9 +11,9 @@ class AllPosStatus { this.returnOrders}); AllPosStatus.fromJson(Map json) { - completeOrders = json['complete_orders']; - cancelledOrders = json['cancelled_orders']; - damagedOrders = json['damaged_orders']; - returnOrders = json['return_orders']; + completeOrders = json['complete_orders'] ?? 0; + cancelledOrders = json['cancelled_orders'] ?? 0; + damagedOrders = json['damaged_orders'] ?? 0; + returnOrders = json['return_orders'] ?? 0; } } diff --git a/lib/application/model/dashboard/graph/POSValueDataWise.dart b/lib/application/model/dashboard/graph/POSValueDataWise.dart index 1982e8c..be6db54 100644 --- a/lib/application/model/dashboard/graph/POSValueDataWise.dart +++ b/lib/application/model/dashboard/graph/POSValueDataWise.dart @@ -1,13 +1,15 @@ +import 'package:wosull/helpers/Utils.dart'; + class POSValueDataWise { String? id; - int? totalAmount; + double? totalAmount; int? index; POSValueDataWise({this.id, this.totalAmount, this.index}); POSValueDataWise.fromJson(Map json) { id = json['_id']; - totalAmount = json['total_amount']; + totalAmount = Utils.checkDouble(json['total_amount']); index = json['index']; } } diff --git a/lib/application/model/dashboard/graph/PosOrderCountTodayTimewise.dart b/lib/application/model/dashboard/graph/PosOrderCountTodayTimewise.dart index 991a3f1..a8bd0ee 100644 --- a/lib/application/model/dashboard/graph/PosOrderCountTodayTimewise.dart +++ b/lib/application/model/dashboard/graph/PosOrderCountTodayTimewise.dart @@ -1,13 +1,15 @@ +import 'package:wosull/helpers/Utils.dart'; + class PosOrderCountTodayTimewise { String? sId; int? count; - int? totalAmount; + double? totalAmount; PosOrderCountTodayTimewise({this.sId, this.count, this.totalAmount}); PosOrderCountTodayTimewise.fromJson(Map json) { sId = json['_id']; count = json['count']; - totalAmount = json['total_amount']; + totalAmount = Utils.checkDouble(json['total_amount']); } } diff --git a/lib/application/model/dashboard/graph/TodaySales.dart b/lib/application/model/dashboard/graph/TodaySales.dart index bffae4d..3885c97 100644 --- a/lib/application/model/dashboard/graph/TodaySales.dart +++ b/lib/application/model/dashboard/graph/TodaySales.dart @@ -1,12 +1,14 @@ +import 'package:wosull/helpers/Utils.dart'; + class TodaySales { Id? id; - int? totalAmount; + double? totalAmount; TodaySales({this.id, this.totalAmount}); TodaySales.fromJson(Map json) { id = json['_id'] != null ? Id.fromJson(json['_id']) : null; - totalAmount = json['total_amount']; + totalAmount = Utils.checkDouble(json['total_amount']); } } diff --git a/lib/application/model/dashboard/graph/TotalIncomeExpense.dart b/lib/application/model/dashboard/graph/TotalIncomeExpense.dart index 1b78cb0..c3de79c 100644 --- a/lib/application/model/dashboard/graph/TotalIncomeExpense.dart +++ b/lib/application/model/dashboard/graph/TotalIncomeExpense.dart @@ -1,13 +1,15 @@ +import 'package:wosull/helpers/Utils.dart'; + class TotalIncomeExpense { String? id; - int? totalIncome; - int? totalExpense; + double? totalIncome; + double? totalExpense; TotalIncomeExpense({this.id, this.totalIncome, this.totalExpense}); TotalIncomeExpense.fromJson(Map json) { id = json['_id']; - totalIncome = json['total_income'] ?? 0; - totalExpense = json['total_expense'] ?? 0; + totalIncome = Utils.checkDouble(json['total_income'])!; + totalExpense = Utils.checkDouble(json['total_expense'])!; } } diff --git a/lib/application/model/discount/StoreDiscountModel.dart b/lib/application/model/discount/StoreDiscountModel.dart index 4e91838..4cb2d9d 100644 --- a/lib/application/model/discount/StoreDiscountModel.dart +++ b/lib/application/model/discount/StoreDiscountModel.dart @@ -2,11 +2,14 @@ import 'package:objectbox/objectbox.dart'; import 'package:wosull/helpers/Utils.dart'; class StoreDiscountModel { - bool? success; - List? storeDiscount; - int? pages; + bool success; + List storeDiscount; + int pages; - StoreDiscountModel({this.success, this.storeDiscount, this.pages}); + StoreDiscountModel( + {required this.success, + required this.storeDiscount, + required this.pages}); factory StoreDiscountModel.fromJson(Map json) { return StoreDiscountModel( @@ -41,6 +44,7 @@ class StoreDiscount { String? discountType; String? discountTypeLabel; double? limitOfDiscount; + double? isUserUsed; String? discountStartDate; String? discountEndDate; bool? isDeleted; @@ -59,6 +63,7 @@ class StoreDiscount { this.value, this.type, this.storeId, + this.isUserUsed, this.categories, this.products, this.status, @@ -95,6 +100,7 @@ class StoreDiscount { categories: json['categories'].cast(), products: json['products'].cast(), status: json['status'] ?? "", + isUserUsed: Utils.checkDouble(json['is_user_used'])!, minAmountLimit: Utils.checkDouble(json['min_amount_limit'])!, maxDiscountLimit: Utils.checkDouble(json['max_discount_limit'])!, discountPercentage: json['discount_percentage'] ?? "", diff --git a/lib/application/model/home/DrawerItem.dart b/lib/application/model/home/DrawerItem.dart new file mode 100644 index 0000000..b5b01b8 --- /dev/null +++ b/lib/application/model/home/DrawerItem.dart @@ -0,0 +1,8 @@ +import 'package:flutter/material.dart'; + +class DrawerItem { + String title; + IconData icon; + + DrawerItem(this.title, this.icon); +} diff --git a/lib/application/model/ingredients/Add.dart b/lib/application/model/ingredients/Add.dart new file mode 100644 index 0000000..6cd79dd --- /dev/null +++ b/lib/application/model/ingredients/Add.dart @@ -0,0 +1,9 @@ +class Add { + String id; + + Add({this.id = ''}); + + factory Add.fromJson(Map json) { + return Add(id: json['_id'] ?? ""); + } +} diff --git a/lib/application/model/inventory/AddIngredientModel.dart b/lib/application/model/ingredients/AddIngredient.dart similarity index 73% rename from lib/application/model/inventory/AddIngredientModel.dart rename to lib/application/model/ingredients/AddIngredient.dart index bedf83e..31cfdb8 100644 --- a/lib/application/model/inventory/AddIngredientModel.dart +++ b/lib/application/model/ingredients/AddIngredient.dart @@ -1,92 +1,6 @@ import 'package:objectbox/objectbox.dart'; - -import '../../localdb/SharedPrefs.dart'; - -class AddIngredientModel { - bool success; - String message; - Add ingredient; - String error_code; - - AddIngredientModel( - {required this.success, - required this.message, - required this.ingredient, - required this.error_code}); - - factory AddIngredientModel.fromJson(Map json) { - return AddIngredientModel( - success: json['success'] as bool, - message: json['message'] == null ? '' : json['message'] as String, - error_code: - json['error_code'] == null ? '' : json['error_code'] as String, - ingredient: json['ingredient'] == null - ? Add(id: '') - : Add.fromJson(json['ingredient']), - ); - } -} - -class AddProductModel { - bool success; - int message; - AddProductItem product; - int error_code; - - AddProductModel( - {required this.success, - required this.message, - required this.product, - required this.error_code}); - - factory AddProductModel.fromJson(Map json) { - return AddProductModel( - success: json['success'] ?? false, - message: json['message'] == null ? 200 : json['message'] as int, - error_code: json['error_code'] == null ? 500 : json['error_code'] as int, - product: json['item'] == null - ? AddProductItem() - : AddProductItem.fromJson(json['item']), - ); - } -} - -class AddProductItem { - String id; - - AddProductItem({this.id = ''}); - - factory AddProductItem.fromJson(Map json) { - return AddProductItem( - id: json['_id'] ?? "", - ); - } -} - -class GetIngredientModel { - bool success; - List ingredient; - - GetIngredientModel({required this.success, required this.ingredient}); - - factory GetIngredientModel.fromJson(Map json) { - return GetIngredientModel( - success: json['success'] as bool, - ingredient: List.from(json['ingrediant']) - .map((i) => AddIngredient.fromJson(i)) - .toList()); - } -} - -class Add { - String id; - - Add({this.id = ''}); - - factory Add.fromJson(Map json) { - return Add(id: json['_id'] ?? ""); - } -} +import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/helpers/Utils.dart'; @Entity() class AddIngredient { @@ -96,23 +10,23 @@ class AddIngredient { String name; String description; String value; - var purchasePrice; - var salePrice; - var defaultSalePrice; + double? purchasePrice; + double? salePrice; + double? defaultSalePrice; String categoryId; String productId; String details; String details1; - var price; - var purchaseCost; - var itemPriceWithoutOffer; + double? price; + double? purchaseCost; + double? itemPriceWithoutOffer; var discountPercentage; var discountValue; var offerMessageOrPercentage; - var totalQuantity; + int? totalQuantity; bool inCartQuantity; - var totalAddedQuantity; - var totalUsedQuantity; + int? totalAddedQuantity; + int? totalUsedQuantity; var sequenceNumber; String noteForItem; String uniqueIdForStoreData; @@ -128,10 +42,10 @@ class AddIngredient { String tags; String itemNameArabic; String itemDescriptionArabic; - var salePriceExclusiveTax; + double? salePriceExclusiveTax; String productCode; - var stockAlertQuantity; - var salePriceInclusiveTax; + int? stockAlertQuantity; + double? salePriceInclusiveTax; String supplier; String discount; String measurementCategory; @@ -141,7 +55,7 @@ class AddIngredient { String expiryDate; String createdAt; String updatedAt; - + String quantity; String measuringUnit; bool checked; @@ -151,6 +65,7 @@ class AddIngredient { {this.name = '', this.description = '', this.value = '', + this.quantity = '', this.purchasePrice, this.salePrice, this.defaultSalePrice, @@ -205,16 +120,19 @@ class AddIngredient { name: json['name'] ?? '', description: json['description'] ?? '', value: json['value'] ?? '', - purchasePrice: json['purchase_price'] ?? '', - salePrice: json['sale_price'] ?? '0.0', - defaultSalePrice: json['default_sale_price'] ?? '', + purchasePrice: Utils.checkDouble(json['purchase_price'] ?? '0'), + salePrice: Utils.checkDouble(json['sale_price'] ?? '0.0'), + defaultSalePrice: + Utils.checkDouble(json['default_sale_price'] ?? '0.0'), categoryId: json['category_id'] ?? '', productId: json['product_id'] ?? '', details: json['details'] ?? '', + quantity: json['quantity'] ?? '', details1: json['details_1'] ?? '', - price: json['price'] ?? 0.0, - purchaseCost: json['purchase_cost'] ?? '', - itemPriceWithoutOffer: json['item_price_without_offer'] ?? '', + price: Utils.checkDouble(json['price'] ?? '0.0'), + purchaseCost: Utils.checkDouble(json['purchase_cost'] ?? '0.0'), + itemPriceWithoutOffer: + Utils.checkDouble(json['item_price_without_offer'] ?? '0.0'), discountPercentage: json['discount_percentage'] ?? '', discountValue: json['discount_value'] ?? '', offerMessageOrPercentage: json['offer_message_or_percentage'] ?? '', @@ -238,10 +156,12 @@ class AddIngredient { tags: json['tags'] ?? '', itemNameArabic: json['item_name_arabic'] ?? '', itemDescriptionArabic: json['item_description_arabic'] ?? '', - salePriceExclusiveTax: json['sale_price_exclusive_tax'] ?? '', + salePriceExclusiveTax: + Utils.checkDouble(json['sale_price_exclusive_tax'] ?? '0.0'), productCode: json['product_code'] ?? '', stockAlertQuantity: json['stock_alert_quantity'] ?? '', - salePriceInclusiveTax: json['sale_price_inclusive_tax'] ?? '', + salePriceInclusiveTax: + Utils.checkDouble(json['sale_price_inclusive_tax'] ?? '0.0'), supplier: json['supplier'] ?? '', discount: json['discount'] ?? '', measurementCategory: json['measurement_category'] ?? '', diff --git a/lib/application/model/ingredients/AddIngredientModel.dart b/lib/application/model/ingredients/AddIngredientModel.dart new file mode 100644 index 0000000..5bea5f4 --- /dev/null +++ b/lib/application/model/ingredients/AddIngredientModel.dart @@ -0,0 +1,26 @@ +import 'package:wosull/application/model/ingredients/Add.dart'; + +class AddIngredientModel { + bool success; + String message; + Add ingredient; + String error_code; + + AddIngredientModel( + {required this.success, + required this.message, + required this.ingredient, + required this.error_code}); + + factory AddIngredientModel.fromJson(Map json) { + return AddIngredientModel( + success: json['success'] as bool, + message: json['message'] == null ? '' : json['message'] as String, + error_code: + json['error_code'] == null ? '' : json['error_code'] as String, + ingredient: json['ingredient'] == null + ? Add(id: '') + : Add.fromJson(json['ingredient']), + ); + } +} diff --git a/lib/application/model/ingredients/AddProdcutModel.dart b/lib/application/model/ingredients/AddProdcutModel.dart new file mode 100644 index 0000000..89ebe90 --- /dev/null +++ b/lib/application/model/ingredients/AddProdcutModel.dart @@ -0,0 +1,25 @@ +import 'package:wosull/application/model/ingredients/AddProductItem.dart'; + +class AddProductModel { + bool success; + int message; + AddProductItem product; + int error_code; + + AddProductModel( + {required this.success, + required this.message, + required this.product, + required this.error_code}); + + factory AddProductModel.fromJson(Map json) { + return AddProductModel( + success: json['success'] ?? false, + message: json['message'] == null ? 200 : json['message'] as int, + error_code: json['error_code'] == null ? 500 : json['error_code'] as int, + product: json['item'] == null + ? AddProductItem() + : AddProductItem.fromJson(json['item']), + ); + } +} diff --git a/lib/application/model/ingredients/AddProductItem.dart b/lib/application/model/ingredients/AddProductItem.dart new file mode 100644 index 0000000..792515d --- /dev/null +++ b/lib/application/model/ingredients/AddProductItem.dart @@ -0,0 +1,11 @@ +class AddProductItem { + String id; + + AddProductItem({this.id = ''}); + + factory AddProductItem.fromJson(Map json) { + return AddProductItem( + id: json['_id'] ?? "", + ); + } +} diff --git a/lib/application/model/ingredients/GetIngredientModel.dart b/lib/application/model/ingredients/GetIngredientModel.dart new file mode 100644 index 0000000..b92ba9f --- /dev/null +++ b/lib/application/model/ingredients/GetIngredientModel.dart @@ -0,0 +1,18 @@ +import 'package:wosull/application/model/ingredients/AddIngredient.dart'; + +class GetIngredientModel { + bool success; + List ingredient; + + GetIngredientModel({required this.success, required this.ingredient}); + + factory GetIngredientModel.fromJson(Map json) { + return GetIngredientModel( + success: json['success'] as bool, + ingredient: json['ingrediant'] != null + ? List.from(json['ingrediant']) + .map((i) => AddIngredient.fromJson(i)) + .toList() + : []); + } +} diff --git a/lib/application/model/inventory/Item.dart b/lib/application/model/inventory/Item.dart index 4667c30..08f3005 100644 --- a/lib/application/model/inventory/Item.dart +++ b/lib/application/model/inventory/Item.dart @@ -1,18 +1,18 @@ import 'package:wosull/helpers/Utils.dart'; class ReportProductModel { - bool? success; - List? storeItems; + bool success; + List storeItems; - ReportProductModel({this.success, this.storeItems}); + ReportProductModel(this.success, this.storeItems); factory ReportProductModel.fromJson(Map json) { return ReportProductModel( - success: json['success'] ?? false, - storeItems: json['item'] != null + json['success'] ?? false, + json['item'] != null ? List.from(json['item']) - .map((i) => Item.fromJson(i)) - .toList() + .map((i) => Item.fromJson(i)) + .toList() : []); } } @@ -25,12 +25,13 @@ class Item { double? price; int? totalQuantity; - Item({this.id, - this.productId, - this.details, - this.name, - this.price, - this.totalQuantity}); + Item( + {this.id, + this.productId, + this.details, + this.name, + this.price, + this.totalQuantity}); factory Item.fromJson(Map json) { return Item( @@ -66,9 +67,6 @@ class CategoryId { CategoryId({this.id, this.name}); factory CategoryId.fromJson(Map json) { - return CategoryId( - id: json['_id'] ?? "", - name: json['name'] ?? "" - ); + return CategoryId(id: json['_id'] ?? "", name: json['name'] ?? ""); } } diff --git a/lib/application/model/inventory/category/ItemCategory.dart b/lib/application/model/inventory/category/ItemCategory.dart index 3bc921a..1d8d6d9 100644 --- a/lib/application/model/inventory/category/ItemCategory.dart +++ b/lib/application/model/inventory/category/ItemCategory.dart @@ -27,7 +27,7 @@ class ItemCategory { {this.name = '', this.id = '', this.categoryAppliedOn = '', - this.isVisibleInStore = false, + this.isVisibleInStore = true, this.createdAt = '', this.updatedAt = '', this.description = '', diff --git a/lib/application/model/inventory/subCategory/SearchSubCategoryResponse.dart b/lib/application/model/inventory/subCategory/SearchSubCategoryResponse.dart new file mode 100644 index 0000000..4b2eca7 --- /dev/null +++ b/lib/application/model/inventory/subCategory/SearchSubCategoryResponse.dart @@ -0,0 +1,18 @@ +import 'package:wosull/application/model/inventory/ItemSubCategoryResponse.dart'; + +class SearchSubCategoryResponse { + bool success; + List categories; + + SearchSubCategoryResponse({this.success = false, this.categories = const []}); + + factory SearchSubCategoryResponse.fromJson(Map json) { + return SearchSubCategoryResponse( + success: json['success'] ?? false, + categories: json['success'] == true + ? List.from(json['subCategory']) + .map((i) => ItemSubCategory.fromJson(i)) + .toList() + : []); + } +} diff --git a/lib/application/model/invoice/Account.dart b/lib/application/model/invoice/Account.dart new file mode 100644 index 0000000..7c162d5 --- /dev/null +++ b/lib/application/model/invoice/Account.dart @@ -0,0 +1,12 @@ +class Account { + String id; + String name; + String type; + + Account(this.id, this.name, this.type); + + factory Account.fromJson(Map json) { + return Account(json['_id'] ?? '', json['account_name'] ?? '', + json['account_type'] ?? ''); + } +} diff --git a/lib/application/model/invoice/MakePayment.dart b/lib/application/model/invoice/MakePayment.dart new file mode 100644 index 0000000..69a4143 --- /dev/null +++ b/lib/application/model/invoice/MakePayment.dart @@ -0,0 +1,22 @@ +class MakePayment { + String account; + String paymentMethod; + String date; + double amount; + String notes; + String invoiceId; + + MakePayment(this.account, this.paymentMethod, this.date, this.amount, + this.notes, this.invoiceId); + + Map toJson() { + return { + 'account': account, + 'payment_method': paymentMethod, + 'transaction_date': date, + 'amount': amount, + 'notes': notes, + 'invoice_id': invoiceId + }; + } +} diff --git a/lib/application/model/invoice/PaymentHistory.dart b/lib/application/model/invoice/PaymentHistory.dart new file mode 100644 index 0000000..c819f9b --- /dev/null +++ b/lib/application/model/invoice/PaymentHistory.dart @@ -0,0 +1,26 @@ +import 'package:wosull/helpers/Utils.dart'; + +class PaymentHistory { + String account; + String paymentMethod; + String date; + double amount; + String notes; + String invoiceId; + double paidAmount; + + PaymentHistory(this.account, this.paymentMethod, this.date, this.amount, + this.notes, this.invoiceId, this.paidAmount); + + factory PaymentHistory.fromJson(Map json) { + return PaymentHistory( + json['account'] ?? '', + json['payment_method'] ?? '', + json['transaction_date'] ?? '', + Utils.checkDouble(json['amount']) ?? 0, + json['notes'] ?? '', + json['invoice_id'] ?? '', + Utils.checkDouble(json['total_paid_amount']) ?? 0, + ); + } +} diff --git a/lib/application/model/invoice/PaymentMethod.dart b/lib/application/model/invoice/PaymentMethod.dart new file mode 100644 index 0000000..0d074d2 --- /dev/null +++ b/lib/application/model/invoice/PaymentMethod.dart @@ -0,0 +1,35 @@ +import 'package:wosull/application/localdb/SharedPrefs.dart'; + +class PaymentMethod { + String? id; + String? paymentMethod; + bool? status; + String? updatedAt; + String? description; + + PaymentMethod( + {this.id, + this.paymentMethod, + this.status, + this.description, + this.updatedAt}); + + factory PaymentMethod.fromJson(Map json) { + return PaymentMethod( + id: json['_id'] ?? '', + paymentMethod: json['paymentMethod'] ?? '', + status: json['status'] ?? false, + description: json['description'] ?? '', + updatedAt: json['updatedAt'] ?? ''); + } + + Map toJson() { + return { + 'description': description, + 'paymentMethod': paymentMethod, + 'status': status ?? true, + 'store_id': sharedPrefs.storeId, + 'payment_id': id + }; + } +} diff --git a/lib/application/model/invoice/PaymentMethodResponse.dart b/lib/application/model/invoice/PaymentMethodResponse.dart new file mode 100644 index 0000000..1c71516 --- /dev/null +++ b/lib/application/model/invoice/PaymentMethodResponse.dart @@ -0,0 +1,19 @@ +import 'package:wosull/application/model/invoice/PaymentMethod.dart'; + +class PaymentMethodResponse { + bool status; + List paymentMethods; + + PaymentMethodResponse(this.status, this.paymentMethods); + + factory PaymentMethodResponse.fromJson(Map json) { + return PaymentMethodResponse( + json['success'] ?? false, + json['payment_methods'] != null + ? List.from(json['payment_methods']) + .map((i) => PaymentMethod.fromJson(i)) + .toList() + : [], + ); + } +} diff --git a/lib/application/model/invoice/QuotationInvioceModel.dart b/lib/application/model/invoice/QuotationInvioceModel.dart index 0db6bd1..08af239 100644 --- a/lib/application/model/invoice/QuotationInvioceModel.dart +++ b/lib/application/model/invoice/QuotationInvioceModel.dart @@ -90,12 +90,8 @@ class QuotationInvoice { currencyId: Utils.checkCurrency(json['currency_id'])!, uniqueId: json['unique_id'] ?? 0, status: json['status'] ?? "", - supplier: json['supplier_id'] != null - ? Supplier.fromJson(json['supplier_id']) - : Supplier(), - customer: json['customer_id'] != null - ? Customer.fromJson(json['customer_id']) - : Customer(), + supplier: Utils.checkSupplier(json['supplier_id']), + customer: Utils.checkCustomer(json['customer_id']), products: json['products'] != null ? List.from(json['products']) .map((i) => StoreInvoiceProduct.fromJson(i)) @@ -133,7 +129,7 @@ class QuotationInvoice { data['vat_number'] = vatNumber; data['total_excluding_vat'] = totalTaxExcluding; data['total_taxable_amount'] = totalTaxableAmount; - data['currency_id'] = currencyId!.id!; + data['currency_id'] = currencyId?.id! ?? ''; return data; } } diff --git a/lib/application/model/invoice/StoreIncomeAccountResponse.dart b/lib/application/model/invoice/StoreIncomeAccountResponse.dart new file mode 100644 index 0000000..d0c9a0e --- /dev/null +++ b/lib/application/model/invoice/StoreIncomeAccountResponse.dart @@ -0,0 +1,19 @@ +import 'package:wosull/application/model/invoice/Account.dart'; + +class StoreIncomeAccountResponse { + bool status; + List accounts; + + StoreIncomeAccountResponse(this.status, this.accounts); + + factory StoreIncomeAccountResponse.fromJson(Map json) { + return StoreIncomeAccountResponse( + json['success'] ?? false, + json['accounts'] != null + ? List.from(json['accounts']) + .map((i) => Account.fromJson(i)) + .toList() + : [], + ); + } +} diff --git a/lib/application/model/invoice/StoreInvoice.dart b/lib/application/model/invoice/StoreInvoice.dart index efc9d6f..0b8410f 100644 --- a/lib/application/model/invoice/StoreInvoice.dart +++ b/lib/application/model/invoice/StoreInvoice.dart @@ -1,4 +1,5 @@ import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/application/model/invoice/PaymentHistory.dart'; import 'package:wosull/application/model/store/GetStoreCurrency.dart'; import 'package:wosull/application/model/store/StoreInvoicesModel.dart'; import 'package:wosull/helpers/Utils.dart'; @@ -16,6 +17,7 @@ class StoreInvoice { Supplier? supplier; Customer? customer; List products = []; + List? paymentHistory = []; double? totalDiscount; double? totalAmount; String? terms; @@ -24,6 +26,8 @@ class StoreInvoice { int? totalVat; double? totalTaxExcluding; double? totalTaxableAmount; + double? totalPaidAmount; + double? totalPendingAmount; String? vatNumber; int? uniqueId; @@ -39,10 +43,13 @@ class StoreInvoice { this.currencyId, this.status, this.customer, + this.paymentHistory, required this.products, this.totalDiscount, this.totalAmount, this.terms, + this.totalPaidAmount, + this.totalPendingAmount, this.productStock, this.totalTax, this.totalVat, @@ -68,11 +75,18 @@ class StoreInvoice { .map((i) => StoreInvoiceProduct.fromJson(i)) .toList() : [], + paymentHistory: json['payment_history'] != null + ? List.from(json['payment_history']) + .map((i) => PaymentHistory.fromJson(i)) + .toList() + : [], totalTax: Utils.checkDouble(json['total_tax'])!, totalVat: json['total_vat'] ?? 0, totalDiscount: Utils.checkDouble(json['total_discount'])!, totalAmount: Utils.checkDouble(json['total_amount'])!, terms: json['terms'], + totalPaidAmount: Utils.checkDouble(json['total_paid_amount'])!, + totalPendingAmount: Utils.checkDouble(json['total_pending_amount'])!, totalTaxExcluding: Utils.checkDouble(json['total_excluding_vat'])!, totalTaxableAmount: Utils.checkDouble(json['total_taxable_amount'])!, vatNumber: json['vat_number'] ?? "", @@ -83,6 +97,7 @@ class StoreInvoice { Map toJson() { final Map data = {}; data['store_id'] = sharedPrefs.storeId; + data['invoice_for'] = invoiceFor!.first; data['invoiceId'] = id ?? ''; data['customer_id'] = customerId ?? ''; data['invoice_number'] = invoiceNumber; diff --git a/lib/application/model/modifierOptions/ModifierId.dart b/lib/application/model/modifierOptions/ModifierId.dart new file mode 100644 index 0000000..4a10d45 --- /dev/null +++ b/lib/application/model/modifierOptions/ModifierId.dart @@ -0,0 +1,13 @@ +class ModifierId { + String? id; + String? name; + + ModifierId({this.id, this.name}); + + factory ModifierId.fromJson(Map json) { + return ModifierId( + id: json['_id'] ?? "", + name: json['name'] ?? "", + ); + } +} diff --git a/lib/application/model/modifierOptions/ModifierOption.dart b/lib/application/model/modifierOptions/ModifierOption.dart new file mode 100644 index 0000000..102bf46 --- /dev/null +++ b/lib/application/model/modifierOptions/ModifierOption.dart @@ -0,0 +1,62 @@ +import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/application/model/ingredients/AddIngredient.dart'; +import 'package:wosull/application/model/modifierOptions/ModifierId.dart'; +import 'package:wosull/application/model/store/WosulStore.dart'; +import 'package:wosull/helpers/Utils.dart'; + +class ModifierOption { + String? id; + ModifierId? modifier; + WosulStore? store; + String? name; + double? price; + bool? status; + String? createdAt; + String? updatedAt; + List? ingredients; + + ModifierOption( + {this.id = '', + this.modifier, + this.store, + this.name = '', + this.price, + this.status = true, + this.createdAt, + this.updatedAt, + this.ingredients}); + + factory ModifierOption.fromJson(Map json) { + return ModifierOption( + id: json['_id'] ?? "", + name: json['name'] ?? "", + modifier: json['modifier_id'] != null + ? ModifierId.fromJson(json['modifier_id']) + : ModifierId(), + store: json['store_id'] != null + ? WosulStore.fromJson(json['store_id']) + : WosulStore(), + price: Utils.checkDouble(json['price']), + status: json['status'] ?? false, + createdAt: json['createdAt'] ?? "", + updatedAt: json['updatedAt'] ?? "", + ingredients: json['ingredients'] != null + ? List.from(json['ingredients']) + .map((i) => AddIngredient.fromJson(i)) + .toList() + : []); + } + + Map toJson() { + final Map data = {}; + data['name'] = name; + data['status'] = status; + data['store_id'] = sharedPrefs.storeId; + data['modifier_id'] = modifier!.id; + data['price'] = price; + data['modifier_option_id'] = id; + data['ingredients'] = ingredients; + + return data; + } +} diff --git a/lib/application/model/modifierOptions/ModifierOptionsResponse.dart b/lib/application/model/modifierOptions/ModifierOptionsResponse.dart new file mode 100644 index 0000000..00d809f --- /dev/null +++ b/lib/application/model/modifierOptions/ModifierOptionsResponse.dart @@ -0,0 +1,19 @@ +import 'package:wosull/application/model/modifierOptions/ModifierOption.dart'; + +class ModifierOptionsResponse { + bool? status; + List? modifierOptions; + + ModifierOptionsResponse({this.status, this.modifierOptions}); + + factory ModifierOptionsResponse.fromJson(Map json) { + return ModifierOptionsResponse( + status: json['success'] ?? "", + modifierOptions: json['modifier_options'] != null + ? List.from(json['modifier_options']) + .map((i) => ModifierOption.fromJson(i)) + .toList() + : [], + ); + } +} diff --git a/lib/application/model/reports/CashierOrder.dart b/lib/application/model/reports/CashierOrder.dart new file mode 100644 index 0000000..d5c6466 --- /dev/null +++ b/lib/application/model/reports/CashierOrder.dart @@ -0,0 +1,107 @@ +import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/application/model/createOrder/CashierCart.dart'; +import 'package:wosull/application/model/store/WosulStore.dart'; +import 'package:wosull/helpers/Utils.dart'; + +class CashierOrder { + String? id; + CashierCart? cart; + double? totalAmount; + double? totalDiscount; + int? cardNumber; + int? timer; + String? deliveryNotes; + WosulStore? storeId; + String? orderType; + String? status; + bool? paymentStatus; + String? paymentMode; + double? amount; + double? changeBalanceAmount; + bool? isDeleted; + String? table; + String? createdAt; + String? updatedAt; + int? uniqueId; + String? returnOrderId; + int? referenceNo; + String? transactionId; + List? returnOrderDetails = []; + + CashierOrder( + {this.id, + this.returnOrderId, + this.totalAmount, + this.referenceNo, + this.transactionId, + this.totalDiscount, + this.cardNumber, + this.timer, + this.cart, + this.deliveryNotes, + this.storeId, + this.orderType, + this.status, + this.paymentStatus, + this.paymentMode, + this.amount, + this.changeBalanceAmount, + this.isDeleted, + this.table, + this.createdAt, + this.updatedAt, + this.uniqueId}); + + Map toJson() { + final Map data = {}; + + data['cart_id'] = cart!.toJsonOrder(); + data['order_id'] = id; + data['status'] = status; + data['store_id'] = sharedPrefs.storeId; + data['order_type'] = orderType; + data['payment_mode'] = paymentMode; + data['amount'] = amount; + data['change_balance_amount'] = changeBalanceAmount; + data['table'] = table; + data['card_number'] = cardNumber; + data['delivery_notes'] = deliveryNotes; + if (returnOrderId!.isNotEmpty) { + data['return_order_id'] = returnOrderId; + } + if (returnOrderDetails!.isNotEmpty) { + data['order_status'] = 'return'; + data['return_order_details'] = returnOrderDetails; + } + + return data; + } + + factory CashierOrder.fromJson(Map json) { + return CashierOrder( + id: json['_id'] ?? "", + totalAmount: Utils.checkDouble(json['total_amount'])!, + totalDiscount: Utils.checkDouble(json['total_discount'])!, + cardNumber: json['card_number'] ?? 0, + cart: json['cart_id'] != null + ? CashierCart.fromJson(json['cart_id']) + : CashierCart(orderDetails: []), + timer: json['timer'] ?? 0, + deliveryNotes: json['delivery_notes'] ?? "", + referenceNo: json['reference'] ?? 0, + transactionId: json['transaction_id'] ?? "", + storeId: WosulStore.fromJson(json['store_id']), + orderType: json['order_type'] ?? "", + status: json['status'] ?? "", + paymentStatus: json['payment_status'] ?? false, + paymentMode: json['payment_mode'] ?? "", + amount: Utils.checkDouble(json['amount'])!, + changeBalanceAmount: Utils.checkDouble(json['change_balance_amount'])!, + table: json['table'] ?? "", + uniqueId: json['order_number'] ?? 0, + createdAt: json['createdAt'] ?? "", + returnOrderId: json['return_order_id'] ?? '', + updatedAt: json['updatedAt'] ?? "", + ); + } +} diff --git a/lib/application/model/reports/CashierOrderHistory.dart b/lib/application/model/reports/CashierOrderHistory.dart index ead2895..ade7ad0 100644 --- a/lib/application/model/reports/CashierOrderHistory.dart +++ b/lib/application/model/reports/CashierOrderHistory.dart @@ -1,134 +1,18 @@ -import 'package:wosull/application/localdb/SharedPrefs.dart'; -import 'package:wosull/helpers/Utils.dart'; - -import '../createOrder/CashierCart.dart'; -import '../store/WosulStore.dart'; +import 'package:wosull/application/model/reports/CashierOrder.dart'; class CashierOrderHistory { - bool? success; - List? topOrders; + bool success; + List topOrders; - CashierOrderHistory({this.success, this.topOrders}); + CashierOrderHistory(this.success, this.topOrders); factory CashierOrderHistory.fromJson(Map json) { return CashierOrderHistory( - success: json['success'] as bool, - topOrders: json['cashier_order'] != null + json['success'] ?? false, + json['cashier_order'] != null ? List.from(json['cashier_order']) .map((i) => CashierOrder.fromJson(i)) .toList() : []); } } - -class CashierSingleOrderHistory { - bool? success; - CashierOrder? order; - - CashierSingleOrderHistory({this.success, this.order}); - - factory CashierSingleOrderHistory.fromJson(Map json) { - return CashierSingleOrderHistory( - success: json['success'] ?? false, - order: json['order'] != null - ? CashierOrder.fromJson(json['order']) - : CashierOrder()); - } -} - -class CashierOrder { - String? id; - CashierCart? cart; - double? totalAmount; - double? totalDiscount; - int? cardNumber; - int? timer; - String? deliveryNotes; - WosulStore? storeId; - String? orderType; - String? status; - bool? paymentStatus; - String? paymentMode; - double? amount; - double? changeBalanceAmount; - bool? isDeleted; - String? table; - String? createdAt; - String? updatedAt; - int? uniqueId; - String? returnOrderId; - List? returnOrderDetails = []; - - CashierOrder( - {this.id, - this.returnOrderId, - this.totalAmount, - this.totalDiscount, - this.cardNumber, - this.timer, - this.cart, - this.deliveryNotes, - this.storeId, - this.orderType, - this.status, - this.paymentStatus, - this.paymentMode, - this.amount, - this.changeBalanceAmount, - this.isDeleted, - this.table, - this.createdAt, - this.updatedAt, - this.uniqueId}); - - Map toJson() { - final Map data = {}; - - data['cart_id'] = cart!.toJsonOrder(); - data['order_id'] = id; - data['status'] = status; - data['store_id'] = sharedPrefs.storeId; - data['order_type'] = orderType; - data['payment_mode'] = paymentMode; - data['amount'] = amount; - data['change_balance_amount'] = changeBalanceAmount; - data['table'] = table; - data['card_number'] = cardNumber; - data['delivery_notes'] = deliveryNotes; - if (returnOrderId!.isNotEmpty) { - data['return_order_id'] = returnOrderId; - } - if (returnOrderDetails!.isNotEmpty) { - data['order_status'] = 'return'; - data['return_order_details'] = returnOrderDetails; - } - - return data; - } - - factory CashierOrder.fromJson(Map json) { - return CashierOrder( - id: json['_id'] ?? "", - totalAmount: Utils.checkDouble(json['total_amount'])!, - totalDiscount: Utils.checkDouble(json['total_discount'])!, - cardNumber: json['card_number'] ?? 0, - cart: json['cart_id'] != null - ? CashierCart.fromJson(json['cart_id']) - : null, - timer: json['timer'] ?? 0, - deliveryNotes: json['delivery_notes'] ?? "", - storeId: WosulStore.fromJson(json['store_id']), - orderType: json['order_type'] ?? "", - status: json['status'] ?? "", - paymentStatus: json['payment_status'] ?? false, - paymentMode: json['payment_mode'] ?? "", - amount: Utils.checkDouble(json['amount'])!, - changeBalanceAmount: Utils.checkDouble(json['change_balance_amount'])!, - table: json['table'] ?? "", - uniqueId: json['order_number'] ?? 0, - createdAt: json['createdAt'] ?? "", - returnOrderId: json['return_order_id'] ?? '', - updatedAt: json['updatedAt'] ?? "", - ); - } -} diff --git a/lib/application/model/reports/CashierSingleOrderHistory.dart b/lib/application/model/reports/CashierSingleOrderHistory.dart new file mode 100644 index 0000000..c6d7143 --- /dev/null +++ b/lib/application/model/reports/CashierSingleOrderHistory.dart @@ -0,0 +1,16 @@ +import 'package:wosull/application/model/reports/CashierOrder.dart'; + +class CashierSingleOrderHistory { + bool? success; + CashierOrder? order; + + CashierSingleOrderHistory({this.success, this.order}); + + factory CashierSingleOrderHistory.fromJson(Map json) { + return CashierSingleOrderHistory( + success: json['success'] ?? false, + order: json['order'] != null + ? CashierOrder.fromJson(json['order']) + : CashierOrder()); + } +} diff --git a/lib/application/model/reports/SearchCashierOrderHistory.dart b/lib/application/model/reports/SearchCashierOrderHistory.dart new file mode 100644 index 0000000..8e0bec6 --- /dev/null +++ b/lib/application/model/reports/SearchCashierOrderHistory.dart @@ -0,0 +1,18 @@ +import 'package:wosull/application/model/reports/CashierOrder.dart'; + +class SearchCashierOrderHistory { + bool? success; + List? topOrders; + + SearchCashierOrderHistory({this.success, this.topOrders}); + + factory SearchCashierOrderHistory.fromJson(Map json) { + return SearchCashierOrderHistory( + success: json['success'] as bool, + topOrders: json['cashier'] != null + ? List.from(json['cashier']) + .map((i) => CashierOrder.fromJson(i)) + .toList() + : []); + } +} diff --git a/lib/application/model/reports/TopOrderItemsModel.dart b/lib/application/model/reports/TopOrderItemsModel.dart index ee8abbb..b487eaf 100644 --- a/lib/application/model/reports/TopOrderItemsModel.dart +++ b/lib/application/model/reports/TopOrderItemsModel.dart @@ -1,39 +1,37 @@ class TopOrderItemsModel { - bool? success; - List? topOrders; + bool success; + List topOrders; - TopOrderItemsModel({this.success, this.topOrders}); + TopOrderItemsModel(this.success, this.topOrders); factory TopOrderItemsModel.fromJson(Map json) { return TopOrderItemsModel( - success: json['success'] as bool, - topOrders: json['data'] != null ? List.from(json['data']) - .map((i) => TopOrderItems.fromJson(i)) - .toList() : []); + json['success'] ?? false, + json['data'] != null + ? List.from(json['data']) + .map((i) => TopOrderItems.fromJson(i)) + .toList() + : []); } } class TopOrderItems { - String? id; - int? uniqueId; - String? itemName; - int? totalOrderQuantity; - int? count; + String id; + int uniqueId; + String itemName; + int totalOrderQuantity; + int count; - TopOrderItems( - {this.id, - this.uniqueId, - this.itemName, - this.totalOrderQuantity, - this.count}); + TopOrderItems(this.id, this.uniqueId, this.itemName, this.totalOrderQuantity, + this.count); factory TopOrderItems.fromJson(Map json) { return TopOrderItems( - id: json['_id'] ?? "", - uniqueId: json['unique_id'] ?? 0, - itemName: json['item_name'] ?? "", - totalOrderQuantity: json['total_ordered_quantity'] ?? 0, - count: json['count'] ?? 0, + json['_id'] ?? "", + json['unique_id'] ?? 0, + json['item_name'] ?? "", + json['total_ordered_quantity'] ?? 0, + json['count'] ?? 0, ); } } diff --git a/lib/application/model/store/GetStoreOrderByIdModel.dart b/lib/application/model/store/GetStoreOrderByIdModel.dart index a7983ff..e3523f9 100644 --- a/lib/application/model/store/GetStoreOrderByIdModel.dart +++ b/lib/application/model/store/GetStoreOrderByIdModel.dart @@ -35,7 +35,6 @@ class StoreOrderByIdModel { String? table; String? deliveryNotes; int? uniqueId; - String? createdAt; String? updatedAt; diff --git a/lib/application/model/store/StoreInvoicesModel.dart b/lib/application/model/store/StoreInvoicesModel.dart index 52c92c2..2ea4890 100644 --- a/lib/application/model/store/StoreInvoicesModel.dart +++ b/lib/application/model/store/StoreInvoicesModel.dart @@ -20,17 +20,15 @@ class StoreInvoicesModel { } class StoreInvoicesByIdModel { - bool? success; - StoreInvoice? invoice; - String? message; + bool success; + StoreInvoice invoice; + String message; - StoreInvoicesByIdModel({this.success, this.invoice, this.message}); + StoreInvoicesByIdModel(this.success, this.invoice, this.message); factory StoreInvoicesByIdModel.fromJson(Map json) { - return StoreInvoicesByIdModel( - message: json['message'] ?? '', - success: json['success'] ?? false, - invoice: StoreInvoice.fromJson(json['invoice'])); + return StoreInvoicesByIdModel(json['success'] ?? false, + StoreInvoice.fromJson(json['invoice']), json['message'] ?? ''); } } diff --git a/lib/application/model/store/StoreItemsResponse.dart b/lib/application/model/store/StoreItemsResponse.dart index 3235fb7..0e0c1bc 100644 --- a/lib/application/model/store/StoreItemsResponse.dart +++ b/lib/application/model/store/StoreItemsResponse.dart @@ -1,11 +1,12 @@ import 'package:objectbox/objectbox.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; import 'package:wosull/application/model/DeliveryPartner/ItemsDeliveryPartner.dart'; +import 'package:wosull/application/model/Modifiers/Modifier.dart'; +import 'package:wosull/application/model/Modifiers/ModifierOption.dart'; +import 'package:wosull/application/model/ingredients/AddIngredient.dart'; import '../../../helpers/Utils.dart'; import '../Combo/GetComboModel.dart'; -import '../Modifiers/GetModifiersModel.dart'; -import '../inventory/AddIngredientModel.dart'; class StoreItemsResponse { bool success; @@ -34,33 +35,18 @@ class StoreItemsResponse { } } -class SearchItemsResponse { - bool? success; - List? storeItems; - - SearchItemsResponse({this.success, this.storeItems}); - - factory SearchItemsResponse.fromJson(Map json) { - return SearchItemsResponse( - success: json['success'] ?? false, - storeItems: json['item'] != null - ? List.from(json['item']) - .map((i) => StoreItems.fromJson(i)) - .toList() - : []); - } -} - @Entity() class StoreItems { - @Id() - int obid = 0; + @Id(assignable: true) + int id = 0; + // @Unique(onConflict: ConflictStrategy.replace) + // var uniqueKey; - String id = ""; + String itemId = ""; String name; - List? noteForItem; + List? noteForItem = []; String storeId; bool isUnlimitedQuantity; String itemNameArabic; @@ -70,7 +56,7 @@ class StoreItems { int uniqueId; String uniqueIdForStoreData; - int quantity; + int? quantity; String imageUrl = ""; String updatedAt; bool isItemInStock = false; @@ -82,7 +68,8 @@ class StoreItems { int totalAddedQuantity; int totalUsedQuantity; double salePriceExclusiveTax; - double totalItemPrice; + + double? totalItemPrice; String supplier; String discount; String measurementCategory; @@ -94,19 +81,19 @@ class StoreItems { bool status; bool isCombo = false; bool isCheckedForReturn = false; - + @Transient() var selectedCombos = ToMany(); + @Transient() var selectedModifiers = ToMany(); var ingredients = ToMany(); var modifiers = ToMany(); var deliveryPartners = ToMany(); var comboProduct = ToMany(); - ProductId productIdUpdate = ProductId(); - StoreItems( {this.name = '', - this.id = '', + this.itemId = '', + this.id = 0, required this.deliveryPartners, this.isUnlimitedQuantity = false, required this.comboProduct, @@ -117,7 +104,7 @@ class StoreItems { this.price = 0.0, this.uniqueId = 0, this.uniqueIdForStoreData = '', - this.quantity = 0, + this.quantity, this.imageUrl = '', this.updatedAt = '', this.totalItemPrice = 0.0, @@ -147,10 +134,11 @@ class StoreItems { factory StoreItems.fromJson(Map json) { return StoreItems( + id: 0, status: json['status'] ?? false, name: json['name'] as String, itemNameArabic: json['item_name_arabic'] ?? "", - id: json['_id'] ?? "", + itemId: json['_id'] ?? "", //noteForItem: json['note_for_item'] != null ? List.from(json['note_for_item']) : [], // noteForItem: json['note_for_item'].cast(), noteForItem: json['note_for_item'] != null @@ -168,9 +156,7 @@ class StoreItems { productId: json['product_id'] ?? "", price: Utils.checkDouble(json['price'])!, uniqueId: json['unique_id'] ?? 0, - totalItemPrice: json['totalItemPrice'] != null - ? Utils.checkDouble(json['totalItemPrice'])! - : 0.0, + totalItemPrice: Utils.checkDouble(json['totalItemPrice'])!, description: json['details'] ?? "", totalAddedQuantity: json['total_quantity'] ?? 0, stockAlertQuantity: json['stock_alert_quantity'] ?? 0, @@ -185,7 +171,7 @@ class StoreItems { Utils.checkDouble(json['sale_price_exclusive_tax'])!, descriptionArabic: json['item_description_arabic'] ?? "", uniqueIdForStoreData: json['unique_id_for_store_data'] ?? "0", - quantity: json['quantity'] ?? 1, + quantity: json['quantity'] ?? 0, selectedModifiers: ToMany( items: json['selectedModifiers'] != null ? List.from(json['selectedModifiers']) @@ -231,7 +217,7 @@ class StoreItems { Map toJson() { final Map data = {}; data['product_id'] = productId; - data['_id'] = id; + data['_id'] = itemId; data['store_id'] = sharedPrefs.storeId; data['name'] = name; data['isCombo'] = isCombo; @@ -263,88 +249,4 @@ class StoreItems { data['note_for_item'] = noteForItem; return data; } - - Map toJsonProduct() { - final Map data = {}; - data['product_id'] = productId; - data['store_id'] = sharedPrefs.storeId; - data['name'] = name; - data['unlimited_quantity'] = isUnlimitedQuantity; - data['unique_id_for_store_data'] = uniqueId; - data['is_item_in_stock'] = isItemInStock; - data['item_name_arabic'] = itemNameArabic; - data['item_description_arabic'] = descriptionArabic; - data['details'] = description; - data['total_quantity'] = totalAddedQuantity ?? 1; - data['sale_price_exclusive_tax'] = salePriceExclusiveTax; - data['stock_alert_quantity'] = stockAlertQuantity; - data['is_visible_in_store'] = true; - data['price'] = price; - if (supplier.isNotEmpty) { - data['supplier'] = supplier; - } - if (discount.isNotEmpty) { - data['discount'] = discount ?? ""; - } - data['purchase_cost'] = purchasePrice; - //data['totalItemPrice'] = totalItemPrice ?? 0.0; - data['delivery_partners'] = deliveryPartners; - data['measurement'] = measurement ?? ""; - data['manufacturer_date'] = manufactureDate; - data['expiry_date'] = expireDate; - data['ingrediants'] = ingredients; - data['modifiers'] = modifiers; - return data; - } - - Map toJsonUpdateProduct() { - final Map data = {}; - data['product_id'] = productIdUpdate.toJson(); - data['store_id'] = sharedPrefs.storeId; - data['name'] = name; - data['unlimited_quantity'] = isUnlimitedQuantity ?? false; - data['productId'] = product_product_id ?? "0"; - data['_id'] = id; - data['unique_id_for_store_data'] = uniqueId; - data['is_item_in_stock'] = isItemInStock; - data['item_name_arabic'] = itemNameArabic; - data['item_description_arabic'] = descriptionArabic; - data['details'] = description; - data['total_quantity'] = totalAddedQuantity; - data['sale_price_exclusive_tax'] = salePriceExclusiveTax; - data['stock_alert_quantity'] = stockAlertQuantity; - data['is_visible_in_store'] = true; - data['price'] = price; - data['purchase_cost'] = purchasePrice; - data['quantity'] = quantity ?? 1; - if (supplier.isNotEmpty) { - data['supplier'] = supplier ?? ""; - } - if (discount.isNotEmpty) { - data['discount'] = discount ?? ""; - } - data['delivery_partners'] = deliveryPartners; - data['measurement'] = measurement ?? ""; - data['manufacturer_date'] = manufactureDate ?? ""; - data['expiry_date'] = expireDate ?? ""; - data['ingrediants'] = ingredients; - data['modifiers'] = modifiers; - return data; - } -} - -@Entity() -class ProductId { - @Id() - int obid = 0; - - String? productId; - String? categoryId; - - Map toJson() { - final Map data = {}; - data['category_id'] = categoryId; - data['_id'] = productId; - return data; - } } diff --git a/lib/application/model/store/WosulStore.dart b/lib/application/model/store/WosulStore.dart index a087a3d..96216f3 100644 --- a/lib/application/model/store/WosulStore.dart +++ b/lib/application/model/store/WosulStore.dart @@ -1,6 +1,10 @@ class WosulStore { String id; String name; + String email; + String countryPhoneCode; + String phone; + String address; int cartUniqueID; Map toJson() { @@ -10,13 +14,25 @@ class WosulStore { return data; } - WosulStore({this.id = '', this.name = '', this.cartUniqueID = 0}); + WosulStore({ + this.id = '', + this.name = '', + this.cartUniqueID = 0, + this.address = '', + this.email = '', + this.countryPhoneCode = '', + this.phone = '', + }); factory WosulStore.fromJson(Map json) { return WosulStore( cartUniqueID: json['cart_unique_id'] ?? 0, id: json['_id'] ?? "", name: json['name'] ?? "", + address: json['address'] ?? "", + email: json['email'] ?? "", + countryPhoneCode: json['country_phone_code'] ?? "", + phone: json['phone'] ?? "", ); } } diff --git a/lib/application/network/APIManager.dart b/lib/application/network/APIManager.dart index 151ae78..e1c1ab9 100644 --- a/lib/application/network/APIManager.dart +++ b/lib/application/network/APIManager.dart @@ -22,6 +22,18 @@ class APIManager { } } + Future getResponse(String value, + [Map? queryParameter]) async { + try { + dynamic response = await apiServices + .getResponse(value, queryParameter) + .timeout(const Duration(seconds: 60)); + return response; + } catch (e) { + return e; + } + } + Future getResponseAuth(String value, [Map? queryParameter]) async { try { @@ -30,6 +42,7 @@ class APIManager { .timeout(const Duration(seconds: 60)); return response; } catch (e) { + print(e.toString()); return e; } } diff --git a/lib/application/network/ApiServices.dart b/lib/application/network/ApiServices.dart index 15aa633..6d72bdf 100644 --- a/lib/application/network/ApiServices.dart +++ b/lib/application/network/ApiServices.dart @@ -33,10 +33,11 @@ class ApiServices extends BaseService { dynamic responseJson; try { dio.options.headers['content-Type'] = 'application/json'; - dio.options.headers["Authorization"] = Constants.auth; + dio.options.headers['Authorization'] = Constants.auth; final response = await dio.get(mediaBaseUrl + url, queryParameters: queryParameter); + responseJson = returnResponseDio(response); } on SocketException { throw FetchDataException('No Internet Connection'); @@ -51,6 +52,7 @@ class ApiServices extends BaseService { dio.options.headers['content-Type'] = 'application/json'; dio.options.headers["Authorization"] = Constants.auth; final response = await dio.post(mediaBaseUrl + url, data: data); + responseJson = returnResponseDio(response); } on SocketException { throw FetchDataException('No Internet Connection'); diff --git a/lib/application/repo/AuthRepository.dart b/lib/application/repo/AuthRepository.dart index 46f2c19..4c6d478 100644 --- a/lib/application/repo/AuthRepository.dart +++ b/lib/application/repo/AuthRepository.dart @@ -29,6 +29,7 @@ class AuthRepository { dynamic response = await apiServices .postResponse(value, data) .timeout(const Duration(seconds: 60)); + return response; } diff --git a/lib/application/repository/WosulRepository.dart b/lib/application/repository/WosulRepository.dart new file mode 100644 index 0000000..e1d6cde --- /dev/null +++ b/lib/application/repository/WosulRepository.dart @@ -0,0 +1,336 @@ +import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/application/model/Combo/GetComboGroupModel.dart'; +import 'package:wosull/application/model/Combo/GetComboMeasurementModel.dart'; +import 'package:wosull/application/model/Combo/GetComboProuctItem.dart'; +import 'package:wosull/application/model/Measurement/InventoryMeasurementModel.dart'; +import 'package:wosull/application/model/Measurement/MeasurementUnitModel.dart'; +import 'package:wosull/application/model/Measurement/MeasuringUnit.dart'; +import 'package:wosull/application/model/Modifiers/GetModifiersModel.dart'; +import 'package:wosull/application/model/Modifiers/Modifier.dart'; +import 'package:wosull/application/model/SimpleResponsModel.dart'; +import 'package:wosull/application/model/StockTransfer/ProductItemCategoryModel.dart'; +import 'package:wosull/application/model/WosulSettings.dart'; +import 'package:wosull/application/model/brands/GetBrandsModel.dart'; +import 'package:wosull/application/model/customers/GetStoreCustomer.dart'; +import 'package:wosull/application/model/discount/StoreDiscountModel.dart'; +import 'package:wosull/application/model/ingredients/AddIngredient.dart'; +import 'package:wosull/application/model/ingredients/GetIngredientModel.dart'; +import 'package:wosull/application/model/inventory/category/ItemCategory.dart'; +import 'package:wosull/application/model/inventory/category/ItemCategoryResponse.dart'; +import 'package:wosull/application/model/invoice/PaymentMethod.dart'; +import 'package:wosull/application/model/invoice/PaymentMethodResponse.dart'; +import 'package:wosull/application/model/store/GetSpecificStores.dart'; +import 'package:wosull/application/model/store/GetStoreCurrency.dart'; +import 'package:wosull/application/model/store/GetStoreSupplier.dart'; +import 'package:wosull/application/model/store/StoreInvoicesModel.dart'; +import 'package:wosull/application/model/tables/GetStoreTable.dart'; +import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/repo/AuthRepository.dart'; +import 'package:wosull/application/utils/Constants.dart'; + +class WosulRepository { + Future> getPaymentMethods( + {Map? map}) async { + var items = []; + map ??= {'page': 1, 'is_pagination_included': false}; + await APIManager() + .getResponseAuth( + "${Constants.getPaymentMethods}/${sharedPrefs.storeId}", map) + .then((result) { + final value = PaymentMethodResponse.fromJson(result); + if (value.status) { + items.addAll(value.paymentMethods); + } + }).onError((error, stackTrace) {}); + return items; + } + + Future> getCompany() async { + var items = []; + Map data = { + 'store': sharedPrefs.storeId, + }; + await APIManager() + .fetchData(Constants.GET_STORE_CUSTOMER, data) + .then((value) { + final response = GetStoreCustomer.fromJson(value); + if (response.success!) { + items.addAll(response.topOrders!); + } + }).onError((error, stackTrace) {}); + + return items; + } + + Future getTables() async { + final value = await APIManager() + .fetchData(Constants.GET_STORE_TABLES, Constants.getStorePayload()); + return GetStoreTable.fromJson(value); + } + + Future> getCurrency() async { + var currencies = []; + await APIManager() + .fetchData(Constants.GET_STORE_CURRENCY, Constants.getStorePayload()) + .then((value) async { + final response = GetStoreCurrency.fromJson(value); + if (response.success) { + currencies.addAll(response.currencies); + } else { + for (var currency in Constants.salesCurrencies) { + currencies.add(Currency(id: '', name: currency)); + } + } + }).onError((error, stackTrace) {}); + + return currencies; + } + + Future> getTax() async { + var items = []; + await APIManager() + .getResponse(Constants.GET_WOSUL_SETTINGS) + .then((value) { + final response = WosulSettings.fromJson(value); + if (response.success!) { + items.addAll(response.wosulSettings!.first.vatTaxes!); + } + }) + .onError((error, stackTrace) {}) + .timeout(const Duration(minutes: 1)); + + return items; + } + + Future> getDiscount() async { + var items = []; + await APIManager() + .fetchData(Constants.GET_DISCOUNT, Constants.getStorePayload()) + .then((value) { + final response = StoreDiscountModel.fromJson(value); + if (response.success!) { + items.addAll(response.storeDiscount!); + } + }).onError((error, stackTrace) {}); + + return items; + } + + Future> getMeasurement() async { + var items = []; + + await APIManager() + .fetchData(Constants.GET_MEASUREMENT, Constants.getStorePayload()) + .then((value) { + final response = InvoiceMeasurementModel.fromJson(value); + if (response.success!) { + items.addAll(response.measurements!); + } + }).onError((error, stackTrace) {}); + + return items; + } + + Future> getMeasurementUnits() async { + var items = []; + Map data = {}; + await APIManager() + .getResponseAuth( + "${Constants.GET_INVENTORY_MEASUREMENTS_UNITS}/${sharedPrefs.storeId}", + data) + .then((value) { + final response = MeasurementUnitModel.fromJson(value); + if (response.success) { + items.addAll(response.measurementUnits); + } + }).onError((error, stackTrace) {}); + return items; + } + + Future> getMeasurements() async { + var items = []; + + await APIManager() + .getResponse(Constants.getMeasuringUnit, Constants.getStorePayload()) + .then((value) { + final response = MeasuringUnit.fromJson(value); + if (response.success) { + items.addAll(response.measurementUnits); + } + }).onError((error, stackTrace) {}); + + return items; + } + + Future> getIngredients() async { + var ingredients = []; + await APIManager() + .getResponseAuth("${Constants.GET_INGREDIENTS}/${sharedPrefs.storeId}") + .then((value) { + final response = GetIngredientModel.fromJson(value); + if (response.success) { + ingredients.addAll(response.ingredient); + } + }).onError((error, stackTrace) {}); + return ingredients; + } + + Future> getModifiers() async { + var modifiers = []; + await APIManager() + .getResponseAuth(Constants.getModifiers + sharedPrefs.storeId) + .then((value) { + final response = GetModifiersModel.fromJson(value); + if (response.success!) { + modifiers.clear(); + modifiers.addAll(response.modifiers!); + } + }).onError((error, stackTrace) {}); + return modifiers; + } + + Future> getCategoriesData() async { + var items = []; + await APIManager() + .fetchData(Constants.GET_STORE_CATEGORY, Constants.getStorePayload()) + .then((value) { + final response = ItemCategoryResponse.fromJson(value); + if (response.success) { + items.addAll(response.categories); + } + }).onError((error, stackTrace) {}); + return items; + } + + Future> getSuppliersData() async { + var suppliers = []; + await APIManager() + .fetchData(Constants.GET_STORE_SUPPLIER, Constants.getStorePayload()) + .then((value) { + final response = GetStoreSupplier.fromJson(value); + suppliers.addAll(response.suppliers!); + }).onError((error, stackTrace) {}); + return suppliers; + } + + Future getSpecificStoresById(Map value) async { + try { + dynamic response = await AuthRepository() + .postResponseAuth(Constants.GET_SPECIFIC_STORES, value); + return GetSpecificStores.fromJson(response); + } catch (e) { + return GetSpecificStores(success: false, stores: [], message: ''); + } + } + + Future> getProductSearchStores( + Map data) async { + try { + dynamic response = await AuthRepository() + .postResponseAuth(Constants.SEARCH_ITEM_STORE, data); + final value = ProductItemCategoryModel.fromJson(response); + return value.categories; + } catch (e) { + return []; + } + } + + Future> getAllProducts() async { + var items = []; + await AuthRepository() + .postResponseAuth( + Constants.SEARCH_ITEM_STORE, Constants.getStorePayload()) + .then((response) { + final value = ProductItemCategoryModel.fromJson(response); + items.addAll(value.categories); + }).onError((error, stackTrace) {}); + return items; + } + + Future getData(String url, Map data) async { + try { + dynamic response = await AuthRepository().postResponseAuth(url, data); + return response; + } catch (e) { + return e; + } + } + + Future getResponsePatch( + String url, Map data) async { + try { + dynamic response = await AuthRepository().patchResponseAuth(url, data); + return SimpleResponseModel.fromJson(response); + } catch (e) { + return SimpleResponseModel(success: false, message: e.toString()); + } + } + + Future> loadProduct(Map map) async { + var items = []; + await APIManager() + .fetchData(Constants.GET_PRODUCT_ITEM_BY_CATEGORY, map) + .then((value) { + final response = GetComboProductItem.fromJson(value); + if (response.success!) { + items.clear(); + items.addAll(response.products!); + } + }).onError((error, stackTrace) {}); + return items; + } + + Future> loadMeasurement() async { + var measurements = []; + await APIManager() + .fetchData(Constants.GET_MEASUREMENT, Constants.getStorePayload()) + .then((value) { + final response = GetComboMeasurementModel.fromJson(value); + if (response.success!) { + measurements.clear(); + measurements.addAll(response.measurements!); + } + }).onError((error, stackTrace) {}); + return measurements; + } + + Future> loadGroups() async { + var groups = []; + await APIManager() + .fetchData(Constants.GET_COMBO_GROUPS, Constants.getStorePayload()) + .then((value) { + final response = GetComboGroupModel.fromJson(value); + if (response.success!) { + groups.addAll(response.comboGroup!); + } + }).onError((error, stackTrace) {}); + return groups; + } + + Future> getBrandsData() async { + var items = []; + await APIManager().getResponseAuth(Constants.GET_BRANDS).then((value) { + final response = GetBrandsModel.fromJson(value); + if (response.success!) { + items.addAll(response.brands!); + } + }).onError((error, stackTrace) {}); + return items; + } + + Future> getStoreCategoriesData() async { + var items = []; + await APIManager() + .fetchData( + Constants.GET_STORE_CATEGORY_LIST, Constants.getStorePayload()) + .then((value) { + final itemCategoryResponse = ItemCategoryResponse.fromJson(value); + if (itemCategoryResponse.success && + itemCategoryResponse.categories.isNotEmpty) { + items.addAll(itemCategoryResponse.categories); + } + }).onError((error, stackTrace) {}); + + return items; + } +} diff --git a/lib/application/theme/MyColors.dart b/lib/application/theme/MyColors.dart index 1e918c8..178e5c8 100644 --- a/lib/application/theme/MyColors.dart +++ b/lib/application/theme/MyColors.dart @@ -1,5 +1,6 @@ import 'package:dropdown_search/dropdown_search.dart'; import 'package:flutter/material.dart'; +import 'package:sizer/sizer.dart'; import 'package:wosull/application/theme/MyFonts.dart'; import 'package:wosull/helpers/ThemeText.dart'; @@ -56,12 +57,22 @@ class MyColors { static const greenColorEnable = Color(0xFF19a263); - static const greenColorDisable = Color(0x5019a263); + static const greenColorDisable = Color(0xFF7EB995); static const fillColor2 = Color(0xFFF5F8FA); static const fillRed = Color(0xFFDC3545); + static const colorOrange = Color(0xFFffa500); + + static const colorRed = Color(0xFFff0000); + + static const colorGreen = Color(0xFF008000); + + static const redLabelColor = Color(0xFFdc3545); + + static const redAlpha50 = Color(0x10dc3545); + static const fillColor3 = Color(0xFFE1E8EF); static const fillColorGray = Color(0xFFE8ECF0); @@ -74,7 +85,8 @@ class MyColors { static TextStyle textStyleValueNormal({Color? textColor = MyColors.white}) { return TextStyle( - fontSize: MyFonts.normal, + fontSize: + SizerUtil.deviceType == DeviceType.mobile ? 11 : MyFonts.normal, fontFamily: MyFonts.DMREGULAR, color: textColor); } @@ -100,23 +112,88 @@ class MyColors { fontSize: 13, fontFamily: MyFonts.Medium, color: MyColors.black); } - static DropDownDecoratorProps dropDownStyle({String hint = 'Choose'}) { + static DropDownDecoratorProps dropDownStyleAddProduct( + {String hint = 'Choose', Color fillColor = const Color(0xFFF4F6FB)}) { + return DropDownDecoratorProps( + // baseStyle: const TextStyle( + // fontFamily: MyFonts.Medium, + // fontSize: 11, + // color: MyColors.textColorBlack20, + // fontWeight: FontWeight.w100, + // ), + baseStyle: ThemeText.textFliedStyleValue, + textAlignVertical: TextAlignVertical.center, + dropdownSearchDecoration: InputDecoration( + fillColor: fillColor, + filled: true, + labelStyle: ThemeText.textFliedStyleValue, + hintStyle: ThemeText.textFliedStyleValue, + isDense: true, + contentPadding: const EdgeInsets.only(left: 8), + focusedBorder: OutlineInputBorder( + borderSide: const BorderSide( + width: 0.5, //<-- SEE HERE + color: MyColors.textColorGray, + ), + borderRadius: BorderRadius.circular(8.0), + ), + // Added + enabledBorder: OutlineInputBorder( + borderSide: const BorderSide( + width: 0, //<-- SEE HERE + color: Colors.transparent, + ), + borderRadius: BorderRadius.circular(8.0), + ), + hintText: hint, + ), + ); + } + + static DropDownDecoratorProps dropDownStyle( + {String hint = 'Choose', Color fillColor = const Color(0xFFF4F6FB)}) { return DropDownDecoratorProps( + // baseStyle: const TextStyle( + // fontFamily: MyFonts.Medium, + // fontSize: 11, + // color: MyColors.textColorBlack20, + // fontWeight: FontWeight.w100, + // ), baseStyle: ThemeText.textStyleValue, textAlignVertical: TextAlignVertical.center, dropdownSearchDecoration: InputDecoration( - border: InputBorder.none, + fillColor: fillColor, + filled: true, + labelStyle: ThemeText.textStyleValue, + hintStyle: ThemeText.textStyleValue, + isDense: true, + contentPadding: const EdgeInsets.only(left: 8), + focusedBorder: OutlineInputBorder( + borderSide: const BorderSide( + width: 0.5, //<-- SEE HERE + color: MyColors.textColorGray, + ), + borderRadius: BorderRadius.circular(8.0), + ), + // Added + enabledBorder: OutlineInputBorder( + borderSide: const BorderSide( + width: 0, //<-- SEE HERE + color: Colors.transparent, + ), + borderRadius: BorderRadius.circular(8.0), + ), hintText: hint, ), ); } static TextStyle textStylePageHeading() { - return const TextStyle( + return TextStyle( fontWeight: FontWeight.bold, fontFamily: MyFonts.Bold, fontSize: MyFonts.bold, - color: Color(0xFF4b5b73)); + color: const Color(0xFF4b5b73)); } static TextStyle textStyleButton( diff --git a/lib/application/theme/MyFonts.dart b/lib/application/theme/MyFonts.dart index 27ffb3c..345771d 100644 --- a/lib/application/theme/MyFonts.dart +++ b/lib/application/theme/MyFonts.dart @@ -1,4 +1,4 @@ -import 'package:flutter/material.dart'; +import 'package:sizer/sizer.dart'; class MyFonts { static const Medium = 'DMSansMedium'; @@ -11,16 +11,19 @@ class MyFonts { static const RobotoBold = 'RobotoBold'; - static const bold = 18.0; + static const DejaVu = 'DejaVuSansMono'; - static const H1 = 16.0; + static final bold = SizerUtil.deviceType == DeviceType.tablet ? 18.0 : 15.0; - static const H2 = 14.0; + static final H1 = SizerUtil.deviceType == DeviceType.tablet ? 16.0 : 14.0; - static const normal = 12.0; + static final H2 = SizerUtil.deviceType == DeviceType.tablet ? 14.0 : 12.0; - static const normalButton = 14.0; - - - static const mediumText = 13.0; + static final normal = SizerUtil.deviceType == DeviceType.tablet ? 12.0 : 11.0; + + static final normalButton = + SizerUtil.deviceType == DeviceType.tablet ? 14.0 : 12.0; + + static final mediumText = + SizerUtil.deviceType == DeviceType.tablet ? 13.0 : 12.0; } diff --git a/lib/application/utils/AppError.dart b/lib/application/utils/AppError.dart index 3973601..14d3e7a 100644 --- a/lib/application/utils/AppError.dart +++ b/lib/application/utils/AppError.dart @@ -1,5 +1,6 @@ import 'package:flutter/cupertino.dart'; -import 'package:wosull/widgets/HeadingText.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/helpers/ThemeText.dart'; class AppError extends StatelessWidget { String error; @@ -8,9 +9,18 @@ class AppError extends StatelessWidget { @override Widget build(BuildContext context) { - // TODO: implement build - return Center( - child: HeadingText(error), - ); + return Container( + height: 42, + margin: const EdgeInsets.only(top: 16), + decoration: const BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(16)), + color: MyColors.white), + width: double.infinity, + child: Center( + child: Text( + error, + style: ThemeText.textStylePopUpHeading, + ), + )); } } diff --git a/lib/application/utils/AppLoader.dart b/lib/application/utils/AppLoader.dart index ee31ff2..96feed3 100644 --- a/lib/application/utils/AppLoader.dart +++ b/lib/application/utils/AppLoader.dart @@ -1,8 +1,15 @@ import 'package:flutter/material.dart'; +import 'package:wosull/application/theme/MyColors.dart'; class AppLoader extends StatelessWidget { @override Widget build(BuildContext context) { - return const Center(child: CircularProgressIndicator()); + return Center( + child: CircularProgressIndicator( + backgroundColor: MyColors.backColorBlue50, + valueColor: AlwaysStoppedAnimation( + MyColors.blueThemeColor, //<-- SEE HERE + ), + )); } } diff --git a/lib/application/utils/Constants.dart b/lib/application/utils/Constants.dart index e326179..c391b77 100644 --- a/lib/application/utils/Constants.dart +++ b/lib/application/utils/Constants.dart @@ -15,14 +15,15 @@ class Constants { static const getStoreDetails = 'api/user/get_store_details'; static const getAccessToken = 'api/store/get_access_token'; static const GET_SUBCATEGORIES_URL = 'api/store/get_sub_category_list_v2'; - + static const CREATE_ACCESS_TOKEN = 'api/store/create_access_token'; static const GET_PRODUCTS = 'api/store/get_product_list_by_category_v2'; static const ITEM_TYPE_CATEGORIES_URL = 'api/store/get_category_list_v2'; static const ITEM_TYPE_SUBCATEGORIES_URL = 'api/user/user_get_store_product_item_list'; static const ITEM_GET_PRODUCT_LIST_BY_CATEGORY = 'api/store/get_product_list_by_category'; - + static const getPaymentMethods = 'api/store/get_payment_methods'; + static const getStoreIncomeAccounts = 'api/store/get_store_income_accounts'; static const returnDamagePOS = 'api/store/return_or_damage_pos'; static const GET_ADMIN_DASHBOARD_DATA = 'api/store/admin_dashboard_data'; static const GET_PRODUCT_BY_ID = 'api/store/get_product_by_id'; @@ -63,8 +64,10 @@ class Constants { static const UPDATE_MEASUREMENT_STATUS = 'api/store/update_measurement_status'; - //stock transfer + static const getMeasuringUnit = 'api/store/get_measuring_unit'; + //stock transfer + static const searchStockTransfer = 'api/store/search_stock'; static const GET_STOCK_TRANSFER = 'api/store/get_stock_transfer'; static const DELETE_STOCK_TRANSFER = 'api/store/delete_stock_transfer'; static const UPDATE_STOCK_TRANSFER = 'api/store/update_stock_status'; @@ -88,6 +91,15 @@ class Constants { static const DELETE_MODIFIER = 'api/store/delete_store_modifier'; static const ADD_UPDATE_MODIFIER = 'api/store/add_modifier'; + static const addModifierOptions = 'api/store/add_modifier_option'; + static const getModifierOptions = 'api/store/get_modifier_options/'; + static const updateModifierOption = 'api/store/update_modifier_option_status'; + static const deleteModifierOption = 'api/store/delete_store_modifier_option'; + static const getModifiers = 'api/store/get_modifiers/'; + + static const getReturnStock = 'api/store/get_return_stock'; + static const addStockReturn = 'api/store/add_store_return_stock'; + static const ADD_STORE_TABLE = 'api/store/add_store_table'; static const UPDATE_STORE_TABLE = 'api/store/update_store_table_status'; static const DELETE_STORE_TABLE = 'api/store/delete_store_table'; @@ -116,6 +128,7 @@ class Constants { static const NEW_COMBO = 'api/store/add_combo'; //invoice + static const updateInvoicePayment = 'api/store/update_invoice_payment'; static const GET_INVOICE_BY_ID = 'api/store/get_invoice_by_id'; static const GET_INVOICE = 'api/store/get_store_invoice'; static const DELETE_NVOICE = 'api/store/delete_invoice'; @@ -141,13 +154,15 @@ class Constants { static const GET_MEASUREMENT_CATEGORY = 'api/store/get_measurement_category'; static const GET_BRANDS = 'api/store/get_brand'; static const ADD_INGREDIENTS = 'api/store/add_ingredient'; + static const searchIngredients = 'api/store/search_ingrediant'; static const GET_STORE_TABLES = 'api/store/get_store_table'; static const GET_STORE_TABLES_LIST = 'api/store/get_store_table_list'; static const GET_STORE_SUB_STORES = 'api/store/get_stores_sub_stores'; static const GET_ORDER_BY_STATUS = 'api/store/get_order_by_status'; static const UPDATE_CASHIER_ORDER = 'api/store/update_cashier_orders'; - + static const searchInvoice = 'api/store/search_invoice'; + static const SEARCH_SUB_CATEGORY = 'api/store/search_subCategory'; static const SEARCH_CATEGORY = 'api/store/search_category'; static const SEARCH_MEASUREMENT = 'api/store/search_measurement'; static const addMeasurementUnit = 'api/store/add_measuring_unit'; @@ -174,11 +189,24 @@ class Constants { static const GET_TOP_POS_SALE = 'api/store/get_pos_sales_for_store/'; static const GET_ITEMS_WITH_CATEGORY = 'api/store/get_items_with_category'; static const GET_ORDER_BY_ID = 'api/store/get_order_by_id/'; + static const searchQuotation = 'api/store/search_quotation'; + static const searchCashier = 'api/store/search_cashier'; //billing counter static const GET_BILLING_COUNTER_BY_ID = 'api/store/get_billing_counter_by_id/'; + static const GET_STORE_ACCOUNTS = 'api/store/get_store_accounts/'; + static const billingDashboardData = 'api/store/billing_dashboard_data'; + static const addBusinessRegister = 'api/store/add_business_register'; + static const getBusinessRegisterById = + 'api/store/get_business_register_by_id'; + static const updateBusinessRegisterById = + 'api/store/update_business_register'; + static const addPaymentMethod = 'api/store/add_payment_method'; + static const updatePaymentMethodStatus = + 'api/store/update_payment_method_status'; + static const deletePaymentMethod = 'api/store/delete_payment_method'; //ingredients static const getIngredientsList = 'api/store/get_ingrediant_list'; @@ -191,17 +219,32 @@ class Constants { static const storeEmail = "storeEmail"; static const storeid = "storeid"; static const billingCounterId = 'billingCounterId'; + static const businessRegisterId = 'businessRegisterId'; static const cartID = 'cartID'; static final auth = sharedPrefs.token; static const store_name = 'store_name'; + static const deliveryService = 'DELIVERY'; + static const dineInService = 'DINE IN'; + static const takeawayService = 'TAKE AWAY'; + static const deliveryPartnerService = 'DELIVERY PARTNER'; + static const cartUniqueToken = 'cartUniqueToken'; static const cartUniqueId = 'cartUniqueId'; static const billingCounterName = 'billingCounterName'; static const preparing = "preparing"; static const holdOrder = "holdOrder"; static const ready = "ready"; + static const completed = "completed"; + static const cancelled = "cancelled"; + + static const dineIn = "dinein"; + static const takeAway = "takeaway"; + static const deliveryPartner = "deliverypartner"; + + static const statusReturn = "return"; + static const statusDamage = "damage"; static const invoiceFilterType = [ 'All', @@ -212,6 +255,26 @@ class Constants { 'Return' ]; + static const posStatus = [ + 'Return', + 'Damage', + ]; + + static const activeStatus = [ + 'Active', + 'Inactive', + ]; + + static const reportsTypes = [ + 'Best Seller', + 'POS Complete', + 'POS Return & Damage', + 'Invoices', + 'Quotations', + 'Categories', + 'Products' + ]; + static const appliedTypes = [ 'allStores', 'specificStore', @@ -234,9 +297,12 @@ class Constants { ]; static const quotationStatus = [ - 'Open', + 'All', + 'Pending', 'Accepted', - 'Rejected', + 'Declined', + 'Expired', + 'Cancelled', ]; static const orderStatus = [ @@ -245,10 +311,32 @@ class Constants { 'Cancelled', ]; + static const paymentMethodForOrders = [ + 'Stc Pay', + 'Mada', + 'Visa', + 'Sure Pay', + 'Express Pay', + 'Near Pay', + ]; + + static const counterTypes = [ + 'All Counter', + 'Open Counter', + 'Closed Counter', + ]; + + static const currencies = [ + 'SAR', + 'AED', + ]; + static const paymentMethod = [ 'Cash', ]; + static const pageLimits = ['10', '25', '50', '100']; + static const discountTypes = ['Automatic', 'Manual']; static const returnProductReason = [ @@ -257,6 +345,49 @@ class Constants { 'Other', ]; + static const types = [ + "Manual", + "Automatic", + ]; + + static const discountType = [ + 'Percentage', + 'Amount', + ]; + + static const salesCurrencies = ['SAR', 'AED', 'USD', 'EUR']; + + static const chooseInvoiceForTypes = [ + 'Customer', + 'Company', + ]; + + static const taxOptions = [ + 'VAT', + ]; + + static const statusTypes = [ + 'Open', + 'Paid Partially', + 'Paid', + 'Cancelled', + ]; + + static const quotationStatusTypes = [ + 'Pending', + 'Accepted', + 'Declined', + 'Expired', + 'Cancelled', + ]; + + static const discountFilters = [ + "All Products", + "Specific Products", + "Specific Categories of Products", + "All Products except specific products" + ]; + static Map getStorePayload() { Map data = { 'store_id': sharedPrefs.storeId, diff --git a/lib/application/views/authModule/checkinViews/CheckInPopUp.dart b/lib/application/views/authModule/checkinViews/CheckInPopUp.dart new file mode 100644 index 0000000..c534bb4 --- /dev/null +++ b/lib/application/views/authModule/checkinViews/CheckInPopUp.dart @@ -0,0 +1,241 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:provider/provider.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/theme/MyFonts.dart'; +import 'package:wosull/application/utils/AppLoader.dart'; +import 'package:wosull/application/utils/CRUDOperatoinState.dart'; +import 'package:wosull/application/views/authModule/checkinViews/viewModel/CheckInViewModel.dart'; +import 'package:wosull/base/BaseStatefulState.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/widgets/BoxContainer.dart'; +import 'package:wosull/widgets/CustomSimpleButton.dart'; +import 'package:wosull/widgets/CustomTextFieldForm.dart'; +import 'package:wosull/widgets/DialogHeader.dart'; +import 'package:wosull/widgets/MandatoryTitleText.dart'; + +class CheckInPopUp extends StatefulWidget { + const CheckInPopUp({ + Key? key, + }) : super(key: key); + + @override + State createState() => _CheckInPopUpState(); +} + +class _CheckInPopUpState extends BaseStatefulState { + bool isPortrait = true; + var viewModel = CheckInViewModel(); + + @override + void initState() { + super.initState(); + } + + @override + void dispose() { + super.dispose(); + viewModel.disposeData(); + } + + @override + Widget build(BuildContext context) { + viewModel = context.watch(); + return Directionality( + textDirection: TextDirection.ltr, + child: Dialog( + elevation: 0, + backgroundColor: const Color(0xffffffff), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: OrientationBuilder(builder: (c, orientation) { + isPortrait = + MediaQuery.of(context).orientation == Orientation.portrait; + return SingleChildScrollView( + child: SizedBox( + width: !isPortrait + ? MediaQuery.of(context).size.width / 1.2 + : double.infinity, + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + DialogHeader( + title: AppLocalizations.of(context)!.check_in, + ), + Container( + margin: const EdgeInsets.all(12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + const MandatoryTitleText(hint: 'Opening Amount'), + AppSpaces.verticalSmall, + CustomTextFieldForm( + keyboardType: TextInputType.number, + onChanged: (value) { + viewModel.cashAmount = value; + }, + hintText: 'Enter Cash in amount'), + AppSpaces.verticalLarge, + Row( + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.max, + children: [ + Flexible( + child: BoxContainer( + fillColor: MyColors.fillColor3, + title: 'Available', + )), + AppSpaces.horizontalSmall, + Flexible( + child: BoxContainer( + fillColor: MyColors.fillRed, + title: AppLocalizations.of(context)! + .not_available), + ), + AppSpaces.horizontalSmall, + Flexible( + child: BoxContainer( + fillColor: MyColors.greenColor, + title: + AppLocalizations.of(context)!.selected), + ), + ], + ), + AppSpaces.verticalLarge, + FutureBuilder( + future: viewModel.showCounters(), + builder: (c, s) { + if (s.hasData) { + var counters = s.data!; + return GridView.builder( + shrinkWrap: true, + itemCount: counters.length, + physics: + const NeverScrollableScrollPhysics(), + gridDelegate: + SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: isPortrait ? 2 : 4, + mainAxisExtent: 90, + crossAxisSpacing: 0, + mainAxisSpacing: 0, + ), + itemBuilder: (context, i) { + return GestureDetector( + onTap: () { + viewModel.setSelectedCounter( + i, counters[i]); + }, + child: Container( + margin: const EdgeInsets.all(4), + padding: const EdgeInsets.all(4), + decoration: BoxDecoration( + borderRadius: + const BorderRadius.all( + Radius.circular(12)), + color: !counters[i] + .isAvailable + ? MyColors.fillRed + : viewModel.selectedItem == + i + ? MyColors.greenColor + : MyColors + .fillColor3), + child: Row( + children: [ + Expanded( + child: Column( + mainAxisAlignment: + MainAxisAlignment + .center, + children: [ + Text( + counters[i].counterCode, + style: TextStyle( + fontSize: MyFonts + .mediumText, + fontFamily: + MyFonts.Bold, + color: !counters[i] + .isAvailable + ? MyColors.white + : viewModel.selectedItem == + i + ? MyColors + .white + : MyColors + .textColorBlack, + fontWeight: + FontWeight + .bold), + ), + AppSpaces.verticalMedium, + Center( + child: Text( + counters[i] + .counterName, + textAlign: + TextAlign.center, + style: TextStyle( + fontSize: MyFonts + .normal, + fontFamily: MyFonts + .DMREGULAR, + color: !counters[ + i] + .isAvailable + ? MyColors + .white + : viewModel.selectedItem == + i + ? MyColors + .white + : MyColors + .textColorBlack), + ), + ) + ], + )) + ], + ), + )); + }); + } else { + return AppLoader(); + } + }), + AppSpaces.verticalMedium, + SizedBox( + width: 100, + child: CustomSimpleButton( + backGroundColor: MyColors.blueThemeColor, + textColor: MyColors.white, + isLoading: viewModel.isLoading, + height: 38, + heading: AppLocalizations.of(context)!.apply, + onPressed: () async { + await viewModel.isValidate(); + if (viewModel.crudOperationState == + CRUDOperationState.add) { + closePopUp(); + } + }, + ), + ), + ], + ), + ) + ], + ), + ), + ); + }), + )); + } + + closePopUp() { + Navigator.pop(context, true); + } +} diff --git a/lib/application/views/authModule/checkinViews/repo/CheckInRepository.dart b/lib/application/views/authModule/checkinViews/repo/CheckInRepository.dart new file mode 100644 index 0000000..61fd580 --- /dev/null +++ b/lib/application/views/authModule/checkinViews/repo/CheckInRepository.dart @@ -0,0 +1,73 @@ +import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/application/model/BusinessRegister/BusinessRegisterResponse.dart'; +import 'package:wosull/application/model/SimpleResponsModel.dart'; +import 'package:wosull/application/model/billingCounter/BillingCounterById.dart'; +import 'package:wosull/application/model/billingCounter/GetBillingCounter.dart'; +import 'package:wosull/application/model/store_accounts/StoreAccounts.dart'; +import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/utils/Constants.dart'; + +class CheckInRepository { + Future getCounterById() async { + final value = await APIManager().getResponseAuth( + Constants.GET_BILLING_COUNTER_BY_ID + sharedPrefs.billingCounterId); + return BillingCounterById.fromJson(value); + } + + Future getBusinessRegisterById() async { + final value = await APIManager().getResponseAuth( + Constants.getBusinessRegisterById + sharedPrefs.billingCounterId); + return BusinessRegisterResponse.fromJson(value); + } + + Future updateBusinessRegister( + Map data) async { + final value = await APIManager() + .fetchData(Constants.updateBusinessRegisterById, data); + return SimpleResponseModel.fromJson(value); + } + + Future getStoreAccounts() async { + final value = await APIManager() + .getResponseAuth(Constants.GET_STORE_ACCOUNTS + sharedPrefs.storeId); + return StoreAccounts.fromJson(value); + } + + Future updateCounter(Map data) async { + final value = + await APIManager().fetchData(Constants.UPDATE_BILLING_COUNTER, data); + return SimpleResponseModel.fromJson(value); + } + + Future addCounter(Map data) async { + final value = + await APIManager().fetchData(Constants.ADD_BILLING_COUNTER, data); + return SimpleResponseModel.fromJson(value); + } + + Future addBusinessRegister( + Map data) async { + final value = + await APIManager().fetchData(Constants.addBusinessRegister, data); + return BusinessRegisterResponse.fromJson(value); + } + + Future> showCounters() async { + var list = []; + Map data = { + 'store_id': sharedPrefs.storeId, + 'is_status_included': true, + }; + await APIManager() + .fetchData(Constants.GET_BILLING_COUNTER, data) + .then((value) async { + final response = GetBillingCounter.fromJson(value); + if (response.success) { + list.clear(); + list.addAll(response.billingCounter); + } + }).onError((error, stackTrace) {}); + + return list; + } +} diff --git a/lib/application/views/authModule/viewModel/CheckInViewModel.dart b/lib/application/views/authModule/checkinViews/viewModel/CheckInViewModel.dart similarity index 75% rename from lib/application/views/authModule/viewModel/CheckInViewModel.dart rename to lib/application/views/authModule/checkinViews/viewModel/CheckInViewModel.dart index 18bb390..7cf0cb0 100644 --- a/lib/application/views/authModule/viewModel/CheckInViewModel.dart +++ b/lib/application/views/authModule/checkinViews/viewModel/CheckInViewModel.dart @@ -1,14 +1,9 @@ -import 'dart:convert'; - import 'package:flutter/material.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; -import 'package:wosull/application/model/SimpleResponsModel.dart'; -import 'package:wosull/application/model/billingCounter/BillingCounterById.dart'; import 'package:wosull/application/model/billingCounter/GetBillingCounter.dart'; -import 'package:wosull/application/model/store_accounts/StoreAccounts.dart'; -import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; import 'package:wosull/application/utils/CRUDOperatoinState.dart'; -import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/authModule/checkinViews/repo/CheckInRepository.dart'; import 'package:wosull/helpers/Utils.dart'; class CheckInViewModel with ChangeNotifier { @@ -16,25 +11,25 @@ class CheckInViewModel with ChangeNotifier { bool get isLoading => _isLoading; - bool _isGettingData = true; + bool _isGettingData = false; bool get isGettingData => _isGettingData; String counterId = ''; - + String counterName = ''; String expenseAccountId = ''; String inComeAccountId = ''; CRUDOperationState _crudOperationState = CRUDOperationState.uninitialized; CRUDOperationState get crudOperationState => _crudOperationState; - + final repository = CheckInRepository(); String cashAmount = ''; - String cashOutAmount = ''; - String cashInAmount = ''; - String availableCash = ''; - String balanceInHand = ''; + String cashOutAmount = '0.0'; + String cashInAmount = '0.0'; + String availableCash = '0.0'; + String balanceInHand = '0.0'; int selectedItem = -1; @@ -42,6 +37,7 @@ class CheckInViewModel with ChangeNotifier { double actualBalanceInHand = 0.0; void disposeData() { + _crudOperationState = CRUDOperationState.uninitialized; _isGettingData = true; _isLoading = false; cashAmount = ''; @@ -71,7 +67,7 @@ class CheckInViewModel with ChangeNotifier { } else if (cashAmount.isEmpty) { Utils.showMessage('Please Enter cash amount'); } else { - await addCounter(loginCounterParams()); + await addCounter(checkInCounterParams()); } } @@ -99,18 +95,34 @@ class CheckInViewModel with ChangeNotifier { notifyListeners(); } + void setCashOutAmountLogout(String value) { + cashOutAmount = value; + if (value.isEmpty) { + availableCash = actualAvailableCash.toString(); + notifyListeners(); + return; + } + availableCash = + (actualAvailableCash + double.parse(value)).toStringAsFixed(2); + notifyListeners(); + } + + void setSelectedCounter(int i, BillingCounter counter) { + if (counter.isAvailable) { + counterId = counter.id; + selectedItem = i; + counterName = counter.counterName; + notifyListeners(); + } + } + Future getCounterById() async { - await APIManager() - .getResponseAuth( - Constants.GET_BILLING_COUNTER_BY_ID + sharedPrefs.billingCounterId) - .then((value) async { - final response = BillingCounterById.fromJson(value); + await repository.getCounterById().then((response) async { if (response.success) { actualBalanceInHand = response.billingCounter.availableCash; - print(actualBalanceInHand); balanceInHand = actualBalanceInHand.toStringAsFixed(2); await getStoreAccounts(); - notifyListeners(); + // notifyListeners(); } }).onError((error, stackTrace) { setLoadingData(false); @@ -118,15 +130,11 @@ class CheckInViewModel with ChangeNotifier { } Future getStoreAccounts() async { - await APIManager() - .getResponseAuth(Constants.GET_STORE_ACCOUNTS + sharedPrefs.storeId) - .then((value) async { - final response = StoreAccounts.fromJson(value); + await repository.getStoreAccounts().then((response) async { if (response.success) { actualAvailableCash = response.storeAccounts .singleWhere((element) => element.accountType == 'INCOME') .initialBalance; - print(actualAvailableCash); availableCash = actualAvailableCash.toStringAsFixed(2); inComeAccountId = response.storeAccounts @@ -144,7 +152,7 @@ class CheckInViewModel with ChangeNotifier { }); } - Map loginCounterParams() { + Map checkInCounterParams() { Map data = { 'amount_cash_in': double.parse(cashAmount), 'available_cash': double.parse(cashAmount), @@ -165,7 +173,8 @@ class CheckInViewModel with ChangeNotifier { 'expense_account_id': expenseAccountId, 'income_account_id': inComeAccountId, 'store_id': sharedPrefs.storeId, - 'initial_balance': double.parse(availableCash), + 'initial_balance': + double.parse(availableCash.isEmpty ? '0' : availableCash), 'is_available': true, 'is_cash_add': true }; @@ -177,7 +186,6 @@ class CheckInViewModel with ChangeNotifier { Utils.showMessage('Please enter cash out amount'); return; } - Map data = { 'amount_cash_out': double.parse(cashOutAmount.isEmpty ? '0.0' : cashOutAmount), @@ -215,11 +223,7 @@ class CheckInViewModel with ChangeNotifier { Future updateCounter(Map data) async { setLoading(true); - print(jsonEncode(data)); - await APIManager() - .fetchData(Constants.UPDATE_BILLING_COUNTER, data) - .then((value) async { - final response = SimpleResponseModel.fromJson(value); + await repository.updateCounter(data).then((response) async { if (response.success) { _crudOperationState = CRUDOperationState.update; } else { @@ -233,57 +237,54 @@ class CheckInViewModel with ChangeNotifier { Future addCounter(Map data) async { setLoading(true); - print(jsonEncode(data)); - await APIManager() - .fetchData(Constants.ADD_BILLING_COUNTER, data) - .then((value) async { - final response = SimpleResponseModel.fromJson(value); + await repository.addCounter(data).then((response) async { if (response.success) { sharedPrefs.billingCounterId = counterId; - _crudOperationState = CRUDOperationState.add; + sharedPrefs.billingCounterName = counterName; + var addBusiness = { + 'billing_counter_id': counterId, + 'openedOn': DataTimeFormat.getCurrentTimeDate(), + 'opened_amount': double.parse(cashAmount), + 'store_id': sharedPrefs.storeId, + 'user': sharedPrefs.store_name, + }; + await addBusinessRegister(addBusiness); } else { Utils.showMessage(response.message); _crudOperationState = CRUDOperationState.error; } - // setLoading(false); }).onError((error, stackTrace) { - print(error.toString()); + setLoading(false); + }); + } + + Future addBusinessRegister(Map data) async { + await repository.addBusinessRegister(data).then((response) async { + if (response.success) { + sharedPrefs.businessRegisterId = response.businessRegister.id; + _crudOperationState = CRUDOperationState.add; + } else { + _crudOperationState = CRUDOperationState.error; + } + setLoading(false); + }).onError((error, stackTrace) { setLoading(false); }); } Future> showCounters() async { var list = []; - Map data = { - 'store_id': sharedPrefs.storeId, - 'is_status_included': true, - }; - await APIManager() - .fetchData(Constants.GET_BILLING_COUNTER, data) - .then((value) async { - final response = GetBillingCounter.fromJson(value); - - if (response.success) { + await repository.showCounters().then((response) async { + if (response.isNotEmpty) { list.clear(); - list.addAll(response.billingCounter); + list.addAll(response); } else { _crudOperationState = CRUDOperationState.emptyCounters; } - setLoading(false); }).onError((error, stackTrace) { setLoading(false); }); - return list; } - - void setSelectedCounter(int i, BillingCounter counter) { - if (counter.isAvailable) { - counterId = counter.id; - selectedItem = i; - sharedPrefs.billingCounterName = counter.counterName; - notifyListeners(); - } - } } diff --git a/lib/application/views/authModule/loginViews/AlreadyLoggedView.dart b/lib/application/views/authModule/loginViews/AlreadyLoggedView.dart index 076d878..1d213d6 100644 --- a/lib/application/views/authModule/loginViews/AlreadyLoggedView.dart +++ b/lib/application/views/authModule/loginViews/AlreadyLoggedView.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/ThemeText.dart'; import 'package:wosull/widgets/CustomSimpleButton.dart'; import 'package:wosull/widgets/DialogHeader.dart'; @@ -17,7 +18,7 @@ class AlreadyLoggedView extends StatelessWidget { elevation: 0, backgroundColor: const Color(0xffffffff), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(15.0), + borderRadius: BorderRadius.circular(8.0), ), child: OrientationBuilder(builder: (c, orientation) { return SingleChildScrollView( @@ -35,7 +36,7 @@ class AlreadyLoggedView extends StatelessWidget { const Padding( padding: EdgeInsets.all(12.0), child: Text( - 'You are already logged in another device.Do you want to logout from that device and login here?', + 'You are already logged in another device. Do you want to logout from that device and login here?', style: ThemeText.textStylePopUpHeading, ), ), @@ -55,9 +56,7 @@ class AlreadyLoggedView extends StatelessWidget { heading: 'Yes', ), ), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, SizedBox( width: 120, child: CustomSimpleButton( diff --git a/lib/application/views/authModule/loginViews/CheckInPopUp.dart b/lib/application/views/authModule/loginViews/CheckInPopUp.dart deleted file mode 100644 index 5417768..0000000 --- a/lib/application/views/authModule/loginViews/CheckInPopUp.dart +++ /dev/null @@ -1,315 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:provider/provider.dart'; -import 'package:wosull/application/theme/MyColors.dart'; -import 'package:wosull/application/theme/MyFonts.dart'; -import 'package:wosull/application/utils/AppLoader.dart'; -import 'package:wosull/application/utils/CRUDOperatoinState.dart'; -import 'package:wosull/application/views/authModule/viewModel/CheckInViewModel.dart'; -import 'package:wosull/base/BaseStatefulState.dart'; -import 'package:wosull/helpers/AppSpaces.dart'; -import 'package:wosull/widgets/CustomSimpleButton.dart'; -import 'package:wosull/widgets/CustomTextFieldForm.dart'; -import 'package:wosull/widgets/MandatoryTitleText.dart'; - -class CheckInPopUp extends StatefulWidget { - CheckInPopUp({ - Key? key, - }) : super(key: key); - - @override - State createState() => _CheckInPopUpState(); -} - -class _CheckInPopUpState extends BaseStatefulState { - bool isPortrait = true; - var viewModel = CheckInViewModel(); - - @override - void initState() { - // TODO: implement initState - super.initState(); - } - - @override - void dispose() { - // TODO: implement dispose - super.dispose(); - viewModel.disposeData(); - } - - @override - Widget build(BuildContext context) { - viewModel = context.watch(); - if (viewModel.crudOperationState == CRUDOperationState.emptyCounters) { - closePopUp(); - } - return WillPopScope( - child: Directionality( - textDirection: TextDirection.ltr, - child: Dialog( - elevation: 0, - backgroundColor: const Color(0xffffffff), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(15.0), - ), - child: OrientationBuilder(builder: (c, orientation) { - isPortrait = - MediaQuery.of(context).orientation == Orientation.portrait; - return SingleChildScrollView( - child: SizedBox( - width: !isPortrait - ? MediaQuery.of(context).size.width / 1.2 - : double.infinity, - child: Column( - crossAxisAlignment: CrossAxisAlignment.end, - mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - Align( - alignment: Alignment.centerLeft, - child: Padding( - padding: const EdgeInsets.all(16), - child: Text( - AppLocalizations.of(context)!.check_in, - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: MyFonts.H1, - fontFamily: MyFonts.Medium, - color: MyColors.textColorPopUp), - ), - ), - ), - Container( - height: 2, - color: MyColors.fillColorGray, - ), - const SizedBox( - height: 8, - ), - Container( - margin: const EdgeInsets.all(12), - child: Column( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - const MandatoryTitleText(hint: 'Cash In Amount'), - AppSpaces.verticalSmall, - CustomTextFieldForm( - keyboardType: TextInputType.number, - onChanged: (value) { - viewModel.cashAmount = value; - }, - hintText: '0.0'), - AppSpaces.verticalLarge, - Row( - mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.max, - children: [ - Container( - width: 20, - height: 20, - decoration: const BoxDecoration( - color: MyColors.fillColor3, - borderRadius: - BorderRadius.all(Radius.circular(4)), - ), - ), - AppSpaces.horizontalSmall, - const Text( - 'Available', - style: TextStyle( - fontSize: MyFonts.normal, - fontWeight: FontWeight.bold, - fontFamily: MyFonts.Medium, - color: MyColors.black), - ), - AppSpaces.horizontalMedium, - Container( - width: 20, - height: 20, - decoration: const BoxDecoration( - color: MyColors.fillRed, - borderRadius: - BorderRadius.all(Radius.circular(4)), - ), - ), - AppSpaces.horizontalSmall, - Text( - AppLocalizations.of(context)!.not_available, - style: const TextStyle( - fontSize: MyFonts.normal, - fontWeight: FontWeight.bold, - fontFamily: MyFonts.Medium, - color: MyColors.black), - ), - AppSpaces.horizontalMedium, - Container( - width: 20, - height: 20, - decoration: const BoxDecoration( - color: MyColors.greenColor, - borderRadius: - BorderRadius.all(Radius.circular(4)), - ), - ), - AppSpaces.horizontalSmall, - Text( - AppLocalizations.of(context)!.selected, - style: const TextStyle( - fontSize: MyFonts.normal, - fontWeight: FontWeight.bold, - fontFamily: MyFonts.Medium, - color: MyColors.black), - ), - ], - ), - AppSpaces.verticalLarge, - FutureBuilder( - future: viewModel.showCounters(), - builder: (c, s) { - if (s.hasData) { - var counters = s.data!; - return GridView.builder( - shrinkWrap: true, - itemCount: counters.length, - physics: - const NeverScrollableScrollPhysics(), - gridDelegate: - SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: isPortrait ? 2 : 4, - mainAxisExtent: 90, - crossAxisSpacing: 0, - mainAxisSpacing: 0, - ), - itemBuilder: (context, i) { - return GestureDetector( - onTap: () { - viewModel.setSelectedCounter( - i, counters[i]); - }, - child: Container( - margin: - const EdgeInsets.all(4), - padding: - const EdgeInsets.all(4), - decoration: BoxDecoration( - borderRadius: - const BorderRadius - .all( - Radius.circular( - 12)), - color: !counters[i] - .isAvailable - ? MyColors.fillRed - : viewModel.selectedItem == - i - ? MyColors - .greenColor - : MyColors - .fillColor3), - child: Row( - children: [ - Expanded( - child: Column( - mainAxisAlignment: - MainAxisAlignment - .center, - children: [ - Text( - counters[i] - .counterCode, - style: TextStyle( - fontSize: MyFonts - .mediumText, - fontFamily: - MyFonts - .Bold, - color: !counters[ - i] - .isAvailable - ? MyColors - .white - : viewModel.selectedItem == - i - ? MyColors - .white - : MyColors - .textColorBlack, - fontWeight: - FontWeight - .bold), - ), - const SizedBox( - height: 8, - ), - Text( - counters[i] - .counterName, - style: TextStyle( - fontSize: - MyFonts - .normal, - fontFamily: - MyFonts - .DMREGULAR, - color: !counters[ - i] - .isAvailable - ? MyColors - .white - : viewModel.selectedItem == - i - ? MyColors - .white - : MyColors - .textColorBlack), - ), - ], - )) - ], - ), - )); - }); - } else { - return AppLoader(); - } - }), - const SizedBox( - height: 8, - ), - SizedBox( - width: 100, - child: CustomSimpleButton( - backGroundColor: MyColors.blueThemeColor, - textColor: MyColors.white, - isLoading: viewModel.isLoading, - height: 38, - heading: AppLocalizations.of(context)!.apply, - onPressed: () async { - await viewModel.isValidate(); - if (viewModel.crudOperationState == - CRUDOperationState.add) { - closePopUp(); - } - }, - ), - ), - ], - ), - ) - ], - ), - ), - ); - }), - )), - onWillPop: () { - viewModel.dispose(); - return Future.value(false); - }); - } - - closePopUp() { - Navigator.pop(context, true); - } -} diff --git a/lib/application/views/authModule/loginViews/LoginVC.dart b/lib/application/views/authModule/loginViews/LoginVC.dart index 3a0290b..93f0d46 100644 --- a/lib/application/views/authModule/loginViews/LoginVC.dart +++ b/lib/application/views/authModule/loginViews/LoginVC.dart @@ -1,21 +1,25 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:provider/provider.dart'; +import 'package:wosull/application/localdb/SharedPrefs.dart'; import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/theme/MyFonts.dart'; +import 'package:wosull/application/views/authModule/checkinViews/CheckInPopUp.dart'; import 'package:wosull/application/views/authModule/loginViews/AlreadyLoggedView.dart'; -import 'package:wosull/application/views/authModule/loginViews/CheckInPopUp.dart'; +import 'package:wosull/application/views/authModule/loginViews/viewModel/LoginViewModel.dart'; +import 'package:wosull/application/views/authModule/loginViews/widgets/LoginButton.dart'; +import 'package:wosull/application/views/authModule/loginViews/widgets/RememberCheckbox.dart'; import 'package:wosull/application/views/authModule/registerViews/RegisterVC.dart'; import 'package:wosull/application/views/authModule/state/LoginState.dart'; -import 'package:wosull/application/views/authModule/viewModel/LoginViewModel.dart'; import 'package:wosull/application/views/home/HomePage.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/ThemeImage.dart'; import 'package:wosull/helpers/ThemeText.dart'; -import 'package:wosull/widgets/CustomCheckBox.dart'; -import 'package:wosull/widgets/CustomSimpleButton.dart'; -import 'package:wosull/widgets/CustomTextButton.dart'; import 'package:wosull/widgets/CustomTextButtonUnderLine.dart'; import 'package:wosull/widgets/CustomTextFieldForm.dart'; import 'package:wosull/widgets/CustomTextFieldPassword.dart'; +import 'package:wosull/widgets/LanguageDropdown.dart'; +import 'package:wosull/widgets/MandatoryTitleText.dart'; class LoginVC extends StatefulWidget { const LoginVC({super.key}); @@ -27,141 +31,193 @@ class LoginVC extends StatefulWidget { class _LoginVCState extends State { var viewModel = LoginViewModel(); + @override + void initState() { + context.read().setDropDownValue(context); + super.initState(); + } + @override void dispose() { - // TODO: implement dispose viewModel.disposeData(); super.dispose(); } @override Widget build(BuildContext context) { - final viewModel = context.watch(); - //viewModel.name = viewModel.name; - return WillPopScope( - child: Directionality( - textDirection: TextDirection.ltr, - child: SafeArea( - child: Scaffold( - resizeToAvoidBottomInset: false, - body: SingleChildScrollView( - child: Container( - decoration: const BoxDecoration( - color: MyColors.fillColor, - image: DecorationImage( - image: AssetImage(ThemeImage.background), - fit: BoxFit.contain, - ), + viewModel = context.watch(); + return Directionality( + textDirection: TextDirection.ltr, + child: SafeArea( + child: Scaffold( + resizeToAvoidBottomInset: false, + body: SingleChildScrollView( + child: Container( + decoration: const BoxDecoration( + color: MyColors.fillColor, + image: DecorationImage( + image: AssetImage(ThemeImage.background), + fit: BoxFit.contain, ), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const SizedBox( - height: 16, - ), - Image.asset(ThemeImage.logo, height: 80), - const SizedBox( - height: 32, - ), - Text( - AppLocalizations.of(context)!.sign_in, - style: ThemeText.bigHeader, - ), - Text( - AppLocalizations.of(context)!.welcome_back, - style: ThemeText.mediumHeader, - ), - Container( - margin: const EdgeInsets.all(16), - child: Center( - child: Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(16.0), - ), - elevation: 5, - color: MyColors.white, - child: Container( - padding: - const EdgeInsets.fromLTRB(16, 32, 16, 32), - child: Column( - children: [ - CustomTextFieldForm( - hintText: 'Enter your email', - labelText: - '${AppLocalizations.of(context)!.email}*', - onChanged: (value) { - viewModel.name = value; - }), - const SizedBox( - height: 16, - ), - buildPassword(context, viewModel), - const SizedBox(height: 8), - Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + AppSpaces.verticalLarge, + AppSpaces.verticalLarge, + Image.asset(ThemeImage.wosulLogo, height: 80), + AppSpaces.verticalLarge, + AppSpaces.verticalLarge, + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Container( + margin: const EdgeInsets.only(right: 30), + child: getLangDropdown(), + ) + ], + ), + AppSpaces.verticalLarge, + Text( + AppLocalizations.of(context)!.sign_in, + style: ThemeText.bigHeader, + ), + Text( + AppLocalizations.of(context)!.welcome_back, + style: ThemeText.mediumHeader, + ), + Container( + margin: const EdgeInsets.all(16), + child: Center( + child: Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16.0), + ), + elevation: 5, + color: MyColors.white, + child: Container( + padding: const EdgeInsets.fromLTRB(16, 32, 16, 32), + child: Column( + children: [ + MandatoryTitleText( + hint: AppLocalizations.of(context)!.email), + AppSpaces.verticalSmall, + CustomTextFieldForm( + height: 60, + hintText: 'Enter your email', + labelText: + '${AppLocalizations.of(context)!.email}*', + onChanged: (value) { + viewModel.name = value; + }), + AppSpaces.verticalLarge, + MandatoryTitleText( + hint: + AppLocalizations.of(context)!.password), + AppSpaces.verticalSmall, + buildPassword(context, viewModel), + AppSpaces.verticalMedium, + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + buildCheckBox(context, viewModel), + CustomTextButtonUnderLine( + onPressed: () {}, + heading: AppLocalizations.of(context)! + .forgot_password, + ) + ], + ), + AppSpaces.verticalMedium, + LoginButton( + isLoading: viewModel.isLoading, + textColor: MyColors.white, + backGroundColor: MyColors.blueThemeColor, + onPressed: () async { + if (viewModel.isValidate()) { + //called the function and waiting for response + //and taking decision + //as error is handling in provider with toast + await viewModel.loginUser(); + if (viewModel.dataState == + LoginState.showAccessAccount) { + showAccessPop(); + } else if (viewModel.dataState == + LoginState.toHome) { + toHome(); + } else if (viewModel.dataState == + LoginState.error) { + } else {} + } + }, + heading: + AppLocalizations.of(context)!.sign_in, + ), + AppSpaces.verticalMedium, + GestureDetector( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + const RegisterVC()), + ); + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.center, children: [ - buildCheckBox(context, viewModel), - CustomTextButtonUnderLine( - onPressed: () {}, - heading: AppLocalizations.of(context)! - .forgot_password, + Text.rich( + TextSpan( + text: 'Don’t have an account?', + style: TextStyle( + fontStyle: FontStyle.normal, + fontFamily: MyFonts.Medium, + fontSize: MyFonts.normal, + fontWeight: FontWeight.w500, + color: MyColors.black, + ), + children: [ + TextSpan( + text: ' Sign up for free', + style: TextStyle( + fontStyle: FontStyle.normal, + fontFamily: MyFonts.Bold, + fontSize: MyFonts.normal, + fontWeight: FontWeight.w500, + color: MyColors.black, + decoration: + TextDecoration.underline, + )), + // can add more TextSpans here... + ], + ), ) ], ), - const SizedBox(height: 16), - CustomSimpleButton( - isLoading: viewModel.isLoading, - textColor: MyColors.white, - backGroundColor: MyColors.blueThemeColor, - onPressed: () async { - if (viewModel.isValidate()) { - //called the function and waiting for response - //and taking decision - //as error is handling in provider with toast - await viewModel.loginUser(); - if (viewModel.dataState == - LoginState.showAccessAccount) { - showAccessPop(); - } else if (viewModel.dataState == - LoginState.showCounters) { - showCounters(); - } else if (viewModel.dataState == - LoginState.toHome) { - toHome(); - } else if (viewModel.dataState == - LoginState.error) { - } else {} - } - }, - heading: - AppLocalizations.of(context)!.sign_in, - ), - CustomTextButton( - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => - const RegisterVC()), - ); - }, - heading: AppLocalizations.of(context)! - .dont_account) - ], - ), + ) + ], ), ), ), ), - ], - ) /* add child content here */, - ), + ), + ], + ) /* add child content here */, ), - ))), - onWillPop: () { - viewModel.dispose(); - return Future.value(false); + ), + ), + )); + } + + Widget getLangDropdown() { + return LanguageDropdown( + dropdownValue: viewModel.dropdownValue, + onChange: (language) { + viewModel.dropdownValue = language!; + viewModel.setLanguage(context, language); }); } @@ -181,6 +237,9 @@ class _LoginVCState extends State { } Future toHome() async { + if (viewModel.rememberValue) { + viewModel.setRememberedValues(); + } viewModel.disposeData(); push(); } @@ -193,7 +252,7 @@ class _LoginVCState extends State { } Widget buildCheckBox(BuildContext context, LoginViewModel viewModel) { - return CustomCheckBox( + return RememberCheckbox( heading: AppLocalizations.of(context)!.remember, onChange: (value) { viewModel.setRemember(value); @@ -221,7 +280,6 @@ class _LoginVCState extends State { } void checkState() { - print(viewModel.dataState); if (viewModel.dataState == LoginState.showAccessAccount) { showAccessPop(); } else if (viewModel.dataState == LoginState.showCounters) { @@ -233,7 +291,6 @@ class _LoginVCState extends State { } Future showAccessPop() async { - print(viewModel.accessMessage); final result = await showDialog( barrierColor: Colors.black26, context: context, @@ -248,7 +305,8 @@ class _LoginVCState extends State { if (result != null) { bool value = result; if (value) { - showCounters(); + await viewModel.createAccessToken(sharedPrefs.token); + checkState(); } } } diff --git a/lib/application/views/authModule/viewModel/LoginViewModel.dart b/lib/application/views/authModule/loginViews/viewModel/LoginViewModel.dart similarity index 61% rename from lib/application/views/authModule/viewModel/LoginViewModel.dart rename to lib/application/views/authModule/loginViews/viewModel/LoginViewModel.dart index bec8f43..fd515cb 100644 --- a/lib/application/views/authModule/viewModel/LoginViewModel.dart +++ b/lib/application/views/authModule/loginViews/viewModel/LoginViewModel.dart @@ -1,15 +1,18 @@ import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:wosull/application/language/AppLanguage.dart'; +import 'package:wosull/application/language/AppLocale.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; import 'package:wosull/application/model/SimpleResponsModel.dart'; import 'package:wosull/application/model/store/StoreResponse.dart'; -import 'package:wosull/application/model/store/StoreServiceResponse.dart'; -import 'package:wosull/application/network/APIManager.dart'; -import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/authModule/repo/AuthRepository.dart'; import 'package:wosull/application/views/authModule/state/LoginState.dart'; import 'package:wosull/helpers/Utils.dart'; import 'package:wosull/main.dart'; class LoginViewModel with ChangeNotifier { + AppLanguage dropdownValue = AppLanguage.languages().first; + final repository = AuthRepository(); var password = ''; var name = sharedPrefs.storeEmail; @@ -31,12 +34,36 @@ class LoginViewModel with ChangeNotifier { String _accessMessage = ''; String get accessMessage => _accessMessage; + var _appLocale; void disposeData() { name = ''; password = ''; } + void setDropDownValue(BuildContext context) { + sharedPrefs.getLocale().then((locale) { + _appLocale ??= Provider.of(context, listen: false); + if (locale.languageCode == 'en') { + dropdownValue = AppLanguage.languages().first; + } else { + _appLocale.changeLocale(Locale(locale.languageCode)); + dropdownValue = AppLanguage.languages().firstWhere( + (element) => element.languageCode == locale.languageCode); + } + //notifyListeners(); + }); + } + + void setLanguage(BuildContext context, AppLanguage language) { + sharedPrefs.isChanged = true; + _appLocale ??= Provider.of(context, listen: false); + _appLocale.changeLocale(Locale(language.languageCode)); + // setDropDownValue(context); + sharedPrefs.setLocale(language.languageCode); + notifyListeners(); + } + bool isValidate() { if (name.isEmpty) { Utils.showMessage('Enter your email'); @@ -66,7 +93,6 @@ class LoginViewModel with ChangeNotifier { void setLoading(bool value) { _isLoading = value; - print('called'); notifyListeners(); } @@ -88,10 +114,7 @@ class LoginViewModel with ChangeNotifier { Future loginUser() async { setLoading(true); - await APIManager() - .fetchData(Constants.LOGIN_URL, loginParams()) - .then((value) async { - final result = StoreResponse.fromJson(value); + await repository.loginUser(loginParams()).then((result) async { if (result.success) { await saveStoreData(result); await getServices(); @@ -103,7 +126,6 @@ class LoginViewModel with ChangeNotifier { setLoading(false); } }).onError((error, stackTrace) { - Utils.showMessage("login " + error.toString()); _dataState = LoginState.error; setLoading(false); }); @@ -120,32 +142,40 @@ class LoginViewModel with ChangeNotifier { } Future getServices() async { - await APIManager() - .fetchData(Constants.Store_services_URL, Constants.getStorePayload()) - .then((value) async { - final response = StoreServiceResponse.fromJson(value); + await repository.getServices().then((response) async { if (response.success) { await objectbox.addServices(response.services); } await checkAccessAccount(); }).onError((error, stackTrace) async { - Utils.showMessage("service " + error.toString()); - _dataState = LoginState.showCounters; - notifyListeners(); + _dataState = LoginState.error; + setLoading(false); }); } Future checkAccessAccount() async { - await APIManager() - .getResponseAuth("${Constants.getAccessToken}/${sharedPrefs.storeId}") - .then((value) async { - final response = SimpleResponseModel.fromJson(value); + await repository.checkAccessAccount().then((response) async { + if (response.success!) { + sharedPrefs.token = response.access!.accessToken ?? ''; + _dataState = LoginState.showAccessAccount; + } else { + _dataState = LoginState.toHome; + } + setLoading(false); + }).onError((error, stackTrace) async { + _dataState = LoginState.error; + setLoading(false); + }); + } + + Future createAccessToken(String token) async { + setLoading(true); + await repository.createAccessToken(token).then((response) async { await checkResponse(response); setLoading(false); }).onError((error, stackTrace) async { - print(stackTrace.toString()); - _dataState = LoginState.showCounters; - notifyListeners(); + _dataState = LoginState.error; + setLoading(false); }); } @@ -159,11 +189,9 @@ class LoginViewModel with ChangeNotifier { checkResponse(SimpleResponseModel response) { if (response.success) { _accessMessage = response.message; - _dataState = LoginState.showAccessAccount; + _dataState = LoginState.toHome; } else { - _dataState = LoginState.showCounters; + _dataState = LoginState.toHome; } - print(accessMessage); - print(dataState); } } diff --git a/lib/application/views/authModule/loginViews/widgets/LoginButton.dart b/lib/application/views/authModule/loginViews/widgets/LoginButton.dart new file mode 100644 index 0000000..dacdecb --- /dev/null +++ b/lib/application/views/authModule/loginViews/widgets/LoginButton.dart @@ -0,0 +1,54 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/theme/MyFonts.dart'; +import 'package:wosull/application/utils/AppLoader.dart'; + +class LoginButton extends StatelessWidget { + String heading; + final void Function() onPressed; + bool? isLoading = false; + Color? backGroundColor = MyColors.backColorBlue50; + Color? textColor = MyColors.black; + double? height; + bool? isEnable = true; + double? radius; + + LoginButton( + {super.key, + this.isLoading, + this.textColor, + this.height = 42, + this.radius = 8, + this.isEnable = true, + this.backGroundColor, + required this.heading, + required this.onPressed}); + + @override + Widget build(BuildContext context) { + return isLoading ?? false + ? Center( + child: AppLoader(), + ) + : ElevatedButton( + style: ElevatedButton.styleFrom( + elevation: 0, + padding: EdgeInsets.zero, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(radius ?? 8), + ), + backgroundColor: backGroundColor, + minimumSize: Size.fromHeight(height!), // NEW + ), + onPressed: isEnable! ? onPressed : null, + child: Text( + heading, + style: TextStyle( + fontSize: MyFonts.H1, + fontWeight: FontWeight.w500, + color: MyColors.white, + fontFamily: MyFonts.Bold), + ), + ); + } +} diff --git a/lib/application/views/authModule/loginViews/widgets/RememberCheckbox.dart b/lib/application/views/authModule/loginViews/widgets/RememberCheckbox.dart new file mode 100644 index 0000000..76c724c --- /dev/null +++ b/lib/application/views/authModule/loginViews/widgets/RememberCheckbox.dart @@ -0,0 +1,48 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/theme/MyFonts.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; + +class RememberCheckbox extends StatelessWidget { + String? heading; + bool value; + final void Function(bool? value) onChange; + + RememberCheckbox( + {super.key, this.heading, required this.value, required this.onChange}); + + @override + Widget build(BuildContext context) { + return Row(mainAxisAlignment: MainAxisAlignment.end, children: [ + SizedBox( + height: 20, + width: 20, + child: Transform.scale( + scale: 1, + child: Checkbox( + shape: + RoundedRectangleBorder(borderRadius: BorderRadius.circular(4)), + value: value, + side: const BorderSide(color: MyColors.fillColorGray2), + onChanged: onChange, + activeColor: MyColors.blueThemeColor, + checkColor: Colors.white, + tristate: true, + ), + ), + ), + AppSpaces.horizontalSmall, + Text( + heading ?? '', + style: TextStyle( + fontStyle: FontStyle.normal, + fontFamily: MyFonts.Medium, + fontSize: MyFonts.normal, + fontWeight: FontWeight.w500, + color: MyColors.black, + ), + textAlign: TextAlign.center, + ) + ]); + } +} diff --git a/lib/application/views/authModule/registerViews/CategoryPopUp.dart b/lib/application/views/authModule/registerViews/CategoryPopUp.dart index bd777bb..d6c88c0 100644 --- a/lib/application/views/authModule/registerViews/CategoryPopUp.dart +++ b/lib/application/views/authModule/registerViews/CategoryPopUp.dart @@ -4,7 +4,7 @@ import 'package:wosull/application/model/discount/CategoryModel.dart'; import 'package:wosull/application/model/inventory/category/CategoriesResponse.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/theme/MyFonts.dart'; -import 'package:wosull/application/views/authModule/viewModel/AuthViewModel.dart'; +import 'package:wosull/application/views/authModule/registerViews/viewModel/AuthViewModel.dart'; class CategoryPopUp extends StatefulWidget { const CategoryPopUp({Key? key, required this.cityId}) : super(key: key); @@ -85,7 +85,7 @@ class _CategoryPopUpState extends State { scrollDirection: Axis.vertical, shrinkWrap: true, itemBuilder: (context, position) { - return new GestureDetector( + return GestureDetector( child: Card( child: Container( height: 48, diff --git a/lib/application/views/authModule/registerViews/CityPopUp.dart b/lib/application/views/authModule/registerViews/CityPopUp.dart index cb464fd..58f946a 100644 --- a/lib/application/views/authModule/registerViews/CityPopUp.dart +++ b/lib/application/views/authModule/registerViews/CityPopUp.dart @@ -4,7 +4,7 @@ import 'package:wosull/application/model/auth/CityModel.dart'; import 'package:wosull/application/model/auth/CityResponse.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/theme/MyFonts.dart'; -import 'package:wosull/application/views/authModule/viewModel/CityViewModel.dart'; +import 'package:wosull/application/views/authModule/registerViews/viewModel/CityViewModel.dart'; class CityPopUp extends StatefulWidget { const CityPopUp({Key? key, required this.countryId}) : super(key: key); @@ -20,7 +20,7 @@ class _CityPopUpState extends State { List cities = List.empty(growable: true); List filteredCitiesList = List.empty(growable: true); - CityViewModel cityViewModel = new CityViewModel(); + CityViewModel cityViewModel = CityViewModel(); @override void initState() { diff --git a/lib/application/views/authModule/registerViews/RegisterVC.dart b/lib/application/views/authModule/registerViews/RegisterVC.dart index 43eaf29..beafd85 100644 --- a/lib/application/views/authModule/registerViews/RegisterVC.dart +++ b/lib/application/views/authModule/registerViews/RegisterVC.dart @@ -5,26 +5,23 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_google_places/flutter_google_places.dart'; import 'package:google_api_headers/google_api_headers.dart'; import 'package:google_maps_webservice/places.dart'; -import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart'; -import 'package:wosull/application/localdb/SharedPrefs.dart'; -import 'package:wosull/application/model/SimpleResponsModel.dart'; -import 'package:wosull/application/model/auth/CityModel.dart'; -import 'package:wosull/application/model/auth/CountryModel.dart'; -import 'package:wosull/application/model/discount/CategoryModel.dart'; -import 'package:wosull/application/model/store/StoreResponse.dart'; -import 'package:wosull/application/model/store/StoreServiceResponse.dart'; -import 'package:wosull/application/model/store/WosulStore.dart'; -import 'package:wosull/application/network/APIManager.dart'; +import 'package:provider/provider.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/theme/MyFonts.dart'; -import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/utils/CRUDOperatoinState.dart'; +import 'package:wosull/application/views/authModule/loginViews/widgets/LoginButton.dart'; import 'package:wosull/application/views/authModule/registerViews/CategoryPopUp.dart'; import 'package:wosull/application/views/authModule/registerViews/CityPopUp.dart'; -import 'package:wosull/application/views/authModule/viewModel/AuthViewModel.dart'; -import 'package:wosull/application/views/home/HomePage.dart'; +import 'package:wosull/application/views/authModule/registerViews/viewModel/AuthViewModel.dart'; import 'package:wosull/application/views/popups/CountryPopUp.dart'; import 'package:wosull/base/BaseStatefulState.dart'; -import 'package:wosull/helpers/Utils.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeImage.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/widgets/CustomControllerTextFieldForm.dart'; +import 'package:wosull/widgets/CustomTextButtonIcon.dart'; +import 'package:wosull/widgets/CustomTextFieldPassword.dart'; +import 'package:wosull/widgets/MandatoryTitleText.dart'; class RegisterVC extends StatefulWidget { const RegisterVC({Key? key}) : super(key: key); @@ -38,59 +35,11 @@ final homeScaffoldKey = GlobalKey(); final searchScaffoldKey = GlobalKey(); class _RegisterVCState extends BaseStatefulState { - TextEditingController nameController = TextEditingController(); - TextEditingController emailController = TextEditingController(); - TextEditingController phoneController = TextEditingController(); - TextEditingController passwordController = TextEditingController(); - String addressController = ''; - - late var lat; - late var lng; - - AuthViewModel authView = AuthViewModel(); - CountryModel selectedCountry = CountryModel( - countryFlag: "", - countryName: "", - phoneCode: "+966", - countryCode: "SAR", - id: ""); - CityModel selectedCity = CityModel(cityName: "", id: ""); - CategoryModel selectedCategory = - CategoryModel(deliveryName: "", imageUrl: "", id: ""); - - bool _isInAsyncCall = false; - - bool isValidate() { - if (nameController.text.isEmpty) { - showMessage('Enter company name'); - return false; - } else if (emailController.text.isEmpty) { - showMessage('Enter your email'); - return false; - } else if (!emailController.text.isValidEmail()) { - showMessage('Enter valid email address'); - return false; - } else if (phoneController.text.isEmpty) { - showMessage('Enter your phone'); - return false; - } else if (passwordController.text.isEmpty) { - showMessage('Enter your password'); - return false; - } else if (selectedCountry.countryName!.isEmpty) { - showMessage('Select Country'); - return false; - } else if (selectedCity.cityName!.isEmpty) { - showMessage('Select city'); - return false; - } else if (selectedCategory.deliveryName!.isEmpty) { - showMessage('Select Business Type'); - return false; - } - return true; - } + var authView = AuthViewModel(); @override Widget build(BuildContext context) { + authView = context.watch(); return Directionality( textDirection: TextDirection.ltr, child: Scaffold( @@ -103,53 +52,43 @@ class _RegisterVCState extends BaseStatefulState { elevation: 0, ), resizeToAvoidBottomInset: true, - body: ModalProgressHUD( - inAsyncCall: _isInAsyncCall, - child: SingleChildScrollView( - child: Stack( - children: [ - Container( - decoration: const BoxDecoration( - color: MyColors.fillColor, - image: DecorationImage( - image: AssetImage("images/login_bg.png"), - fit: BoxFit.contain, + body: SingleChildScrollView( + child: Stack( + children: [ + Container( + decoration: const BoxDecoration( + color: MyColors.fillColor, + image: DecorationImage( + image: AssetImage("images/login_bg.png"), + fit: BoxFit.contain, + ), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset(ThemeImage.wosulLogo, height: 80), + AppSpaces.verticalLarge, + Text( + AppLocalizations.of(context)!.register, + style: ThemeText.bigHeader, + ), + Container( + margin: const EdgeInsets.all(16), + child: Center( + child: getMainDesign(), ), ), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Image.asset('images/logo_sub_title.png', height: 80), - const SizedBox( - height: 16, - ), - Text( - AppLocalizations.of(context)!.register, - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 40, - fontFamily: MyFonts.Bold), - ), - Container( - margin: const EdgeInsets.all(16), - child: Center( - child: getMainDesign('Email'), - ), - ), - ], - ) /* add child content here */, - ) - ], - ), - )), + ], + ) /* add child content here */, + ) + ], + ), + ), )); } void onError(PlacesAutocompleteResponse response) { SnackBar(content: Text(response.errorMessage!)); - // homeScaffoldKey.currentState.showSnackBar( - // - // ); } Future _handlePressButton() async { @@ -174,7 +113,8 @@ class _RegisterVCState extends BaseStatefulState { ), ), components: [ - Component(Component.country, selectedCountry.countryCode ?? "AE") + Component( + Component.country, authView.selectedCountry.countryCode ?? "AE") ], ); @@ -188,80 +128,30 @@ class _RegisterVCState extends BaseStatefulState { ); PlacesDetailsResponse detail = await _places.getDetailsByPlaceId(p.placeId!); - lat = detail.result.geometry!.location.lat; - lng = detail.result.geometry!.location.lng; - - setState(() { - addressController = p.description!; - }); - // print("object${p.description}"); - - //SnackBar(content: Text("${p.description} - $lat/$lng")); - // scaffold.showSnackBar( - // - // ); + authView.updateAddress(detail, p.description ?? ''); } Widget getMandatoryTextField( TextEditingController controller, String title, String hint) { return Column( children: [ - Row( - children: [ - Text( - title, - style: const TextStyle( - fontSize: 16, - fontFamily: MyFonts.Medium, - color: MyColors.black), - ), - const SizedBox( - width: 4, - ), - const Text( - '*', - style: TextStyle( - fontSize: 16, - fontFamily: MyFonts.Medium, - color: MyColors.primary), - ) - ], - ), - const SizedBox( - height: 8, - ), - TextField( + MandatoryTitleText(hint: title), + AppSpaces.verticalSmall, + CustomControllerTextFieldForm( controller: controller, - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: 16, - color: MyColors.black), - decoration: InputDecoration( - hintText: hint, - fillColor: MyColors.fillColor, - filled: true, - focusedBorder: OutlineInputBorder( - borderSide: - const BorderSide(color: MyColors.strokeColor, width: 1.0), - borderRadius: BorderRadius.circular(8.0), - ), - enabledBorder: OutlineInputBorder( - borderSide: const BorderSide( - width: 1, //<-- SEE HERE - color: MyColors.strokeColor, - ), - borderRadius: BorderRadius.circular(8.0), - ), - ), + onChanged: (String value) { + // controller.text = value; + }, + hintText: hint, ), ], ); } - Widget getMainDesign(String text) { + Widget getMainDesign() { return Card( shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(30.0), + borderRadius: BorderRadius.circular(16.0), ), elevation: 5, color: MyColors.white, @@ -270,95 +160,80 @@ class _RegisterVCState extends BaseStatefulState { child: Column( children: [ getMandatoryTextField( - nameController, + authView.nameController, AppLocalizations.of(context)!.company_name, 'Enter Company name'), - const SizedBox( - height: 8, - ), - getMandatoryTextField(emailController, + AppSpaces.verticalMedium, + getMandatoryTextField(authView.emailController, AppLocalizations.of(context)!.company_email, 'Company email'), - const SizedBox(height: 8), + AppSpaces.verticalMedium, getMandatoryPopUpButton(context, AppLocalizations.of(context)!.country, "Select Country"), - const SizedBox(height: 8), + AppSpaces.verticalMedium, getMandatoryCityButton( context, AppLocalizations.of(context)!.city, "Select City"), - const SizedBox(height: 8), + AppSpaces.verticalMedium, getMandatoryAddressButton( context, AppLocalizations.of(context)!.company_address, "Enter your address"), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, buildCountryCode(), - const SizedBox(height: 8), + AppSpaces.verticalMedium, getMandatoryBusinessTypeButton( context, AppLocalizations.of(context)!.business_type, "Select Business type"), - const SizedBox(height: 8), + AppSpaces.verticalMedium, buildPassword(), - const SizedBox(height: 16), - ElevatedButton( - style: ElevatedButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(6.0), - ), - backgroundColor: MyColors.primary, - minimumSize: const Size.fromHeight(38), // NEW - ), - onPressed: () { - if (isValidate()) { - Map data = { - 'device_type': 'android', - 'slogan': '', - 'website_url': '', - 'latitude': lat, - 'longitude': lng, - 'app_version': '1.0', - 'referral_code': '', - 'is_phone_number_verified': 'false', - 'is_email_verified': 'false', - 'social_id': '', - 'login_by': 'manual', - 'name': nameController.text, - 'email': emailController.text, - 'country_phone_code': selectedCountry.phoneCode, - 'phone': phoneController.text, - 'address': addressController, - 'password': passwordController.text, - 'store_delivery_id': selectedCategory.id!, - 'country_id': selectedCountry.id!, - 'city_id': selectedCity.id!, - 'name_type': selectedCategory.deliveryName!, - }; - registerUser(data); - } + AppSpaces.verticalLarge, + LoginButton( + isLoading: authView.isInAsyncCall, + textColor: MyColors.white, + backGroundColor: MyColors.blueThemeColor, + onPressed: () async { + await authView.validate(); + checkState(); }, - child: Text( - AppLocalizations.of(context)!.register, - style: const TextStyle( - fontSize: MyFonts.bold, - color: MyColors.white, - fontFamily: MyFonts.Bold), + heading: AppLocalizations.of(context)!.register, + ), + AppSpaces.verticalMedium, + GestureDetector( + onTap: () { + Navigator.pop(context); + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text.rich( + TextSpan( + text: 'Already have an account?', + style: TextStyle( + fontStyle: FontStyle.normal, + fontFamily: MyFonts.Medium, + fontSize: MyFonts.normal, + fontWeight: FontWeight.w500, + color: MyColors.black, + ), + children: [ + TextSpan( + text: ' Login', + style: TextStyle( + fontStyle: FontStyle.normal, + fontFamily: MyFonts.Bold, + fontSize: MyFonts.normal, + fontWeight: FontWeight.w500, + color: MyColors.black, + decoration: TextDecoration.underline, + )), + // can add more TextSpans here... + ], + ), + ) + ], ), ), - TextButton( - onPressed: () { - Navigator.pop(context); - }, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text(AppLocalizations.of(context)!.already_account_login, - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: 15, - color: MyColors.black)), - ], - )) ], ), ), @@ -369,73 +244,16 @@ class _RegisterVCState extends BaseStatefulState { BuildContext context, String title, String hint) { return Column( children: [ - Row( - children: [ - Text( - title, - style: const TextStyle( - fontSize: 16, - fontFamily: MyFonts.Medium, - color: MyColors.black), - ), - const SizedBox( - width: 4, - ), - const Text( - '*', - style: TextStyle( - fontSize: 16, - fontFamily: MyFonts.Medium, - color: MyColors.primary), - ) - ], - ), - const SizedBox( - height: 8, - ), - Container( - height: 55, - decoration: BoxDecoration( - border: Border.all( - color: MyColors.strokeColor, - width: 1, - ), - color: MyColors.fillColor, - borderRadius: BorderRadius.circular(8.0), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Expanded( - child: TextButton( - onPressed: () { - _navigateAndDisplayCountry(context); - }, - child: Align( - alignment: Alignment.centerLeft, - child: Text( - selectedCountry.countryName!.isEmpty - ? hint - : selectedCountry.countryName!, - textAlign: TextAlign.left, - style: TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: 16, - color: selectedCountry.countryName!.isEmpty - ? Colors.black54 - : Colors.black), - ), - ), - )), - const Icon( - // <-- Icon - Icons.arrow_drop_down, - size: 24.0, - color: MyColors.black, - ) - ], - ), + MandatoryTitleText(hint: title), + AppSpaces.verticalSmall, + CustomTextButtonIcon( + icon: Icons.arrow_drop_down_outlined, + heading: authView.selectedCountry.countryName!.isEmpty + ? hint + : authView.selectedCountry.countryName!, + onPressed: () { + _navigateAndDisplayCountry(context); + }, ) ], ); @@ -445,77 +263,20 @@ class _RegisterVCState extends BaseStatefulState { BuildContext context, String title, String hint) { return Column( children: [ - Row( - children: [ - Text( - title, - style: const TextStyle( - fontSize: 16, - fontFamily: MyFonts.Medium, - color: MyColors.black), - ), - const SizedBox( - width: 4, - ), - const Text( - '*', - style: TextStyle( - fontSize: 16, - fontFamily: MyFonts.Medium, - color: MyColors.primary), - ) - ], - ), - const SizedBox( - height: 8, - ), - Container( - height: 55, - decoration: BoxDecoration( - border: Border.all( - color: MyColors.strokeColor, - width: 1, - ), - color: MyColors.fillColor, - borderRadius: BorderRadius.circular(8.0), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Expanded( - child: TextButton( - onPressed: () { - if (selectedCountry.id!.isNotEmpty) { - _navigateAndDisplayCity(context); - } else { - showMessage('Select country'); - } - }, - child: Align( - alignment: Alignment.centerLeft, - child: Text( - selectedCity.cityName!.isEmpty - ? hint - : selectedCity.cityName!, - textAlign: TextAlign.left, - style: TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: 16, - color: selectedCity.cityName!.isEmpty - ? Colors.black54 - : Colors.black), - ), - ), - )), - const Icon( - // <-- Icon - Icons.arrow_drop_down, - size: 24.0, - color: MyColors.black, - ) - ], - ), + MandatoryTitleText(hint: title), + AppSpaces.verticalSmall, + CustomTextButtonIcon( + icon: Icons.arrow_drop_down_outlined, + heading: authView.selectedCity.cityName!.isEmpty + ? hint + : authView.selectedCity.cityName!, + onPressed: () { + if (authView.selectedCountry.id!.isNotEmpty) { + _navigateAndDisplayCity(context); + } else { + showMessage('Select country'); + } + }, ) ], ); @@ -525,77 +286,20 @@ class _RegisterVCState extends BaseStatefulState { BuildContext context, String title, String hint) { return Column( children: [ - Row( - children: [ - Text( - title, - style: const TextStyle( - fontSize: 16, - fontFamily: MyFonts.Medium, - color: MyColors.black), - ), - const SizedBox( - width: 4, - ), - const Text( - '*', - style: TextStyle( - fontSize: 16, - fontFamily: MyFonts.Medium, - color: MyColors.primary), - ) - ], - ), - const SizedBox( - height: 8, - ), - Container( - height: 55, - decoration: BoxDecoration( - border: Border.all( - color: MyColors.strokeColor, - width: 1, - ), - color: MyColors.fillColor, - borderRadius: BorderRadius.circular(8.0), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Expanded( - child: TextButton( - onPressed: () { - if (!selectedCountry.id!.isEmpty) { - _handlePressButton(); - } else { - showMessage('Select city'); - } - }, - child: Align( - alignment: Alignment.centerLeft, - child: Text( - addressController.isEmpty - ? 'Enter Address' - : addressController, - textAlign: TextAlign.left, - style: TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: 16, - color: addressController.isEmpty - ? Colors.black54 - : Colors.black), - ), - ), - )), - const Icon( - // <-- Icon - Icons.arrow_drop_down, - size: 24.0, - color: MyColors.black, - ) - ], - ), + MandatoryTitleText(hint: title), + AppSpaces.verticalSmall, + CustomTextButtonIcon( + icon: Icons.arrow_drop_down_outlined, + heading: authView.addressController.isEmpty + ? 'Enter Address' + : authView.addressController, + onPressed: () { + if (authView.selectedCountry.id!.isNotEmpty) { + _handlePressButton(); + } else { + showMessage('Select city'); + } + }, ) ], ); @@ -605,77 +309,20 @@ class _RegisterVCState extends BaseStatefulState { BuildContext context, String title, String hint) { return Column( children: [ - Row( - children: [ - Text( - title, - style: const TextStyle( - fontSize: 16, - fontFamily: MyFonts.Medium, - color: MyColors.black), - ), - const SizedBox( - width: 4, - ), - const Text( - '*', - style: TextStyle( - fontSize: 16, - fontFamily: MyFonts.Medium, - color: MyColors.primary), - ) - ], - ), - const SizedBox( - height: 8, - ), - Container( - height: 55, - decoration: BoxDecoration( - border: Border.all( - color: MyColors.strokeColor, - width: 1, - ), - color: MyColors.fillColor, - borderRadius: BorderRadius.circular(8.0), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Expanded( - child: TextButton( - onPressed: () { - if (selectedCity.id!.isNotEmpty) { - _navigateAndDisplayDelivery(context); - } else { - showMessage('Select City'); - } - }, - child: Align( - alignment: Alignment.centerLeft, - child: Text( - selectedCategory.deliveryName!.isEmpty - ? hint - : selectedCategory.deliveryName!, - textAlign: TextAlign.left, - style: TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: 16, - color: selectedCategory.deliveryName!.isEmpty - ? Colors.black54 - : Colors.black), - ), - ), - )), - const Icon( - // <-- Icon - Icons.arrow_drop_down, - size: 24.0, - color: MyColors.black, - ) - ], - ), + MandatoryTitleText(hint: title), + AppSpaces.verticalSmall, + CustomTextButtonIcon( + icon: Icons.arrow_drop_down_outlined, + heading: authView.selectedCategory.deliveryName!.isEmpty + ? hint + : authView.selectedCategory.deliveryName!, + onPressed: () { + if (authView.selectedCity.id!.isNotEmpty) { + _navigateAndDisplayDelivery(context); + } else { + showMessage('Select City'); + } + }, ) ], ); @@ -683,38 +330,16 @@ class _RegisterVCState extends BaseStatefulState { Widget buildCountryCode() { return Column(children: [ - Row( - children: [ - Text( - AppLocalizations.of(context)!.company_phone, - style: const TextStyle( - fontSize: 16, - fontFamily: MyFonts.Medium, - color: MyColors.black), - ), - const SizedBox( - width: 4, - ), - const Text( - '*', - style: TextStyle( - fontSize: 16, - fontFamily: MyFonts.Medium, - color: MyColors.primary), - ) - ], - ), - const SizedBox( - height: 8, - ), + MandatoryTitleText(hint: AppLocalizations.of(context)!.company_phone), + AppSpaces.verticalSmall, Container( - height: 55, + height: 48, decoration: BoxDecoration( border: Border.all( - color: MyColors.strokeColor, + color: Colors.transparent, width: 1, ), - color: MyColors.fillColor, + color: MyColors.backFillColor, borderRadius: BorderRadius.circular(8.0), ), child: Row( @@ -723,7 +348,7 @@ class _RegisterVCState extends BaseStatefulState { ElevatedButton( style: ElevatedButton.styleFrom( elevation: 0, - backgroundColor: MyColors.fillColor, + backgroundColor: MyColors.backFillColor, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), // <-- Radius ), @@ -733,17 +358,18 @@ class _RegisterVCState extends BaseStatefulState { mainAxisAlignment: MainAxisAlignment.start, children: [ Text( - selectedCountry.phoneCode!, - style: const TextStyle(color: MyColors.black), + authView.selectedCountry.phoneCode!, + style: TextStyle( + fontFamily: MyFonts.DMREGULAR, + fontSize: MyFonts.normal, + color: MyColors.black), ), // <-- Text - const SizedBox( - width: 5, - ), + AppSpaces.horizontalSmall, const Icon( // <-- Icon Icons.arrow_drop_down, size: 24.0, - color: MyColors.black, + color: MyColors.textColorGray, ), ], ), @@ -751,18 +377,18 @@ class _RegisterVCState extends BaseStatefulState { Expanded( // optional flex property if flex is 1 because the default flex is 1 flex: 1, - child: TextField( + child: TextFormField( keyboardType: TextInputType.phone, - controller: phoneController, - style: const TextStyle( + controller: authView.phoneController, + style: TextStyle( fontFamily: MyFonts.DMREGULAR, - fontSize: 16, + fontSize: MyFonts.normal, color: MyColors.black), - decoration: const InputDecoration( + decoration: InputDecoration( hintText: 'Enter your phone', - fillColor: MyColors.fillColor, + fillColor: MyColors.backFillColor, filled: true, - contentPadding: EdgeInsets.all(0.0), + contentPadding: const EdgeInsets.all(0.0), isDense: true, border: InputBorder.none, ), @@ -774,69 +400,29 @@ class _RegisterVCState extends BaseStatefulState { ]); } - Widget buildPassword() { - return Column(children: [ - Row( - children: [ - Text( - AppLocalizations.of(context)!.password, - style: const TextStyle( - fontSize: 16, - fontFamily: MyFonts.Medium, - color: MyColors.black), - ), - const SizedBox( - width: 4, - ), - const Text( - '*', - style: TextStyle( - fontSize: 16, - fontFamily: MyFonts.Medium, - color: MyColors.primary), - ) - ], - ), - const SizedBox( - height: 8, - ), - Container( - height: 55, + Widget password() { + return Container( decoration: BoxDecoration( - border: Border.all( - color: MyColors.strokeColor, - width: 1, - ), - color: MyColors.fillColor, + color: MyColors.fillColor2, borderRadius: BorderRadius.circular(8.0), ), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Expanded( - // optional flex property if flex is 1 because the default flex is 1 - flex: 1, - child: TextField( - controller: passwordController, - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: 16, - color: MyColors.black), - decoration: const InputDecoration( - hintText: 'Enter your password', - fillColor: MyColors.fillColor, - filled: true, - isDense: true, - border: InputBorder.none, - ), - ), - ), - IconButton( - onPressed: () {}, - icon: const Icon(Icons.remove_red_eye_outlined, size: 24)), - ], - ), - ) + child: CustomTextFieldPassword( + obscure: authView.obscureText, + hint: 'Enter your password', + onChanged: (value) { + authView.passwordController.text = value; + }, + onPressed: () { + authView.showHidePassword(); + }, + )); + } + + Widget buildPassword() { + return Column(children: [ + MandatoryTitleText(hint: AppLocalizations.of(context)!.password), + AppSpaces.verticalSmall, + password(), ]); } @@ -851,10 +437,9 @@ class _RegisterVCState extends BaseStatefulState { // When a BuildContext is used from a StatefulWidget, the mounted property // must be checked after an asynchronous gap. if (!mounted) return; - selectedCountry = country; - selectedCategory = CategoryModel(deliveryName: "", id: "", imageUrl: ""); - selectedCity = CityModel(cityName: "", id: ""); - setState(() {}); + if (country != null) { + authView.updateCountry(country); + } } Future _navigateAndDisplayDelivery(BuildContext context) async { @@ -863,14 +448,16 @@ class _RegisterVCState extends BaseStatefulState { final result = await Navigator.push( context, MaterialPageRoute( - builder: (context) => CategoryPopUp(cityId: selectedCity.id!)), + builder: (context) => + CategoryPopUp(cityId: authView.selectedCity.id!)), ); // When a BuildContext is used from a StatefulWidget, the mounted property // must be checked after an asynchronous gap. if (!mounted) return; - selectedCategory = result; - setState(() {}); + if (result != null) { + authView.updateCategory(result); + } } Future _navigateAndDisplayCity(BuildContext context) async { @@ -880,69 +467,21 @@ class _RegisterVCState extends BaseStatefulState { final city = await Navigator.push( context, MaterialPageRoute( - builder: (context) => CityPopUp(countryId: selectedCountry.id!)), + builder: (context) => + CityPopUp(countryId: authView.selectedCountry.id!)), ); // When a BuildContext is used from a StatefulWidget, the mounted property // must be checked after an asynchronous gap. if (!mounted) return; - selectedCity = city; - selectedCategory = CategoryModel(deliveryName: "", id: "", imageUrl: ""); - setState(() {}); - } - - void registerUser(Map map) async { - progressDialogue(context); - - StoreResponse storeResponse = await authView.loginRegisterUser(map); - if (storeResponse.success) { - addAccount(storeResponse.store); - } else { - hideProgressBar(); - showMessage('Try Again'); - // showMessage(error); - // showMessage(AppLocalizations.of(context)![error]); + if (city != null) { + authView.updateCity(city); } } - void addAccount(WosulStore store) async { - Map data = { - 'store_id': store.id, - 'account_name': store.name, - }; - - await APIManager().fetchData(Constants.addStoreAccount, data).then((value) { - hideProgressBar(); - final response = SimpleResponseModel.fromJson(value); - if (response.success) { - showMessage('Registered'); - Navigator.of(context).pop(); - } else { - showMessage(response.message); - // showMessage(AppLocalizations.of(context)![error]); - } - }).onError((error, stackTrace) { - hideProgressBar(); - }); - } - - void getServices(BuildContext context, String id) async { - Map json = { - 'store_id': id, - }; - StoreServiceResponse storeServiceResponse = - await authView.getStoreService(json); - if (storeServiceResponse.success) { - _isInAsyncCall = false; - sharedPrefs.isLoggedIn = true; - - Navigator.pushReplacement( - context, - MaterialPageRoute(builder: (context) => const HomePage()), - ); - } else { - _isInAsyncCall = false; - setState(() {}); + void checkState() { + if (authView.crudOperation == CRUDOperationState.add) { + Navigator.pop(context); } } } diff --git a/lib/application/views/authModule/registerViews/viewModel/AuthViewModel.dart b/lib/application/views/authModule/registerViews/viewModel/AuthViewModel.dart new file mode 100644 index 0000000..9f8655b --- /dev/null +++ b/lib/application/views/authModule/registerViews/viewModel/AuthViewModel.dart @@ -0,0 +1,173 @@ +import 'package:flutter/material.dart'; +import 'package:google_maps_webservice/src/places.dart'; +import 'package:wosull/application/model/auth/CityModel.dart'; +import 'package:wosull/application/model/auth/CountryModel.dart'; +import 'package:wosull/application/model/discount/CategoryModel.dart'; +import 'package:wosull/application/model/inventory/category/CategoriesResponse.dart'; +import 'package:wosull/application/model/store/WosulStore.dart'; +import 'package:wosull/application/utils/CRUDOperatoinState.dart'; +import 'package:wosull/application/views/authModule/repo/AuthRepository.dart'; +import 'package:wosull/helpers/Utils.dart'; + +class AuthViewModel with ChangeNotifier { + final repository = AuthRepository(); + var nameController = TextEditingController(); + var emailController = TextEditingController(); + var phoneController = TextEditingController(); + var passwordController = TextEditingController(); + String addressController = ''; + + var _crudOperation = CRUDOperationState.uninitialized; + + CRUDOperationState get crudOperation => _crudOperation; + + late var lat; + late var lng; + + bool obscureText = true; + + var selectedCountry = CountryModel( + countryFlag: "", + countryName: "", + phoneCode: "+966", + countryCode: "SAR", + id: ""); + var selectedCity = CityModel(cityName: "", id: ""); + var selectedCategory = CategoryModel(deliveryName: "", imageUrl: "", id: ""); + + bool isInAsyncCall = false; + + void setOperation(CRUDOperationState state) { + _crudOperation = state; + } + + void setLoading(bool value) { + isInAsyncCall = value; + notifyListeners(); + } + + void showHidePassword() { + obscureText = !obscureText; + notifyListeners(); + } + + bool isValidate() { + if (nameController.text.isEmpty) { + Utils.showMessage('Enter company name'); + return false; + } else if (emailController.text.isEmpty) { + Utils.showMessage('Enter your email'); + return false; + } else if (!emailController.text.isValidEmail()) { + Utils.showMessage('Enter valid email address'); + return false; + } else if (phoneController.text.isEmpty) { + Utils.showMessage('Enter your phone'); + return false; + } else if (passwordController.text.isEmpty) { + Utils.showMessage('Enter your password'); + return false; + } else if (selectedCountry.countryName!.isEmpty) { + Utils.showMessage('Select Country'); + return false; + } else if (selectedCity.cityName!.isEmpty) { + Utils.showMessage('Select city'); + return false; + } else if (selectedCategory.deliveryName!.isEmpty) { + Utils.showMessage('Select Business Type'); + return false; + } + return true; + } + + Future validate() async { + if (isValidate()) { + setLoading(true); + Map data = { + 'device_type': 'android', + 'slogan': '', + 'website_url': '', + 'latitude': lat, + 'longitude': lng, + 'app_version': '1.0', + 'referral_code': '', + 'is_phone_number_verified': 'false', + 'is_email_verified': 'false', + 'social_id': '', + 'login_by': 'manual', + 'name': nameController.text, + 'email': emailController.text, + 'country_phone_code': selectedCountry.phoneCode, + 'phone': phoneController.text, + 'address': addressController, + 'password': passwordController.text, + 'store_delivery_id': selectedCategory.id!, + 'country_id': selectedCountry.id!, + 'city_id': selectedCity.id!, + 'name_type': selectedCategory.deliveryName!, + }; + await registerUser(data); + } + } + + Future registerUser(Map map) async { + await repository.loginRegisterUser(map).then((storeResponse) { + if (storeResponse.success) { + addAccount(storeResponse.store); + } else { + setLoading(false); + Utils.showMessage('Try Again'); + // showMessage(error); + // showMessage(AppLocalizations.of(context)![error]); + } + }).onError((error, stackTrace) {}); + } + + void addAccount(WosulStore store) async { + Map data = { + 'store_id': store.id, + 'account_name': store.name, + }; + + await repository.addAccount(data).then((response) { + if (response.success) { + setOperation(CRUDOperationState.add); + Utils.showMessage('Registered'); + } else { + Utils.showMessage(response.message); + } + setLoading(false); + }).onError((error, stackTrace) { + setLoading(false); + }); + } + + void updateAddress(PlacesDetailsResponse detail, String description) { + lat = detail.result.geometry!.location.lat; + lng = detail.result.geometry!.location.lng; + addressController = description; + notifyListeners(); + } + + void updateCity(city) { + selectedCity = city; + selectedCategory = CategoryModel(deliveryName: "", id: "", imageUrl: ""); + notifyListeners(); + } + + void updateCategory(result) { + selectedCategory = result; + notifyListeners(); + } + + void updateCountry(country) { + selectedCountry = country; + selectedCategory = CategoryModel(deliveryName: "", id: "", imageUrl: ""); + selectedCity = CityModel(cityName: "", id: ""); + notifyListeners(); + } + + Future getCategories(Map data) async { + return await repository.getCategories(data); + } +} diff --git a/lib/application/views/authModule/viewModel/CityViewModel.dart b/lib/application/views/authModule/registerViews/viewModel/CityViewModel.dart similarity index 100% rename from lib/application/views/authModule/viewModel/CityViewModel.dart rename to lib/application/views/authModule/registerViews/viewModel/CityViewModel.dart index 67b5b7d..4dfeda2 100644 --- a/lib/application/views/authModule/viewModel/CityViewModel.dart +++ b/lib/application/views/authModule/registerViews/viewModel/CityViewModel.dart @@ -1,6 +1,6 @@ import 'package:wosull/application/model/auth/CityResponse.dart'; -import 'package:wosull/application/utils/Constants.dart'; import 'package:wosull/application/repo/AuthRepository.dart'; +import 'package:wosull/application/utils/Constants.dart'; class CityViewModel { Future getCities(Map data) async { diff --git a/lib/application/views/authModule/viewModel/CountryViewModel.dart b/lib/application/views/authModule/registerViews/viewModel/CountryViewModel.dart similarity index 100% rename from lib/application/views/authModule/viewModel/CountryViewModel.dart rename to lib/application/views/authModule/registerViews/viewModel/CountryViewModel.dart diff --git a/lib/application/views/authModule/repo/AuthRepository.dart b/lib/application/views/authModule/repo/AuthRepository.dart new file mode 100644 index 0000000..8259bab --- /dev/null +++ b/lib/application/views/authModule/repo/AuthRepository.dart @@ -0,0 +1,70 @@ +import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/application/model/SimpleResponsModel.dart'; +import 'package:wosull/application/model/auth/AccessTokenModel.dart'; +import 'package:wosull/application/model/inventory/category/CategoriesResponse.dart'; +import 'package:wosull/application/model/store/StoreResponse.dart'; +import 'package:wosull/application/model/store/StoreServiceResponse.dart'; +import 'package:wosull/application/model/store/WosulStore.dart'; +import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/utils/Constants.dart'; + +class AuthRepository { + Future loginRegisterUser(Map data) async { + try { + final result = await APIManager().fetchData(Constants.REGISTER_URL, data); + return StoreResponse.fromJson(result); + } catch (e) { + return StoreResponse( + success: false, + error_code: 500, + message: 500, + token: '', + currency: '', + store: WosulStore(id: '', name: ''), + ); + } + } + + Future addAccount(Map map) async { + final response = + await APIManager().fetchData(Constants.addStoreAccount, map); + return SimpleResponseModel.fromJson(response); + } + + Future loginUser(Map map) async { + final result = await APIManager().fetchData(Constants.LOGIN_URL, map); + return StoreResponse.fromJson(result); + } + + Future getServices() async { + final response = await APIManager() + .fetchData(Constants.Store_services_URL, Constants.getStorePayload()); + return StoreServiceResponse.fromJson(response); + } + + Future checkAccessAccount() async { + final result = await APIManager() + .getResponseAuth('${Constants.getAccessToken}/${sharedPrefs.storeId}'); + + return AccessTokenModel.fromJson(result); + } + + Future createAccessToken(String token) async { + Map data = { + 'token': token, + }; + final result = + await APIManager().fetchData(Constants.CREATE_ACCESS_TOKEN, data); + return SimpleResponseModel.fromJson(result); + } + + Future getCategories(Map data) async { + try { + final result = await APIManager() + .fetchData(Constants.STORE_TYPE_CATEGORIES_URL, data); + return CategoriesResponse.fromJson(result); + } catch (e) { + return CategoriesResponse(); + } + } +} diff --git a/lib/application/views/authModule/viewModel/AuthViewModel.dart b/lib/application/views/authModule/viewModel/AuthViewModel.dart deleted file mode 100644 index 3f1a5d3..0000000 --- a/lib/application/views/authModule/viewModel/AuthViewModel.dart +++ /dev/null @@ -1,68 +0,0 @@ -import 'package:wosull/application/model/inventory/category/CategoriesResponse.dart'; -import 'package:wosull/application/model/store/StoreResponse.dart'; -import 'package:wosull/application/model/store/StoreServiceResponse.dart'; -import 'package:wosull/application/model/store/WosulStore.dart'; -import 'package:wosull/application/repo/AuthRepository.dart'; -import 'package:wosull/application/utils/Constants.dart'; - -class AuthViewModel { - Future getCategories(Map data) async { - try { - return CategoriesResponse.fromJson(await AuthRepository() - .postResponse(Constants.STORE_TYPE_CATEGORIES_URL, data)); - } catch (e) { - return CategoriesResponse(); - } - } - - Future getStoreService(Map data) async { - try { - dynamic response = await AuthRepository() - .postResponse(Constants.Store_services_URL, data); - return StoreServiceResponse.fromJson(response); - } catch (e) { - return StoreServiceResponse(); - } - } - - Future loginUser(Map data) async { - try { - return StoreResponse.fromJson( - await AuthRepository().postResponse(Constants.LOGIN_URL, data)); - } catch (e) { - return StoreResponse( - success: false, - error_code: 500, - message: 500, - token: '', - currency: '', - store: WosulStore(id: '', name: ''), - ); - } - } - - Future getData(String url, Map data) async { - try { - dynamic response = await AuthRepository().postResponseAuth(url, data); - return response; - } catch (e) { - return e; - } - } - - Future loginRegisterUser(Map data) async { - try { - return StoreResponse.fromJson( - await AuthRepository().postResponse(Constants.REGISTER_URL, data)); - } catch (e) { - return StoreResponse( - success: false, - error_code: 500, - message: 500, - token: '', - currency: '', - store: WosulStore(id: '', name: ''), - ); - } - } -} diff --git a/lib/application/views/billingCounterDashboard/BillingCounterDashBoard.dart b/lib/application/views/billingCounterDashboard/BillingCounterDashBoard.dart new file mode 100644 index 0000000..f96cc68 --- /dev/null +++ b/lib/application/views/billingCounterDashboard/BillingCounterDashBoard.dart @@ -0,0 +1,157 @@ +import 'package:dropdown_search/dropdown_search.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/AppLoader.dart'; +import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/billingCounterDashboard/viewModels/BillingCounterViewModel.dart'; +import 'package:wosull/application/views/billingCounterDashboard/widgets/BillingCounterGrid.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeDropDown.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/widgets/CustomTextButtonIcon.dart'; +import 'package:wosull/widgets/DropdownItemBuilder.dart'; + +class BillingCounterDashBoard extends StatefulWidget { + const BillingCounterDashBoard({super.key}); + + @override + State createState() => + _BillingCounterDashBoardState(); +} + +class _BillingCounterDashBoardState extends State { + bool isPortrait = false; + var viewModel = BillingCounterViewModel(); + + @override + void initState() { + context.read().fetchCounters(); + super.initState(); + } + + @override + Widget build(BuildContext context) { + viewModel = context.watch(); + return Scaffold( + backgroundColor: MyColors.fillColor, + body: OrientationBuilder(builder: (c, orientation) { + isPortrait = + MediaQuery.of(context).orientation == Orientation.portrait; + return SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(12), + child: Column( + children: [ + isPortrait + ? Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + 'Billing Counter Dashboard', + style: ThemeText.textStylePageHeading, + ), + const SizedBox( + width: 4, + ), + Flexible(child: getCounterTypeDropdown()) + ], + ), + AppSpaces.verticalSmall, + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Flexible(child: getStartDateButton()), + AppSpaces.horizontalSmall, + Flexible(child: getEndDateButton()) + ], + ), + ], + ) + : Row( + children: [ + Text( + 'Billing Counter Dashboard', + style: ThemeText.textStylePageHeading, + ), + AppSpaces.horizontalSmall, + Expanded( + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + SizedBox( + width: 130, + child: getCounterTypeDropdown(), + ), + AppSpaces.horizontalSmall, + SizedBox( + width: 130, + child: getStartDateButton(), + ), + AppSpaces.horizontalSmall, + SizedBox( + width: 130, + child: getEndDateButton(), + ), + ], + )) + ], + ), + AppSpaces.verticalLarge, + viewModel.isLoading + ? AppLoader() + : BillingCounterGrid( + isPortrait: isPortrait, data: viewModel.filteredList) + ], + ), + ), + ); + })); + } + + Widget getCounterTypeDropdown() { + return DropdownSearch( + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + selectedItem: Constants.counterTypes.first, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 180)), + items: Constants.counterTypes, + itemAsString: (String u) => u, + onChanged: (String? data) { + viewModel.filterCounter(data); + }, + dropdownDecoratorProps: MyColors.dropDownStyle(fillColor: MyColors.white), + ); + } + + Widget getEndDateButton() { + return CustomTextButtonIcon( + backgroundColor: MyColors.white, + icon: Icons.calendar_month, + heading: viewModel.endDate.isEmpty ? 'dd/mm/yyyy' : viewModel.endDate, + onPressed: () { + viewModel.presentDatePicker(context, false); + }, + ); + } + + Widget getStartDateButton() { + return CustomTextButtonIcon( + backgroundColor: MyColors.white, + icon: Icons.calendar_month, + heading: viewModel.startDate.isEmpty ? 'dd/mm/yyyy' : viewModel.startDate, + onPressed: () { + viewModel.presentDatePicker(context, true); + }, + ); + } +} diff --git a/lib/application/views/billingCounterDashboard/BillingCounterMainVC.dart b/lib/application/views/billingCounterDashboard/BillingCounterMainVC.dart new file mode 100644 index 0000000..39cb6f4 --- /dev/null +++ b/lib/application/views/billingCounterDashboard/BillingCounterMainVC.dart @@ -0,0 +1,51 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/interfaces/DrawerWidgetSelect.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/views/billingCounterDashboard/BillingCounterDashBoard.dart'; +import 'package:wosull/widgets/BackTabBarContainer.dart'; + +class BillingCounterMainVC extends StatefulWidget { + final DrawerWidgetSelect delegateDrawer; + const BillingCounterMainVC({super.key, required this.delegateDrawer}); + + @override + State createState() => _BillingCounterMainVCState(); +} + +class _BillingCounterMainVCState extends State { + @override + Widget build(BuildContext context) { + return DefaultTabController( + length: 1, + child: Scaffold( + body: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + mainAxisSize: MainAxisSize.min, + children: [ + Container( + margin: const EdgeInsets.only(left: 6.0, right: 6.0), + height: 0.5, + width: double.infinity, + color: MyColors.fillColorGray2, + ), + BackTabBarContainer( + onPressed: () { + widget.delegateDrawer.goToHome(); + }, + tabs: const [ + Tab( + text: 'Billing Counter Dashboard', + ), + ], + ), + const Expanded( + child: TabBarView( + children: [BillingCounterDashBoard()], + )) + ], + ), + ), + ); + } +} diff --git a/lib/application/views/billingCounterDashboard/repo/BillingCounterRepository.dart b/lib/application/views/billingCounterDashboard/repo/BillingCounterRepository.dart new file mode 100644 index 0000000..a399260 --- /dev/null +++ b/lib/application/views/billingCounterDashboard/repo/BillingCounterRepository.dart @@ -0,0 +1,12 @@ +import 'package:wosull/application/model/billingCounter/BillingCounterDashboard.dart'; +import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/utils/Constants.dart'; + +class BillingCounterRepository { + Future fetchCounters( + Map map) async { + final value = + await APIManager().getResponseAuth(Constants.billingDashboardData, map); + return BillingCounterDashboard.fromJson(value); + } +} diff --git a/lib/application/views/billingCounterDashboard/viewModels/BillingCounterViewModel.dart b/lib/application/views/billingCounterDashboard/viewModels/BillingCounterViewModel.dart new file mode 100644 index 0000000..503550e --- /dev/null +++ b/lib/application/views/billingCounterDashboard/viewModels/BillingCounterViewModel.dart @@ -0,0 +1,100 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/enum/DataState.dart'; +import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/application/model/billingCounter/CounterDashboard.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/billingCounterDashboard/repo/BillingCounterRepository.dart'; + +class BillingCounterViewModel with ChangeNotifier { + String startDate = ""; + String endDate = ""; + + var _isLoading = true; + + bool get isLoading => _isLoading; + + final repository = BillingCounterRepository(); + + //using this state to handle for get data and pagination + DataState _dataState = DataState.uninitialized; + + DataState get dataState => _dataState; + List _allCounters = []; + List _filteredCounters = []; + + List get dataList => _allCounters; + + List get filteredList => _filteredCounters; + + void disposeData() { + _isLoading = true; + startDate = ""; + endDate = ""; + } + + void setLoading(bool value) { + _isLoading = value; + notifyListeners(); + } + + void presentDatePicker(BuildContext context, bool isStart) { + // showDatePicker is a pre-made function of Flutter + showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime.utc(1965, 1, 1), + lastDate: DateTime(2030)) + .then((pickedDate) { + // Check if no date is selected + if (pickedDate == null) { + return; + } + if (isStart) { + startDate = DataTimeFormat.formatDateFromPicket(pickedDate); + } else { + endDate = DataTimeFormat.formatDateFromPicket(pickedDate); + } + notifyListeners(); + }); + } + + void filterCounter(String? data) { + if (data! == Constants.counterTypes[1]) { + filteredList.clear(); + filteredList.addAll(dataList + .where((element) => element.counterDetails!.isAvailable == true)); + } else if (data == Constants.counterTypes[2]) { + filteredList.clear(); + filteredList.addAll(dataList + .where((element) => element.counterDetails!.isAvailable == false)); + } else if (data == Constants.counterTypes[0]) { + filteredList.clear(); + filteredList.addAll(dataList); + } + notifyListeners(); + } + + Future fetchCounters() async { + Map data = { + 'store_id': sharedPrefs.storeId, + 'start_date': startDate, + 'end_date': endDate + }; + await repository.fetchCounters(data).then((response) { + if (response.success) { + _allCounters.clear(); + _filteredCounters.clear(); + _allCounters.addAll(response.billingCounter); + _filteredCounters.addAll(response.billingCounter); + _dataState = DataState.fetched; + } else { + _dataState = DataState.fetched; + } + setLoading(false); + }).onError((error, stackTrace) { + _dataState = DataState.error; + setLoading(false); + }); + } +} diff --git a/lib/application/views/billingCounterDashboard/widgets/BillingCounterGrid.dart b/lib/application/views/billingCounterDashboard/widgets/BillingCounterGrid.dart new file mode 100644 index 0000000..f93a8e2 --- /dev/null +++ b/lib/application/views/billingCounterDashboard/widgets/BillingCounterGrid.dart @@ -0,0 +1,28 @@ +import 'package:auto_height_grid_view/auto_height_grid_view.dart'; +import 'package:flutter/material.dart'; +import 'package:wosull/application/model/billingCounter/CounterDashboard.dart'; +import 'package:wosull/application/views/billingCounterDashboard/widgets/BillingCounterView.dart'; +import 'package:wosull/widgets/EmptyDataWidget.dart'; + +class BillingCounterGrid extends StatelessWidget { + bool isPortrait; + List data; + + BillingCounterGrid({super.key, required this.isPortrait, required this.data}); + + @override + Widget build(BuildContext context) { + return data.isNotEmpty + ? AutoHeightGridView( + physics: const NeverScrollableScrollPhysics(), + padding: EdgeInsets.zero, + shrinkWrap: true, + itemCount: data.length, + crossAxisCount: isPortrait ? 1 : 2, + builder: (BuildContext c, int i) { + return BillingCounterView(counter: data[i]); + }, + ) + : const EmptyDataWidget(); + } +} diff --git a/lib/application/views/billingCounterDashboard/widgets/BillingCounterView.dart b/lib/application/views/billingCounterDashboard/widgets/BillingCounterView.dart new file mode 100644 index 0000000..78d1f66 --- /dev/null +++ b/lib/application/views/billingCounterDashboard/widgets/BillingCounterView.dart @@ -0,0 +1,179 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/application/model/billingCounter/CounterDashboard.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/theme/MyFonts.dart'; +import 'package:wosull/application/views/billingCounterDashboard/widgets/DetailsView.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/widgets/LineView.dart'; + +class BillingCounterView extends StatelessWidget { + CounterDashboard counter; + + BillingCounterView({super.key, required this.counter}); + + @override + Widget build(BuildContext context) { + return Card( + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)), + elevation: 2, + color: MyColors.white, + child: Padding( + padding: const EdgeInsets.all(12), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + '${counter.counterDetails!.counterName} - ${counter.counterDetails!.counterCode}', + style: ThemeText.textStylePopUpHeading, + ), + Container( + height: 38, + decoration: BoxDecoration( + color: counter.counterDetails!.isAvailable + ? MyColors.greenColor10 + : MyColors.redAlpha50, + borderRadius: + const BorderRadius.all(Radius.circular(10.0))), + child: Padding( + padding: const EdgeInsets.all(10.0), + child: Center( + child: Text( + counter.counterDetails!.isAvailable + ? 'Open' + : 'Closed', + style: TextStyle( + fontStyle: FontStyle.normal, + fontFamily: MyFonts.Bold, + fontSize: MyFonts.normal, + fontWeight: FontWeight.w700, + color: counter.counterDetails!.isAvailable + ? MyColors.greenColor + : MyColors.redLabelColor), + ), + ))), + ], + ), + AppSpaces.verticalMedium, + const LineView(), + AppSpaces.verticalLarge, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Total Orders', + style: ThemeText.labelStyleTextField, + ), + Text( + 'Order Value', + style: ThemeText.labelStyleTextField, + ), + ], + ), + AppSpaces.verticalMedium, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + counter.orderCount.toString(), + style: ThemeText.labelStyleTextField, + ), + Text( + '${sharedPrefs.currency} ${counter.orderValues!.toStringAsFixed(2)}', + style: ThemeText.labelStyleTextField, + ), + ], + ), + AppSpaces.verticalLarge, + const LineView(), + AppSpaces.verticalLarge, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Text( + 'Payment Method', + style: ThemeText.labelStyleTextField, + ), + ), + Flexible( + child: Text( + 'No of Orders', + style: ThemeText.labelStyleTextField, + ), + ), + Flexible( + child: Text( + 'Order Value', + style: ThemeText.labelStyleTextField, + ), + ), + ], + ), + AppSpaces.verticalMedium, + DetailsView( + paymentMethod: 'Stc Pay', + mode: counter.paymentModes!.stcPay!, + ), + AppSpaces.verticalMedium, + DetailsView( + paymentMethod: 'Mada', mode: counter.paymentModes!.mada!), + AppSpaces.verticalMedium, + DetailsView( + paymentMethod: 'Visa', mode: counter.paymentModes!.visa!), + AppSpaces.verticalMedium, + DetailsView( + paymentMethod: 'Cash', mode: counter.paymentModes!.cash!), + AppSpaces.verticalMedium, + DetailsView( + paymentMethod: 'Sure Pay', + mode: counter.paymentModes!.surePay!), + AppSpaces.verticalMedium, + DetailsView( + paymentMethod: 'Express Pay', + mode: counter.paymentModes!.expressPay!), + AppSpaces.verticalMedium, + DetailsView( + paymentMethod: 'Near Pay', + mode: counter.paymentModes!.nearPay!), + AppSpaces.verticalMedium, + const LineView(), + AppSpaces.verticalLarge, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Recently Opened On', + style: ThemeText.labelStyleTextField, + ), + Text( + 'Opened By', + style: ThemeText.labelStyleTextField, + ), + ], + ), + AppSpaces.verticalMedium, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + DataTimeFormat.getFormatDate( + counter.counterDetails!.checkInTime ?? ''), + style: ThemeText.labelStyleTextField, + ), + Text( + counter.counterDetails!.storeName ?? '', + style: ThemeText.labelStyleTextField, + ), + ], + ), + ], + ), + ), + ); + } +} diff --git a/lib/application/views/billingCounterDashboard/widgets/DetailsView.dart b/lib/application/views/billingCounterDashboard/widgets/DetailsView.dart new file mode 100644 index 0000000..05a30c3 --- /dev/null +++ b/lib/application/views/billingCounterDashboard/widgets/DetailsView.dart @@ -0,0 +1,43 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/application/model/billingCounter/PaymentModes.dart'; +import 'package:wosull/helpers/ThemeText.dart'; + +class DetailsView extends StatelessWidget { + String paymentMethod; + PaymentModes mode; + DetailsView({super.key, required this.paymentMethod, required this.mode}); + + @override + Widget build(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + flex: 1, + child: Text( + paymentMethod, + textAlign: TextAlign.left, + style: ThemeText.labelStyleTextField, + ), + ), + Expanded( + flex: 1, + child: Text( + mode.count?.toString() ?? '0', + textAlign: TextAlign.center, + style: ThemeText.labelStyleTextField, + ), + ), + Expanded( + flex: 1, + child: Text( + '${sharedPrefs.currency} ${mode.amount?.toStringAsFixed(2) ?? 0}', + textAlign: TextAlign.right, + style: ThemeText.labelStyleTextField, + ), + ), + ], + ); + } +} diff --git a/lib/application/views/businessAccounts/BusinessAccountMainVC.dart b/lib/application/views/businessAccounts/BusinessAccountMainVC.dart new file mode 100644 index 0000000..a32666f --- /dev/null +++ b/lib/application/views/businessAccounts/BusinessAccountMainVC.dart @@ -0,0 +1,81 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:wosull/application/interfaces/DrawerWidgetSelect.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/views/businessAccounts/views/TransactionPOSReturnVC.dart'; +import 'package:wosull/application/views/businessAccounts/views/TransactionPosDamageVC.dart'; +import 'package:wosull/application/views/salesandordermodule/views/invoiceModule/views/InvoicesVC.dart'; +import 'package:wosull/application/views/transactions/TransactionVC.dart'; +import 'package:wosull/widgets/BackTabBarContainer.dart'; + +class BusinessAccountMainVC extends StatefulWidget { + final DrawerWidgetSelect delegateDrawer; + + const BusinessAccountMainVC({super.key, required this.delegateDrawer}); + + @override + State createState() => _BusinessAccountMainVCState(); +} + +class _BusinessAccountMainVCState extends State { + @override + Widget build(BuildContext context) { + return DefaultTabController( + length: 5, + child: Scaffold( + body: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + mainAxisSize: MainAxisSize.min, + children: [ + Container( + margin: const EdgeInsets.only(left: 6.0, right: 6.0), + height: 0.5, + width: double.infinity, + color: MyColors.fillColorGray2, + ), + BackTabBarContainer( + onPressed: () { + widget.delegateDrawer.goToHome(); + }, + tabs: [ + Tab( + text: AppLocalizations.of(context)!.transactions, + ), + const Tab( + text: 'POS Return', + ), + const Tab( + text: 'POS Damage', + ), + const Tab( + text: 'Return Invoices', + ), + const Tab( + text: 'Damage Invoices', + ), + ], + ), + Expanded( + child: TabBarView( + children: [ + const TransactionVC(), + const TransactionPOSReturnVC(), + const TransactionPosDamageVC(), + InvoicesVC( + filter: 'Return', + ), + InvoicesVC( + filter: 'Damage', + ), + // TransactionPOSReturnVC(), + // ReturnTransactionInvoiceVC(), + // TransactionDamageInvoiceVC(), + ], + )) + ], + ), + ), + ); + } +} diff --git a/lib/application/views/businessAccounts/repository/TransactionPosReturnRepository.dart b/lib/application/views/businessAccounts/repository/TransactionPosReturnRepository.dart new file mode 100644 index 0000000..f5be3fc --- /dev/null +++ b/lib/application/views/businessAccounts/repository/TransactionPosReturnRepository.dart @@ -0,0 +1,39 @@ +import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/application/model/cart/GetHoldOrderModel.dart'; +import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/utils/Constants.dart'; + +class TransactionPosReturnRepository { + Future> fetch(Map data) async { + var categories = []; + await APIManager() + .fetchData(Constants.GET_CASHIER_ORDER_HISTORY, data) + .then((result) { + final value = GetReturnOrderModel.fromJson(result); + if (value.success!) { + categories.addAll(value.orderModel!); + } + }).onError((error, stackTrace) { + print(stackTrace.toString()); + }); + return categories; + } + + Future> search({String searchValue = ""}) async { + var items = []; + List status = ['completed']; + Map data = { + 'store_id': sharedPrefs.storeId, + 'searchTerm': searchValue, + 'status': status + }; + await APIManager().fetchData(Constants.searchCashier, data).then((result) { + final value = SearchCashier.fromJson(result); + if (value.success!) { + items.addAll(value.orderModel!); + } + }).onError((error, stackTrace) {}); + + return items; + } +} diff --git a/lib/application/views/businessAccounts/viewModels/TransactionPosReturnViewModel.dart b/lib/application/views/businessAccounts/viewModels/TransactionPosReturnViewModel.dart new file mode 100644 index 0000000..bc81378 --- /dev/null +++ b/lib/application/views/businessAccounts/viewModels/TransactionPosReturnViewModel.dart @@ -0,0 +1,116 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:wosull/application/enum/DataState.dart'; +import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/application/model/cart/GetHoldOrderModel.dart'; +import 'package:wosull/application/views/businessAccounts/repository/TransactionPosReturnRepository.dart'; + +class TransactionPosReturnViewModel with ChangeNotifier { + int _currentPageNumber = 1; + bool isPortrait = false; + + //using this state to handle for get data and pagination + DataState _dataState = DataState.uninitialized; + + DataState get dataState => _dataState; + + bool _didLastLoad = false; + + bool _isLoading = false; + + bool get isLoading => _isLoading; + + final List _dataList = []; + final List _filteredList = []; + + List get dataList => _dataList; + + List get filteredList => _filteredList; + + var repository = TransactionPosReturnRepository(); + + int limit = 10; + + fetch(String filter, {bool isRefresh = false, int limit = 10}) async { + this.limit = limit; + _isLoading = true; + if (!isRefresh) { + _dataState = (_dataState == DataState.uninitialized) + ? DataState.initialFetching + : DataState.moreFetching; + } else { + _didLastLoad = false; + _currentPageNumber = 1; + _dataState = DataState.refreshing; + } + notifyListeners(); + Map data = { + 'store_id': sharedPrefs.storeId, + 'page': _currentPageNumber, + 'limit': this.limit, + 'order_status': filter + }; + print(jsonEncode(data)); + try { + if (_didLastLoad) { + _dataState = DataState.noMoreData; + } else { + await repository.fetch(data).then((value) { + if (_dataState == DataState.refreshing) { + _filteredList.clear(); + _dataList.clear(); + } + if (value.isNotEmpty) { + _filteredList.addAll(value); + _dataList.addAll(value); + if (value.length < this.limit) { + _didLastLoad = true; + } else { + _didLastLoad = false; + } + } + _dataState = DataState.fetched; + _currentPageNumber += 1; + _isLoading = false; + notifyListeners(); + }).onError((error, stackTrace) { + _dataState = DataState.error; + _isLoading = false; + notifyListeners(); + }); + } + } catch (e) { + _isLoading = false; + _dataState = DataState.error; + notifyListeners(); + } + } + + search({String searchValue = ""}) async { + if (searchValue.isEmpty) { + _dataState = DataState.fetched; + _filteredList.clear(); + _filteredList.addAll(_dataList); + notifyListeners(); + } else { + _dataState = DataState.searching; + notifyListeners(); + try { + await repository.search(searchValue: searchValue).then((result) { + filteredList.clear(); + if (result.isNotEmpty) { + filteredList.addAll(result); + } + _dataState = DataState.fetched; + }).onError((error, stackTrace) { + _dataState = DataState.error; + }); + notifyListeners(); + } catch (e) { + _dataState = DataState.error; + notifyListeners(); + } + } + } +} diff --git a/lib/application/views/businessAccounts/views/TransactionPOSReturnVC.dart b/lib/application/views/businessAccounts/views/TransactionPOSReturnVC.dart new file mode 100644 index 0000000..e7e1484 --- /dev/null +++ b/lib/application/views/businessAccounts/views/TransactionPOSReturnVC.dart @@ -0,0 +1,210 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:provider/provider.dart'; +import 'package:sizer/sizer.dart'; +import 'package:wosull/application/enum/DataState.dart'; +import 'package:wosull/application/model/cart/GetHoldOrderModel.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/AppError.dart'; +import 'package:wosull/application/utils/AppLoader.dart'; +import 'package:wosull/application/views/businessAccounts/viewModels/TransactionPosReturnViewModel.dart'; +import 'package:wosull/application/views/businessAccounts/views/ViewPOSOrderVC.dart'; +import 'package:wosull/application/views/businessAccounts/widgets/PosReturnDamageListView.dart'; +import 'package:wosull/base/BaseStatefulState.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/widgets/PageLimitDropDown.dart'; +import 'package:wosull/widgets/SearchBox.dart'; + +class TransactionPOSReturnVC extends StatefulWidget { + const TransactionPOSReturnVC({super.key}); + + @override + State createState() => _TransactionPOSReturnVCState(); +} + +class _TransactionPOSReturnVCState + extends BaseStatefulState { + var viewModel = TransactionPosReturnViewModel(); + late ScrollController _controller; + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + _controller = ScrollController()..addListener(_scrollNotification); + return Scaffold( + backgroundColor: MyColors.fillColor, + resizeToAvoidBottomInset: true, + body: OrientationBuilder(builder: (c, orientation) { + viewModel.isPortrait = + MediaQuery.of(context).orientation == Orientation.portrait; + return SingleChildScrollView( + controller: _controller, + child: Container( + padding: const EdgeInsets.all(12), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + viewModel.isPortrait + ? Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + 'POS Return', + style: ThemeText.textStylePageHeading, + ), + AppSpaces.horizontalSmall, + Flexible( + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + PageLimitDropdown( + onChange: (value) { + viewModel.fetch('return', + isRefresh: true, + limit: int.parse(value!)); + }, + ) + ], + )) + ], + ), + AppSpaces.verticalSmall, + SizedBox( + height: 48, + child: getSearchBox(), + ), + ], + ) + : Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + 'POS Return', + style: ThemeText.textStylePageHeading, + ), + AppSpaces.horizontalSmall, + Expanded( + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + SizedBox( + width: + SizerUtil.deviceType == DeviceType.mobile + ? 200 + : 200, + height: 48, + child: getSearchBox(), + ), + AppSpaces.horizontalSmall, + PageLimitDropdown( + onChange: (value) { + viewModel.fetch('return', + isRefresh: true, + limit: int.parse(value!)); + }, + ) + ], + )) + ], + ), + AppSpaces.verticalMedium, + ChangeNotifierProvider( + create: (context) => viewModel, + child: Consumer( + builder: (BuildContext context, + TransactionPosReturnViewModel controller, Widget? _) { + switch (controller.dataState) { + case DataState.uninitialized: + Future(() { + controller.fetch( + 'return', + ); + }); + return showData(controller.filteredList); + case DataState.initialFetching: + return AppLoader(); + case DataState.moreFetching: + case DataState.refreshing: + return showData(controller.filteredList); + case DataState.error: + return AppError( + error: 'Error', + ); + case DataState.searching: + case DataState.fetched: + case DataState.noMoreData: + return showData(controller.filteredList); + } + }, + ), + ), + ], + ), + ), + ); + })); + } + + Widget showData(List orders) { + return Column( + children: [ + PosReturnDamageListView( + onView: (order) { + onView(order); + }, + posOrders: orders, + isPortrait: viewModel.isPortrait), + if (viewModel.dataState == DataState.moreFetching) AppLoader(), + ], + ); + } + + bool _scrollNotification() { + if (!viewModel.isLoading && _controller.position.extentAfter < 300) { + viewModel.fetch('return', limit: viewModel.limit); + } + return true; + } + + void onView(ReturnOrderModel order) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => ViewPOSOrderVC( + cashierOrder: order, + )), + ); + } + + getSearchBox() { + return SearchBox( + onEditingDone: (text) { + filterSearchResults(text); + }, + onChanged: (text) { + filterSearchResults(text); + }, + hint: AppLocalizations.of(context)!.search, + ); + } + + Future filterSearchResults(String query) async { + if (query.isNotEmpty) { + viewModel.search(searchValue: query); + } else { + Future.delayed(const Duration(milliseconds: 700), () { + viewModel.search(searchValue: ""); + }); + } + } +} diff --git a/lib/application/views/businessAccounts/views/TransactionPosDamageVC.dart b/lib/application/views/businessAccounts/views/TransactionPosDamageVC.dart new file mode 100644 index 0000000..067182a --- /dev/null +++ b/lib/application/views/businessAccounts/views/TransactionPosDamageVC.dart @@ -0,0 +1,209 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:provider/provider.dart'; +import 'package:sizer/sizer.dart'; +import 'package:wosull/application/enum/DataState.dart'; +import 'package:wosull/application/model/cart/GetHoldOrderModel.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/AppError.dart'; +import 'package:wosull/application/utils/AppLoader.dart'; +import 'package:wosull/application/views/businessAccounts/viewModels/TransactionPosReturnViewModel.dart'; +import 'package:wosull/application/views/businessAccounts/widgets/PosReturnDamageListView.dart'; +import 'package:wosull/base/BaseStatefulState.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/widgets/PageLimitDropDown.dart'; +import 'package:wosull/widgets/SearchBox.dart'; + +import 'ViewPOSOrderVC.dart'; + +class TransactionPosDamageVC extends StatefulWidget { + const TransactionPosDamageVC({super.key}); + + @override + State createState() => _TransactionPosDamageVCState(); +} + +class _TransactionPosDamageVCState + extends BaseStatefulState { + var viewModel = TransactionPosReturnViewModel(); + late ScrollController _controller; + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + _controller = ScrollController()..addListener(_scrollNotification); + return Scaffold( + backgroundColor: MyColors.fillColor, + resizeToAvoidBottomInset: true, + body: OrientationBuilder(builder: (c, orientation) { + viewModel.isPortrait = + MediaQuery.of(context).orientation == Orientation.portrait; + return SingleChildScrollView( + controller: _controller, + child: Container( + padding: const EdgeInsets.all(12), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + viewModel.isPortrait + ? Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + 'POS Return', + style: ThemeText.textStylePageHeading, + ), + AppSpaces.horizontalSmall, + Flexible( + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + PageLimitDropdown( + onChange: (value) { + viewModel.fetch('damage', + isRefresh: true, + limit: int.parse(value!)); + }, + ) + ], + )) + ], + ), + AppSpaces.verticalSmall, + SizedBox( + height: 48, + child: getSearchBox(), + ), + ], + ) + : Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + 'POS Return', + style: ThemeText.textStylePageHeading, + ), + AppSpaces.horizontalSmall, + Expanded( + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + SizedBox( + width: + SizerUtil.deviceType == DeviceType.mobile + ? 200 + : 200, + height: 48, + child: getSearchBox(), + ), + AppSpaces.horizontalSmall, + PageLimitDropdown( + onChange: (value) { + viewModel.fetch('damage', + isRefresh: true, + limit: int.parse(value!)); + }, + ) + ], + )) + ], + ), + AppSpaces.verticalMedium, + ChangeNotifierProvider( + create: (context) => viewModel, + child: Consumer( + builder: (BuildContext context, + TransactionPosReturnViewModel controller, Widget? _) { + switch (controller.dataState) { + case DataState.uninitialized: + Future(() { + controller.fetch('damage'); + }); + return showData(controller.filteredList); + case DataState.initialFetching: + return AppLoader(); + case DataState.moreFetching: + case DataState.refreshing: + return showData(controller.filteredList); + case DataState.error: + return AppError( + error: 'Error', + ); + case DataState.searching: + case DataState.fetched: + case DataState.noMoreData: + return showData(controller.filteredList); + } + }, + ), + ), + ], + ), + ), + ); + })); + } + + Widget showData(List orders) { + return Column( + children: [ + PosReturnDamageListView( + onView: (order) { + onView(order); + }, + posOrders: orders, + isPortrait: viewModel.isPortrait), + if (viewModel.dataState == DataState.moreFetching) AppLoader(), + ], + ); + } + + bool _scrollNotification() { + if (!viewModel.isLoading && _controller.position.extentAfter < 300) { + viewModel.fetch('damage', limit: viewModel.limit); + } + return true; + } + + void onView(ReturnOrderModel order) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => ViewPOSOrderVC( + cashierOrder: order, + )), + ); + } + + getSearchBox() { + return SearchBox( + onEditingDone: (text) { + filterSearchResults(text); + }, + onChanged: (text) { + filterSearchResults(text); + }, + hint: AppLocalizations.of(context)!.search, + ); + } + + Future filterSearchResults(String query) async { + if (query.isNotEmpty) { + viewModel.search(searchValue: query); + } else { + Future.delayed(const Duration(milliseconds: 700), () { + viewModel.search(searchValue: ""); + }); + } + } +} diff --git a/lib/application/views/businessAccounts/views/ViewPOSOrderVC.dart b/lib/application/views/businessAccounts/views/ViewPOSOrderVC.dart new file mode 100644 index 0000000..ed55a4d --- /dev/null +++ b/lib/application/views/businessAccounts/views/ViewPOSOrderVC.dart @@ -0,0 +1,761 @@ +import 'package:dropdown_search/dropdown_search.dart'; +import 'package:flutter/material.dart'; +import 'package:wosull/application/model/cart/GetHoldOrderModel.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/application/model/store/StoreItemsResponse.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeDropDown.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/helpers/Utils.dart'; +import 'package:wosull/widgets/BorderContainer.dart'; +import 'package:wosull/widgets/ChildContainer.dart'; +import 'package:wosull/widgets/CustomAppBar.dart'; +import 'package:wosull/widgets/CustomOptionalTitle.dart'; +import 'package:wosull/widgets/CustomTextButtonIcon.dart'; +import 'package:wosull/widgets/CustomTextFieldForm.dart'; +import 'package:wosull/widgets/DropdownItemBuilder.dart'; +import 'package:wosull/widgets/HeadingContainer.dart'; +import 'package:wosull/widgets/HeadingText.dart'; +import 'package:wosull/widgets/PortraitContainer.dart'; +import 'package:wosull/widgets/ValueText.dart'; +import 'package:wosull/widgets/WrapHeightContainer.dart'; + +class ViewPOSOrderVC extends StatelessWidget { + ReturnOrderModel cashierOrder; + bool isPortrait = false; + + ViewPOSOrderVC({super.key, required this.cashierOrder}); + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: MyColors.fillColor, + resizeToAvoidBottomInset: true, + appBar: CustomAppBar( + heading: 'View Order', + ), + body: OrientationBuilder(builder: (c, orientation) { + isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; + return SingleChildScrollView( + child: Container( + padding: const EdgeInsets.all(8), + child: Column( + children: [ + AppSpaces.verticalLarge, + Card( + elevation: 5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: Padding( + padding: const EdgeInsets.all(15), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Expanded( + flex: 1, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: lang(context).status, + ), + AppSpaces.verticalSmall, + getStatusDropdown(cashierOrder.status ?? ''), + AppSpaces.verticalMedium, + CustomOptionalTitle( + hint: lang(context).store, + ), + AppSpaces.verticalSmall, + getSubStoresWidget( + cashierOrder.storeId?.name ?? ''), + AppSpaces.verticalMedium, + CustomOptionalTitle( + hint: lang(context).order_type, + ), + AppSpaces.verticalSmall, + getOrderTypeWidget( + cashierOrder.orderType ?? ''), + isPortrait + ? Column( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + AppSpaces.verticalMedium, + getPaymentModeWidget(context), + getTableWidget(context), + getAmountWidget(context), + AppSpaces.verticalMedium, + getBalanceOrChange(context), + AppSpaces.verticalMedium, + getCreatedAtWidget(context), + AppSpaces.verticalMedium, + getDeliveryNotesWidget(context), + ], + ) + : Container() + ], + ), + ), + isPortrait + ? Container() + : AppSpaces.horizontalMedium, + isPortrait + ? Container() + : Expanded( + flex: 2, + child: Column( + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + Row( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + getPaymentModeWidget(context), + AppSpaces.verticalMedium, + getAmountWidget(context), + AppSpaces.verticalMedium, + getBalanceOrChange(context) + ], + )), + AppSpaces.horizontalMedium, + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + getTableWidget(context), + getCreatedAtWidget(context), + AppSpaces.verticalMedium, + getDeliveryNotesWidget(context) + ], + )), + ], + ), + ], + )), + ], + ), + ], + ), + ), + ), + AppSpaces.verticalLarge, + Card( + elevation: 5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: Container( + padding: const EdgeInsets.all(15), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + lang(context).search_and_add_products, + style: ThemeText.textStyleHeadingCart, + ), + AppSpaces.verticalLarge, + isPortrait + ? Container() + : BorderContainer( + child: Row( + children: [ + Expanded( + child: HeadingContainer( + heading: lang(context).name_or_barcode, + )), + Expanded( + child: HeadingContainer( + heading: lang(context).item_note, + )), + Expanded( + child: HeadingContainer( + heading: lang(context).quantity, + )), + Expanded( + child: HeadingContainer( + heading: lang(context).total_cost_price, + )), + HeadingContainer( + width: 84, + heading: lang(context).total_price, + ), + HeadingContainer( + width: 84, + heading: lang(context).total_amount, + ), + ], + ), + ), + ListView.builder( + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (c, position) { + var orderDetails = + cashierOrder.cart!.orderDetails![position]; + return ListView.builder( + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (c, i) { + var item = cashierOrder + .cart!.orderDetails![position].items![i]; + if (isPortrait) { + return WrapHeightContainer( + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + Expanded( + flex: 2, + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + PortraitContainer( + width: double.infinity, + child: Align( + alignment: Alignment + .centerLeft, + child: HeadingText( + lang(context) + .name_or_barcode, + ), + ), + ), + PortraitContainer( + width: double.infinity, + child: Align( + alignment: Alignment + .centerLeft, + child: HeadingText( + lang(context) + .item_note, + ), + ), + ), + PortraitContainer( + width: double.infinity, + child: Align( + alignment: Alignment + .centerLeft, + child: HeadingText( + lang(context) + .quantity, + ), + ), + ), + PortraitContainer( + width: double.infinity, + child: Align( + alignment: Alignment + .centerLeft, + child: HeadingText( + lang(context) + .total_cost_price, + ), + ), + ), + PortraitContainer( + width: double.infinity, + child: Align( + alignment: Alignment + .centerLeft, + child: HeadingText( + lang(context) + .total_price, + ), + ), + ), + ], + )), + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + PortraitContainer( + width: double.infinity, + child: + getShowProductsWidget( + item, + position, + i), + ), + PortraitContainer( + width: double.infinity, + child: Center( + child: getItemNotesWidget( + cashierOrder + .cart! + .orderDetails![ + position] + .items![i] + .noteForItem + .toString()), + ), + ), + PortraitContainer( + width: double.infinity, + child: Center( + child: getItemQuantityWidget( + cashierOrder + .cart! + .orderDetails![ + position] + .items![i] + .quantity + ?.toString() ?? + ''), + ), + ), + PortraitContainer( + width: double.infinity, + child: Center( + child: getItemCostPriceWidget( + cashierOrder + .cart! + .orderDetails![ + position] + .items![i] + .price + ?.toStringAsFixed( + 2) ?? + ''), + ), + ), + PortraitContainer( + width: double.infinity, + child: Center( + child: + getItemPriceWidget( + item), + ), + ), + ], + )), + ], + )), + ], + ), + ); + } else { + return BorderContainer( + backgroundColor: MyColors.white, + child: Row( + children: [ + Expanded( + child: ChildContainer( + child: getShowProductsWidget( + item, position, i), + ), + ), + Expanded( + child: ChildContainer( + child: Center( + child: getItemNotesWidget( + cashierOrder + .cart! + .orderDetails![position] + .items![i] + .noteForItem + ?.toString() ?? + ''), + ), + )), + Expanded( + child: ChildContainer( + child: Center( + child: getItemQuantityWidget( + cashierOrder + .cart! + .orderDetails![position] + .items![i] + .quantity + ?.toString() ?? + ''), + ), + )), + Expanded( + child: ChildContainer( + child: Center( + child: getItemCostPriceWidget( + cashierOrder + .cart! + .orderDetails![position] + .items![i] + .price + ?.toStringAsFixed(2) ?? + ''), + ), + )), + ChildContainer( + width: 84, + child: getItemPriceWidget(item), + ), + ChildContainer( + width: 84, + child: Center( + child: ValueText( + '', + ), + ), + ), + ], + ), + ); + } + }, + itemCount: orderDetails.items!.length, + ); + }, + itemCount: cashierOrder.cart!.orderDetails!.length, + ), + isPortrait + ? BorderContainer( + backgroundColor: MyColors.white, + child: Row( + children: [ + Expanded( + child: ChildContainer( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + lang(context).total_amount), + ), + )), + Expanded( + child: ChildContainer( + child: Center( + child: HeadingText( + getItemsPriceWithModifier(), + ), + ), + )), + ], + ), + ) + : BorderContainer( + backgroundColor: MyColors.white, + child: Row( + children: [ + Expanded( + child: HeadingContainer( + heading: '', + )), + Expanded( + child: HeadingContainer( + heading: '', + )), + Expanded( + child: HeadingContainer( + heading: '', + )), + Expanded( + child: HeadingContainer( + heading: '', + )), + HeadingContainer( + width: 84, + heading: getItemsPriceOnly(), + ), + HeadingContainer( + width: 84, + heading: getItemsPriceWithModifier(), + ), + ], + ), + ), + AppSpaces.verticalLarge, + ], + ), + ), + ), + AppSpaces.verticalLarge, + ], + ), + ), + ); + }), + ); + } + + String getItemsPriceWithModifier() { + double price = 0.0; + for (var order in cashierOrder.cart!.orderDetails!) { + for (var item in order.items!) { + price += (item.quantity! * item.price); + if (item.selectedModifiers.isNotEmpty) { + for (var modi in item.selectedModifiers) { + price += modi.price; + } + } + } + } + cashierOrder.changeBalanceAmount = (cashierOrder.amount! - price); + print(cashierOrder.changeBalanceAmount.toString()); + + return price.toStringAsFixed(2); + } + + String getItemsPriceOnly() { + double price = 0.0; + for (var order in cashierOrder.cart!.orderDetails!) { + for (var item in order.items!) { + price += (item.quantity! * item.price); + } + } + + return price.toStringAsFixed(2); + } + + Widget getOrderTypeWidget(String selectedItem) { + return DropdownSearch( + enabled: false, + selectedItem: selectedItem, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 180)), + items: Constants.counterTypes, + itemAsString: (String u) => u, + onChanged: (String? data) {}, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), + ); + } + + Widget getStoreTables(String selectedItem) { + return DropdownSearch( + enabled: false, + selectedItem: selectedItem, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + items: Constants.counterTypes, + itemAsString: (String u) => u, + onChanged: (String? data) {}, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), + ); + } + + Widget getSubStoresWidget(String selectedItem) { + return DropdownSearch( + enabled: false, + selectedItem: selectedItem, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + items: Constants.counterTypes, + itemAsString: (String u) => u, + onChanged: (String? data) {}, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), + ); + } + + Widget getSelectedPaymentMode(String selectedItem) { + return DropdownSearch( + enabled: false, + selectedItem: selectedItem, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + items: Constants.counterTypes, + itemAsString: (String u) => u, + onChanged: (String? data) {}, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), + ); + } + + Widget getStatusDropdown(String selectedItem) { + return DropdownSearch( + enabled: false, + selectedItem: selectedItem, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + items: Constants.counterTypes, + itemAsString: (String u) => u, + onChanged: (String? data) {}, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), + ); + } + + Widget getBalanceOrChange(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: lang(context).balance_change, + ), + AppSpaces.verticalSmall, + CustomTextFieldForm( + readOnly: true, + key: Key(cashierOrder.changeBalanceAmount?.toString() ?? ''), + hintText: 'Enter Amount', + initialValue: cashierOrder.changeBalanceAmount?.toString() ?? '', + onChanged: (String value) {}, + ) + ], + ); + } + + getAmountWidget(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: lang(context).amount, + ), + AppSpaces.verticalSmall, + CustomTextFieldForm( + readOnly: true, + keyboardType: TextInputType.number, + hintText: 'Enter Amount', + initialValue: cashierOrder.amount?.toString() ?? '', + onChanged: (String value) {}, + ) + ], + ); + } + + Widget getCreatedAtWidget(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: lang(context).created_at, + ), + AppSpaces.verticalSmall, + CustomTextFieldForm( + hintText: '', + readOnly: true, + initialValue: + DataTimeFormat.getFormatDate(cashierOrder.createdAt ?? ''), + onChanged: (String value) {}, + ) + ], + ); + } + + getTableWidget(BuildContext context) { + return Visibility( + visible: cashierOrder.orderType!.toLowerCase().compareTo('dinein') == 0, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + AppSpaces.verticalMedium, + CustomOptionalTitle(hint: lang(context).table), + AppSpaces.verticalSmall, + getStoreTables(cashierOrder.table ?? ''), + AppSpaces.verticalMedium, + ], + )); + } + + Widget getDeliveryNotesWidget(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: lang(context).delivery_note, + ), + AppSpaces.verticalSmall, + CustomTextFieldForm( + readOnly: true, + hintText: 'Enter Delivery Note', + initialValue: cashierOrder.deliveryNotes ?? '', + onChanged: (String value) {}, + ), + ], + ); + } + + getPaymentModeWidget(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: lang(context).payment_mode, + ), + AppSpaces.verticalSmall, + getSelectedPaymentMode(cashierOrder.paymentMode ?? ''), + ], + ); + } + + getShowProductsWidget(StoreItems item, int position, int i) { + return CustomTextButtonIcon( + icon: Icons.arrow_drop_down, + heading: item.name.isEmpty ? 'Choose' : item.name, + onPressed: () {}, + ); + } + + getItemNotesWidget(String notes) { + return CustomTextFieldForm( + readOnly: true, + hintText: 'Enter item note', + initialValue: notes, + onChanged: (value) {}, + ); + } + + getItemQuantityWidget(String quantity) { + return CustomTextFieldForm( + readOnly: true, + hintText: 'Enter item quantity', + keyboardType: TextInputType.number, + initialValue: quantity, + onChanged: (value) {}, + ); + } + + getItemCostPriceWidget(String price) { + return CustomTextFieldForm( + readOnly: true, + hintText: 'Enter item price', + keyboardType: TextInputType.number, + initialValue: price, + onChanged: (value) {}, + ); + } + + getItemPriceWidget(StoreItems item) { + return ValueText( + (item.price * item.quantity!).toStringAsFixed(2), + ); + } +} diff --git a/lib/application/views/businessAccounts/widgets/PosReturnDamageListView.dart b/lib/application/views/businessAccounts/widgets/PosReturnDamageListView.dart new file mode 100644 index 0000000..bf1dc29 --- /dev/null +++ b/lib/application/views/businessAccounts/widgets/PosReturnDamageListView.dart @@ -0,0 +1,266 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/model/cart/GetHoldOrderModel.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/helpers/Utils.dart'; +import 'package:wosull/widgets/ActionPopUpContainer.dart'; +import 'package:wosull/widgets/CustomPopuoMenuButton.dart'; +import 'package:wosull/widgets/EmptyDataWidget.dart'; +import 'package:wosull/widgets/HeadingText.dart'; +import 'package:wosull/widgets/ListHeadingContainer.dart'; +import 'package:wosull/widgets/ValueText.dart'; + +class PosReturnDamageListView extends StatelessWidget { + List posOrders = []; + bool isPortrait = false; + bool? isOrder = false; + final void Function(ReturnOrderModel order) onView; + + PosReturnDamageListView( + {super.key, + required this.onView, + required this.posOrders, + required this.isPortrait, + this.isOrder}); + + @override + Widget build(BuildContext context) { + return posOrders.isEmpty + ? const EmptyDataWidget() + : Column( + children: [ + isPortrait + ? Container() + : ListHeadingContainer( + child: Row( + children: [ + Expanded( + child: HeadingText( + 'Reference Number', + )), + Expanded( + child: HeadingText( + 'Transaction Code', + )), + Expanded( + child: HeadingText(lang(context).order_number)), + Expanded( + child: HeadingText(lang(context).store_name)), + Expanded(child: HeadingText(lang(context).status)), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: + HeadingText(lang(context).created_on))), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: + HeadingText(lang(context).updated_on))), + SizedBox( + width: 56, + child: HeadingText(lang(context).action), + ), + ], + ), + ), + ListView.builder( + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (c, position) { + if (isPortrait) { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + color: MyColors.white, + child: Container( + padding: const EdgeInsets.fromLTRB(8, 0, 0, 8), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + child: Container( + padding: const EdgeInsets.only(top: 16), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + HeadingText( + 'Reference Number', + ), + AppSpaces.verticalMedium, + HeadingText( + 'Transaction Code', + ), + AppSpaces.verticalMedium, + HeadingText( + lang(context).order_number, + ), + AppSpaces.verticalMedium, + HeadingText( + lang(context).store_name, + ), + AppSpaces.verticalMedium, + HeadingText( + lang(context).status, + ), + AppSpaces.verticalMedium, + HeadingText( + lang(context).created_on, + ), + AppSpaces.verticalMedium, + HeadingText(lang(context).updated_on), + AppSpaces.verticalMedium, + ], + )), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + ValueText( + posOrders[position] + .reference! + .toString(), + ), + AppSpaces.verticalMedium, + ValueText( + posOrders[position].transactionId ?? '', + ), + AppSpaces.verticalMedium, + ValueText( + posOrders[position] + .orderNumber! + .toString(), + ), + AppSpaces.verticalMedium, + ValueText( + posOrders[position].storeId!.name ?? '', + ), + AppSpaces.verticalMedium, + Text( + posOrders[position] + .status! + .toCapitalized(), + style: posOrders[position].status == + 'completed' + ? ThemeText.textStyleValueGreen + : ThemeText.textStyleValueRed, + ), + AppSpaces.verticalMedium, + ValueText( + DataTimeFormat.getFormatDate( + posOrders[position].createdAt ?? + ''), + ), + AppSpaces.verticalMedium, + ValueText(DataTimeFormat.getFormatDate( + posOrders[position].updatedAt ?? '')), + AppSpaces.verticalMedium, + ], + )), + ], + ), + )), + getPopUpMenu(position) + ], + ), + ), + ); + } else { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: ListHeadingContainer( + child: Row( + children: [ + Expanded( + child: ValueText( + posOrders[position].reference!.toString(), + )), + Expanded( + child: ValueText( + posOrders[position].transactionId ?? '', + )), + Expanded( + child: ValueText( + posOrders[position].orderNumber!.toString(), + )), + Expanded( + child: ValueText( + posOrders[position].storeId!.name, + )), + Expanded( + child: Text( + posOrders[position].status!.toCapitalized(), + style: posOrders[position].status == 'completed' + ? ThemeText.textStyleValueGreen + : ThemeText.textStyleValueRed, + )), + Expanded( + child: ValueText( + DataTimeFormat.getFormatDate( + posOrders[position].createdAt!), + )), + Expanded( + child: ValueText( + DataTimeFormat.getFormatDate( + posOrders[position].updatedAt!), + )), + Padding( + padding: const EdgeInsets.all(4), + child: Align( + alignment: Alignment.centerRight, + child: ActionPopUpContainer( + child: getPopUpMenu(position), + ), + ), + ) + ], + ), + ), + ); + } + }, + itemCount: posOrders.length, + ) + ], + ); + } + + List> getPopUpMenuButton(String? status) { + return [ + PopupMenuItem( + value: 'view', + child: ValueText('View'), + ), + ]; + } + + void actionPopUpItemSelected(String value, ReturnOrderModel order) { + if (value == 'view') { + onView(order); + } + } + + getPopUpMenu(int position) { + return CustomPopupMenuButton( + onSelected: (String value) => + actionPopUpItemSelected(value, posOrders[position]), + items: getPopUpMenuButton(posOrders[position].status), + ); + } +} diff --git a/lib/application/views/create_order_module/CartVC.dart b/lib/application/views/create_order_module/CartVC.dart index 5fd3a55..865acaf 100644 --- a/lib/application/views/create_order_module/CartVC.dart +++ b/lib/application/views/create_order_module/CartVC.dart @@ -2,15 +2,17 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:provider/provider.dart'; +import 'package:wosull/application/interfaces/DrawerWidgetSelect.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; import 'package:wosull/application/model/CreateAndUpdateOrder.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; import 'package:wosull/application/model/store/StoreItemsResponse.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/theme/MyFonts.dart'; import 'package:wosull/application/utils/Constants.dart'; import 'package:wosull/application/views/create_order_module/states/CashierState.dart'; -import 'package:wosull/application/views/create_order_module/viewModels/CartViewModel.dart'; -import 'package:wosull/application/views/create_order_module/views/PrintInvoiceVC.dart'; +import 'package:wosull/application/views/create_order_module/viewModels/CreateOrderViewModel.dart'; +import 'package:wosull/application/views/create_order_module/views/PrintReceiptVC.dart'; import 'package:wosull/application/views/create_order_module/views/popups/ItemModifiersPopUp.dart'; import 'package:wosull/application/views/create_order_module/views/popups/PaymentOptionPopUpVC.dart'; import 'package:wosull/application/views/create_order_module/views/popups/SelectComboPopUp.dart'; @@ -20,12 +22,16 @@ import 'package:wosull/application/views/inventorymodule/comboviews/ComboInforma import 'package:wosull/application/views/popups/ViewItemNotesPopUp.dart'; import 'package:wosull/base/BaseStatefulState.dart'; import 'package:wosull/helpers/AppSpaces.dart'; -import 'package:wosull/helpers/ThemeImage.dart'; import 'package:wosull/helpers/Utils.dart'; +import 'package:wosull/main.dart'; +import 'package:wosull/widgets/CustomSimpleButton.dart'; +import 'package:wosull/widgets/EmptyDataWidget.dart'; class CartVC extends StatefulWidget { - CartVC({ + final DrawerWidgetSelect delegateDrawer; + const CartVC({ Key? key, + required this.delegateDrawer, }) : super(key: key); @override @@ -33,20 +39,20 @@ class CartVC extends StatefulWidget { } class _CartVCState extends BaseStatefulState { - var homeViewModel = CartViewModel(); + var homeViewModel = CreateOrderViewModel(); String createOrderId = ''; @override void initState() { super.initState(); - //openDB(); } @override Widget build(BuildContext context) { - homeViewModel = context.watch(); + homeViewModel = context.watch(); return Scaffold( + backgroundColor: MyColors.white, body: Padding( padding: const EdgeInsets.all(12), child: Column( @@ -56,7 +62,7 @@ class _CartVCState extends BaseStatefulState { Visibility( visible: count() || CreateAndUpdateOrder - .cartOrder.selectedTableName!.isNotEmpty, + .cartOrder.selectedTableName.isNotEmpty, child: Column( children: [ const SizedBox( @@ -73,7 +79,7 @@ class _CartVCState extends BaseStatefulState { CreateAndUpdateOrder .cartOrder.selectedTableName ?? "", - style: const TextStyle( + style: TextStyle( fontFamily: MyFonts.Medium, fontSize: MyFonts.normal, color: MyColors.black), @@ -82,33 +88,16 @@ class _CartVCState extends BaseStatefulState { Visibility( visible: count(), child: SizedBox( - width: 105, - child: ElevatedButton( - style: ElevatedButton.styleFrom( - elevation: 0, - shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.circular(8.0), - ), - backgroundColor: MyColors.fillRed, - minimumSize: - const Size.fromHeight(28), // NEW - ), + width: 90, + child: CustomSimpleButton( + height: 28, + textColor: MyColors.white, + backGroundColor: MyColors.fillRed, onPressed: () { homeViewModel.clearCart(); }, - child: Align( - alignment: Alignment.centerRight, - child: Text( - textAlign: TextAlign.end, - AppLocalizations.of(context)! - .clear_cart, - style: const TextStyle( - fontSize: MyFonts.normal, - color: MyColors.white, - fontFamily: MyFonts.Medium), - ), - ), + heading: AppLocalizations.of(context)! + .clear_cart, ))), ], ), @@ -143,8 +132,8 @@ class _CartVCState extends BaseStatefulState { Align( alignment: Alignment.centerRight, child: Text( - '${AppLocalizations.of(context)!.total_amount} ${CreateAndUpdateOrder.cartOrder.totalCartPrice ?? 0.0} ${sharedPrefs.currency}', - style: const TextStyle( + '${AppLocalizations.of(context)!.total_amount} ${CreateAndUpdateOrder.cartOrder.totalCartPrice?.toStringAsFixed(2) ?? 0.0} ${sharedPrefs.currency}', + style: TextStyle( fontWeight: FontWeight.bold, fontSize: MyFonts.normal, fontFamily: MyFonts.Bold, @@ -157,14 +146,26 @@ class _CartVCState extends BaseStatefulState { onTap: () async { if (CreateAndUpdateOrder.cartOrder.totalCartPrice != null) { + showProgress(); + if (isConnected) { + await homeViewModel.getCartIdFromServer(); + } else { + sharedPrefs.cartUniqueID = + int.parse('0${sharedPrefs.getCartUniqueId}'); + CreateAndUpdateOrder.cartOrder.cartUniqueId = + sharedPrefs.getCartUniqueId; + CreateAndUpdateOrder.cartOrder.createdAt = + DataTimeFormat.formatDateFromPicketINVOICE( + DateTime.now()); + } + + hideProgressBar(); showPaymentOption("", false, CreateAndUpdateOrder.cartOrder.totalCartPrice!); } }, ), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, Row( children: [ Flexible( @@ -246,7 +247,8 @@ class _CartVCState extends BaseStatefulState { future: homeViewModel.getCart(), builder: (c, snapshot) { if (snapshot.hasData) { - var cartItems = snapshot.data!; + var cartItems = snapshot.data ?? []; + if (cartItems.isNotEmpty) { homeViewModel.noteControllers.clear(); return ListView.builder( @@ -256,12 +258,13 @@ class _CartVCState extends BaseStatefulState { try { homeViewModel.noteControllers.add(TextEditingController( text: cartItems[position] - .noteForItem![cartItems[position].quantity - 1])); + .noteForItem![cartItems[position].quantity! - 1])); } catch (e) { if (kDebugMode) { print(e.toString()); } } + return CartItemView( storeItems: cartItems[position], onShowNotes: () { @@ -294,13 +297,7 @@ class _CartVCState extends BaseStatefulState { itemCount: cartItems.length, ); } else { - return Align( - alignment: Alignment.center, - child: Image.asset( - ThemeImage.emptyImage, - height: 128, - ), - ); + return const EmptyDataWidget(); } } else { return Center( @@ -313,12 +310,12 @@ class _CartVCState extends BaseStatefulState { Future increaseItem(StoreItems storeItem) async { if (storeItem.isCombo) { addComboPopup(storeItem, false); - } else if (storeItem.modifiers!.isNotEmpty) { + } else if (homeViewModel.getIsModifier(storeItem)) { showModifiers(storeItem, false); } else { showProgress(); var item = storeItem; - item.quantity = item.quantity + 1; + item.quantity = item.quantity! + 1; await homeViewModel.increaseItem(item, ""); checkState(); } @@ -380,10 +377,13 @@ class _CartVCState extends BaseStatefulState { if (result != null) { showProgress(); List data = result; - await homeViewModel.getCartIdFromServer(); - await homeViewModel.sendToKitchen(data[0], data[1], data[2], data[3], - data[4], data[5], data[6], orderId ?? ''); - await homeViewModel.getStoreDetails(); + if (isConnected) { + await homeViewModel.sendToKitchen(data[0], data[1], data[2], data[3], + data[4], data[5], data[6], data[7], data[8], data[9]); + await homeViewModel.getStoreDetails(); + } else { + await homeViewModel.updateOrderDb(data); + } checkState(); } } @@ -403,26 +403,19 @@ class _CartVCState extends BaseStatefulState { Future updateOrderStatus(String status) async { if (CreateAndUpdateOrder.cartOrder.totalCartPrice != null) { showProgress(); - await homeViewModel.getCartIdFromServer(); - await homeViewModel.sendToKitchen(false, status); - await homeViewModel.getStoreDetails(); + await homeViewModel.updateOrder(status); checkState(); } } - void upDateNoteForItem(StoreItems items, String note) async { - // items.noteForItem!.add(note); - CreateAndUpdateOrder.cartOrder.addNote(items, items.productId, note); - // createUpdateOrder(false); - } - void checkState() { Utils.hideProgressBar(context); if (homeViewModel.cashierState == CashierState.createOrder) { + widget.delegateDrawer.changeBottomNavigation(1); Navigator.push( context, MaterialPageRoute( - builder: (context) => PrintInvoiceVC( + builder: (context) => PrintReceiptVC( id: homeViewModel.createOrderId, )), ); @@ -440,9 +433,6 @@ class _CartVCState extends BaseStatefulState { } bool count() { - if (CreateAndUpdateOrder.cartOrder.orderDetails != null) { - return CreateAndUpdateOrder.cartOrder.orderDetails!.isNotEmpty; - } - return false; + return CreateAndUpdateOrder.cartOrder.orderDetails.isNotEmpty; } } diff --git a/lib/application/views/create_order_module/HoldOrderVC.dart b/lib/application/views/create_order_module/HoldOrderVC.dart index 8a5f7a7..f1c5fd0 100644 --- a/lib/application/views/create_order_module/HoldOrderVC.dart +++ b/lib/application/views/create_order_module/HoldOrderVC.dart @@ -1,62 +1,57 @@ -import 'dart:convert'; - import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:wosull/application/ViewModel/InventoryViewModel.dart'; +import 'package:provider/provider.dart'; import 'package:wosull/application/interfaces/DrawerWidgetSelect.dart'; -import 'package:wosull/application/localdb/SharedPrefs.dart'; import 'package:wosull/application/model/CreateAndUpdateOrder.dart'; -import 'package:wosull/application/model/SimpleResponsModel.dart'; -import 'package:wosull/application/model/cart/GetCartModel.dart'; -import 'package:wosull/application/model/cart/GetHoldOrderModel.dart'; import 'package:wosull/application/theme/MyColors.dart'; -import 'package:wosull/application/theme/MyFonts.dart'; +import 'package:wosull/application/utils/AppLoader.dart'; import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/create_order_module/states/CashierState.dart'; +import 'package:wosull/application/views/create_order_module/viewModels/CreateOrderViewModel.dart'; +import 'package:wosull/application/views/create_order_module/views/PrintReceiptVC.dart'; import 'package:wosull/application/views/create_order_module/views/popups/PaymentOptionPopUpVC.dart'; +import 'package:wosull/application/views/create_order_module/widgets/HoldOrderOffline.dart'; +import 'package:wosull/application/views/create_order_module/widgets/HoldOrderView.dart'; import 'package:wosull/base/BaseStatefulState.dart'; -import 'package:wosull/helpers/ThemeImage.dart'; +import 'package:wosull/helpers/Utils.dart'; +import 'package:wosull/main.dart'; +import 'package:wosull/widgets/EmptyDataWidget.dart'; class HoldOrderVC extends StatefulWidget { final DrawerWidgetSelect delegateDrawer; - HoldOrderVC({Key? key, required this.delegateDrawer}) : super(key: key); + const HoldOrderVC({Key? key, required this.delegateDrawer}) : super(key: key); @override State createState() => _HoldOrderVCState(); } class _HoldOrderVCState extends BaseStatefulState { - final homeViewModel = InventoryViewModel(); - - //late Future> orders; + var viewModel = CreateOrderViewModel(); @override void initState() { - // TODO: implement initState super.initState(); - //orders = getHoldOrders(); } @override Widget build(BuildContext context) { - return MaterialApp( - debugShowCheckedModeBanner: false, - home: Scaffold( - body: Padding( - padding: const EdgeInsets.all(12), - child: Column( - children: [ - Expanded(child: getHoldItem(context)), - ], - )), - ), + viewModel = context.watch(); + return Scaffold( + backgroundColor: MyColors.white, + body: Padding( + padding: const EdgeInsets.all(12), + child: Column( + children: [ + Expanded(child: isConnected ? getHoldItem() : getDbHoldItem()), + ], + )), ); } - Widget getHoldItem(BuildContext context) { + Widget getHoldItem() { return FutureBuilder( - future: getHoldOrders(), - builder: (c, snapshot) { + future: viewModel.getHoldOrders(), + builder: (ctx, snapshot) { if (snapshot.hasData) { var cartItems = snapshot.data!; if (cartItems.isNotEmpty) { @@ -64,367 +59,133 @@ class _HoldOrderVCState extends BaseStatefulState { physics: const AlwaysScrollableScrollPhysics(), shrinkWrap: true, itemBuilder: (c, position) { - return Container( - margin: const EdgeInsets.only(top: 8), - padding: const EdgeInsets.all(8), - decoration: BoxDecoration( - border: - Border.all(width: 1, color: MyColors.fillColor3), - borderRadius: - const BorderRadius.all(Radius.circular(12))), - child: Column( - children: [ - Container( - padding: const EdgeInsets.all(4), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - Expanded( - flex: 2, - child: Align( - alignment: Alignment.centerLeft, - child: Text( - '#Order ID: ${cartItems[position].uniqueId!}', - style: TextStyle( - fontSize: MyFonts.H2, - fontFamily: MyFonts.Bold, - color: MyColors.blueThemeColor), - ), - )), - Expanded( - flex: 2, - child: Align( - alignment: Alignment.centerRight, - child: Text( - cartItems[position].orderType!, - style: const TextStyle( - fontSize: MyFonts.H2, - fontFamily: MyFonts.Medium, - color: MyColors.textColorBlack), - ), - )) - ], - ), - ), - Container( - padding: const EdgeInsets.fromLTRB(4, 0, 4, 0), - child: Row( - children: [ - Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .payment_status, - style: const TextStyle( - fontSize: MyFonts.H2, - fontFamily: MyFonts.Medium, - color: MyColors.textColorBlack), - ), - ), - const SizedBox( - width: 4, - ), - Container( - decoration: const BoxDecoration( - color: MyColors.greenColor10, - borderRadius: BorderRadius.all( - Radius.circular(10.0))), - child: Padding( - padding: const EdgeInsets.all(10.0), - child: Text( - cartItems[position].paymentStatus! - ? AppLocalizations.of(context)! - .paid - : AppLocalizations.of(context)! - .un_paid, - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: MyFonts.normal, - color: MyColors.greenColor), - ))), - ], - ), - ), - Row( - mainAxisAlignment: MainAxisAlignment.end, - mainAxisSize: MainAxisSize.max, - children: [ - Expanded( - child: ElevatedButton( - style: ElevatedButton.styleFrom( - elevation: 0, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - backgroundColor: MyColors.greenColorEnable, - minimumSize: const Size.fromHeight(36), // NEW - ), - onPressed: () async { - final newOrder = cartItems[position]; - if (newOrder.paymentStatus! && - newOrder.status! == Constants.ready) { - completeOrder(newOrder.id!); - } else if (!newOrder.paymentStatus! && - newOrder.status! == Constants.ready) { - final result = await showDialog( - barrierColor: Colors.black26, - context: context, - builder: (context) { - return PaymentOptionPopUpVC( - status: cartItems[position].status!, - paymentStatus: cartItems[position] - .paymentStatus!, - cartAmount: cartItems[position] - .cart! - .orderDetails! - .first - .totalItemPrice!, - ); - }, - ); - - if (!mounted) return; - if (result != null) { - List data = result; - sharedPrefs.cartID = - cartItems[position].id!; - sendToKitchen( - data[0], - data[1], - data[2], - data[3], - data[4], - data[5], - data[6], - data[7]); - } - } else if (!newOrder.paymentStatus! && - newOrder.status! == Constants.ready) { - CreateAndUpdateOrder.cartOrder.clearCart(); - getCartById( - newOrder.cart!.id!, newOrder.id!); - } else { - CreateAndUpdateOrder.cartOrder.clearCart(); - getCartById( - newOrder.cart!.id!, newOrder.id!); - } - }, - child: Text( - getOrderText(cartItems[position]), - style: const TextStyle( - fontSize: MyFonts.normal, - color: MyColors.white, - fontFamily: MyFonts.Bold), - ), - )), - const SizedBox( - width: 10, - ), - Expanded( - child: ElevatedButton.icon( - style: ElevatedButton.styleFrom( - elevation: 0, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - backgroundColor: MyColors.fillRed, - minimumSize: const Size.fromHeight(36), // NEW - ), - onPressed: () { - updateOrderStatus( - cartItems[position].id!, "cancelled"); - }, - label: const Text( - "CANCEL", - style: TextStyle( - fontSize: MyFonts.normal, - color: MyColors.white, - fontFamily: MyFonts.Bold), - ), - icon: const Icon( - Icons.close, - color: MyColors.white, - ), - )) - ], - ) - ], - )); + return HoldOrderView( + holdOrder: cartItems[position], + onAction: () async { + showProgress(); + await viewModel.onHoldOrderAction(cartItems[position]); + checkState(); + }, + onCancel: () { + viewModel.updateOrderStatus( + cartItems[position].id!, Constants.cancelled); + }, + actionButtonHeading: + viewModel.getOrderText(context, cartItems[position]), + ); }, itemCount: cartItems.length, ); } else { - return Align( - alignment: Alignment.center, - child: Image.asset( - ThemeImage.emptyImage, - height: 128, - ), - ); + return const EmptyDataWidget(); } } else { - return const Center( - child: CircularProgressIndicator(), - ); + return AppLoader(); } }); } - void sendToKitchen(bool paymentStatus, String status, - [double? changeBalanceAmount, - String? deliveryNotes, - int? timer, - double? amount, - double? totalAmount, - String? paymentMode]) async { - progressDialogue(context); - Map data = {}; - if (paymentStatus) { - data = { - 'store_id': sharedPrefs.storeId, - 'orderId': sharedPrefs.cartID, - 'order_type': CreateAndUpdateOrder.cartOrder.orderType ?? "", - 'status': status, - 'payment_status': paymentStatus, - // 'orderId': CreateAndUpdateOrder.cartOrder.orderId!, - 'change_balance_amount': changeBalanceAmount, - 'delivery_notes': deliveryNotes, - 'timer': timer ?? 0, - 'amount': amount, - 'total_amount': totalAmount, - 'payment_mode': paymentMode ?? "Cash" - }; - } else { - data = { - 'store_id': sharedPrefs.storeId, - 'cart_id': sharedPrefs.cartID, - 'order_type': CreateAndUpdateOrder.cartOrder.orderType ?? "", - 'status': status, - 'payment_status': paymentStatus, - // 'orderId': CreateAndUpdateOrder.cartOrder.orderId!, - }; - } - - print(jsonEncode(data)); - - await homeViewModel.getData(Constants.CREATE_ORDER, data).then((value) { - hideProgressBar(); - final response = SimpleResponseModel.fromJson(value); - if (response.success) { - showMessage(response.message); - setState(() { - CreateAndUpdateOrder.cartOrder.clearCart(); - }); - } - }).onError((error, stackTrace) { - hideProgressBar(); - }); + Widget getDbHoldItem() { + return StreamBuilder>( + stream: objectbox.getHoldOrders(), + builder: (ctx, snapshot) { + if (snapshot.hasData) { + var cartItems = snapshot.data!; + if (cartItems.isNotEmpty) { + return ListView.builder( + physics: const AlwaysScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (c, position) { + return HoldOrderOfflineView( + holdOrder: cartItems[position], + onAction: () async { + showProgress(); + await viewModel.checkStatusOrderDb(cartItems[position]); + checkState(); + }, + onCancel: () async { + viewModel.cancelDbOrder(cartItems[position].obid); + }, + actionButtonHeading: + viewModel.getOrderTextDb(context, cartItems[position]), + ); + }, + itemCount: cartItems.length, + ); + } else { + return const EmptyDataWidget(); + } + } else { + return AppLoader(); + } + }, + ); } - void completeOrder(String id) async { - progressDialogue(context); - Map data = {}; - data = { - 'store_id': sharedPrefs.storeId, - 'orderId': id, - 'status': 'completed', - }; - - print(jsonEncode(data)); - - await homeViewModel.getData(Constants.CREATE_ORDER, data).then((value) { - hideProgressBar(); - print(value); - final response = SimpleResponseModel.fromJson(value); - if (response.success!) { - showMessage(response.message!); - setState(() {}); - } else { - showMessage(response.message!); - } - }).onError((error, stackTrace) { - hideProgressBar(); - }); + void showProgress() { + Utils.progressDialogue(context); } - void updateOrderStatus(String id, String status) async { - progressDialogue(context); - Map data = {}; - - data = { - 'store_id': sharedPrefs.storeId, - 'order_id': id, - 'status': status, - }; - print(jsonEncode(data)); + void checkState() { + Utils.hideProgressBar(context); + if (viewModel.cashierState == CashierState.getCartOnEdit) { + widget.delegateDrawer.changeBottomNavigation(2); + return; + } + if (viewModel.cashierState == CashierState.createOrder) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => PrintReceiptVC( + id: viewModel.createOrderId, + )), + ); + return; + } - await homeViewModel - .getData(Constants.UPDATE_ORDER_STATUS, data) - .then((value) { - hideProgressBar(); - final response = SimpleResponseModel.fromJson(value); - if (response.success!) { - showMessage(response.message!); - setState(() {}); + if (viewModel.cashierState == CashierState.showPayment) { + if (isConnected) { + showPaymentOption( + viewModel.completedOrder.status ?? '', + viewModel.completedOrder.paymentStatus ?? false, + viewModel.getTotalCartPrice( + viewModel.completedOrder.cart!.orderDetails ?? [])); + } else { + showPaymentOption( + CreateAndUpdateOrder.cartOrder.orderStatus ?? '', + CreateAndUpdateOrder.cartOrder.paymentStatus, + CreateAndUpdateOrder.cartOrder.totalCartPrice!); } - }).onError((error, stackTrace) { - hideProgressBar(); - }); - } - - Future getCartById(String s, String orderId) async { - progressDialogue(context); - Map data = { - 'store_id': sharedPrefs.storeId, - 'cart_id': s, - }; - await homeViewModel - .getData(Constants.GET_STORE_ORDER_BY_ID, data) - .then((value) async { - hideProgressBar(); - final response = GetCartModel.fromJson(value); - if (response.success!) { - setState(() { - CreateAndUpdateOrder.cartOrder = response.cart!; - sharedPrefs.cartID = response.cart!.cartId!; - CreateAndUpdateOrder.cartOrder.orderId = orderId; - widget.delegateDrawer.changeBottomNavigation(11); - }); - } - }).onError((error, stackTrace) {}); + return; + } } - Future> getHoldOrders() async { - var items = []; + Future showPaymentOption( + String orderStatus, bool paymentStatus, double cartAmount) async { + final result = await showDialog( + barrierColor: Colors.black26, + context: context, + builder: (context) { + return PaymentOptionPopUpVC( + status: orderStatus, + paymentStatus: paymentStatus, + cartAmount: cartAmount, + ); + }, + ); - await homeViewModel - .getData(Constants.GET_STORE_ORDER, Constants.getStorePayload()) - .then((value) { - final response = GetHoldOrderModel.fromJson(value); - if (response.success != null) { - items.addAll(response.orderModel!); + if (result != null) { + showProgress(); + List data = result; + if (isConnected) { + await viewModel.sendToKitchen(data[0], data[1], data[2], data[3], + data[4], data[5], data[6], data[7], data[8], data[9]); + await viewModel.getStoreDetails(); + } else { + await viewModel.updateOrderDb(data); } - }).onError((error, stackTrace) { - items = []; - }); - - return items; - } - - String getOrderText(OrderModel cartItem) { - if (cartItem.paymentStatus! && cartItem.status! == Constants.ready) { - return AppLocalizations.of(context)!.done; - } else if (!cartItem.paymentStatus! && - cartItem.status! == Constants.ready) { - return AppLocalizations.of(context)!.pay; - } else if (!cartItem.paymentStatus! && - cartItem.status! == Constants.ready) { - return AppLocalizations.of(context)!.edit; - } else { - return AppLocalizations.of(context)!.edit; + checkState(); } } } diff --git a/lib/application/views/create_order_module/repo/CreateOrderRepository.dart b/lib/application/views/create_order_module/repo/CreateOrderRepository.dart new file mode 100644 index 0000000..2f58315 --- /dev/null +++ b/lib/application/views/create_order_module/repo/CreateOrderRepository.dart @@ -0,0 +1,254 @@ +import 'dart:convert'; +import 'dart:developer'; + +import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/application/model/Combo/GetComboModel.dart'; +import 'package:wosull/application/model/Combo/SearchComboItemModel.dart'; +import 'package:wosull/application/model/CreateAndUpdateOrder.dart'; +import 'package:wosull/application/model/SimpleResponsModel.dart'; +import 'package:wosull/application/model/cart/GetCartModel.dart'; +import 'package:wosull/application/model/cart/GetHoldOrderModel.dart'; +import 'package:wosull/application/model/inventory/ItemSubCategoryResponse.dart'; +import 'package:wosull/application/model/inventory/category/ItemCategoryResponse.dart'; +import 'package:wosull/application/model/store/GetStoreOrderModel.dart'; +import 'package:wosull/application/model/store/SearchItemsResponse.dart'; +import 'package:wosull/application/model/store/StoreDetails.dart'; +import 'package:wosull/application/model/store/StoreItemsResponse.dart'; +import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/main.dart'; + +class CreateOrderRepository { + Future getStoreDetails() async { + final value = await APIManager() + .fetchData(Constants.getStoreDetails, Constants.getStorePayload()); + return StoreDetails.fromJson(value); + } + + Future fetchCategories( + Map data) async { + final response = + await APIManager().fetchData(Constants.GET_STORE_CATEGORY_LIST, data); + return ItemCategoryResponse.fromJson(response); + } + + Future getSub(Map data) async { + final response = await APIManager().fetchData(Constants.GET_PRODUCTS, data); + return ItemSubCategoryResponse.fromJson(response); + } + + Future getItems(Map data) async { + final value = await APIManager().fetchData(Constants.GET_ITEMS_URL, data); + return StoreItemsResponse.fromJson(value); + } + + Future> getComboData(String categoryID) async { + var items = []; + Map data = { + 'store_id': sharedPrefs.storeId, + 'category_id': categoryID, + }; + + await APIManager().fetchData(Constants.GET_COMBO_GROUP, data).then((value) { + final response = GetComboModel.fromJson(value); + if (response.success != null) { + if (response.success!) { + items.addAll(response.combos!); + } + } + }).onError((error, stackTrace) {}); + + return items; + } + + Future> searchItems(String searchValue) async { + var searchItems = []; + if (!isConnected) { + searchItems.clear(); + searchItems.addAll(objectbox.searchItems(searchValue)); + } else { + Map data = { + 'store_id': sharedPrefs.storeId, + 'search_value': searchValue, + 'page': 1 + }; + await APIManager() + .fetchData(Constants.SEARCH_ALL_ITEMS, data) + .then((value) async { + searchItems.clear(); + final response = SearchItemResponse.fromJson(value); + if (response.success!) { + if (response.item!.isNotEmpty) { + if (response.item!.first.storeItems!.isNotEmpty) { + searchItems.addAll(response.item!.first.storeItems!); + } + } + } + }).onError((error, stackTrace) {}); + } + + return searchItems; + } + + Future> searchCombo(String searchValue) async { + var items = []; + Map data = { + 'store_id': sharedPrefs.storeId, + 'search_value': searchValue, + 'page': 1 + }; + + await APIManager() + .fetchData(Constants.SEARCH_ALL_COMBO, data) + .then((value) { + final response = SearchComboItemModel.fromJson(value); + if (response.success!) { + if (response.item!.isNotEmpty) { + if (response.item!.first.storeItems!.isNotEmpty) { + items.addAll(response.item!.first.storeItems!); + } + } + } + }).onError((error, stackTrace) {}); + + return items; + } + + Future getCartIdFromServer() async { + final map = CreateAndUpdateOrder.cartOrder.toJson(); + final response = + await APIManager().fetchData(Constants.CREATE_UPDATE_ORDER, map); + return NewCartModel.fromJson(response); + } + + Future completeOrder(String id) async { + Map data = { + 'store_id': sharedPrefs.storeId, + 'orderId': id, + 'status': Constants.completed, + }; + final response = await APIManager().fetchData(Constants.CREATE_ORDER, data); + return SimpleResponseModel.fromJson(response); + } + + Future updateOrderStatus( + String id, String status) async { + Map data = { + 'store_id': sharedPrefs.storeId, + 'order_id': id, + 'status': status, + }; + + final response = + await APIManager().fetchData(Constants.UPDATE_ORDER_STATUS, data); + return SimpleResponseModel.fromJson(response); + } + + Future> getHoldOrders() async { + var items = []; + await APIManager() + .fetchData(Constants.GET_STORE_ORDER, Constants.getStorePayload()) + .then((value) { + final response = GetHoldOrderModel.fromJson(value); + if (response.success != null) { + items.addAll(response.orderModel!); + } + }).onError((error, stackTrace) {}); + + return items; + } + + Future sendToKitchen(bool paymentStatus, String status, + [double? changeBalanceAmount, + String? deliveryNotes, + int? timer, + double? amount, + double? totalAmount, + String? paymentMode, + double? totalDiscount, + String? discountId]) async { + Map data = {}; + if (paymentStatus) { + if (status == Constants.ready) { + data = { + 'billing_counter_id': sharedPrefs.billingCounterId, + 'store_id': sharedPrefs.storeId, + // 'orderId': orderId, + 'order_type': CreateAndUpdateOrder.cartOrder.orderType, + 'status': status, + 'payment_mode': paymentMode, + 'payment_status': paymentStatus, + 'change_balance_amount': changeBalanceAmount, + 'delivery_notes': deliveryNotes, + 'timer': timer, + 'amount': amount, + 'total_amount': totalAmount, + 'total_discount': totalDiscount, + 'discountId': discountId, + }; + } else if (status == Constants.completed) { + data = { + 'payment_mode': paymentMode, + 'total_discount': totalDiscount, + 'discountId': discountId, + 'store_id': sharedPrefs.storeId, + 'cart_id': sharedPrefs.cartID, + 'orderId': CreateAndUpdateOrder.cartOrder.orderId, + 'order_type': CreateAndUpdateOrder.cartOrder.orderType, + 'status': status, + 'payment_status': paymentStatus, + 'change_balance_amount': changeBalanceAmount, + 'delivery_notes': deliveryNotes, + 'timer': timer, + 'amount': amount, + 'total_amount': totalAmount, + }; + if (sharedPrefs.cartID.isEmpty) { + data.remove('cart_id'); + } else { + data.remove('orderId'); + } + } else { + data = { + 'payment_mode': paymentMode, + 'total_discount': totalDiscount, + 'discountId': discountId, + 'billing_counter_id': sharedPrefs.billingCounterId, + 'store_id': sharedPrefs.storeId, + 'cart_id': sharedPrefs.cartID, + 'status': status, + 'payment_status': paymentStatus, + 'change_balance_amount': changeBalanceAmount, + 'delivery_notes': deliveryNotes, + 'timer': timer, + 'amount': amount, + 'total_amount': totalAmount, + }; + } + } else { + data = { + 'billing_counter_id': sharedPrefs.billingCounterId, + 'store_id': sharedPrefs.storeId, + 'cart_id': sharedPrefs.cartID, + 'order_type': CreateAndUpdateOrder.cartOrder.orderType, + 'status': status, + 'payment_status': paymentStatus, + // 'orderId': CreateAndUpdateOrder.cartOrder.orderId!, + }; + } + log(jsonEncode(data)); + final response = await APIManager().fetchData(Constants.CREATE_ORDER, data); + return GetStoreOrderModel.fromJson(response); + } + + Future getCartById(String cartId) async { + Map data = { + 'store_id': sharedPrefs.storeId, + 'cart_id': cartId, + }; + + final response = + await APIManager().fetchData(Constants.GET_STORE_ORDER_BY_ID, data); + return GetCartModel.fromJson(response); + } +} diff --git a/lib/application/views/create_order_module/viewModels/CartViewModel.dart b/lib/application/views/create_order_module/viewModels/CartViewModel.dart index ff0bc78..8a975ab 100644 --- a/lib/application/views/create_order_module/viewModels/CartViewModel.dart +++ b/lib/application/views/create_order_module/viewModels/CartViewModel.dart @@ -8,10 +8,11 @@ import 'package:objectbox/objectbox.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; import 'package:wosull/application/model/Combo/GetComboModel.dart'; import 'package:wosull/application/model/CreateAndUpdateOrder.dart'; -import 'package:wosull/application/model/Modifiers/GetModifiersModel.dart'; +import 'package:wosull/application/model/Modifiers/Modifier.dart'; import 'package:wosull/application/model/SimpleResponsModel.dart'; import 'package:wosull/application/model/cart/GetCartModel.dart'; import 'package:wosull/application/model/cart/GetHoldOrderModel.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; import 'package:wosull/application/model/createOrder/OrderDetails.dart'; import 'package:wosull/application/model/store/GetStoreOrderModel.dart'; import 'package:wosull/application/model/store/StoreDetails.dart'; @@ -20,6 +21,7 @@ import 'package:wosull/application/network/APIManager.dart'; import 'package:wosull/application/utils/Constants.dart'; import 'package:wosull/application/views/create_order_module/states/CashierState.dart'; import 'package:wosull/helpers/Utils.dart'; +import 'package:wosull/main.dart'; class CartViewModel with ChangeNotifier { List noteControllers = []; @@ -40,6 +42,7 @@ class CartViewModel with ChangeNotifier { .then((value) { final response = StoreDetails.fromJson(value); if (response.success) { + sharedPrefs.cartUniqueID = response.store.cartUniqueID; CreateAndUpdateOrder.cartOrder.cartUniqueId = response.store.cartUniqueID; } @@ -47,6 +50,25 @@ class CartViewModel with ChangeNotifier { }).onError((error, stackTrace) {}); } + bool getIsModifier(StoreItems storeItem) { + // bool value = false; + var list = []; + //0 true + //1 false + if (storeItem.modifiers.isEmpty) { + return false; + } else { + for (var modifiers in storeItem.modifiers) { + if (modifiers.options.isEmpty) { + list.add(0); + } else { + list.add(1); + } + } + } + return list.contains(1); + } + void completeOrder(String id) async { Map data = {}; data = { @@ -73,10 +95,10 @@ class CartViewModel with ChangeNotifier { CreateAndUpdateOrder.cartOrder.selectedTableName ?? ""; CreateAndUpdateOrder.cartOrder.orderType = orderType; CreateAndUpdateOrder.cartOrder.selectedTableName = selectedTableName; - final map = CreateAndUpdateOrder.cartOrder.toJson(); - //showing for debug - //TODO need to remove - log(jsonEncode(map)); + // final map = CreateAndUpdateOrder.cartOrder.toJ(); + // //showing for debug + // //TODO need to remove + // log(jsonEncode(map)); _cashierState = CashierState.makeUpdateOrder; notifyListeners(); return true; @@ -92,7 +114,6 @@ class CartViewModel with ChangeNotifier { await APIManager() .fetchData(Constants.CREATE_UPDATE_ORDER, map) .then((value) { - print(value); final response = NewCartModel.fromJson(value); if (response.success!) { @@ -100,12 +121,9 @@ class CartViewModel with ChangeNotifier { updateCartValues(response); sharedPrefs.cartID = response.cartId ?? ""; } - }).onError((error, stackTrace) { - print('error' + error.toString()); - }); + }).onError((error, stackTrace) {}); } catch (e) { _cashierState = CashierState.error; - print(e); } } @@ -125,7 +143,6 @@ class CartViewModel with ChangeNotifier { Future increaseItem(StoreItems item, String note) async { item.noteForItem!.add(note); - print(item.noteForItem!.length); CreateAndUpdateOrder.cartOrder .increaseDecreaseItemQuantity(item, item.productId); await createUpdateOrder(); @@ -136,7 +153,7 @@ class CartViewModel with ChangeNotifier { removeNoteFromList(item); CreateAndUpdateOrder.cartOrder.removeItem(item, item.productId); - if (CreateAndUpdateOrder.cartOrder.orderDetails!.isEmpty) { + if (CreateAndUpdateOrder.cartOrder.orderDetails.isEmpty) { await clearCart(); } else { await createUpdateOrder(); @@ -147,7 +164,7 @@ class CartViewModel with ChangeNotifier { if (item.quantity == 1) { removeNoteFromList(item); CreateAndUpdateOrder.cartOrder.removeItem(item, item.productId); - if (CreateAndUpdateOrder.cartOrder.orderDetails!.isEmpty) { + if (CreateAndUpdateOrder.cartOrder.orderDetails.isEmpty) { await clearCart(); } else { await createUpdateOrder(); @@ -157,8 +174,8 @@ class CartViewModel with ChangeNotifier { .removeModifierOnDecrease(item, item.productId); item.noteForItem = CreateAndUpdateOrder.cartOrder.getNotes(item, item.productId); - item.quantity = item.quantity - 1; - item.noteForItem!.removeAt(item.quantity); + item.quantity = item.quantity! - 1; + item.noteForItem!.removeAt(item.quantity!); CreateAndUpdateOrder.cartOrder .increaseDecreaseItemQuantity(item, item.productId); @@ -167,9 +184,9 @@ class CartViewModel with ChangeNotifier { } } - Future> getCart() async { - var items = []; - for (var item in CreateAndUpdateOrder.cartOrder.orderDetails!) { + Future?> getCart() async { + var items = []; + for (var item in CreateAndUpdateOrder.cartOrder.orderDetails) { // items.ad items.addAll(item.items); } @@ -204,99 +221,19 @@ class CartViewModel with ChangeNotifier { // }); } - Future sendToKitchen(bool paymentStatus, String status, - [double? changeBalanceAmount, - String? deliveryNotes, - int? timer, - double? amount, - double? totalAmount, - String? orderId]) async { - Map data = {}; - if (paymentStatus) { - if (status == Constants.ready) { - data = { - 'store_id': sharedPrefs.storeId, - 'orderId': orderId, - 'order_type': CreateAndUpdateOrder.cartOrder.orderType, - 'status': status, - 'payment_status': paymentStatus, - 'change_balance_amount': changeBalanceAmount, - 'delivery_notes': deliveryNotes, - 'timer': timer, - 'amount': amount, - 'total_amount': totalAmount, - }; - } else { - data = { - 'store_id': sharedPrefs.storeId, - 'cart_id': sharedPrefs.cartID, - 'order_type': CreateAndUpdateOrder.cartOrder.orderType, - 'status': status, - 'payment_status': paymentStatus, - 'orderId': CreateAndUpdateOrder.cartOrder.orderId!, - 'change_balance_amount': changeBalanceAmount, - 'delivery_notes': deliveryNotes, - 'timer': timer, - 'amount': amount, - 'total_amount': totalAmount, - }; - } - } else { - data = { - 'store_id': sharedPrefs.storeId, - 'cart_id': sharedPrefs.cartID, - 'order_type': CreateAndUpdateOrder.cartOrder.orderType, - 'status': status, - 'payment_status': paymentStatus, - // 'orderId': CreateAndUpdateOrder.cartOrder.orderId!, - }; - } - - print(jsonEncode(data)); - - await APIManager() - .fetchData(Constants.CREATE_ORDER, data) - .then((value) async { - final response = GetStoreOrderModel.fromJson(value); - if (response.success!) { - if (paymentStatus) { - _cashierState = CashierState.createOrder; - } else { - if (status == Constants.holdOrder) { - _cashierState = CashierState.holdOrder; - } else { - _cashierState = CashierState.sendToKitchen; - } - } - - createOrderId = response.orderModel!.id ?? ''; - await clearCartData(); - notifyListeners(); - } - }).onError((error, stackTrace) { - print(stackTrace.toString()); - _cashierState = CashierState.error; - notifyListeners(); - - // Utils. hideProgressBar(context); - }); - } - bool count() { if (CreateAndUpdateOrder.cartOrder.orderDetails != null) { - return CreateAndUpdateOrder.cartOrder.orderDetails!.isNotEmpty; + return CreateAndUpdateOrder.cartOrder.orderDetails.isNotEmpty; } return false; } double getTotalCartPrice(List orderDetails) { double totalPrice = 0.0; - for (int i = 0; i < orderDetails.length; i++) { final itemPrice = orderDetails[i].totalItemPrice!; totalPrice += itemPrice; } - return totalPrice; } @@ -375,25 +312,19 @@ class CartViewModel with ChangeNotifier { CreateAndUpdateOrder.cartOrder = response.cart!; CreateAndUpdateOrder.cartOrder.orderType = orderType; CreateAndUpdateOrder.cartOrder.selectedTableName = selectedTableName; - // CreateAndUpdateOrder.cartOrder.orderType = services[selectedService].name ?? ""; - // CreateAndUpdateOrder.cartOrder.selectedTableName = selectedTable.tableName ?? ""; - //notifyListeners(); } void saveNewCartOnEdit(GetCartModel response, String orderId) { CreateAndUpdateOrder.cartOrder = response.cart!; CreateAndUpdateOrder.cartOrder.orderId = orderId; - // CreateAndUpdateOrder.cartOrder.orderType = services[selectedService].name!; - // CreateAndUpdateOrder.cartOrder.selectedTableName = selectedTable.tableName!; sharedPrefs.cartID = response.cart!.cartId!; notifyListeners(); } StoreItems addUpdateCombo(StoreItems item) { - for (int i = 0; i < item.selectedCombos!.length; i++) { - item.selectedCombos![i].qtyIdx = item.quantity; + for (int i = 0; i < item.selectedCombos.length; i++) { + item.selectedCombos[i].qtyIdx = item.quantity; } - return item; } @@ -401,11 +332,11 @@ class CartViewModel with ChangeNotifier { StoreItems item, List selectedModifier) { for (int i = 0; i < selectedModifier.length; i++) { var modifier = selectedModifier[i].selected; - for (int j = 0; j < modifier!.length; j++) { + for (int j = 0; j < modifier.length; j++) { var option = modifier[j]; option.modifierName = selectedModifier[i].name; - option.qtyIdx = item.quantity; - item.selectedModifiers!.add(option); + option.qtyIdx = item.quantity ?? 1; + item.selectedModifiers.add(option); } } @@ -415,7 +346,7 @@ class CartViewModel with ChangeNotifier { Future setCombos(result, bool isItemAdd, StoreItems item) async { //if user choose any combos _cashierState = CashierState.uninitialized; - item.quantity = item.quantity + 1; + item.quantity = item.quantity! + 1; item.isCombo = true; if (result != null) { @@ -433,12 +364,11 @@ class CartViewModel with ChangeNotifier { Future setModifier(result, bool isItemAdd, StoreItems item) async { //if user choose any modifier - print('hrere'); _cashierState = CashierState.uninitialized; if (isItemAdd) { item.quantity = 1; } else { - item.quantity = item.quantity + 1; + item.quantity = item.quantity! + 1; } if (result != null) { increaseItemWithModifier(item, result); @@ -447,7 +377,6 @@ class CartViewModel with ChangeNotifier { item.selectedModifiers = ToMany( items: CreateAndUpdateOrder.cartOrder .getModifiers(item, item.productId)); - print('here'); item.noteForItem = CreateAndUpdateOrder.cartOrder.getNotes(item, item.productId); increaseItem(item, ""); @@ -459,4 +388,133 @@ class CartViewModel with ChangeNotifier { CreateAndUpdateOrder.cartOrder.getItemIndexWithId(item, item.productId); noteControllers.removeAt(cartIndex); } + + updateOrder(String status) async { + if (isConnected) { + await getCartIdFromServer(); + await sendToKitchen(false, status); + await getStoreDetails(); + } else { + await addOrderToDb(status); + } + } + + addOrderToDb(String status) async { + sharedPrefs.cartUniqueID = int.parse('0${sharedPrefs.getCartUniqueId}'); + CreateAndUpdateOrder.cartOrder.cartUniqueId = sharedPrefs.getCartUniqueId; + CreateAndUpdateOrder.cartOrder.orderStatus = status; + CreateAndUpdateOrder.cartOrder.paymentStatus = false; + CreateAndUpdateOrder.cartOrder.createdAt = + DataTimeFormat.formatDateFromPicketINVOICE(DateTime.now()); + await objectbox.addOrder(CreateAndUpdateOrder.cartOrder); + await clearCart(); + increaseOrderNumberOffline(); + } + + updateOrderDb(data) async { + bool paymentStatus = data[0]; + String status = data[1]; + CreateAndUpdateOrder.cartOrder.orderStatus = status; + CreateAndUpdateOrder.cartOrder.paymentStatus = paymentStatus; + print(paymentStatus); + if (paymentStatus) { + CreateAndUpdateOrder.cartOrder.orderStatus = Constants.preparing; + CreateAndUpdateOrder.cartOrder.changeBalanceAmount = data[2]; + CreateAndUpdateOrder.cartOrder.deliveryNotes = data[3]; + CreateAndUpdateOrder.cartOrder.timer = data[4]; + CreateAndUpdateOrder.cartOrder.amount = data[5]; + CreateAndUpdateOrder.cartOrder.totalAmount = data[6]; + CreateAndUpdateOrder.cartOrder.paymentMode = data[7]; + CreateAndUpdateOrder.cartOrder.totalDiscount = data[8]; + CreateAndUpdateOrder.cartOrder.discountId = data[9]; + } + await objectbox.addOrder(CreateAndUpdateOrder.cartOrder); + // await objectbox.updateOrder(CreateAndUpdateOrder.cartOrder); + createOrderId = CreateAndUpdateOrder.cartOrder.cartUniqueId.toString(); + increaseOrderNumberOffline(); + await clearCart(); + _cashierState = CashierState.createOrder; + } + + void increaseOrderNumberOffline() { + sharedPrefs.cartUniqueID = CreateAndUpdateOrder.cartOrder.cartUniqueId + 1; + } + + Future sendToKitchen(bool paymentStatus, String status, + [double? changeBalanceAmount, + String? deliveryNotes, + int? timer, + double? amount, + double? totalAmount, + String? paymentMode, + double? totalDiscount, + String? discountId]) async { + Map data = {}; + if (paymentStatus) { + if (status == Constants.ready) { + data = { + 'billing_counter_id': sharedPrefs.billingCounterId, + 'store_id': sharedPrefs.storeId, + 'order_type': CreateAndUpdateOrder.cartOrder.orderType, + 'status': status, + 'payment_status': paymentStatus, + 'change_balance_amount': changeBalanceAmount, + 'delivery_notes': deliveryNotes, + 'timer': timer, + 'amount': amount, + 'total_amount': totalAmount, + 'total_discount': totalDiscount, + 'discountId': discountId, + }; + } else { + data = { + 'store_id': sharedPrefs.storeId, + 'cart_id': sharedPrefs.cartID, + 'order_type': CreateAndUpdateOrder.cartOrder.orderType, + 'status': status, + 'billing_counter_id': sharedPrefs.billingCounterId, + 'payment_status': paymentStatus, + 'change_balance_amount': changeBalanceAmount, + 'delivery_notes': deliveryNotes, + 'timer': timer, + 'amount': amount, + 'total_amount': totalAmount, + 'total_discount': totalDiscount, + 'discountId': discountId, + }; + } + } else { + data = { + 'billing_counter_id': sharedPrefs.billingCounterId, + 'store_id': sharedPrefs.storeId, + 'cart_id': sharedPrefs.cartID, + 'order_type': CreateAndUpdateOrder.cartOrder.orderType, + 'status': status, + 'payment_status': paymentStatus, + }; + } + + await APIManager() + .fetchData(Constants.CREATE_ORDER, data) + .then((value) async { + final response = GetStoreOrderModel.fromJson(value); + if (response.success!) { + if (paymentStatus) { + _cashierState = CashierState.createOrder; + } else { + if (status == Constants.holdOrder) { + _cashierState = CashierState.holdOrder; + } else { + _cashierState = CashierState.sendToKitchen; + } + } + createOrderId = response.orderModel!.id ?? ''; + await clearCartData(); + notifyListeners(); + } + }).onError((error, stackTrace) { + _cashierState = CashierState.error; + notifyListeners(); + }); + } } diff --git a/lib/application/views/create_order_module/viewModels/CounterCloseViewMdoel.dart b/lib/application/views/create_order_module/viewModels/CounterCloseViewMdoel.dart new file mode 100644 index 0000000..b33bb27 --- /dev/null +++ b/lib/application/views/create_order_module/viewModels/CounterCloseViewMdoel.dart @@ -0,0 +1,66 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/application/utils/CRUDOperatoinState.dart'; +import 'package:wosull/application/views/authModule/checkinViews/repo/CheckInRepository.dart'; +import 'package:wosull/helpers/Utils.dart'; + +class CounterCloseViewModel with ChangeNotifier { + final repository = CheckInRepository(); + var isLoading = false; + var cashAmount = ''; + var creditAmount = ''; + + var _crudOperation = CRUDOperationState.uninitialized; + + CRUDOperationState get crudOperation => _crudOperation; + + void setState(CRUDOperationState state) { + _crudOperation = state; + } + + void setLoading(bool value) { + isLoading = value; + notifyListeners(); + } + + Future getBusinessRegisterById() async { + await repository.getBusinessRegisterById().then((value) { + if (value.success) { + cashAmount = + value.businessRegister.expectedCashAmount.toStringAsFixed(2); + creditAmount = + value.businessRegister.expectedCreditAmount.toStringAsFixed(2); + } + }).onError((error, stackTrace) {}); + notifyListeners(); + } + + Future isValidate() async { + if (cashAmount.isEmpty) { + Utils.showMessage('Please fill cash amount'); + } else if (creditAmount.isEmpty) { + Utils.showMessage('Please fill credit amount'); + } else { + await updateBusinessRegister(); + } + } + + Future updateBusinessRegister() async { + setLoading(true); + Map data = { + 'businessRegisterId': sharedPrefs.businessRegisterId, + 'cashAmount': double.parse(cashAmount), + 'creditAmount': double.parse(creditAmount), + }; + await repository.updateBusinessRegister(data).then((value) { + sharedPrefs.billingCounterId = ''; + sharedPrefs.billingCounterName = ''; + if (value.success) { + setState(CRUDOperationState.add); + } else { + setState(CRUDOperationState.error); + } + setLoading(false); + }).onError((error, stackTrace) {}); + } +} diff --git a/lib/application/views/create_order_module/viewModels/CreateOrderViewModel.dart b/lib/application/views/create_order_module/viewModels/CreateOrderViewModel.dart index abd473d..0e18132 100644 --- a/lib/application/views/create_order_module/viewModels/CreateOrderViewModel.dart +++ b/lib/application/views/create_order_module/viewModels/CreateOrderViewModel.dart @@ -1,5 +1,4 @@ import 'dart:convert'; -import 'dart:developer'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -8,24 +7,18 @@ import 'package:objectbox/objectbox.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; import 'package:wosull/application/model/Combo/GetComboModel.dart'; import 'package:wosull/application/model/CreateAndUpdateOrder.dart'; -import 'package:wosull/application/model/Modifiers/GetModifiersModel.dart'; -import 'package:wosull/application/model/SimpleResponsModel.dart'; +import 'package:wosull/application/model/Modifiers/Modifier.dart'; import 'package:wosull/application/model/cart/GetCartModel.dart'; import 'package:wosull/application/model/cart/GetHoldOrderModel.dart'; import 'package:wosull/application/model/converters/DataTimeFormat.dart'; import 'package:wosull/application/model/createOrder/OrderDetails.dart'; import 'package:wosull/application/model/inventory/ItemSubCategoryResponse.dart'; -import 'package:wosull/application/model/inventory/SearchComboItemModel.dart'; import 'package:wosull/application/model/inventory/category/ItemCategory.dart'; -import 'package:wosull/application/model/inventory/category/ItemCategoryResponse.dart'; -import 'package:wosull/application/model/store/GetStoreOrderModel.dart'; -import 'package:wosull/application/model/store/SearchItemsResponse.dart'; -import 'package:wosull/application/model/store/StoreDetails.dart'; import 'package:wosull/application/model/store/StoreItemsResponse.dart'; import 'package:wosull/application/model/store/StoreServiceModel.dart'; import 'package:wosull/application/model/tables/GetStoreTable.dart'; -import 'package:wosull/application/network/APIManager.dart'; import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/create_order_module/repo/CreateOrderRepository.dart'; import 'package:wosull/application/views/create_order_module/states/CashierState.dart'; import 'package:wosull/helpers/Utils.dart'; import 'package:wosull/main.dart'; @@ -48,17 +41,17 @@ class CreateOrderViewModel with ChangeNotifier { var subCategoryItems = []; late ItemSubCategory itemSubCategory; - final searchController = TextEditingController(); + var searchController = ''; - bool isInternetConnected = false; late var selectedTable = StoreTable(); + var repository = CreateOrderRepository(); + String tableName = ''; - //Store store = Store(name: ""); int categoryPosition = 0; int selectedSubCategoryPosition = 0; - int selectedService = 1; + int selectedService = 0; String selectedDeliveryPartner = ''; String selectedProductId = ""; @@ -80,6 +73,7 @@ class CreateOrderViewModel with ChangeNotifier { OrderModel get completedOrder => _newOrder; void disposeData() { + searchController = ''; categoryPosition = 0; itemCategories.clear(); filteredItems.clear(); @@ -119,26 +113,19 @@ class CreateOrderViewModel with ChangeNotifier { } Future getStoreDetails() async { - await APIManager() - .fetchData(Constants.getStoreDetails, Constants.getStorePayload()) - .then((value) { - final response = StoreDetails.fromJson(value); + await repository.getStoreDetails().then((response) { if (response.success) { sharedPrefs.cartUniqueID = response.store.cartUniqueID; CreateAndUpdateOrder.cartOrder.cartUniqueId = response.store.cartUniqueID; } - notifyListeners(); + // notifyListeners(); }).onError((error, stackTrace) {}); } void fetchData() async { - getSelectedService(); - - await APIManager() - .fetchData(Constants.GET_STORE_CATEGORY_LIST, getCategoryParam()) - .then((value) { - final response = ItemCategoryResponse.fromJson(value); + await repository.fetchCategories(getCategoryParam()).then((response) { + getSelectedService(); if (response.success && response.categories.isNotEmpty) { itemCategories.clear(); itemCategories.addAll(response.categories); @@ -157,15 +144,19 @@ class CreateOrderViewModel with ChangeNotifier { setLoading(true); } - await APIManager() - .fetchData(Constants.GET_PRODUCTS, getSubCategoryParam(categoryID)) - .then((value) { - final response = ItemSubCategoryResponse.fromJson(value); + await repository.getSub(getSubCategoryParam(categoryID)).then((response) { if (response.success && response.categories.isNotEmpty) { subCategoryItems.clear(); subCategoryItems.addAll(response.categories); selectedProductId = subCategoryItems.first.id; - getItems(categoryID, selectedProductId, false, 0); + getItems(categoryID, selectedProductId, false, 0, + deliveryPartnerId: selectedDeliveryPartner); + } else { + subCategoryItems.clear(); + filteredItems.clear(); + searchedItems.clear(); + setLoading(false); + setFirstLoading(false); } }).onError((error, stackTrace) { subCategoryItems.clear(); @@ -179,36 +170,33 @@ class CreateOrderViewModel with ChangeNotifier { Future getItems(String categoryID, String selectedProductId, bool loader, int subCategoryPosition, {String deliveryPartnerId = ''}) async { + filteredItems.clear(); + searchedItems.clear(); + selectedDeliveryPartner = deliveryPartnerId; CreateAndUpdateOrder.cartOrder.deliveryPartnerId = deliveryPartnerId; if (loader) { setLoading(true); } Map data = {}; - if (deliveryPartnerId.isEmpty) { + if (selectedDeliveryPartner.isEmpty) { data = { 'store_id': sharedPrefs.storeId, 'category_id': categoryID, 'isItemInStock': true, 'product_id': selectedProductId, - // 'page': 1 + 'page': 1 }; } else { data = { 'store_id': sharedPrefs.storeId, 'category_id': categoryID, 'isItemInStock': true, - 'delivery_partner_id': deliveryPartnerId, + 'delivery_partner_id': selectedDeliveryPartner, 'product_id': selectedProductId, 'page': 1 }; } - - await APIManager() - .fetchData(Constants.GET_ITEMS_URL, data) - .then((value) async { - final storeItemsResponse = StoreItemsResponse.fromJson(value); - filteredItems.clear(); - searchedItems.clear(); + await repository.getItems(data).then((storeItemsResponse) async { if (subCategoryPosition == 0) { final comboItems = await getComboData(categoryID); this.comboItems.clear(); @@ -237,13 +225,41 @@ class CreateOrderViewModel with ChangeNotifier { }); } + updateOrderDb(data) async { + bool paymentStatus = data[0]; + String status = data[1]; + CreateAndUpdateOrder.cartOrder.orderStatus = status; + CreateAndUpdateOrder.cartOrder.paymentStatus = paymentStatus; + if (paymentStatus) { + CreateAndUpdateOrder.cartOrder.orderStatus = Constants.preparing; + CreateAndUpdateOrder.cartOrder.changeBalanceAmount = data[2]; + CreateAndUpdateOrder.cartOrder.deliveryNotes = data[3]; + CreateAndUpdateOrder.cartOrder.timer = data[4]; + CreateAndUpdateOrder.cartOrder.amount = data[5]; + CreateAndUpdateOrder.cartOrder.totalAmount = data[6]; + CreateAndUpdateOrder.cartOrder.paymentMode = data[7]; + CreateAndUpdateOrder.cartOrder.totalDiscount = data[8]; + CreateAndUpdateOrder.cartOrder.discountId = data[9]; + } + //await objectbox.addOrder(CreateAndUpdateOrder.cartOrder); + await objectbox.updateOrder(CreateAndUpdateOrder.cartOrder); + createOrderId = CreateAndUpdateOrder.cartOrder.cartUniqueId.toString(); + increaseOrderNumberOffline(); + await clearCart(); + _cashierState = CashierState.createOrder; + } + + void increaseOrderNumberOffline() { + sharedPrefs.cartUniqueID = CreateAndUpdateOrder.cartOrder.cartUniqueId + 1; + } + Future fillCombos(List comboItems) async { for (var combo in comboItems) { var item = StoreItems( imageUrl: '', deliveryPartners: ToMany(items: []), productId: selectedProductId, - id: combo.id!, + itemId: combo.id!, isCombo: true, name: combo.comboName!, price: combo.comboPrice, @@ -259,17 +275,9 @@ class CreateOrderViewModel with ChangeNotifier { Future> getComboData(String categoryID) async { var items = []; - Map data = { - 'store_id': sharedPrefs.storeId, - 'category_id': categoryID, - }; - - await APIManager().fetchData(Constants.GET_COMBO_GROUP, data).then((value) { - final response = GetComboModel.fromJson(value); - if (response.success != null) { - if (response.success!) { - items.addAll(response.combos!); - } + await repository.getComboData(categoryID).then((response) { + if (response.isNotEmpty) { + items.addAll(response); } }).onError((error, stackTrace) {}); @@ -277,46 +285,22 @@ class CreateOrderViewModel with ChangeNotifier { } Future searchItems(String searchValue) async { - Map data = { - 'store_id': sharedPrefs.storeId, - 'search_value': searchValue, - 'page': 1 - }; - await APIManager() - .fetchData(Constants.SEARCH_ALL_ITEMS, data) - .then((value) async { + await repository.searchItems(searchValue).then((value) async { searchedItems.clear(); - final response = SearchItemResponse.fromJson(value); - await searchCombo(searchValue); - if (response.success!) { - if (response.item!.isNotEmpty) { - if (response.item!.first.storeItems!.isNotEmpty) { - searchedItems.addAll(response.item!.first.storeItems!); - notifyListeners(); - } - } + if (!isConnected) { + searchedItems.clear(); + searchedItems.addAll(value); + notifyListeners(); + } else { + await searchCombo(searchValue); + searchedItems.addAll(value); } }).onError((error, stackTrace) {}); } Future searchCombo(String searchValue) async { - Map data = { - 'store_id': sharedPrefs.storeId, - 'search_value': searchValue, - 'page': 1 - }; - - await APIManager() - .fetchData(Constants.SEARCH_ALL_COMBO, data) - .then((value) { - final response = SearchComboItemModel.fromJson(value); - if (response.success!) { - if (response.item!.isNotEmpty) { - if (response.item!.first.storeItems!.isNotEmpty) { - fillComboSearch(response.item!.first.storeItems!); - } - } - } + await repository.searchCombo(searchValue).then((value) { + fillComboSearch(value); }).onError((error, stackTrace) {}); } @@ -325,7 +309,7 @@ class CreateOrderViewModel with ChangeNotifier { var item = StoreItems( imageUrl: '', deliveryPartners: ToMany(items: []), - id: combo.id!, + itemId: combo.id!, isCombo: true, name: combo.comboName!, price: combo.comboPrice, @@ -339,14 +323,7 @@ class CreateOrderViewModel with ChangeNotifier { } void completeOrder(String id) async { - Map data = {}; - data = { - 'store_id': sharedPrefs.storeId, - 'orderId': id, - 'status': 'completed', - }; - await APIManager().fetchData(Constants.CREATE_ORDER, data).then((value) { - final response = SimpleResponseModel.fromJson(value); + await repository.completeOrder(id).then((response) { if (response.success) { _cashierState = CashierState.completeOrder; Utils.showMessage(response.message); @@ -354,38 +331,21 @@ class CreateOrderViewModel with ChangeNotifier { } }).onError((error, stackTrace) { _cashierState = CashierState.error; - // Utils. hideProgressBar(context); }); } Future> getHoldOrders() async { var items = []; - await APIManager() - .fetchData(Constants.GET_STORE_ORDER, Constants.getStorePayload()) - .then((value) { - final response = GetHoldOrderModel.fromJson(value); - if (response.success != null) { - items.addAll(response.orderModel!); - } + await repository.getHoldOrders().then((value) { + items.addAll(value); }).onError((error, stackTrace) {}); - return items; } void updateOrderStatus(String id, String status) async { - // Utils.progressDialogue(context); - Map data = {}; - data = { - 'store_id': sharedPrefs.storeId, - 'order_id': id, - 'status': status, - }; - await APIManager() - .fetchData(Constants.UPDATE_ORDER_STATUS, data) - .then((value) { - final response = SimpleResponseModel.fromJson(value); + await repository.updateOrderStatus(id, status).then((response) { if (response.success) { - if (status == "cancelled") { + if (status == Constants.cancelled) { isCartShow = false; _cashierState = CashierState.cancelled; } else { @@ -395,50 +355,34 @@ class CreateOrderViewModel with ChangeNotifier { } }).onError((error, stackTrace) { _cashierState = CashierState.error; - // Utils.hideProgressBar(context); }); } Future createUpdateOrder() async { - var orderType = CreateAndUpdateOrder.cartOrder.orderType ?? ""; - var selectedTableName = - CreateAndUpdateOrder.cartOrder.selectedTableName ?? ""; + var orderType = CreateAndUpdateOrder.cartOrder.orderType; + var selectedTableName = CreateAndUpdateOrder.cartOrder.selectedTableName; CreateAndUpdateOrder.cartOrder.orderType = orderType; CreateAndUpdateOrder.cartOrder.selectedTableName = selectedTableName; - final map = CreateAndUpdateOrder.cartOrder.toJson(); + //final map = CreateAndUpdateOrder.cartOrder.toJson(); //showing for debug //TODO need to remove - log(jsonEncode(map)); + // log(jsonEncode(CreateAndUpdateOrder.cartOrder)); _cashierState = CashierState.makeUpdateOrder; notifyListeners(); return true; } Future getCartIdFromServer() async { - // print('hrere'); - try { - final map = CreateAndUpdateOrder.cartOrder.toJson(); - //showing for debug - //TODO need to remove - sharedPrefs.cartID = ''; - log(jsonEncode(map)); - await APIManager() - .fetchData(Constants.CREATE_UPDATE_ORDER, map) - .then((value) { - final response = NewCartModel.fromJson(value); - - if (response.success!) { - _cashierState = CashierState.makeUpdateOrder; - updateCartValues(response); - sharedPrefs.cartID = response.cartId ?? ""; - } - }).onError((error, stackTrace) { - _cashierState = CashierState.error; - notifyListeners(); - }); - } catch (e) { + await repository.getCartIdFromServer().then((response) { + if (response.success!) { + _cashierState = CashierState.makeUpdateOrder; + updateCartValues(response); + sharedPrefs.cartID = response.cartId ?? ""; + } + }).onError((error, stackTrace) { _cashierState = CashierState.error; - } + notifyListeners(); + }); } String getOrderText(BuildContext context, OrderModel cartItem) { @@ -505,8 +449,8 @@ class CreateOrderViewModel with ChangeNotifier { .removeModifierOnDecrease(item, item.productId); item.noteForItem = CreateAndUpdateOrder.cartOrder.getNotes(item, item.productId); - item.quantity = item.quantity - 1; - item.noteForItem!.removeAt(item.quantity); + item.quantity = item.quantity! - 1; + item.noteForItem!.removeAt(item.quantity!); CreateAndUpdateOrder.cartOrder .increaseDecreaseItemQuantity(item, item.productId); @@ -525,16 +469,26 @@ class CreateOrderViewModel with ChangeNotifier { } Future addItem(StoreItems items, String note) async { + items.id = 0; + if (CreateAndUpdateOrder.cartOrder.createdAt.isEmpty) { CreateAndUpdateOrder.cartOrder.createdAt = DataTimeFormat.formatDateFromPicket(DateTime.now()); } - CreateAndUpdateOrder.cartOrder.orderType = services[selectedService].name!; + + if (selectedService < 0) { + CreateAndUpdateOrder.cartOrder.orderType = Constants.takeawayService; + } else { + CreateAndUpdateOrder.cartOrder.orderType = + services[selectedService].name!; + } + items.quantity = 1; // items.productId ??= selectedProductId; items.noteForItem = []; items.noteForItem!.add(note); CreateAndUpdateOrder.cartOrder.addItem(items, items.productId); + await createUpdateOrder(); } @@ -571,52 +525,22 @@ class CreateOrderViewModel with ChangeNotifier { int? timer, double? amount, double? totalAmount, - String? orderId]) async { - Map data = {}; - if (paymentStatus) { - if (status == Constants.ready) { - data = { - 'store_id': sharedPrefs.storeId, - 'orderId': orderId, - 'order_type': services[selectedService].name!, - 'status': status, - 'payment_status': paymentStatus, - 'change_balance_amount': changeBalanceAmount, - 'delivery_notes': deliveryNotes, - 'timer': timer, - 'amount': amount, - 'total_amount': totalAmount, - }; - } else { - data = { - 'store_id': sharedPrefs.storeId, - 'cart_id': sharedPrefs.cartID, - 'order_type': services[selectedService].name!, - 'status': status, - 'payment_status': paymentStatus, - 'orderId': CreateAndUpdateOrder.cartOrder.orderId!, - 'change_balance_amount': changeBalanceAmount, - 'delivery_notes': deliveryNotes, - 'timer': timer, - 'amount': amount, - 'total_amount': totalAmount, - }; - } - } else { - data = { - 'store_id': sharedPrefs.storeId, - 'cart_id': sharedPrefs.cartID, - 'order_type': services[selectedService].name!, - 'status': status, - 'payment_status': paymentStatus, - // 'orderId': CreateAndUpdateOrder.cartOrder.orderId!, - }; - } - - await APIManager() - .fetchData(Constants.CREATE_ORDER, data) - .then((value) async { - final response = GetStoreOrderModel.fromJson(value); + String? paymentMode, + double? totalDiscount, + String? discountId]) async { + await repository + .sendToKitchen( + paymentStatus, + status, + changeBalanceAmount, + deliveryNotes, + timer, + amount, + totalAmount, + paymentMode, + totalDiscount, + discountId) + .then((response) async { if (response.success!) { if (paymentStatus) { _cashierState = CashierState.createOrder; @@ -642,10 +566,7 @@ class CreateOrderViewModel with ChangeNotifier { } bool count() { - if (CreateAndUpdateOrder.cartOrder.orderDetails != null) { - return CreateAndUpdateOrder.cartOrder.orderDetails.isNotEmpty; - } - return false; + return CreateAndUpdateOrder.cartOrder.orderDetails.isNotEmpty; } double getTotalCartPrice(List orderDetails) { @@ -673,16 +594,8 @@ class CreateOrderViewModel with ChangeNotifier { return CreateAndUpdateOrder.cartOrder.isThere(id); } - Future getCartById(String s, String orderId) async { - Map data = { - 'store_id': sharedPrefs.storeId, - 'cart_id': s, - }; - - await APIManager() - .fetchData(Constants.GET_STORE_ORDER_BY_ID, data) - .then((value) async { - final response = GetCartModel.fromJson(value); + Future getCartById(String cartId, String orderId) async { + await repository.getCartById(cartId).then((response) async { if (response.success!) { _cashierState = CashierState.getCartOnEdit; saveNewCartOnEdit(response, orderId); @@ -727,7 +640,7 @@ class CreateOrderViewModel with ChangeNotifier { item.selectedCombos = ToMany( items: CreateAndUpdateOrder.cartOrder.getCombos(item, selectedProductId)); - ; + item.noteForItem = CreateAndUpdateOrder.cartOrder.getNotes(item, selectedProductId); List data = result; @@ -760,7 +673,8 @@ class CreateOrderViewModel with ChangeNotifier { } void setDineTable(result) { - setSelectedService('DINE IN'); + selectedDeliveryPartner = ''; + setSelectedService(Constants.dineInService); selectedTable = result; tableName = selectedTable.tableName; CreateAndUpdateOrder.cartOrder.selectedTableName = tableName; @@ -778,10 +692,9 @@ class CreateOrderViewModel with ChangeNotifier { } void onScrollCategory(int index) { - selectedDeliveryPartner = ''; categoryPosition = index; selectedSubCategoryPosition = 0; - if (isInternetConnected) { + if (isConnected) { getSub(itemCategories[index].id, false); } else { notifyListeners(); @@ -794,16 +707,21 @@ class CreateOrderViewModel with ChangeNotifier { } else if (!newOrder.paymentStatus! && newOrder.status! == Constants.ready) { _newOrder = newOrder; + sharedPrefs.cartID = ''; + CreateAndUpdateOrder.cartOrder.orderId = newOrder.id ?? ''; _cashierState = CashierState.showPayment; - } else if (!newOrder.paymentStatus! && - newOrder.status! == Constants.ready) { - CreateAndUpdateOrder.cartOrder.clearCart(); - getCartById(newOrder.cart!.id!, newOrder.id!); - } else { + } + // else if (!newOrder.paymentStatus! && + // newOrder.status! == Constants.ready) { + // CreateAndUpdateOrder.cartOrder.clearCart(); + // getCartById(newOrder.cart!.id!, newOrder.id!); + // } + else { //edit + print('on eidt'); isCartShow = true; CreateAndUpdateOrder.cartOrder.clearCart(); - getCartById(newOrder.cart!.id!, newOrder.id!); + await getCartById(newOrder.cart!.id!, newOrder.id!); } } @@ -816,14 +734,15 @@ class CreateOrderViewModel with ChangeNotifier { } void getSelectedService() { - if (CreateAndUpdateOrder.cartOrder.orderDetails != null) { + if (CreateAndUpdateOrder.cartOrder.orderDetails.isEmpty) { selectedService = services.indexWhere((element) => - element.name! == CreateAndUpdateOrder.cartOrder.orderType); + element.name!.toLowerCase() == + CreateAndUpdateOrder.cartOrder.orderType!.toLowerCase()); } else { //if there is no cart if (services.isNotEmpty) { CreateAndUpdateOrder.cartOrder.orderType = services - .singleWhere((element) => element.name! == "TAKE AWAY") + .singleWhere((element) => element.name == Constants.takeawayService) .name!; selectedService = services.indexWhere((element) => element.name! == CreateAndUpdateOrder.cartOrder.orderType); @@ -835,8 +754,7 @@ class CreateOrderViewModel with ChangeNotifier { sharedPrefs.cartID = response.cartId ?? ""; CreateAndUpdateOrder.cartOrder.cartUniqueId = response.cartUniqueId ?? 0; var orderType = CreateAndUpdateOrder.cartOrder.orderType ?? ""; - var selectedTableName = - CreateAndUpdateOrder.cartOrder.selectedTableName ?? ""; + var selectedTableName = CreateAndUpdateOrder.cartOrder.selectedTableName; CreateAndUpdateOrder.cartOrder = response.cart!; CreateAndUpdateOrder.cartOrder.orderType = orderType; @@ -870,7 +788,7 @@ class CreateOrderViewModel with ChangeNotifier { for (int j = 0; j < modifier.length; j++) { var option = modifier[j]; option.modifierName = selectedModifier[i].name; - option.qtyIdx = item.quantity; + option.qtyIdx = item.quantity!; item.selectedModifiers.add(option); } } @@ -885,7 +803,7 @@ class CreateOrderViewModel with ChangeNotifier { if (isItemAdd) { item.quantity = 1; } else { - item.quantity = item.quantity + 1; + item.quantity = item.quantity! + 1; } item.isCombo = true; if (result != null) { @@ -917,7 +835,7 @@ class CreateOrderViewModel with ChangeNotifier { if (isItemAdd) { item.quantity = 1; } else { - item.quantity = item.quantity + 1; + item.quantity = item.quantity! + 1; } if (result != null) { if (isItemAdd) { @@ -962,8 +880,8 @@ class CreateOrderViewModel with ChangeNotifier { void updateItemList(List list) { filteredItems.clear(); filteredItems.addAll(list); - //update price with delivery parter - if (selectedDeliveryPartner.isNotEmpty && !isInternetConnected) { + //update price with delivery partnrer + if (selectedDeliveryPartner.isNotEmpty && !isConnected) { for (int i = 0; i < filteredItems.length; i++) { var item = filteredItems[i]; if (!item.isCombo) { @@ -995,27 +913,96 @@ class CreateOrderViewModel with ChangeNotifier { checkStatusOrderDb(CreateAndUpdateOrder newOrder) { if (newOrder.paymentStatus && newOrder.orderStatus! == Constants.ready) { - //completeOrder(newOrder.id!); + completeOrderDb(newOrder); } else if (!newOrder.paymentStatus && newOrder.orderStatus! == Constants.ready) { // _newOrder = newOrder; - _cashierState = CashierState.showPayment; - } else if (!newOrder.paymentStatus && - newOrder.orderStatus! == Constants.ready) { CreateAndUpdateOrder.cartOrder.clearCart(); - getCartByIdDb(newOrder.obid); - } else { + CreateAndUpdateOrder.cartOrder = newOrder; + _cashierState = CashierState.showPayment; + } + // else if (!newOrder.paymentStatus && + // newOrder.orderStatus! == Constants.ready) { + // CreateAndUpdateOrder.cartOrder.clearCart(); + // getCartByIdDb(newOrder.obid); + // } + else { //edit - print('object'); isCartShow = true; + CreateAndUpdateOrder.cartOrder.clearCart(); - getCartByIdDb(newOrder.obid); + getCartByIdDb(newOrder.cartUniqueId); } } + completeOrderDb(CreateAndUpdateOrder order) async { + order.orderStatus = 'complete'; + await objectbox.updateOrder(order); + notifyListeners(); + } + void getCartByIdDb(id) async { - var order = objectbox.getOrderById(id); + var order = await objectbox.getOrderById(id); + order.orderDetails = ToMany( + items: List.from(jsonDecode(order.orderDetailsOffline!)) + .map((i) => OrderDetails.fromJson(i)) + .toList()); CreateAndUpdateOrder.cartOrder = order; + _cashierState = CashierState.getCartOnEdit; notifyListeners(); } + + Future checkLastSelectedService() async { + if (CreateAndUpdateOrder.cartOrder.orderType == + Constants.deliveryPartnerService) { + if (isConnected) { + getItems(selectedCategoryId, selectedProductId, true, + selectedSubCategoryPosition, + deliveryPartnerId: selectedDeliveryPartner); + } else { + setItemsDeliveryPartnerId(''); + } + } + } + + updateOrder(String status) async { + if (isConnected) { + await getCartIdFromServer(); + await sendToKitchen(false, status); + await getStoreDetails(); + } else { + await addOrderToDb(status); + } + } + + addOrderToDb(String status) async { + sharedPrefs.cartUniqueID = int.parse('0${sharedPrefs.getCartUniqueId}'); + CreateAndUpdateOrder.cartOrder.cartUniqueId = sharedPrefs.getCartUniqueId; + CreateAndUpdateOrder.cartOrder.orderStatus = status; + CreateAndUpdateOrder.cartOrder.paymentStatus = false; + CreateAndUpdateOrder.cartOrder.createdAt = + DataTimeFormat.formatDateFromPicketINVOICE(DateTime.now()); + await objectbox.addOrder(CreateAndUpdateOrder.cartOrder); + await clearCart(); + increaseOrderNumberOffline(); + } + + bool getIsModifier(StoreItems storeItem) { + // bool value = false; + var list = []; + //0 true + //1 false + if (storeItem.modifiers.isEmpty) { + return false; + } else { + for (var modifiers in storeItem.modifiers) { + if (modifiers.options.isEmpty) { + list.add(0); + } else { + list.add(1); + } + } + } + return list.contains(1); + } } diff --git a/lib/application/views/create_order_module/viewModels/DineInViewModel.dart b/lib/application/views/create_order_module/viewModels/DineInViewModel.dart new file mode 100644 index 0000000..4cee466 --- /dev/null +++ b/lib/application/views/create_order_module/viewModels/DineInViewModel.dart @@ -0,0 +1,79 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/model/tables/GetStoreTable.dart'; +import 'package:wosull/application/repository/WosulRepository.dart'; +import 'package:wosull/main.dart'; + +class DineInViewModel with ChangeNotifier { + bool isPortrait = true; + int selectedItem = -1; + int selectedNo = 0; + bool isLoading = true; + List tablesSeats = []; + List tables = []; + List filteredTables = []; + + void updateSelectedTable(int i) { + if (filteredTables[i].isAvailable) { + selectedItem = i; + } + notifyListeners(); + } + + Future> getTables(int selectedItem) async { + var items = []; + if (isConnected) { + final repository = WosulRepository(); + await repository.getTables().then((response) { + if (response.success && response.storeTables.isNotEmpty) { + setTablesData(response.storeTables); + notifyListeners(); + } else { + tables.clear(); + filteredTables.clear(); + isLoading = false; + notifyListeners(); + } + }).onError((error, stackTrace) { + tables.clear(); + filteredTables.clear(); + isLoading = false; + notifyListeners(); + }); + } else { + isLoading = false; + } + + return items; + } + + Future setTablesData(List storeTables) async { + tables.clear(); + if (tablesSeats.isEmpty) { + tablesSeats.add('All'); + for (var item in storeTables) { + tablesSeats.add(item.noOfOccupants.toString()); + } + + tablesSeats = tablesSeats.toSet().toList(); + } + tables.addAll(storeTables); + filteredTables.addAll(storeTables); + isLoading = false; + } + + void onFilterSeats(int position) { + selectedNo = position; + filteredTables.clear(); + if (selectedNo == 0) { + filteredTables.addAll(tables); + } else { + for (var table in tables) { + if (table.noOfOccupants.toString() == + tablesSeats[selectedNo].toString()) { + filteredTables.add(table); + } + } + } + notifyListeners(); + } +} diff --git a/lib/application/views/create_order_module/viewModels/ItemModifiersViewModel.dart b/lib/application/views/create_order_module/viewModels/ItemModifiersViewModel.dart new file mode 100644 index 0000000..0cac18d --- /dev/null +++ b/lib/application/views/create_order_module/viewModels/ItemModifiersViewModel.dart @@ -0,0 +1,97 @@ +import 'package:flutter/material.dart'; +import 'package:objectbox/objectbox.dart'; +import 'package:wosull/application/model/Modifiers/Modifier.dart'; +import 'package:wosull/application/model/Modifiers/ModifierOption.dart'; +import 'package:wosull/application/model/store/StoreItemsResponse.dart'; + +class ItemModifiersViewModel with ChangeNotifier { + bool isPortrait = true; + int selectedItem = -1; + List selectedModifier = []; + List? selectedOption = []; + + var noteController = ''; + late StoreItems item; + + void disposeData() { + noteController = ''; + selectedModifier.clear(); + selectedOption!.clear(); + selectedItem = -1; + } + + void initData(StoreItems item) { + this.item = item; + for (int i = 0; i < item.modifiers.length; i++) { + for (int j = 0; j < item.modifiers[i].options.length; j++) { + item.modifiers[i].options[j].isSelected = false; + item.modifiers[i].selected.clear(); + } + } + selectedItem = -1; + selectedModifier = []; + } + + void onSelectModifierOption(int position, int i) { + var modifier = + Modifier(options: ToMany(items: []), selected: ToMany(items: [])); + modifier = item.modifiers[position]; + + if (modifier.selected.isEmpty) { + //for first time + item.modifiers[position].isSelected = true; + item.modifiers[position].options[i].isSelected = true; + modifier.selected.add(item.modifiers[position].options[i]); + } + //if modifier parent is already added with child and multiple off ha + else if (modifier.selected.isNotEmpty && !modifier.isMultiple) { + if (modifier.selected.contains(item.modifiers[position].options[i])) { + modifier.selected.remove(item.modifiers[position].options[i]); + item.modifiers[position].options[i].isSelected = false; + } else { + modifier.selected.clear(); + for (int j = 0; j < item.modifiers[position].options.length; j++) { + item.modifiers[position].options[j].isSelected = false; + } + item.modifiers[position].options[i].isSelected = true; + modifier.selected.add(item.modifiers[position].options[i]); + } + //then we will remove already added item and will add new one + } + // else if (modifier.selected!.isNotEmpty && modifier.isMultiple!) { + // + // //then we will remove already added item and will add new one + // item.modifiers[position].options![i].isSelected = true; + // modifier.selected!.add(item.modifiers[position].options![i]); + // + // } + //if modifier parent is already added with child and multiple on ha + else if (!modifier.selected.contains(item.modifiers[position].options[i]) && + modifier.isMultiple) { + //then we will add new option + item.modifiers[position].options[i].isSelected = true; + modifier.selected.add(item.modifiers[position].options[i]); + } else { + modifier.selected.remove(item.modifiers[position].options[i]); + item.modifiers[position].options[i].isSelected = false; + } + + // modifier.selectedModifierIndex = + // item.quantity ?? 1; + + if (selectedModifier.isEmpty) { + selectedModifier.add(modifier); + } else { + var modi = + selectedModifier.indexWhere((element) => element.id == modifier.id); + if (modi >= 0) { + if (selectedModifier[modi].selected.isEmpty) { + selectedModifier.removeAt(modi); + } + } else { + selectedModifier.add(modifier); + } + } + notifyListeners(); + } +} diff --git a/lib/application/views/create_order_module/viewModels/PaymentOptionViewModel.dart b/lib/application/views/create_order_module/viewModels/PaymentOptionViewModel.dart new file mode 100644 index 0000000..940695f --- /dev/null +++ b/lib/application/views/create_order_module/viewModels/PaymentOptionViewModel.dart @@ -0,0 +1,241 @@ +import 'package:flutter/cupertino.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/application/model/discount/ApplyDiscountModel.dart'; +import 'package:wosull/application/model/discount/StoreDiscountModel.dart'; +import 'package:wosull/application/model/invoice/PaymentMethod.dart'; +import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/repository/WosulRepository.dart'; +import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/helpers/Utils.dart'; + +class PaymentOptionViewModel with ChangeNotifier { + var cashAmountController = ''; + var balanceOrChangeController = ''; + var discountAmountController = ''; + var deliveryNoteController = ''; + var selectedPaymentMethod = 'Cash'; + bool isPortrait = true; + var isCash = true; + var isCard = false; + var isCredit = false; + var enable = false; + + String discountId = ''; + double totalAmount = 0.0; + double subTotalAmount = 0.0; + List paymentMethod = []; + + void disposeData() { + paymentMethod.clear(); + enable = false; + isCash = true; + isCard = false; + isCredit = false; + discountId = ''; + cashAmountController = ''; + balanceOrChangeController = ''; + discountAmountController = ''; + deliveryNoteController = ''; + } + + void setAmountValue(double cartAmount) { + subTotalAmount = cartAmount; + totalAmount = cartAmount; + getPaymentMethods(); + } + + Future getPaymentMethods() async { + await WosulRepository().getPaymentMethods().then((value) { + if (value.isNotEmpty) { + paymentMethod.addAll(value); + } + }); + } + + void calculateDiscount(StoreDiscount? storeDiscount) { + //check limit of discount + //first will check expire + //then will check min_amount for cart + //then will check value or percentage + //then will calculate + //then will check max discount + + if (storeDiscount == null) { + discountId = ''; + if (discountAmountController.isNotEmpty) { + totalAmount += double.parse(discountAmountController); + } + discountAmountController = ''; + } else { + if (!storeDiscount.isUnlimited!) { + if (storeDiscount.isUserUsed! >= storeDiscount.limitOfDiscount!) { + Utils.showMessage('Discount is Expired'); + return; + } + } + + if (DataTimeFormat.isDateExpired(storeDiscount.discountEndDate!)) { + Utils.showMessage('Discount is Expired'); + return; + } + + if (storeDiscount.isMinAmount!) { + if (totalAmount < storeDiscount.minAmountLimit!) { + Utils.showMessage( + 'Discount is applicable with minimum ${storeDiscount.minAmountLimit!}'); + return; + } + } + var discount = double.parse(storeDiscount.discountPercentage!); + if (storeDiscount.discountTypeLabel == 'Percentage') { + discount = + (totalAmount * double.parse(storeDiscount.discountPercentage!)) / + 100; + } + if (storeDiscount.isMaxDiscount!) { + if (discount > storeDiscount.maxDiscountLimit!) { + totalAmount -= storeDiscount.maxDiscountLimit!; + discount = storeDiscount.maxDiscountLimit!; + } else { + totalAmount -= discount; + } + } else { + totalAmount -= discount; + } + discountAmountController = discount.toString(); + discountId = storeDiscount.id!; + } + notifyListeners(); + } + + Future applyDiscount(String cartId, StoreDiscount? discount) async { + Map data = {}; + if (discount == null) { + data = { + 'cartId': cartId, + }; + } else { + data = { + 'cartId': cartId, + 'discId': discount.id, + }; + } + + await APIManager().fetchData(Constants.APPLY_DISCOUNT, data).then((value) { + final response = ApplyDiscountModel.fromJson(value); + if (response.success!) { + discountId = discount!.id!; + discountAmountController = response.discountAmount!.toString(); + totalAmount = subTotalAmount; + totalAmount -= response.discountAmount!; + // totalAmount -= double.tryParse(data.minAmountLimit)!; + if (totalAmount < 0) { + totalAmount = 0.0; + } + } else { + Utils.showMessage(response.message!); + totalAmount = subTotalAmount; + discountAmountController = "0.0"; + } + + if (cashAmountController.isNotEmpty) { + getChange(cashAmountController); + } else { + getChange("0.0"); + } + }).onError((error, stackTrace) {}); + } + + void getChange(String value) { + cashAmountController = value; + setChange(value); + } + + void setChange(String value) { + var cashAmount = 0.0; + if (value.isNotEmpty) { + cashAmount = double.parse(value); + } + if (cashAmount >= totalAmount) { + if (isCash) { + enable = true; + } + + final changeAmount = cashAmount - totalAmount; + balanceOrChangeController = changeAmount.toStringAsFixed(2); + } else { + if (isCash) { + enable = false; + } + balanceOrChangeController = "0.0"; + } + + notifyListeners(); + } + + void setCashView() { + isCash = true; + isCredit = false; + isCard = false; + setChange(cashAmountController); + notifyListeners(); + } + + void setCreditCardView() { + enable = true; + isCash = false; + isCard = true; + isCredit = false; + notifyListeners(); + } + + Future sendOrder(String status) async { + if (enable) { + var change = 0.0; + if (balanceOrChangeController.isNotEmpty) { + change = double.parse(balanceOrChangeController); + } else { + change = 0.0; + } + if (isCash) { + selectedPaymentMethod = 'Cash'; + } + List result = [ + true, + status == "ready" ? 'completed' : Constants.preparing, + change, + deliveryNoteController, + 10, + subTotalAmount, + totalAmount, + selectedPaymentMethod, + discountAmountController.isNotEmpty + ? double.parse(discountAmountController) + : 0.0, + discountId + ]; + return result; + } + } + + void setDiscountOnChange(String value) { + if (value.isEmpty) { + totalAmount = subTotalAmount; + } else { + totalAmount = subTotalAmount; + var discountValue = double.parse(value); + totalAmount -= discountValue; + if (totalAmount < 0) { + totalAmount = 0.0; + } + } + } + + void setPaymentMethod(PaymentMethod? data) { + if (data == null) { + selectedPaymentMethod = ''; + } else { + selectedPaymentMethod = data.paymentMethod!; + } + } +} diff --git a/lib/application/views/create_order_module/viewModels/PrintInvoiceViewModel.dart b/lib/application/views/create_order_module/viewModels/PrintInvoiceViewModel.dart index 713e9c2..c46c834 100644 --- a/lib/application/views/create_order_module/viewModels/PrintInvoiceViewModel.dart +++ b/lib/application/views/create_order_module/viewModels/PrintInvoiceViewModel.dart @@ -1,27 +1,80 @@ import 'dart:convert'; +import 'dart:io'; +import 'dart:typed_data'; +import 'package:android_path_provider/android_path_provider.dart'; import 'package:flutter/cupertino.dart'; +import 'package:objectbox/objectbox.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:pdf/pdf.dart'; +import 'package:pdf/widgets.dart' as pw; +import 'package:permission_handler/permission_handler.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/application/model/CreateAndUpdateOrder.dart'; import 'package:wosull/application/model/SimpleResponsModel.dart'; +import 'package:wosull/application/model/createOrder/OrderDetails.dart'; import 'package:wosull/application/model/store/GetStoreOrderByIdModel.dart'; import 'package:wosull/application/network/APIManager.dart'; import 'package:wosull/application/network/ApiResponse.dart'; import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/helpers/Utils.dart'; +import 'package:wosull/main.dart'; class PrintInvoiceViewModel extends ChangeNotifier { + int itemQuantity = 0; + int allItemsQuantity = 0; + String orderId = ''; + + var pdf = pw.Document(); ApiResponse order = ApiResponse.loading(); ApiResponse updateOrderResponse = ApiResponse.initial(); + ApiResponse offlineOrder = ApiResponse.loading(); + setOrderResponse(ApiResponse data) { order = data; notifyListeners(); } + setOfflineOrderResponse(ApiResponse data) { + offlineOrder = data; + notifyListeners(); + } + + calculateOfflineTotalItems(List orderDetails) { + itemQuantity = 0; + allItemsQuantity = 0; + for (var order in orderDetails) { + for (var item in order.items) { + itemQuantity++; + allItemsQuantity += item.quantity ?? 1; + } + } + } + + getTotalItems() { + itemQuantity = 0; + allItemsQuantity = 0; + for (var order in order.data!.cart!.orderDetails!) { + for (var item in order.items) { + itemQuantity++; + allItemsQuantity += item.quantity ?? 1; + } + } + } + setUpdateOrderResponse(ApiResponse data) { updateOrderResponse = data; notifyListeners(); } + Future updateOrderDb() async { + offlineOrder.data!.orderStatus = Constants.completed; + await objectbox.updateOrder(offlineOrder.data!); + updateOrderResponse.status = Status.COMPLETED; + notifyListeners(); + } + Future getReceipt(String id) async { await APIManager() .getResponseAuth(Constants.GET_ORDER_BY_ID + id) @@ -48,7 +101,6 @@ class PrintInvoiceViewModel extends ChangeNotifier { 'order_id': id, 'status': 'completed', }; - print(jsonEncode(data)); await APIManager() .fetchData(Constants.UPDATE_ORDER_STATUS, data) .then((result) { @@ -60,4 +112,102 @@ class PrintInvoiceViewModel extends ChangeNotifier { notifyListeners(); }); } + + Future getOfflineReceipt(int id) async { + var order = await objectbox.getOrderById(id); + order.orderDetails = ToMany( + items: List.from(jsonDecode(order.orderDetailsOffline!)) + .map((i) => OrderDetails.fromJson(i)) + .toList()); + setOfflineOrderResponse(ApiResponse.completed(order)); + } + + createPDF(Uint8List image) async { + pdf = pw.Document(); + pdf.addPage(pw.Page( + pageFormat: PdfPageFormat.a4, + build: (pw.Context contex) { + return pw.Image(pw.MemoryImage(image), fit: pw.BoxFit.contain); + })); + } + + static Future getDownloadPath() async { + String? externalStorageDirPath; + if (Platform.isAndroid) { + try { + externalStorageDirPath = await AndroidPathProvider.downloadsPath; + // externalStorageDirPath = "/storage/emulated/0/Download"; + } catch (e) { + // print('permisison error == $e'); + final directory = await getExternalStorageDirectory(); + externalStorageDirPath = directory?.path; + // print('stoarge path == $externalStorageDirPath'); + } + } else if (Platform.isIOS) { + externalStorageDirPath = (await getApplicationDocumentsDirectory()).path; + } + return externalStorageDirPath; + } + + savePDF() async { + try { + //ask for permission + await Permission.manageExternalStorage.request(); + var status = await Permission.manageExternalStorage.status; + if (status.isDenied) { + // We didn't ask for permission yet or the permission has been denied before but not permanently. + return; + } + +// You can can also directly ask the permission about its status. + if (await Permission.storage.isRestricted) { + // The OS restricts access, for example because of parental controls. + return; + } + if (status.isGranted) { +//here you add the code to store the file + String savePath; + if (Platform.isIOS) { + final directory = await getApplicationDocumentsDirectory(); + savePath = '${directory.path}/${DateTime.now()}_receipt.pdf'; + } else if (Platform.isAndroid) { + savePath = + '/storage/emulated/0/Download/${DateTime.now()}_receipt.pdf'; + } else { + // Handle other platforms if necessary + return; + } + print(savePath); + await File(savePath).writeAsBytes(await pdf.save()); + + // final outPut = await getExternalStorageDirectory(); + // String? p = await getDownloadPath(); + + // String? appDocDir = await getDownloadPath(); + // // String appDocPath = appDocDir!.path; + // // String path = '${appDocPath}/${DateTime.now()}_receipt.pdf'; + // //await Directory('$appDocDir/Wosul').create(recursive: true); + // final file = File('$appDocDir/${DateTime.now()}_receipt.pdf'); + // print('$appDocDir/Wosul'); + // + // // final file = File(path); + // + // var sink = file.openWrite(); + // await sink.close(); + // String path = '/storage/emulated/0'; + // print(path); + // await Directory('$path/Wosul').create(recursive: true); + // final file = File('$path/Wosul/${DateTime.now()}_receipt.pdf'); + // await file.writeAsBytes(await pdf.save()); + Utils.showMessage('success saved to documents'); + // print('success saved to documents'); + } + //print(_hasAcceptedPermissions()); + // Directory? directory = await getExternalStorageDirectory(); + // String path = directory.path; + } catch (e) { + Utils.showMessage('error ${e.toString()}'); + print('error ${e.toString()}'); + } + } } diff --git a/lib/application/views/create_order_module/views/PrintInvoiceVC.dart b/lib/application/views/create_order_module/views/PrintInvoiceVC.dart index ea17ff2..7c41e51 100644 --- a/lib/application/views/create_order_module/views/PrintInvoiceVC.dart +++ b/lib/application/views/create_order_module/views/PrintInvoiceVC.dart @@ -7,8 +7,10 @@ import 'package:wosull/application/model/store/GetStoreOrderByIdModel.dart'; import 'package:wosull/application/network/ApiResponse.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/theme/MyFonts.dart'; +import 'package:wosull/application/utils/AppLoader.dart'; import 'package:wosull/base/BaseStatefulState.dart'; import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeImage.dart'; import 'package:wosull/widgets/CustomSimpleButton.dart'; import 'package:wosull/widgets/IconButton.dart'; @@ -65,8 +67,7 @@ class _PrintInvoiceVCState extends BaseStatefulState { builder: (context, value, _) { switch (value.order.status) { case Status.LOADING: - return const Center( - child: CircularProgressIndicator()); + return AppLoader(); case Status.ERROR: return Text(value.order.toString()); case Status.COMPLETED: @@ -147,7 +148,7 @@ class _PrintInvoiceVCState extends BaseStatefulState { mainAxisAlignment: MainAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Image.asset('images/logo_sub_title.png'), + Image.asset(ThemeImage.wosulLogo, width: 80), const SizedBox( height: 12, ), @@ -174,7 +175,7 @@ class _PrintInvoiceVCState extends BaseStatefulState { Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const Text( + Text( 'Simplified Tax Invoice', style: TextStyle( fontFamily: MyFonts.RobotoBold, @@ -188,7 +189,7 @@ class _PrintInvoiceVCState extends BaseStatefulState { children: [ Text( AppLocalizations.of(context)!.invoice_no, - style: const TextStyle( + style: TextStyle( fontFamily: MyFonts.RobotoMedium, fontSize: MyFonts.H1, color: MyColors.black1, @@ -197,7 +198,7 @@ class _PrintInvoiceVCState extends BaseStatefulState { AppSpaces.horizontalSmall, Text( order.uniqueId!.toString(), - style: const TextStyle( + style: TextStyle( fontFamily: MyFonts.RobotoBold, fontSize: MyFonts.H1, color: MyColors.black1, @@ -231,7 +232,7 @@ class _PrintInvoiceVCState extends BaseStatefulState { children: [ Text( AppLocalizations.of(context)!.invoice_number, - style: const TextStyle( + style: TextStyle( fontFamily: MyFonts.RobotoBold, fontSize: MyFonts.normal, color: MyColors.black1, @@ -242,7 +243,7 @@ class _PrintInvoiceVCState extends BaseStatefulState { ), Text( AppLocalizations.of(context)!.store, - style: const TextStyle( + style: TextStyle( fontFamily: MyFonts.RobotoBold, fontSize: MyFonts.normal, color: MyColors.black1, @@ -254,7 +255,7 @@ class _PrintInvoiceVCState extends BaseStatefulState { Text( AppLocalizations.of(context)! .invoice_issue_date, - style: const TextStyle( + style: TextStyle( fontFamily: MyFonts.RobotoBold, fontSize: MyFonts.normal, color: MyColors.black1, @@ -268,30 +269,26 @@ class _PrintInvoiceVCState extends BaseStatefulState { children: [ Text( order.uniqueId!.toString(), - style: const TextStyle( + style: TextStyle( fontFamily: MyFonts.RobotoBold, fontSize: MyFonts.normal, color: MyColors.black1, fontWeight: FontWeight.w500), ), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, Text( - order.storeId!.name!, - style: const TextStyle( + order.storeId!.name, + style: TextStyle( fontFamily: MyFonts.RobotoBold, fontSize: MyFonts.normal, color: MyColors.black1, fontWeight: FontWeight.w500), ), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, Text( DataTimeFormat.getFormatDate( order.createdAt!), - style: const TextStyle( + style: TextStyle( fontFamily: MyFonts.RobotoBold, fontSize: MyFonts.normal, color: MyColors.black1, @@ -304,9 +301,7 @@ class _PrintInvoiceVCState extends BaseStatefulState { )), ], ), - const SizedBox( - height: 16, - ), + AppSpaces.verticalLarge, Container( padding: const EdgeInsets.only(left: 8, right: 8), height: 32, @@ -443,7 +438,7 @@ class _PrintInvoiceVCState extends BaseStatefulState { Expanded( child: Text( AppLocalizations.of(context)!.discount, - style: const TextStyle( + style: TextStyle( fontFamily: MyFonts.RobotoBold, fontSize: MyFonts.normal, color: MyColors.black1, @@ -452,7 +447,7 @@ class _PrintInvoiceVCState extends BaseStatefulState { ), Text( order.totalDiscount!.toStringAsFixed(2), - style: const TextStyle( + style: TextStyle( fontFamily: MyFonts.RobotoBold, fontSize: MyFonts.normal, color: MyColors.black1, @@ -460,16 +455,14 @@ class _PrintInvoiceVCState extends BaseStatefulState { ), ], ), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, Row( crossAxisAlignment: CrossAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end, children: [ Text( AppLocalizations.of(context)!.total_amount_due, - style: const TextStyle( + style: TextStyle( fontStyle: FontStyle.normal, fontFamily: MyFonts.RobotoBold, fontSize: MyFonts.H1, @@ -479,7 +472,7 @@ class _PrintInvoiceVCState extends BaseStatefulState { const Spacer(), Text( order.totalAmount!.toStringAsFixed(2), - style: const TextStyle( + style: TextStyle( fontStyle: FontStyle.normal, fontFamily: MyFonts.RobotoBold, fontSize: MyFonts.H1, @@ -491,24 +484,20 @@ class _PrintInvoiceVCState extends BaseStatefulState { ], ), ), - const SizedBox( - height: 16, - ), + AppSpaces.verticalLarge, Container( width: double.infinity, height: 2, color: MyColors.fillColor, ), - const SizedBox( - height: 16, - ), + AppSpaces.verticalLarge, Row( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ Text( AppLocalizations.of(context)!.powered_by_wosul, - style: const TextStyle( + style: TextStyle( fontFamily: MyFonts.RobotoBold, fontSize: MyFonts.normal, color: MyColors.black1, diff --git a/lib/application/views/create_order_module/views/PrintReceiptVC.dart b/lib/application/views/create_order_module/views/PrintReceiptVC.dart new file mode 100644 index 0000000..8b4d351 --- /dev/null +++ b/lib/application/views/create_order_module/views/PrintReceiptVC.dart @@ -0,0 +1,727 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:provider/provider.dart'; +import 'package:qr_flutter/qr_flutter.dart'; +import 'package:screenshot/screenshot.dart'; +import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/application/model/CreateAndUpdateOrder.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/application/model/createOrder/OrderDetails.dart'; +import 'package:wosull/application/model/store/GetStoreOrderByIdModel.dart'; +import 'package:wosull/application/network/ApiResponse.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/theme/MySeparator.dart'; +import 'package:wosull/application/utils/AppLoader.dart'; +import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/create_order_module/viewModels/PrintInvoiceViewModel.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeImage.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/main.dart'; +import 'package:wosull/widgets/CustomSimpleButton.dart'; +import 'package:wosull/widgets/IconButton.dart'; + +class PrintReceiptVC extends StatefulWidget { + String id; + + PrintReceiptVC({super.key, required this.id}); + + @override + State createState() => _PrintReceiptVCState(); +} + +class _PrintReceiptVCState extends State { + bool isPortrait = false; + var viewModel = PrintInvoiceViewModel(); + ScreenshotController screenshotController = ScreenshotController(); + + @override + void initState() { + if (isConnected) { + context.read().getReceipt(widget.id); + } else { + context + .read() + .getOfflineReceipt(int.parse(widget.id)); + } + + super.initState(); + } + + @override + Widget build(BuildContext context) { + viewModel = context.watch(); + return Scaffold( + resizeToAvoidBottomInset: true, + backgroundColor: MyColors.white, + appBar: AppBar( + leading: BackButton( + color: MyColors.black1, + onPressed: () { + Navigator.pop(context); + }, // <-- SEE HERE + ), + backgroundColor: MyColors.white, + elevation: 0, + ), + body: OrientationBuilder(builder: (c, orientation) { + isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; + return SingleChildScrollView( + child: Container( + width: double.infinity, + color: MyColors.white, + padding: const EdgeInsets.all(10), + child: isConnected + ? viewModel.order.status == Status.LOADING + ? AppLoader() + : showInvoice(viewModel.order.data!) + : viewModel.offlineOrder.status == Status.LOADING + ? AppLoader() + : showOfflineInvoice(viewModel.offlineOrder.data!), + ), + ); + }), + ); + } + + Widget showOfflineInvoice(CreateAndUpdateOrder order) { + viewModel.calculateOfflineTotalItems(order.orderDetails); + return Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + getActionButtons(order.orderStatus == Constants.completed), + AppSpaces.verticalLarge, + Screenshot( + controller: screenshotController, + child: Container( + margin: EdgeInsets.fromLTRB( + isPortrait ? 8 : 80, 0, isPortrait ? 8 : 80, 0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Image.asset( + ThemeImage.wosulLogo, + width: 80, + ), + AppSpaces.verticalLarge, + const Text( + 'info@wosul.ae', + style: ThemeText.textStyleSmallDJMono, + ), + AppSpaces.verticalSmall, + const Text( + 'Tel :0549249523', + style: ThemeText.textStyleSmallDJMono, + ), + AppSpaces.verticalSmall, + const Text( + 'VAT Reg. #: 45398587537', + style: ThemeText.textStyleSmallDJMono, + ), + AppSpaces.verticalSmall, + const Text( + 'Address :شارع العليا العام - الرياض', + style: ThemeText.textStyleSmallDJMono, + ), + AppSpaces.verticalLarge, + const Text( + 'Welcome', + style: ThemeText.textStyleMediumDJMono, + ), + AppSpaces.verticalSmall, + Text( + 'Printed at : ${DataTimeFormat.getFormatDateWithTime()}', + style: ThemeText.textStyleMediumDJMono, + ), + AppSpaces.verticalMedium, + const MySeparator( + color: MyColors.black, + ), + AppSpaces.verticalMedium, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Order #${order.cartUniqueId.toString()}', + style: ThemeText.textStyleBOLDDJMono, + ), + Text( + 'Date : ${DataTimeFormat.getFormatDate(order.createdAt ?? '')}', + style: ThemeText.textStyleMediumDJMono, + ), + ], + ), + AppSpaces.verticalMedium, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Text( + overflow: TextOverflow.ellipsis, + softWrap: false, + maxLines: 3, + 'Billed by: ${sharedPrefs.billingCounterName}', + style: ThemeText.textStyleMediumDJMono, + )), + Flexible( + child: Text( + '${viewModel.itemQuantity} Items : (${viewModel.allItemsQuantity} Qty)', + overflow: TextOverflow.ellipsis, + softWrap: false, + maxLines: 3, + style: ThemeText.textStyleMediumDJMono, + )), + ], + ), + AppSpaces.verticalLarge, + const MySeparator( + color: MyColors.black, + ), + AppSpaces.verticalLarge, + const Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Text( + 'Description', + overflow: TextOverflow.ellipsis, + softWrap: false, + maxLines: 3, + style: ThemeText.textStyleBOLDDJMono, + )), + Row( + children: [ + SizedBox( + width: 30, + child: Text( + 'Qty', + style: ThemeText.textStyleBOLDDJMono, + ), + ), + AppSpaces.horizontalMedium, + SizedBox( + width: 30, + child: Text( + 'Price', + style: ThemeText.textStyleBOLDDJMono, + ), + ), + AppSpaces.horizontalMedium, + SizedBox( + width: 50, + child: Text( + 'Amount', + style: ThemeText.textStyleBOLDDJMono, + ), + ), + ], + ) + ], + ), + AppSpaces.verticalMedium, + getOrderDetails(order.orderDetails), + AppSpaces.verticalLarge, + const MySeparator( + color: MyColors.black, + ), + AppSpaces.verticalMedium, + const Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Sub Total Exclude Tax', + style: ThemeText.textStyleMediumDJMono, + ), + Text( + 'N/A', + style: ThemeText.textStyleMediumDJMono, + ), + ], + ), + AppSpaces.verticalMedium, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Text( + 'Discount', + style: ThemeText.textStyleMediumDJMono, + ), + Text( + order.totalDiscount?.toStringAsFixed(2) ?? '0.0', + style: ThemeText.textStyleMediumDJMono, + ), + ], + ), + AppSpaces.verticalMedium, + const Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Sub Total After Disc.', + style: ThemeText.textStyleMediumDJMono, + ), + Text( + 'N/A', + style: ThemeText.textStyleMediumDJMono, + ), + ], + ), + AppSpaces.verticalMedium, + const Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'VAT (15.00%)', + style: ThemeText.textStyleMediumDJMono, + ), + Text( + 'N/A', + style: ThemeText.textStyleMediumDJMono, + ), + ], + ), + AppSpaces.verticalLarge, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Text( + 'Bill Total', + style: ThemeText.textStyleBOLDDJMono, + ), + Text( + '${sharedPrefs.currency} ${order.totalAmount?.toStringAsFixed(2) ?? '0.0'}', + style: ThemeText.textStyleMediumDJMono, + ), + ], + ), + AppSpaces.verticalLarge, + const MySeparator( + color: MyColors.black, + ), + AppSpaces.verticalLarge, + QrImageView( + data: order.cartUniqueId.toString(), + version: QrVersions.auto, + size: 80.0, + ), + AppSpaces.verticalMedium, + const Text( + 'Terms & Condition', + style: ThemeText.textStyleMediumDJMono, + ), + AppSpaces.verticalSmall, + const Text( + 'شكراً لزيارتكم وعشمنا منكم وفيكم', + style: ThemeText.textStyleMediumDJMono, + ), + AppSpaces.verticalSmall, + const Text( + 'POWERED BY WOSUL', + style: ThemeText.textStyleMediumDJMono, + ), + ], + ), + )) + ], + ); + } + + Widget showInvoice(StoreOrderByIdModel order) { + viewModel.getTotalItems(); + return Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + getActionButtons(order.status == Constants.completed), + AppSpaces.verticalLarge, + Screenshot( + controller: screenshotController, + child: Container( + margin: EdgeInsets.fromLTRB( + isPortrait ? 8 : 80, 0, isPortrait ? 8 : 80, 0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Image.asset( + ThemeImage.wosulLogo, + width: 80, + ), + AppSpaces.verticalLarge, + Text( + order.storeId!.email, + style: ThemeText.textStyleSmallDJMono, + ), + AppSpaces.verticalSmall, + Text( + 'Tel: ${order.storeId!.phone}', + style: ThemeText.textStyleSmallDJMono, + ), + AppSpaces.verticalSmall, + Text( + 'Address: ${order.storeId!.address}', + textAlign: TextAlign.center, + style: ThemeText.textStyleSmallDJMono, + ), + AppSpaces.verticalLarge, + const Text( + 'Welcome', + style: ThemeText.textStyleMediumDJMono, + ), + AppSpaces.verticalSmall, + Text( + 'Printed at : ${DataTimeFormat.getFormatDateWithTime()}', + style: ThemeText.textStyleMediumDJMono, + ), + AppSpaces.verticalMedium, + const MySeparator( + color: MyColors.black, + ), + AppSpaces.verticalMedium, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Order #${order.uniqueId!.toString()}', + style: ThemeText.textStyleBOLDDJMono, + ), + Text( + 'Date : ${DataTimeFormat.getFormatDate(order.createdAt ?? '')}', + style: ThemeText.textStyleMediumDJMono, + ), + ], + ), + AppSpaces.verticalMedium, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Text( + 'Billed by: ${sharedPrefs.billingCounterName}', + overflow: TextOverflow.ellipsis, + softWrap: false, + maxLines: 3, + style: ThemeText.textStyleMediumDJMono, + )), + Flexible( + child: Text( + '${viewModel.itemQuantity} Items : (${viewModel.allItemsQuantity} Qty)', + overflow: TextOverflow.ellipsis, + softWrap: false, + maxLines: 3, + style: ThemeText.textStyleMediumDJMono, + ), + ) + ], + ), + AppSpaces.verticalLarge, + const MySeparator( + color: MyColors.black, + ), + AppSpaces.verticalLarge, + const Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Text( + 'Description', + style: ThemeText.textStyleBOLDDJMono, + )), + Row( + children: [ + SizedBox( + width: 30, + child: Text( + 'Qty', + style: ThemeText.textStyleBOLDDJMono, + ), + ), + AppSpaces.horizontalMedium, + SizedBox( + width: 30, + child: Text( + 'Price', + style: ThemeText.textStyleBOLDDJMono, + ), + ), + AppSpaces.horizontalMedium, + SizedBox( + width: 50, + child: Text( + 'Amount', + style: ThemeText.textStyleBOLDDJMono, + ), + ), + ], + ) + ], + ), + AppSpaces.verticalMedium, + getOrderDetails(order.cart!.orderDetails), + AppSpaces.verticalLarge, + const MySeparator( + color: MyColors.black, + ), + AppSpaces.verticalMedium, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Text( + 'Discount', + style: ThemeText.textStyleMediumDJMono, + ), + Text( + order.totalDiscount!.toStringAsFixed(2), + style: ThemeText.textStyleMediumDJMono, + ), + ], + ), + AppSpaces.verticalMedium, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Text( + 'Sub Total After Disc.', + style: ThemeText.textStyleMediumDJMono, + ), + Text( + '${sharedPrefs.currency} ${order.amount!.toStringAsFixed(2)}', + style: ThemeText.textStyleMediumDJMono, + ), + ], + ), + AppSpaces.verticalLarge, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Text( + 'Bill Total', + style: ThemeText.textStyleBOLDDJMono, + ), + Text( + '${sharedPrefs.currency} ${order.totalAmount!.toStringAsFixed(2)}', + style: ThemeText.textStyleMediumDJMono, + ), + ], + ), + AppSpaces.verticalLarge, + const MySeparator( + color: MyColors.black, + ), + AppSpaces.verticalLarge, + QrImageView( + data: order.uniqueId!.toString(), + version: QrVersions.auto, + size: 80.0, + ), + AppSpaces.verticalMedium, + const Text( + 'Terms & Condition', + style: ThemeText.textStyleMediumDJMono, + ), + AppSpaces.verticalSmall, + const Text( + 'POWERED BY WOSUL', + style: ThemeText.textStyleMediumDJMono, + ), + ], + ), + )) + ], + ); + } + + Future updateOrderStatus(String id) async { + await viewModel.updateOrderStatus(id); + checkState(); + } + + void checkState() { + if (viewModel.updateOrderResponse.status == Status.COMPLETED) { + Navigator.pop(context); + } + } + + void captureImage() { + screenshotController + .capture(delay: const Duration(milliseconds: 5)) + .then((capturedImage) async { + await viewModel.createPDF(capturedImage!); + viewModel.savePDF(); + }).catchError((onError) {}); + } + + Widget getActionButtons(bool orderCompleted) { + return Container( + margin: + EdgeInsets.fromLTRB(isPortrait ? 6 : 80, 0, isPortrait ? 6 : 80, 0), + child: isPortrait + ? Column( + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Flexible( + child: getPrintButton(), + ), + AppSpaces.horizontalSmall, + Flexible( + child: getDownloadButton(), + ), + ], + ), + getDoneButton() + ], + ) + : Row( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + SizedBox( + width: 110, + child: getPrintButton(), + ), + AppSpaces.horizontalSmall, + SizedBox( + width: 140, + child: getDownloadButton(), + ), + AppSpaces.horizontalSmall, + SizedBox( + width: 100, + child: getDoneButton(), + ), + ], + ), + ); + } + + getOrderDetails(List? orderDetails) { + return ListView.builder( + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (c, parent) { + return ListView.builder( + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (c, child) { + final item = orderDetails[parent].items[child]; + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Text( + item.name, + style: ThemeText.textStyleMediumDJMono, + )), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + SizedBox( + width: 30, + child: Text( + item.quantity.toString(), + textAlign: TextAlign.center, + style: ThemeText.textStyleMediumDJMono, + ), + ), + AppSpaces.horizontalSmall, + SizedBox( + width: 40, + child: Text( + item.price.toStringAsFixed(2), + textAlign: TextAlign.center, + style: ThemeText.textStyleMediumDJMono, + ), + ), + AppSpaces.horizontalSmall, + SizedBox( + width: 50, + child: Text( + (item.totalItemPrice?.toStringAsFixed(2) ?? '0.0'), + textAlign: TextAlign.center, + style: ThemeText.textStyleMediumDJMono, + ), + ), + ], + ) + ], + ); + }, + itemCount: orderDetails[parent].items.length, + ); + }, + itemCount: orderDetails!.length, + ); + } + + getPrintButton() { + return CustomIconButton( + textColor: MyColors.white, + backgroundColor: MyColors.blueThemeColor, + onPressed: () {}, + icon: Icons.print, + heading: AppLocalizations.of(context)!.print_now, + ); + } + + getDownloadButton() { + return CustomIconButton( + textColor: MyColors.white, + backgroundColor: MyColors.blueThemeColor, + onPressed: () { + captureImage(); + }, + heading: AppLocalizations.of(context)!.download, + icon: Icons.download, + ); + } + + getDoneButton() { + return CustomSimpleButton( + isLoading: viewModel.updateOrderResponse.status == Status.LOADING, + textColor: MyColors.white, + backGroundColor: MyColors.blueThemeColor, + onPressed: () async { + if (isConnected) { + updateOrderStatus(viewModel.order.data!.id!); + } else { + await viewModel.updateOrderDb(); + checkState(); + } + }, + heading: AppLocalizations.of(context)!.done, + ); + } + +// Future getPdf(Uint8List screenShot) async { +// pw.Document pdf = pw.Document(); +// pdf.addPage( +// pw.Page( +// pageFormat: PdfPageFormat.a4, +// build: (context) { +// return pw.Expanded( +// child: +// pw.Image(pw.MemoryImage(screenShot), fit: pw.BoxFit.contain)); +// }, +// ), +// ); +// final path = await _localPath; +// File pdfFile = File('$path/${DateTime.now()}_receipt.pdf'); +// print('saved'); +// pdfFile.writeAsBytesSync(pdf.save()); +// } +// +// Future get _localPath async { +// final directory = await getApplicationDocumentsDirectory(); +// return directory.path; +// } +} diff --git a/lib/application/views/create_order_module/views/TabBarHomeVC.dart b/lib/application/views/create_order_module/views/TabBarHomeVC.dart index 8fba3bd..6a2ae07 100644 --- a/lib/application/views/create_order_module/views/TabBarHomeVC.dart +++ b/lib/application/views/create_order_module/views/TabBarHomeVC.dart @@ -3,7 +3,6 @@ import 'dart:async'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:internet_connection_checker/internet_connection_checker.dart'; import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart'; import 'package:provider/provider.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; @@ -15,11 +14,13 @@ import 'package:wosull/application/model/store/StoreItemsResponse.dart'; import 'package:wosull/application/model/store/StoreServiceModel.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/theme/MyFonts.dart'; +import 'package:wosull/application/utils/AppError.dart'; import 'package:wosull/application/utils/AppLoader.dart'; import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/authModule/checkinViews/CheckInPopUp.dart'; import 'package:wosull/application/views/create_order_module/states/CashierState.dart'; import 'package:wosull/application/views/create_order_module/viewModels/CreateOrderViewModel.dart'; -import 'package:wosull/application/views/create_order_module/views/PrintInvoiceVC.dart'; +import 'package:wosull/application/views/create_order_module/views/PrintReceiptVC.dart'; import 'package:wosull/application/views/create_order_module/views/popups/DeliveryPartnerPopUp.dart'; import 'package:wosull/application/views/create_order_module/views/popups/DineInPopup.dart'; import 'package:wosull/application/views/create_order_module/views/popups/ItemModifiersPopUp.dart'; @@ -64,98 +65,91 @@ class _TabBarHomeVCState extends BaseStatefulState { @override void initState() { - viewModel.getStoreDetails(); + context.read().getStoreDetails(); + Future.delayed(const Duration(seconds: 2), () { + if (sharedPrefs.billingCounterId.isEmpty) { + showCounters(); + } + }); super.initState(); } @override Widget build(BuildContext context) { viewModel = context.watch(); - viewModel.isInternetConnected = - Provider.of(context) == - InternetConnectionStatus.connected; - if (viewModel.itemCategories.isEmpty && viewModel.isInternetConnected) { + // isConnected = + // Provider.of(context) == + // InternetConnectionStatus.connected; + + if (viewModel.itemCategories.isEmpty && isConnected) { viewModel.fetchData(); } else { viewModel.setLoadingOffline(false); } - return WillPopScope( - child: Directionality( - textDirection: TextDirection.ltr, - child: SafeArea( - child: Scaffold( - backgroundColor: MyColors.backFillColor, - resizeToAvoidBottomInset: true, - body: OrientationBuilder(builder: (context, orientation) { - viewModel.isPortrait = - MediaQuery.of(context).orientation == Orientation.portrait; - //using this height for cart/hold view - viewModel.height = MediaQuery.of(context).size.height / 1.6; - return ModalProgressHUD( - inAsyncCall: viewModel.isFirstLoading, - child: Container( - padding: const EdgeInsets.all(8), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, + + return Directionality( + textDirection: TextDirection.ltr, + child: SafeArea( + child: Scaffold( + backgroundColor: MyColors.backFillColor, + resizeToAvoidBottomInset: true, + body: OrientationBuilder(builder: (context, orientation) { + viewModel.isPortrait = + MediaQuery.of(context).orientation == Orientation.portrait; + //using this height for cart/hold view + viewModel.height = MediaQuery.of(context).size.height / 1.6; + return ModalProgressHUD( + inAsyncCall: viewModel.isFirstLoading, + child: Container( + padding: const EdgeInsets.all(8), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.min, children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - searchBarBuilder(), - const SizedBox( - height: 8, - ), - getServiceBuilder(), - const SizedBox( - height: 4, - ), - Visibility( - visible: - viewModel.searchController.text.isEmpty, - child: Expanded(child: getCategoryWidget())), - Visibility( - visible: - viewModel.searchController.text.isNotEmpty, - child: Expanded( - child: - getItemGrid(viewModel.searchedItems))) - ], - )), - (!viewModel.isPortrait && DeviceUtil.isTablet) - ? SizedBox( - width: 330, - child: SingleChildScrollView( - child: Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10), - ), - padding: - const EdgeInsets.fromLTRB(6, 0, 0, 0), - child: getCartHoldContainer(), - ), - )) - : Container(), + searchBarBuilder(), + AppSpaces.verticalMedium, + getServiceBuilder(), + AppSpaces.verticalSmall, + Visibility( + visible: viewModel.searchController.isEmpty, + child: Expanded(child: getCategoryWidget())), + Visibility( + visible: viewModel.searchController.isNotEmpty, + child: Expanded( + child: getItemGrid(viewModel.searchedItems))) ], - ), - ), - ); - }), - ))), - onWillPop: () { - viewModel.dispose(); - return Future.value(false); - }); + )), + (!viewModel.isPortrait && DeviceUtil.isTablet) + ? SizedBox( + width: 330, + child: SingleChildScrollView( + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + ), + padding: const EdgeInsets.fromLTRB(6, 0, 0, 0), + child: getCartHoldContainer(), + ), + )) + : Container(), + ], + ), + ), + ); + }), + ))); } Widget getCategoryWidget() { - if (viewModel.isInternetConnected) { + if (isConnected) { return tabCategory(); } else { - print('aaaaaofflie'); return StreamBuilder>( stream: objectbox.getCategories(), builder: (context, snapshot) { @@ -182,13 +176,11 @@ class _TabBarHomeVCState extends BaseStatefulState { ? SingleChildScrollView( child: Column( children: [ - const SizedBox( - height: 4, - ), - viewModel.isInternetConnected + AppSpaces.verticalSmall, + isConnected ? SizedBox(height: 42, child: getItemSubcategory(context)) : getItemSubcategory(context), - viewModel.isInternetConnected + isConnected ? viewModel.isLoading ? AppLoader() : getItemGrid(viewModel.filteredItems) @@ -205,18 +197,15 @@ class _TabBarHomeVCState extends BaseStatefulState { } Widget getItemSubcategory(BuildContext context) { - if (viewModel.subCategoryItems.isNotEmpty && - viewModel.isInternetConnected) { + if (viewModel.subCategoryItems.isNotEmpty && isConnected) { var itemsList = viewModel.subCategoryItems; return subItemList(itemsList); - } else if (!viewModel.isInternetConnected) { - print('offlinesub'); + } else if (!isConnected) { return StreamBuilder>( stream: objectbox.getSubCategories( viewModel.itemCategories[viewModel.categoryPosition].id), builder: (context, snapshot) { if (snapshot.hasData) { - print('data'); viewModel.subCategoryItems.clear(); viewModel.subCategoryItems.addAll(snapshot.data ?? []); if (viewModel.subCategoryItems.isNotEmpty) { @@ -224,7 +213,6 @@ class _TabBarHomeVCState extends BaseStatefulState { .subCategoryItems[viewModel.selectedSubCategoryPosition].id; return subItemList(viewModel.subCategoryItems); } else { - print('no data'); return const EmptyDataWidget(); } } else { @@ -233,7 +221,9 @@ class _TabBarHomeVCState extends BaseStatefulState { }, ); } else { - return Center(child: Container()); + return AppError( + error: 'No Sub-Category found for this Category', + ); } } @@ -243,11 +233,10 @@ class _TabBarHomeVCState extends BaseStatefulState { viewModel.selectedProductId, viewModel.selectedDeliveryPartner), builder: (context, snapshot) { if (snapshot.hasData) { - print('getOfflineItem'); viewModel.updateItemList(snapshot.data ?? []); return getItemGrid(viewModel.filteredItems); } else { - return Container(); + return AppLoader(); } }, ); @@ -268,16 +257,28 @@ class _TabBarHomeVCState extends BaseStatefulState { color: MyColors.white, child: GestureDetector( onTap: () { - if (!CreateAndUpdateOrder.cartOrder - .isThere(filteredItems[i].id)) { - addItem(filteredItems[i]); + if (!filteredItems[i].isUnlimitedQuantity && + filteredItems[i].totalAddedQuantity <= 0 && + !filteredItems[i].isCombo) { + } else { + if (!CreateAndUpdateOrder.cartOrder + .isThere(filteredItems[i].itemId)) { + addItem(filteredItems[i]); + } else { + increaseItem(filteredItems[i]); + } } }, child: ProductItemView( storeItems: filteredItems[i], viewModel: viewModel, addItem: () { - addItem(filteredItems[i]); + if (!filteredItems[i].isUnlimitedQuantity && + filteredItems[i].totalAddedQuantity <= 0 && + !filteredItems[i].isCombo) { + } else { + addItem(filteredItems[i]); + } }, showComboInformation: () { showComboPopup(filteredItems[i]); @@ -300,6 +301,8 @@ class _TabBarHomeVCState extends BaseStatefulState { ); } else if (viewModel.isLoading) { return AppLoader(); + } else if (viewModel.subCategoryItems.isEmpty) { + return Container(); } else { return const Center(child: EmptyDataWidget()); } @@ -320,12 +323,24 @@ class _TabBarHomeVCState extends BaseStatefulState { if (!mounted) return; try { - showProgress(); - await viewModel.setModifier(result, isItemAdd, item); - checkState(); + if (result != null) { + showProgress(); + await viewModel.setModifier(result, isItemAdd, item); + checkState(); + } } catch (c) {} } + showCounters() { + showDialog( + barrierColor: Colors.black26, + context: context, + builder: (context) { + return const CheckInPopUp(); + }, + ); + } + Future addComboPopup(StoreItems item, bool isItemAdd) async { final result = await showDialog( barrierColor: Colors.black26, @@ -411,8 +426,7 @@ class _TabBarHomeVCState extends BaseStatefulState { } Future showPaymentOption( - String orderStatus, bool paymentStatus, double cartAmount, - {String? orderId}) async { + String orderStatus, bool paymentStatus, double cartAmount) async { final result = await showDialog( barrierColor: Colors.black26, context: context, @@ -424,14 +438,16 @@ class _TabBarHomeVCState extends BaseStatefulState { ); }, ); - if (result != null) { showProgress(); List data = result; - await viewModel.getCartIdFromServer(); - await viewModel.sendToKitchen(data[0], data[1], data[2], data[3], data[4], - data[5], data[6], orderId ?? ''); - await viewModel.getStoreDetails(); + if (isConnected) { + await viewModel.sendToKitchen(data[0], data[1], data[2], data[3], + data[4], data[5], data[6], data[7], data[8], data[9]); + await viewModel.getStoreDetails(); + } else { + await viewModel.updateOrderDb(data); + } checkState(); } } @@ -451,22 +467,8 @@ class _TabBarHomeVCState extends BaseStatefulState { Future updateOrderStatus(String status) async { if (CreateAndUpdateOrder.cartOrder.totalCartPrice != null) { showProgress(); - if (isConnected) { - await viewModel.getCartIdFromServer(); - await viewModel.sendToKitchen(false, status); - await viewModel.getStoreDetails(); - checkState(); - } else { - sharedPrefs.cartUniqueID = int.parse('0${sharedPrefs.getCartUniqueId}'); - CreateAndUpdateOrder.cartOrder.cartUniqueId = - sharedPrefs.getCartUniqueId; - CreateAndUpdateOrder.cartOrder.orderStatus = status; - CreateAndUpdateOrder.cartOrder.createdAt = - DataTimeFormat.formatDateFromPicketINVOICE(DateTime.now()); - objectbox.addOrder(CreateAndUpdateOrder.cartOrder); - await viewModel.clearCart(); - checkState(); - } + await viewModel.updateOrder(status); + checkState(); } } @@ -479,6 +481,7 @@ class _TabBarHomeVCState extends BaseStatefulState { if (snapshot.hasData) { viewModel.services.clear(); viewModel.services.addAll(snapshot.data ?? []); + // viewModel.getSelectedService(); return GridView.builder( padding: EdgeInsets.zero, shrinkWrap: true, @@ -539,7 +542,7 @@ class _TabBarHomeVCState extends BaseStatefulState { Visibility( visible: viewModel.count(), child: SizedBox( - width: 105, + width: 90, child: CustomSimpleButton( textColor: MyColors.white, backGroundColor: @@ -567,7 +570,7 @@ class _TabBarHomeVCState extends BaseStatefulState { children: [ SizedBox( height: viewModel.height - 155, - child: viewModel.isInternetConnected + child: isConnected ? getHoldItem(context) : getDbHoldItem(context), ) @@ -600,7 +603,7 @@ class _TabBarHomeVCState extends BaseStatefulState { }, onCancel: () { viewModel.updateOrderStatus( - cartItems[position].id!, "cancelled"); + cartItems[position].id!, Constants.cancelled); }, actionButtonHeading: viewModel.getOrderText(context, cartItems[position]), @@ -625,7 +628,7 @@ class _TabBarHomeVCState extends BaseStatefulState { Widget getDbHoldItem(BuildContext context) { return StreamBuilder>( - stream: objectbox.getOrders(Constants.holdOrder), + stream: objectbox.getHoldOrders(), builder: (context, snapshot) { if (snapshot.hasData) { var cartItems = snapshot.data!; @@ -678,8 +681,6 @@ class _TabBarHomeVCState extends BaseStatefulState { physics: const AlwaysScrollableScrollPhysics(), shrinkWrap: true, itemBuilder: (c, position) { - print('notes'); - print(cartItems[position].noteForItem); try { viewModel.noteControllers.add(TextEditingController( text: cartItems[position] @@ -748,8 +749,8 @@ class _TabBarHomeVCState extends BaseStatefulState { ); if (result != null) { - viewModel.setSelectedService('DELIVERY PARTNER'); - if (viewModel.isInternetConnected) { + viewModel.setSelectedService(Constants.deliveryPartnerService); + if (isConnected) { viewModel.getItems( viewModel.selectedCategoryId, viewModel.selectedProductId, true, 1, deliveryPartnerId: result); @@ -769,6 +770,7 @@ class _TabBarHomeVCState extends BaseStatefulState { ); if (result != null) { + await viewModel.checkLastSelectedService(); viewModel.setDineTable(result); } } @@ -776,16 +778,17 @@ class _TabBarHomeVCState extends BaseStatefulState { Widget searchBarBuilder() { return SizedBox( height: 38, - child: TextField( - controller: viewModel.searchController, + child: TextFormField( + initialValue: viewModel.searchController, onChanged: (value) { + viewModel.searchController = value; Future.delayed(const Duration(milliseconds: 500), () { viewModel.searchItems(value); }); }, - style: ThemeText.textStyleH2Black, + style: ThemeText.textStyleNormalMedium, decoration: InputDecoration( - hintText: AppLocalizations.of(context)!.search, + hintText: 'Search Product Name or Product Code', prefixIcon: const Icon(Icons.search), fillColor: Colors.white, filled: true, @@ -793,13 +796,13 @@ class _TabBarHomeVCState extends BaseStatefulState { enabledBorder: OutlineInputBorder( borderSide: const BorderSide( width: 1, //<-- SEE HERE - color: Colors.white, + color: Colors.transparent, ), borderRadius: BorderRadius.circular(19.0), ), focusedBorder: OutlineInputBorder( borderSide: - const BorderSide(color: MyColors.strokeColor, width: 1.0), + const BorderSide(color: MyColors.textColorGray, width: 0.5), borderRadius: BorderRadius.circular(8.0), ), )), @@ -824,9 +827,7 @@ class _TabBarHomeVCState extends BaseStatefulState { getCartHoldBuilder(), ], )), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisSize: MainAxisSize.max, @@ -854,7 +855,7 @@ class _TabBarHomeVCState extends BaseStatefulState { Align( alignment: Alignment.centerRight, child: Text( - '${AppLocalizations.of(context)!.total_amount} ${CreateAndUpdateOrder.cartOrder.totalCartPrice ?? 0.0} ${sharedPrefs.currency}', + '${AppLocalizations.of(context)!.total_amount} ${CreateAndUpdateOrder.cartOrder.totalCartPrice?.toStringAsFixed(2) ?? 0.0} ${sharedPrefs.currency}', style: ThemeText.textStyleNormalWhite, ), ), @@ -863,6 +864,19 @@ class _TabBarHomeVCState extends BaseStatefulState { ), onTap: () async { if (CreateAndUpdateOrder.cartOrder.totalCartPrice != null) { + showProgress(); + if (isConnected) { + await viewModel.getCartIdFromServer(); + } else { + sharedPrefs.cartUniqueID = + int.parse('0${sharedPrefs.getCartUniqueId}'); + CreateAndUpdateOrder.cartOrder.cartUniqueId = + sharedPrefs.getCartUniqueId; + CreateAndUpdateOrder.cartOrder.createdAt = + DataTimeFormat.formatDateFromPicketINVOICE( + DateTime.now()); + } + hideProgressBar(); showPaymentOption("", false, CreateAndUpdateOrder.cartOrder.totalCartPrice!); } @@ -916,14 +930,16 @@ class _TabBarHomeVCState extends BaseStatefulState { itemBuilder: (c, position) { return GestureDetector( onTap: () { + viewModel.selectedSubCategoryPosition = position; viewModel.selectedProductId = itemsList[position].id; - if (viewModel.isInternetConnected) { + if (isConnected) { viewModel.getItems( viewModel .itemCategories[viewModel.categoryPosition].id, viewModel.selectedProductId, true, - position); + position, + deliveryPartnerId: viewModel.selectedDeliveryPartner); } else { viewModel.setSubCategoryPosition(position); } @@ -936,18 +952,19 @@ class _TabBarHomeVCState extends BaseStatefulState { itemCount: itemsList.length, ), ), - viewModel.isInternetConnected ? Container() : getOfflineItem(), + isConnected ? Container() : getOfflineItem(), ], ); } void checkState() { Utils.hideProgressBar(context); + if (viewModel.cashierState == CashierState.createOrder) { Navigator.push( context, MaterialPageRoute( - builder: (context) => PrintInvoiceVC( + builder: (context) => PrintReceiptVC( id: viewModel.createOrderId, )), ); @@ -967,7 +984,7 @@ class _TabBarHomeVCState extends BaseStatefulState { Future addItem(StoreItems storeItem) async { if (storeItem.isCombo) { addComboPopup(storeItem, true); - } else if (storeItem.modifiers!.isNotEmpty) { + } else if (viewModel.getIsModifier(storeItem)) { showModifiers(storeItem, true); } else { showProgress(); @@ -979,12 +996,14 @@ class _TabBarHomeVCState extends BaseStatefulState { Future increaseItem(StoreItems storeItem) async { if (storeItem.isCombo) { addComboPopup(storeItem, false); - } else if (storeItem.modifiers!.isNotEmpty) { + } else if (viewModel.getIsModifier(storeItem)) { showModifiers(storeItem, false); } else { showProgress(); var item = storeItem; - item.quantity = item.quantity + 1; + item.noteForItem = + CreateAndUpdateOrder.cartOrder.getNotes(item, item.productId); + item.quantity = item.quantity! + 1; await viewModel.increaseItem(item, ""); checkState(); } @@ -1006,20 +1025,22 @@ class _TabBarHomeVCState extends BaseStatefulState { Utils.progressDialogue(context); } - void _serviceTap(int i) { + Future _serviceTap(int i) async { if (viewModel.services[i].name .toString() .replaceAll(' ', '') .toLowerCase() == - 'dinein') { + Constants.dineIn) { showDineInTable(); } else if (viewModel.services[i].name .toString() .replaceAll(' ', '') .toLowerCase() == - 'deliverypartner') { + Constants.deliveryPartner) { showDeliveryPartners(); } else { + await viewModel.checkLastSelectedService(); + viewModel.selectedDeliveryPartner = ''; viewModel.changeServiceType(i); } } diff --git a/lib/application/views/create_order_module/views/popups/CashOutVC.dart b/lib/application/views/create_order_module/views/popups/CashOutVC.dart index cdb4dfa..b25df29 100644 --- a/lib/application/views/create_order_module/views/popups/CashOutVC.dart +++ b/lib/application/views/create_order_module/views/popups/CashOutVC.dart @@ -3,7 +3,7 @@ import 'package:provider/provider.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/utils/AppLoader.dart'; import 'package:wosull/application/utils/CRUDOperatoinState.dart'; -import 'package:wosull/application/views/authModule/viewModel/CheckInViewModel.dart'; +import 'package:wosull/application/views/authModule/checkinViews/viewModel/CheckInViewModel.dart'; import 'package:wosull/widgets/CustomOptionalTitle.dart'; import 'package:wosull/widgets/CustomSimpleButton.dart'; import 'package:wosull/widgets/CustomTextFieldForm.dart'; @@ -38,82 +38,76 @@ class _CashOutVCState extends State { if (viewModel.isGettingData) { viewModel.getCounterById(); } - return WillPopScope( - onWillPop: () { - viewModel.dispose(); - return Future.value(false); - }, - child: Directionality( - textDirection: TextDirection.ltr, - child: Dialog( - elevation: 0, - backgroundColor: const Color(0xffffffff), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(15.0), - ), - child: OrientationBuilder(builder: (c, orientation) { - isPortrait = MediaQuery.of(c).orientation == Orientation.portrait; + return Directionality( + textDirection: TextDirection.ltr, + child: Dialog( + elevation: 0, + backgroundColor: const Color(0xffffffff), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: OrientationBuilder(builder: (c, orientation) { + isPortrait = MediaQuery.of(c).orientation == Orientation.portrait; - return SingleChildScrollView( - child: Container( - width: MediaQuery.of(c).orientation == Orientation.landscape - ? MediaQuery.of(context).size.width / 1.2 - : double.infinity, - padding: const EdgeInsets.only(bottom: 8), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.end, - mainAxisAlignment: MainAxisAlignment.end, - children: [ - DialogHeader(title: 'Cash Out'), - Padding( - padding: const EdgeInsets.all(16), - child: viewModel.isGettingData - ? AppLoader() - : getCashOutAmount(), - ), - Padding( - padding: const EdgeInsets.only(right: 16), - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - SizedBox( - width: 120, - child: CustomSimpleButton( - textColor: MyColors.white, - isLoading: viewModel.isLoading, - backGroundColor: MyColors.blueThemeColor, - onPressed: () async { - await viewModel.cashOutParams(); - checkState(); - }, - heading: 'Cashout', - ), + return SingleChildScrollView( + child: Container( + width: MediaQuery.of(c).orientation == Orientation.landscape + ? MediaQuery.of(context).size.width / 1.2 + : double.infinity, + padding: const EdgeInsets.only(bottom: 8), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + DialogHeader(title: 'Cash Out'), + Padding( + padding: const EdgeInsets.all(16), + child: viewModel.isGettingData + ? AppLoader() + : getCashOutAmount(), + ), + Padding( + padding: const EdgeInsets.only(right: 16), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + SizedBox( + width: 120, + child: CustomSimpleButton( + textColor: MyColors.white, + isLoading: viewModel.isLoading, + backGroundColor: MyColors.blueThemeColor, + onPressed: () async { + await viewModel.cashOutParams(); + checkState(); + }, + heading: 'Cashout', ), - const SizedBox( - width: 8, + ), + const SizedBox( + width: 8, + ), + SizedBox( + width: 120, + child: CustomSimpleButton( + textColor: MyColors.white, + backGroundColor: MyColors.blueThemeColor, + onPressed: () { + Navigator.pop(context, false); + }, + heading: 'Cancel', ), - SizedBox( - width: 120, - child: CustomSimpleButton( - textColor: MyColors.white, - backGroundColor: MyColors.blueThemeColor, - onPressed: () { - Navigator.pop(context, false); - }, - heading: 'Cancel', - ), - ) - ], - ), - ) - ], - ), + ) + ], + ), + ) + ], ), - ); - }), - )), - ); + ), + ); + }), + )); } void checkState() { @@ -136,7 +130,7 @@ class _CashOutVCState extends State { onChanged: (value) { viewModel.setCashOutAmount(value); }, - hintText: '0,0') + hintText: '0.0') ], ); } diff --git a/lib/application/views/create_order_module/views/popups/CounterCloseVC.dart b/lib/application/views/create_order_module/views/popups/CounterCloseVC.dart new file mode 100644 index 0000000..1be1205 --- /dev/null +++ b/lib/application/views/create_order_module/views/popups/CounterCloseVC.dart @@ -0,0 +1,115 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/CRUDOperatoinState.dart'; +import 'package:wosull/application/views/create_order_module/viewModels/CounterCloseViewMdoel.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/widgets/CustomOptionalTitle.dart'; +import 'package:wosull/widgets/CustomSimpleButton.dart'; +import 'package:wosull/widgets/CustomTextFieldForm.dart'; +import 'package:wosull/widgets/DialogHeader.dart'; + +class CounterCloseVC extends StatefulWidget { + const CounterCloseVC({super.key}); + + @override + State createState() => _CounterCloseVCState(); +} + +class _CounterCloseVCState extends State { + bool isPortrait = true; + var viewModel = CounterCloseViewModel(); + + @override + void initState() { + context.read().getBusinessRegisterById(); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Directionality( + textDirection: TextDirection.ltr, + child: Dialog( + elevation: 0, + backgroundColor: const Color(0xffffffff), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: OrientationBuilder(builder: (c, orientation) { + isPortrait = MediaQuery.of(c).orientation == Orientation.portrait; + + return SingleChildScrollView( + child: Container( + width: !isPortrait + ? MediaQuery.of(context).size.width / 1.2 + : double.infinity, + padding: const EdgeInsets.only(bottom: 8), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + DialogHeader(title: 'Close Counter'), + Padding( + padding: const EdgeInsets.all(12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle(hint: 'Credit'), + AppSpaces.verticalSmall, + CustomTextFieldForm( + keyboardType: TextInputType.number, + initialValue: viewModel.creditAmount, + onChanged: (value) { + viewModel.creditAmount = value; + }, + hintText: '0.0'), + AppSpaces.verticalMedium, + const CustomOptionalTitle(hint: 'Cash'), + AppSpaces.verticalSmall, + CustomTextFieldForm( + keyboardType: TextInputType.number, + initialValue: viewModel.cashAmount, + onChanged: (value) { + viewModel.cashAmount = value; + }, + hintText: '0.0'), + ], + ), + ), + Padding( + padding: const EdgeInsets.only(right: 12), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + SizedBox( + width: 120, + child: CustomSimpleButton( + textColor: MyColors.white, + backGroundColor: MyColors.blueThemeColor, + isLoading: viewModel.isLoading, + onPressed: () async { + await viewModel.isValidate(); + checkState(); + }, + heading: 'Close', + ), + ), + ], + ), + ) + ], + ), + ), + ); + }), + )); + } + + void checkState() { + if (viewModel.crudOperation == CRUDOperationState.add) { + Navigator.pop(context, true); + } + } +} diff --git a/lib/application/views/create_order_module/views/popups/DeliveryPartnerPopUp.dart b/lib/application/views/create_order_module/views/popups/DeliveryPartnerPopUp.dart index 92cb505..1d0ff63 100644 --- a/lib/application/views/create_order_module/views/popups/DeliveryPartnerPopUp.dart +++ b/lib/application/views/create_order_module/views/popups/DeliveryPartnerPopUp.dart @@ -1,12 +1,12 @@ import 'package:flutter/material.dart'; -import 'package:group_radio_button/group_radio_button.dart'; import 'package:provider/provider.dart'; +import 'package:sizer/sizer.dart'; import 'package:wosull/application/model/DeliveryPartner/GetDeliveryPartner.dart'; import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/theme/MyFonts.dart'; import 'package:wosull/application/utils/AppLoader.dart'; import 'package:wosull/application/views/inventorymodule/deliveryPartnerViews/viewModels/DeliveryPartnerPriceViewModel.dart'; import 'package:wosull/helpers/AppSpaces.dart'; -import 'package:wosull/helpers/ThemeText.dart'; import 'package:wosull/main.dart'; import 'package:wosull/widgets/CustomSimpleButton.dart'; import 'package:wosull/widgets/DialogHeader.dart'; @@ -31,6 +31,12 @@ class _DeliveryPartnerPopUpState extends State { super.initState(); } + @override + void dispose() { + viewModel.disposeData(); + super.dispose(); + } + @override Widget build(BuildContext context) { viewModel = context.watch(); @@ -40,16 +46,18 @@ class _DeliveryPartnerPopUpState extends State { elevation: 0, backgroundColor: const Color(0xffffffff), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(15.0), + borderRadius: BorderRadius.circular(8.0), ), child: OrientationBuilder(builder: (c, orientation) { + viewModel.isPortrait = + MediaQuery.of(context).orientation == Orientation.portrait; return SingleChildScrollView( child: Container( + padding: const EdgeInsets.only(bottom: 8), width: MediaQuery.of(context).orientation == Orientation.landscape ? MediaQuery.of(context).size.width / 1.3 : double.infinity, - color: MyColors.fillColor, child: Column( crossAxisAlignment: CrossAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.start, @@ -71,8 +79,8 @@ class _DeliveryPartnerPopUpState extends State { textColor: MyColors.white, height: 38, onPressed: () { - Navigator.pop( - context, viewModel.selectedType.id); + Navigator.pop(context, + viewModel.selectedDeliveryPartner.id); }, heading: 'Apply', ), @@ -106,37 +114,89 @@ class _DeliveryPartnerPopUpState extends State { stream: objectbox.getDeliveryPartners(), builder: (context, snapshot) { if (snapshot.hasData) { - print('offline partners'); - return partnersWidget(snapshot.data ?? []); + if (viewModel.filteredList.isEmpty) { + viewModel.filteredList.addAll(snapshot.data ?? []); + } + if (viewModel.filteredList.isNotEmpty) { + return partnersWidget(viewModel.filteredList); + } else { + return const EmptyDataWidget(); + } } else { - return const EmptyDataWidget(); + return AppLoader(); } }, ); } - Widget partnersWidget(partners) { - print(viewModel.selectedType.name); - return RadioGroup.builder( - direction: Axis.vertical, - horizontalAlignment: MainAxisAlignment.start, - textStyle: ThemeText.textStyleValue, - groupValue: viewModel.selectedType, - onChanged: (value) { - viewModel.changeSelectedType(value); - }, - items: partners, - itemBuilder: (item) => RadioButtonBuilder( - item.name, - ), - activeColor: MyColors.blueThemeColor, - fillColor: - MaterialStateColor.resolveWith((states) => MyColors.blueThemeColor), - ); + Widget partnersWidget(List partners) { + return GridView.builder( + shrinkWrap: true, + itemCount: partners.length, + physics: const NeverScrollableScrollPhysics(), + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: viewModel.isPortrait ? 2 : 3, + mainAxisExtent: SizerUtil.deviceType == DeviceType.tablet ? 70 : 90, + crossAxisSpacing: 0, + mainAxisSpacing: 0, + ), + itemBuilder: (context, i) { + return GestureDetector( + onTap: () { + viewModel.changeSelectedType(partners[i], i); + }, + child: Card( + elevation: 5, + color: viewModel.selectedItem == i + ? MyColors.blueThemeColor + : MyColors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: Container( + margin: const EdgeInsets.all(4), + padding: const EdgeInsets.all(4), + decoration: const BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(8)), + ), + child: Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + partners[i].name, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: MyFonts.normal, + fontFamily: MyFonts.Bold, + color: viewModel.selectedItem == i + ? MyColors.white + : MyColors.textColorBlack, + fontWeight: FontWeight.bold), + ), + AppSpaces.verticalLarge, + Text('${partners[i].totalItemCount} Product Affected', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 11, + fontFamily: MyFonts.DMREGULAR, + color: viewModel.selectedItem == i + ? MyColors.white + : MyColors.textColorBlack, + )), + ], + )) + ], + ), + ), + )); + }); } showPartners() { - print('abc'); if (isConnected) { return partnersFromServer(); } else { diff --git a/lib/application/views/create_order_module/views/popups/DineInPopup.dart b/lib/application/views/create_order_module/views/popups/DineInPopup.dart index 84d4815..e4dbc8e 100644 --- a/lib/application/views/create_order_module/views/popups/DineInPopup.dart +++ b/lib/application/views/create_order_module/views/popups/DineInPopup.dart @@ -1,14 +1,16 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:provider/provider.dart'; import 'package:sizer/sizer.dart'; -import 'package:wosull/application/ViewModel/InventoryViewModel.dart'; import 'package:wosull/application/model/tables/GetStoreTable.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/theme/MyFonts.dart'; import 'package:wosull/application/utils/AppLoader.dart'; -import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/create_order_module/viewModels/DineInViewModel.dart'; import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/main.dart'; +import 'package:wosull/widgets/BoxContainer.dart'; +import 'package:wosull/widgets/CustomSimpleButton.dart'; import 'package:wosull/widgets/DialogHeader.dart'; import 'package:wosull/widgets/EmptyDataWidget.dart'; @@ -22,43 +24,36 @@ class DineInPopup extends StatefulWidget { } class _DineInPopupState extends State { - bool isPortrait = true; - int selectedItem = -1; - int selectedNo = 0; - bool isLoading = true; - List tablesSeats = []; - List tables = []; - List filteredTables = []; + var viewModel = DineInViewModel(); @override void initState() { - // TODO: implement initState super.initState(); if (isConnected) { - getTables(selectedItem); + context.read().getTables(viewModel.selectedItem); } else { - isLoading = false; + viewModel.isLoading = false; } } @override Widget build(BuildContext context) { + viewModel = context.watch(); return Directionality( textDirection: TextDirection.ltr, child: Dialog( elevation: 0, backgroundColor: const Color(0xffffffff), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(15.0), + borderRadius: BorderRadius.circular(8.0), ), child: OrientationBuilder(builder: (c, orientation) { return SingleChildScrollView( - child: Container( + child: SizedBox( width: MediaQuery.of(context).orientation == Orientation.landscape ? MediaQuery.of(context).size.width / 1.3 : double.infinity, - color: MyColors.fillColor, child: Column( crossAxisAlignment: CrossAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.start, @@ -75,25 +70,16 @@ class _DineInPopupState extends State { AppSpaces.verticalMedium, SizedBox( width: 100, - child: ElevatedButton( - style: ElevatedButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - backgroundColor: MyColors.blueThemeColor, - minimumSize: const Size.fromHeight(38), // NEW - ), + child: CustomSimpleButton( + backGroundColor: MyColors.blueThemeColor, + textColor: MyColors.white, onPressed: () { Navigator.pop( - context, filteredTables[selectedItem]); + context, + viewModel.filteredTables[ + viewModel.selectedItem]); }, - child: Text( - AppLocalizations.of(context)!.apply, - style: const TextStyle( - fontSize: MyFonts.normalButton, - color: MyColors.white, - fontFamily: MyFonts.Bold), - ), + heading: AppLocalizations.of(context)!.apply, ), ), ], @@ -112,9 +98,9 @@ class _DineInPopupState extends State { } Widget getTablesBuilder(BuildContext context) { - if (!isLoading) { + if (!viewModel.isLoading) { if (isConnected) { - return gridBuilder(filteredTables); + return gridBuilder(viewModel.filteredTables); } else { return tablesFromDatabase(); } @@ -125,14 +111,14 @@ class _DineInPopupState extends State { Widget tablesFromDatabase() { return StreamBuilder>( - stream: objectbox.getTablesWithOccupants(tablesSeats.isEmpty + stream: objectbox.getTablesWithOccupants(viewModel.tablesSeats.isEmpty ? 0 - : selectedNo == 0 + : viewModel.selectedNo == 0 ? 0 - : int.parse(tablesSeats[selectedNo])), + : int.parse(viewModel.tablesSeats[viewModel.selectedNo])), builder: (context, snapshot) { if (snapshot.hasData) { - setTablesData(snapshot.data ?? []); + viewModel.setTablesData(snapshot.data ?? []); return gridBuilder(snapshot.data ?? []); } else { return const EmptyDataWidget(); @@ -151,7 +137,7 @@ class _DineInPopupState extends State { itemCount: itemsList.length, physics: const NeverScrollableScrollPhysics(), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: isPortrait ? 3 : 4, + crossAxisCount: viewModel.isPortrait ? 3 : 4, mainAxisExtent: SizerUtil.deviceType == DeviceType.tablet ? 70 : 90, crossAxisSpacing: 0, @@ -160,11 +146,7 @@ class _DineInPopupState extends State { itemBuilder: (context, i) { return GestureDetector( onTap: () { - setState(() { - if (itemsList[i].isAvailable) { - selectedItem = i; - } - }); + viewModel.updateSelectedTable(i); }, child: Container( margin: const EdgeInsets.all(4), @@ -174,7 +156,7 @@ class _DineInPopupState extends State { const BorderRadius.all(Radius.circular(12)), color: !itemsList[i].isAvailable ? MyColors.fillRed - : selectedItem == i + : viewModel.selectedItem == i ? MyColors.greenColor : MyColors.fillColor3), child: Row( @@ -192,7 +174,7 @@ class _DineInPopupState extends State { fontFamily: MyFonts.Bold, color: !itemsList[i].isAvailable ? MyColors.white - : selectedItem == i + : viewModel.selectedItem == i ? MyColors.white : MyColors.textColorBlack, fontWeight: FontWeight.bold), @@ -206,7 +188,7 @@ class _DineInPopupState extends State { fontFamily: MyFonts.DMREGULAR, color: !itemsList[i].isAvailable ? MyColors.white - : selectedItem == i + : viewModel.selectedItem == i ? MyColors.white : MyColors.textColorBlack, )), @@ -220,40 +202,6 @@ class _DineInPopupState extends State { ); } - Future> getTables(int selectedItem) async { - // = await (Connectivity().checkConnectivity()); - var items = []; - if (isConnected) { - final viewModel = InventoryViewModel(); - await viewModel - .getData(Constants.GET_STORE_TABLES, Constants.getStorePayload()) - .then((value) { - final response = GetStoreTable.fromJson(value); - if (response.success && response.storeTables.isNotEmpty) { - setState(() { - setTablesData(response.storeTables); - }); - } else { - tables.clear(); - filteredTables.clear(); - setState(() { - isLoading = false; - }); - } - }).onError((error, stackTrace) { - tables.clear(); - filteredTables.clear(); - setState(() { - isLoading = false; - }); - }); - } else { - isLoading = false; - } - - return items; - } - Widget getSizeList() { return ListView.builder( scrollDirection: Axis.horizontal, @@ -261,20 +209,7 @@ class _DineInPopupState extends State { itemBuilder: (context, position) { return GestureDetector( onTap: () { - setState(() { - selectedNo = position; - filteredTables.clear(); - if (selectedNo == 0) { - filteredTables.addAll(tables); - } else { - for (var table in tables) { - if (table.noOfOccupants.toString() == - tablesSeats[selectedNo].toString()) { - filteredTables.add(table); - } - } - } - }); + viewModel.onFilterSeats(position); }, child: Padding( padding: const EdgeInsets.all(2), @@ -288,15 +223,15 @@ class _DineInPopupState extends State { color: MyColors.strokeColor, width: 1, ), - color: selectedNo == position + color: viewModel.selectedNo == position ? MyColors.blueThemeColor : MyColors.fillColor, borderRadius: BorderRadius.circular(8.0), ), child: Center( - child: Text(tablesSeats[position], + child: Text(viewModel.tablesSeats[position], style: TextStyle( - color: selectedNo == position + color: viewModel.selectedNo == position ? MyColors.white : MyColors.textColorBlack, fontSize: MyFonts.normal, @@ -308,32 +243,19 @@ class _DineInPopupState extends State { ), ); }, - itemCount: tablesSeats.length, + itemCount: viewModel.tablesSeats.length, ); } - Future setTablesData(List storeTables) async { - tables.clear(); - if (tablesSeats.isEmpty) { - tablesSeats.add('All'); - for (var item in storeTables) { - tablesSeats.add(item.noOfOccupants.toString()); - } - } - tables.addAll(storeTables); - filteredTables.addAll(storeTables); - isLoading = false; - } - Widget availableDetails() { return Column( children: [ - isPortrait + viewModel.isPortrait ? Column( children: [ Row( children: [ - const Text( + Text( 'Seats:', style: TextStyle( fontSize: MyFonts.H1, @@ -341,9 +263,7 @@ class _DineInPopupState extends State { fontFamily: MyFonts.Bold, color: MyColors.black), ), - const SizedBox( - width: 4, - ), + AppSpaces.horizontalSmall, Flexible( child: SizedBox( height: SizerUtil.deviceType == DeviceType.tablet @@ -359,71 +279,25 @@ class _DineInPopupState extends State { mainAxisAlignment: MainAxisAlignment.start, mainAxisSize: MainAxisSize.max, children: [ - Container( - width: 24, - height: 24, - decoration: const BoxDecoration( - color: MyColors.fillColor3, - borderRadius: BorderRadius.all(Radius.circular(4)), - ), - ), - const SizedBox( - width: 4, - ), - Text( - AppLocalizations.of(context)!.available, - style: const TextStyle( - fontSize: MyFonts.normal, - fontWeight: FontWeight.bold, - fontFamily: MyFonts.Bold, - color: MyColors.black), - ), - const SizedBox( - width: 8, - ), - Container( - width: 24, - height: 24, - decoration: const BoxDecoration( - color: MyColors.fillRed, - borderRadius: BorderRadius.all(Radius.circular(4)), - ), - ), - const SizedBox( - width: 4, - ), - Text( - AppLocalizations.of(context)!.not_available, - style: const TextStyle( - fontSize: MyFonts.normal, - fontWeight: FontWeight.bold, - fontFamily: MyFonts.Bold, - color: MyColors.black), - ), - const SizedBox( - width: 8, - ), - Container( - width: 24, - height: 24, - decoration: const BoxDecoration( - color: MyColors.greenColor, - borderRadius: BorderRadius.all(Radius.circular(4)), - ), - ), - const SizedBox( - width: 4, + Flexible( + child: BoxContainer( + fillColor: MyColors.fillColor3, + title: 'Available', + )), + AppSpaces.horizontalSmall, + Flexible( + child: BoxContainer( + fillColor: MyColors.fillRed, + title: AppLocalizations.of(context)!.not_available), ), - Text( - AppLocalizations.of(context)!.selected, - style: const TextStyle( - fontSize: MyFonts.normal, - fontWeight: FontWeight.bold, - fontFamily: MyFonts.Bold, - color: MyColors.black), + AppSpaces.horizontalSmall, + Flexible( + child: BoxContainer( + fillColor: MyColors.greenColor, + title: AppLocalizations.of(context)!.selected), ), ], - ) + ), ], ) : Row( @@ -431,7 +305,7 @@ class _DineInPopupState extends State { Expanded( child: Row( children: [ - const Text( + Text( 'Seats:', style: TextStyle( fontSize: MyFonts.H1, @@ -467,7 +341,7 @@ class _DineInPopupState extends State { ), Text( AppLocalizations.of(context)!.available, - style: const TextStyle( + style: TextStyle( fontSize: MyFonts.H2, fontWeight: FontWeight.bold, fontFamily: MyFonts.Bold, @@ -489,7 +363,7 @@ class _DineInPopupState extends State { ), Text( AppLocalizations.of(context)!.not_available, - style: const TextStyle( + style: TextStyle( fontSize: MyFonts.H2, fontWeight: FontWeight.bold, fontFamily: MyFonts.Bold, @@ -511,7 +385,7 @@ class _DineInPopupState extends State { ), Text( AppLocalizations.of(context)!.selected, - style: const TextStyle( + style: TextStyle( fontSize: MyFonts.H2, fontWeight: FontWeight.bold, fontFamily: MyFonts.Bold, @@ -521,9 +395,7 @@ class _DineInPopupState extends State { )) ], ), - const SizedBox( - height: 16, - ), + AppSpaces.verticalLarge, ], ); } diff --git a/lib/application/views/create_order_module/views/popups/ItemModifiersPopUp.dart b/lib/application/views/create_order_module/views/popups/ItemModifiersPopUp.dart index 4c52f1b..3421d0a 100644 --- a/lib/application/views/create_order_module/views/popups/ItemModifiersPopUp.dart +++ b/lib/application/views/create_order_module/views/popups/ItemModifiersPopUp.dart @@ -1,13 +1,17 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:objectbox/objectbox.dart'; +import 'package:provider/provider.dart'; import 'package:sizer/sizer.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; -import 'package:wosull/application/model/Modifiers/GetModifiersModel.dart'; import 'package:wosull/application/model/store/StoreItemsResponse.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/theme/MyFonts.dart'; +import 'package:wosull/application/views/create_order_module/viewModels/ItemModifiersViewModel.dart'; import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/widgets/CustomSimpleButton.dart'; +import 'package:wosull/widgets/CustomTextFieldForm.dart'; +import 'package:wosull/widgets/DialogHeader.dart'; +import 'package:wosull/widgets/HeadingText.dart'; class ItemModifiersPopUp extends StatefulWidget { late StoreItems item; @@ -19,48 +23,39 @@ class ItemModifiersPopUp extends StatefulWidget { } class _ItemModifiersPopUpState extends State { - bool isPortrait = true; - int selectedItem = -1; - List selectedModifier = []; - List? selectedOption = []; - - final noteController = TextEditingController(); + var viewModel = ItemModifiersViewModel(); @override void initState() { - // TODO: implement initState super.initState(); + context.read().initData(widget.item); + } - setState(() { - for (int i = 0; i < widget.item.modifiers!.length; i++) { - for (int j = 0; j < widget.item.modifiers![i].options!.length; j++) { - widget.item.modifiers![i].options![j].isSelected = false; - widget.item.modifiers![i].selected!.clear(); - } - } - selectedItem = -1; - selectedModifier = []; - }); + @override + void dispose() { + viewModel.disposeData(); + super.dispose(); } @override Widget build(BuildContext context) { + viewModel = context.watch(); return Directionality( textDirection: TextDirection.ltr, child: Dialog( elevation: 0, backgroundColor: const Color(0xffffffff), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(15.0), + borderRadius: BorderRadius.circular(8.0), ), child: OrientationBuilder(builder: (c, orientation) { - isPortrait = + viewModel.isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; return SingleChildScrollView( child: Container( margin: const EdgeInsets.all(8), - width: !isPortrait + width: !viewModel.isPortrait ? MediaQuery.of(context).size.width / 1.2 : double.infinity, color: MyColors.white, @@ -69,311 +64,167 @@ class _ItemModifiersPopUpState extends State { mainAxisAlignment: MainAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ - Row( - mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.max, - children: [ - const Expanded( - child: Padding( - padding: EdgeInsets.only(left: 16), - child: Text( - 'Select Modifiers', - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: MyFonts.H1, - fontFamily: MyFonts.Medium, - color: MyColors.textColorPopUp), - ), - )), - Align( - alignment: Alignment.topRight, - child: IconButton( - onPressed: () { - Navigator.pop(context, false); - }, - icon: const Icon(Icons.close)), - ), - ], - ), - Container( - height: 2, - color: MyColors.fillColorGray, - ), - const SizedBox( - height: 8, - ), + DialogHeader(title: 'Select Modifiers'), + AppSpaces.verticalMedium, Container( padding: const EdgeInsets.fromLTRB(8, 8, 8, 16), child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( + HeadingText( AppLocalizations.of(context)!.note, - style: const TextStyle( - fontSize: MyFonts.normalButton, - fontWeight: FontWeight.w600, - fontFamily: MyFonts.DMREGULAR, - color: MyColors.textColorPopUp), ), AppSpaces.verticalSmall, - TextField( - controller: noteController, - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: 16, - color: MyColors.black), - decoration: InputDecoration( - contentPadding: - const EdgeInsets.fromLTRB(8, 0, 8, 0), - hintText: 'Enter Note', - fillColor: MyColors.fillColor2, - filled: true, - focusedBorder: OutlineInputBorder( - borderSide: const BorderSide( - color: Colors.transparent, width: 1.0), - borderRadius: BorderRadius.circular(8.0), - ), - enabledBorder: OutlineInputBorder( - borderSide: const BorderSide( - width: 1, //<-- SEE HERE - color: Colors.transparent, - ), - borderRadius: BorderRadius.circular(8.0), - ), - ), + CustomTextFieldForm( + hintText: 'Enter Note', + onChanged: (String value) { + viewModel.noteController = value; + }, ), AppSpaces.verticalMedium, ListView.builder( physics: const NeverScrollableScrollPhysics(), shrinkWrap: true, itemBuilder: (context, position) { - return GridView.builder( - shrinkWrap: true, - itemCount: widget.item.modifiers![position] - .options!.length, - physics: const NeverScrollableScrollPhysics(), - gridDelegate: - SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: widget.item - .modifiers![position].options!.length, - mainAxisExtent: SizerUtil.deviceType == - DeviceType.mobile - ? 60 - : 80, - crossAxisSpacing: 0, - mainAxisSpacing: 0, - ), - itemBuilder: (context, i) { - return GestureDetector( - onTap: () { - setState(() { - var modifier = Modifier( - options: ToMany(items: []), - selected: ToMany(items: [])); - modifier = widget - .item.modifiers![position]; - - if (modifier.selected!.isEmpty) { - //for first time - widget.item.modifiers![position] - .isSelected = true; - widget + if (viewModel.item.modifiers[position].options + .isNotEmpty) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + HeadingText(viewModel + .item.modifiers[position].name), + AppSpaces.verticalSmall, + GridView.builder( + shrinkWrap: true, + itemCount: viewModel.item + .modifiers[position].options.length, + physics: + const NeverScrollableScrollPhysics(), + gridDelegate: + SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: viewModel .item - .modifiers![position] - .options![i] - .isSelected = true; - modifier.selected!.add(widget + .modifiers[position] + .options + .isEmpty + ? 1 + : viewModel .item - .modifiers![position] - .options![i]); - } - //if modifier parent is already added with child and multiple off ha - else if (modifier - .selected!.isNotEmpty && - !modifier.isMultiple) { - if (modifier.selected!.contains( - widget - .item - .modifiers![position] - .options![i])) { - modifier.selected!.remove(widget - .item - .modifiers![position] - .options![i]); - widget - .item - .modifiers![position] - .options![i] - .isSelected = false; - } else { - modifier.selected!.clear(); - for (int j = 0; - j < - widget + .modifiers[position] + .options + .length, + mainAxisExtent: + SizerUtil.deviceType == + DeviceType.mobile + ? 60 + : 80, + crossAxisSpacing: 0, + mainAxisSpacing: 0, + ), + itemBuilder: (context, i) { + return GestureDetector( + onTap: () { + viewModel + .onSelectModifierOption( + position, i); + }, + child: Container( + margin: const EdgeInsets.all(4), + padding: + const EdgeInsets.all(4), + decoration: BoxDecoration( + color: viewModel .item - .modifiers![ - position] - .options! - .length; - j++) { - widget - .item - .modifiers![position] - .options![j] - .isSelected = false; - } - widget - .item - .modifiers![position] - .options![i] - .isSelected = true; - modifier.selected!.add(widget - .item - .modifiers![position] - .options![i]); - } - //then we will remove already added item and will add new one - } - // else if (modifier.selected!.isNotEmpty && modifier.isMultiple!) { - // - // //then we will remove already added item and will add new one - // widget.item.modifiers[position].options![i].isSelected = true; - // modifier.selected!.add(widget.item.modifiers[position].options![i]); - // - // } - //if modifier parent is already added with child and multiple on ha - else if (!modifier.selected! - .contains(widget - .item - .modifiers![position] - .options![i]) && - modifier.isMultiple) { - //then we will add new option - widget - .item - .modifiers![position] - .options![i] - .isSelected = true; - modifier.selected!.add(widget - .item - .modifiers![position] - .options![i]); - } else { - modifier.selected!.remove(widget - .item - .modifiers![position] - .options![i]); - widget - .item - .modifiers![position] - .options![i] - .isSelected = false; - } - - // modifier.selectedModifierIndex = - // widget.item.quantity ?? 1; - - if (selectedModifier.isEmpty) { - selectedModifier.add(modifier); - } else { - var modi = selectedModifier - .indexWhere((element) => - element.id == - modifier.id); - if (modi >= 0) { - if (selectedModifier[modi] - .selected! - .isEmpty) { - selectedModifier - .removeAt(modi); - } - } else { - selectedModifier.add(modifier); - } - } - }); - }, - child: Container( - margin: const EdgeInsets.all(4), - padding: const EdgeInsets.all(4), - decoration: BoxDecoration( - color: widget - .item - .modifiers![position] - .options![i] - .isSelected - ? MyColors.blueThemeColor - : Colors.transparent, - border: Border.all( - width: 1, - color: widget - .item - .modifiers![position] - .options![i] - .isSelected - ? MyColors.blueThemeColor - : MyColors.fillColor3), - borderRadius: - const BorderRadius.all( - Radius.circular(12))), - child: Row( - children: [ - Expanded( - child: Column( - mainAxisAlignment: - MainAxisAlignment.center, - children: [ - Text( - widget - .item - .modifiers![position] - .options![i] - .name, - style: TextStyle( - fontSize: MyFonts.H2, - fontFamily: - MyFonts.Bold, - color: widget + .modifiers[position] + .options[i] + .isSelected + ? MyColors + .blueThemeColor + : Colors.transparent, + border: Border.all( + width: 1, + color: viewModel .item - .modifiers![ + .modifiers[ position] - .options![i] + .options[i] .isSelected - ? MyColors.white + ? MyColors + .blueThemeColor : MyColors - .textColorBlack, - fontWeight: - FontWeight.bold), - ), - const SizedBox( - height: 4, - ), - Text( - '${widget.item.modifiers![position].options![i].price.toString()} ${sharedPrefs.currency}', - style: TextStyle( - fontSize: MyFonts.normal, - fontFamily: - MyFonts.Medium, - color: widget + .fillColor3), + borderRadius: + const BorderRadius.all( + Radius.circular( + 12))), + child: Row( + children: [ + Expanded( + child: Column( + mainAxisAlignment: + MainAxisAlignment + .center, + children: [ + Text( + viewModel .item - .modifiers![ + .modifiers[ position] - .options![i] - .isSelected - ? MyColors.white - : MyColors - .textColorBlack, - ), - ), - ], - )) - ], - ), - )); - }); + .options[i] + .name, + style: TextStyle( + fontSize: + MyFonts.H2, + fontFamily: + MyFonts.Bold, + color: viewModel + .item + .modifiers[ + position] + .options[ + i] + .isSelected + ? MyColors + .white + : MyColors + .textColorBlack, + fontWeight: + FontWeight + .bold), + ), + AppSpaces.verticalSmall, + Text( + '${viewModel.item.modifiers[position].options[i].price.toString()} ${sharedPrefs.currency}', + style: TextStyle( + fontSize: + MyFonts.normal, + fontFamily: + MyFonts.Medium, + color: viewModel + .item + .modifiers[ + position] + .options[i] + .isSelected + ? MyColors.white + : MyColors + .textColorBlack, + ), + ), + ], + )) + ], + ), + )); + }) + ], + ); + } else { + return Container(); + } }, - itemCount: widget.item.modifiers!.length, + itemCount: viewModel.item.modifiers.length, ), AppSpaces.verticalMedium, Row( @@ -382,57 +233,29 @@ class _ItemModifiersPopUpState extends State { children: [ SizedBox( width: 100, - child: ElevatedButton( - style: ElevatedButton.styleFrom( - elevation: 0, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - backgroundColor: MyColors.fillColorGray2, - minimumSize: - const Size.fromHeight(38), // NEW - ), + child: CustomSimpleButton( + backGroundColor: MyColors.fillColorGray2, + textColor: MyColors.blueThemeColor, onPressed: () { Navigator.of(context).pop(); }, - child: Text( - "Skip", - style: TextStyle( - fontSize: MyFonts.normalButton, - color: MyColors.blueThemeColor, - fontFamily: MyFonts.Bold), - ), + heading: "Skip", ), ), - const SizedBox( - width: 10, - ), + AppSpaces.horizontalMedium, SizedBox( width: 100, - child: ElevatedButton( - style: ElevatedButton.styleFrom( - elevation: 0, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - backgroundColor: MyColors.blueThemeColor, - minimumSize: - const Size.fromHeight(38), // NEW - ), + child: CustomSimpleButton( + backGroundColor: MyColors.blueThemeColor, + textColor: MyColors.white, onPressed: () { var result = [ - selectedModifier, - noteController.text + viewModel.selectedModifier, + viewModel.noteController ]; Navigator.pop(context, result); }, - child: Text( - AppLocalizations.of(context)!.apply, - style: const TextStyle( - fontSize: MyFonts.normalButton, - color: MyColors.white, - fontFamily: MyFonts.Bold), - ), + heading: AppLocalizations.of(context)!.apply, ), ), ], diff --git a/lib/application/views/create_order_module/views/popups/LogoutVC.dart b/lib/application/views/create_order_module/views/popups/LogoutVC.dart index a551441..c588da2 100644 --- a/lib/application/views/create_order_module/views/popups/LogoutVC.dart +++ b/lib/application/views/create_order_module/views/popups/LogoutVC.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/utils/CRUDOperatoinState.dart'; -import 'package:wosull/application/views/authModule/viewModel/CheckInViewModel.dart'; +import 'package:wosull/application/views/authModule/checkinViews/viewModel/CheckInViewModel.dart'; import 'package:wosull/widgets/CustomSimpleButton.dart'; import 'package:wosull/widgets/CustomTextFieldForm.dart'; import 'package:wosull/widgets/DialogHeader.dart'; @@ -23,6 +23,7 @@ class _LogoutVCState extends State { @override void initState() { + context.read().getCounterById(); super.initState(); } @@ -35,16 +36,13 @@ class _LogoutVCState extends State { @override Widget build(BuildContext context) { viewModel = context.watch(); - if (viewModel.isGettingData) { - viewModel.getCounterById(); - } return Directionality( textDirection: TextDirection.ltr, child: Dialog( elevation: 0, backgroundColor: const Color(0xffffffff), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(15.0), + borderRadius: BorderRadius.circular(8.0), ), child: OrientationBuilder(builder: (c, orientation) { isPortrait = MediaQuery.of(c).orientation == Orientation.portrait; @@ -128,9 +126,9 @@ class _LogoutVCState extends State { keyboardType: TextInputType.number, initialValue: viewModel.cashOutAmount, onChanged: (value) { - viewModel.setCashOutAmount(value); + viewModel.setCashOutAmountLogout(value); }, - hintText: '0,0') + hintText: '0.0') ], ); } diff --git a/lib/application/views/create_order_module/views/popups/PaymentOptionPopUpVC.dart b/lib/application/views/create_order_module/views/popups/PaymentOptionPopUpVC.dart index c2b04ee..76fc2f1 100644 --- a/lib/application/views/create_order_module/views/popups/PaymentOptionPopUpVC.dart +++ b/lib/application/views/create_order_module/views/popups/PaymentOptionPopUpVC.dart @@ -1,18 +1,26 @@ import 'package:dropdown_search/dropdown_search.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:wosull/application/ViewModel/InventoryViewModel.dart'; +import 'package:provider/provider.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; -import 'package:wosull/application/model/discount/ApplyDiscountModel.dart'; -import 'package:wosull/application/model/discount/StoreDiscountModel.dart'; +import 'package:wosull/application/model/invoice/PaymentMethod.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/theme/MyFonts.dart'; import 'package:wosull/application/theme/MySeparator.dart'; -import 'package:wosull/application/utils/AppLoader.dart'; import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/create_order_module/viewModels/PaymentOptionViewModel.dart'; import 'package:wosull/base/BaseStatefulState.dart'; import 'package:wosull/helpers/AppSpaces.dart'; -import 'package:wosull/helpers/Utils.dart'; +import 'package:wosull/helpers/ThemeDropDown.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/main.dart'; +import 'package:wosull/widgets/CustomOptionalTitle.dart'; +import 'package:wosull/widgets/CustomSimpleButton.dart'; +import 'package:wosull/widgets/CustomTextFieldForm.dart'; +import 'package:wosull/widgets/DialogHeader.dart'; +import 'package:wosull/widgets/DiscountDropdown.dart'; +import 'package:wosull/widgets/DropdownItemBuilder.dart'; +import 'package:wosull/widgets/MandatoryTitleText.dart'; class PaymentOptionPopUpVC extends StatefulWidget { double cartAmount = 0.0; @@ -32,46 +40,37 @@ class PaymentOptionPopUpVC extends StatefulWidget { class _PaymentOptionPopUpVCState extends BaseStatefulState { - final viewModel = InventoryViewModel(); - - TextEditingController cashAmountController = TextEditingController(); - TextEditingController balanceOrChangeController = TextEditingController(); - TextEditingController timerController = TextEditingController(text: "10"); - TextEditingController discountAmountController = TextEditingController(); - TextEditingController deliveryNoteController = TextEditingController(); - TextEditingController cardNumberController = TextEditingController(); - - bool isPortrait = true; - var isCash = true; - var isCard = false; - var isCredit = false; - double totalAmount = 0.0; - double subTotalAmount = 0.0; + var viewModel = PaymentOptionViewModel(); @override void initState() { - // TODO: implement initState super.initState(); - subTotalAmount = widget.cartAmount; - totalAmount = widget.cartAmount; + context.read().setAmountValue(widget.cartAmount); + } + + @override + void dispose() { + viewModel.disposeData(); + super.dispose(); } @override Widget build(BuildContext context) { + viewModel = context.watch(); return Directionality( textDirection: TextDirection.ltr, child: Dialog( elevation: 0, backgroundColor: const Color(0xffffffff), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(15.0), + borderRadius: BorderRadius.circular(8.0), ), child: OrientationBuilder(builder: (c, orientation) { - isPortrait = + viewModel.isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; return SingleChildScrollView( child: Container( - width: !isPortrait + width: !viewModel.isPortrait ? MediaQuery.of(context).size.width / 1.2 : double.infinity, padding: const EdgeInsets.only(bottom: 8), @@ -80,32 +79,8 @@ class _PaymentOptionPopUpVCState crossAxisAlignment: CrossAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end, children: [ - Row( - mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.max, - children: [ - Expanded( - child: Padding( - padding: const EdgeInsets.only(left: 16), - child: Text( - AppLocalizations.of(context)!.payment_option, - style: MyColors.textStylePopUpHeading(), - ), - )), - Align( - alignment: Alignment.topRight, - child: IconButton( - onPressed: () { - Navigator.of(context).pop(); - }, - icon: const Icon(Icons.close)), - ), - ], - ), - Container( - height: 2, - color: MyColors.fillColorGray, - ), + DialogHeader( + title: AppLocalizations.of(context)!.payment_option), Container( margin: const EdgeInsets.all(8), width: double.infinity, @@ -114,10 +89,10 @@ class _PaymentOptionPopUpVCState borderRadius: const BorderRadius.all(Radius.circular(8)), ), - padding: isPortrait + padding: viewModel.isPortrait ? const EdgeInsets.fromLTRB(0, 4, 0, 4) : const EdgeInsets.fromLTRB(0, 0, 0, 0), - child: isPortrait + child: viewModel.isPortrait ? Column( children: [ Row( @@ -131,10 +106,10 @@ class _PaymentOptionPopUpVCState borderRadius: const BorderRadius.all( Radius.circular(8)), - color: isCash + color: viewModel.isCash ? MyColors.white : Colors.transparent, - border: isCash + border: viewModel.isCash ? Border.all( width: 1, color: MyColors @@ -149,7 +124,9 @@ class _PaymentOptionPopUpVCState crossAxisAlignment: CrossAxisAlignment.center, children: [ - Icon(Icons.money, + Icon( + Icons + .monetization_on_outlined, color: MyColors.blueThemeColor, size: 18), @@ -168,11 +145,7 @@ class _PaymentOptionPopUpVCState ), ), onTap: () { - setState(() { - isCash = true; - isCard = false; - isCredit = false; - }); + viewModel.setCashView(); }, )), Expanded( @@ -184,10 +157,10 @@ class _PaymentOptionPopUpVCState borderRadius: const BorderRadius.all( Radius.circular(8)), - color: isCard + color: viewModel.isCard ? MyColors.white : Colors.transparent, - border: isCard + border: viewModel.isCard ? Border.all( width: 1, color: MyColors @@ -202,17 +175,16 @@ class _PaymentOptionPopUpVCState crossAxisAlignment: CrossAxisAlignment.center, children: [ - Icon(Icons.money, + Icon(Icons.card_membership, color: MyColors.blueThemeColor, size: 18), const SizedBox( width: 2, ), - Text( - AppLocalizations.of(context)! - .card_machine, - style: const TextStyle( + const Text( + 'Credit', + style: TextStyle( fontSize: 10, color: MyColors.black, fontFamily: MyFonts.Medium), @@ -221,11 +193,7 @@ class _PaymentOptionPopUpVCState ), ), onTap: () { - setState(() { - isCash = false; - isCard = true; - isCredit = false; - }); + viewModel.setCreditCardView(); }, )), // Expanded( @@ -305,10 +273,10 @@ class _PaymentOptionPopUpVCState borderRadius: const BorderRadius.all( Radius.circular(8)), - color: isCash + color: viewModel.isCash ? MyColors.white : Colors.transparent, - border: isCash + border: viewModel.isCash ? Border.all( width: 1, color: MyColors @@ -328,14 +296,14 @@ class _PaymentOptionPopUpVCState .monetization_on_outlined, color: MyColors.blueThemeColor, - size: 24), + size: 18), const SizedBox( width: 8, ), Text( AppLocalizations.of(context)! .cash, - style: const TextStyle( + style: TextStyle( fontSize: MyFonts.H2, color: MyColors.black, fontFamily: @@ -345,11 +313,7 @@ class _PaymentOptionPopUpVCState ), ), onTap: () { - setState(() { - isCash = true; - isCard = false; - isCredit = false; - }); + viewModel.setCashView(); }, ), ), @@ -364,10 +328,10 @@ class _PaymentOptionPopUpVCState borderRadius: const BorderRadius.all( Radius.circular(8)), - color: isCard + color: viewModel.isCard ? MyColors.white : Colors.transparent, - border: isCard + border: viewModel.isCard ? Border.all( width: 1, color: MyColors @@ -385,14 +349,13 @@ class _PaymentOptionPopUpVCState Icon(Icons.card_membership, color: MyColors.blueThemeColor, - size: 24), + size: 18), const SizedBox( width: 8, ), Text( - AppLocalizations.of(context)! - .card_machine, - style: const TextStyle( + 'Credit', + style: TextStyle( fontSize: MyFonts.H2, color: MyColors.black, fontFamily: @@ -402,11 +365,7 @@ class _PaymentOptionPopUpVCState ), ), onTap: () { - setState(() { - isCash = false; - isCard = true; - isCredit = false; - }); + viewModel.setCreditCardView(); }, ), ), @@ -489,382 +448,62 @@ class _PaymentOptionPopUpVCState )); } - Widget credit() { - return Visibility( - visible: isCredit, - child: Card( - child: Container( - padding: const EdgeInsets.all(MyFonts.normal), - width: double.infinity, - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - AppLocalizations.of(context)!.credit, - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - fontFamily: MyFonts.Bold, - color: MyColors.textColorPopUp), - ), - const SizedBox( - height: MyFonts.normal, - ), - Row( - children: [ - Expanded( - child: Column( - children: [ - Row( - children: [ - Text( - AppLocalizations.of(context)!.credit, - style: const TextStyle( - fontSize: MyFonts.normal, - fontWeight: FontWeight.w600, - fontFamily: MyFonts.DMREGULAR, - color: MyColors.textColorPopUp), - ), - const SizedBox( - width: 4, - ), - ], - ), - const SizedBox( - height: 4, - ), - SizedBox( - height: 42, - child: TextField( - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normal, - color: MyColors.black), - decoration: InputDecoration( - contentPadding: - const EdgeInsets.fromLTRB(8, 0, 8, 0), - hintText: '0.00', - fillColor: MyColors.fillColor2, - filled: true, - focusedBorder: OutlineInputBorder( - borderSide: const BorderSide( - color: Colors.transparent, width: 1.0), - borderRadius: BorderRadius.circular(8.0), - ), - enabledBorder: OutlineInputBorder( - borderSide: const BorderSide( - width: 1, - //<-- SEE HERE - color: Colors.transparent, - ), - borderRadius: BorderRadius.circular(8.0), - ), - ), - ), - ), - ], - )), - const SizedBox( - width: 8, - ), - Expanded( - child: Column( - children: [ - Row( - children: [ - Text( - AppLocalizations.of(context)!.balance_change, - style: const TextStyle( - fontSize: MyFonts.normal, - fontWeight: FontWeight.w600, - fontFamily: MyFonts.DMREGULAR, - color: MyColors.textColorPopUp), - ), - const SizedBox( - width: 4, - ), - ], - ), - const SizedBox( - height: 4, - ), - SizedBox( - height: 42, - child: TextField( - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normal, - color: MyColors.black), - decoration: InputDecoration( - contentPadding: - const EdgeInsets.fromLTRB(8, 0, 8, 0), - hintText: '0.00', - fillColor: MyColors.fillColor2, - filled: true, - focusedBorder: OutlineInputBorder( - borderSide: const BorderSide( - color: Colors.transparent, width: 1.0), - borderRadius: BorderRadius.circular(8.0), - ), - enabledBorder: OutlineInputBorder( - borderSide: const BorderSide( - width: 1, - //<-- SEE HERE - color: Colors.transparent, - ), - borderRadius: BorderRadius.circular(8.0), - ), - ), - ), - ), - ], - )) - ], - ), - const SizedBox( - height: MyFonts.normal, - ), - ElevatedButton( - style: ElevatedButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(28.0), - ), - backgroundColor: MyColors.greenColorEnable, - minimumSize: const Size.fromHeight(48), // NEW - ), - onPressed: () {}, - child: Text( - widget.status == "ready" - ? AppLocalizations.of(context)!.done - : AppLocalizations.of(context)!.send_to_kitchen, - style: const TextStyle( - fontSize: MyFonts.bold, - color: MyColors.white, - fontFamily: MyFonts.Bold), - ), - ) - ], - ), - ), - )); - } - Widget cardMachine() { return Visibility( - visible: isCard, + visible: viewModel.isCard, child: Card( child: Container( - padding: const EdgeInsets.all(MyFonts.normal), + padding: EdgeInsets.all(MyFonts.normal), width: double.infinity, child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - AppLocalizations.of(context)!.card_machine, - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - fontFamily: MyFonts.Bold, - color: MyColors.textColorPopUp), - ), - const SizedBox( - height: MyFonts.normal, + 'Credit', + style: ThemeText.textStylePageHeading, ), - isPortrait + AppSpaces.verticalMedium, + viewModel.isPortrait ? Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - AppLocalizations.of(context)!.card, - style: const TextStyle( - fontSize: MyFonts.normal, - fontWeight: FontWeight.w600, - fontFamily: MyFonts.DMREGULAR, - color: MyColors.textColorPopUp), - ), - AppSpaces.verticalSmall, - SizedBox( - height: 42, - child: TextField( - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normal, - color: MyColors.black), - decoration: InputDecoration( - contentPadding: - const EdgeInsets.fromLTRB(8, 0, 8, 0), - hintText: 'Enter card number', - fillColor: MyColors.fillColor2, - filled: true, - focusedBorder: OutlineInputBorder( - borderSide: const BorderSide( - color: Colors.transparent, width: 1.0), - borderRadius: BorderRadius.circular(8.0), - ), - enabledBorder: OutlineInputBorder( - borderSide: const BorderSide( - width: 1, - //<-- SEE HERE - color: Colors.transparent, - ), - borderRadius: BorderRadius.circular(8.0), - ), - ), - ), - ), - AppSpaces.verticalMedium, - Text( - AppLocalizations.of(context)!.cash_amount, - style: const TextStyle( - fontSize: MyFonts.normal, - fontWeight: FontWeight.w600, - fontFamily: MyFonts.DMREGULAR, - color: MyColors.textColorPopUp), - ), + const CustomOptionalTitle(hint: 'Credit'), AppSpaces.verticalSmall, - SizedBox( - height: 42, - child: getCashAmountText(), - ), + getCardNumberText(), AppSpaces.verticalMedium, - Text( - AppLocalizations.of(context)!.balance_change, - style: const TextStyle( - fontSize: MyFonts.normal, - fontWeight: FontWeight.w600, - fontFamily: MyFonts.DMREGULAR, - color: MyColors.textColorPopUp), - ), + const CustomOptionalTitle(hint: 'Payment Methods'), AppSpaces.verticalSmall, - SizedBox( - height: 42, - child: getEnterBalanceOrChange(), - ), + paymentMethod(), AppSpaces.verticalMedium, - Text( - AppLocalizations.of(context)!.timer, - style: const TextStyle( - fontSize: MyFonts.normal, - fontWeight: FontWeight.w600, - fontFamily: MyFonts.DMREGULAR, - color: MyColors.textColorPopUp), - ), - AppSpaces.verticalSmall, - SizedBox( - height: 42, - child: getTimerText(), - ), ], ) - : Column( + : Row( children: [ - Row( + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - AppLocalizations.of(context)!.card, - style: const TextStyle( - fontSize: MyFonts.normal, - fontWeight: FontWeight.w600, - fontFamily: MyFonts.DMREGULAR, - color: MyColors.textColorPopUp), - ), - const SizedBox( - height: 4, - ), - SizedBox( - height: 42, - child: getCardNumberText(), - ), - ], - )), - const SizedBox( - width: 8, - ), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - AppLocalizations.of(context)!.cash_amount, - style: const TextStyle( - fontSize: MyFonts.normal, - fontWeight: FontWeight.w600, - fontFamily: MyFonts.DMREGULAR, - color: MyColors.textColorPopUp), - ), - const SizedBox( - height: 4, - ), - SizedBox( - height: 42, - child: getCashAmountText(), - ), - ], - )), + const CustomOptionalTitle(hint: 'Credit'), + AppSpaces.verticalSmall, + getCardNumberText(), ], - ), - Row( + )), + AppSpaces.horizontalSmall, + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - AppLocalizations.of(context)! - .balance_change, - style: const TextStyle( - fontSize: MyFonts.normal, - fontWeight: FontWeight.w600, - fontFamily: MyFonts.DMREGULAR, - color: MyColors.textColorPopUp), - ), - const SizedBox( - height: 4, - ), - SizedBox( - height: 42, - child: getEnterBalanceOrChange(), - ), - ], - )), - const SizedBox( - width: 8, - ), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'Timer', - style: TextStyle( - fontSize: MyFonts.normal, - fontWeight: FontWeight.w600, - fontFamily: MyFonts.DMREGULAR, - color: MyColors.textColorPopUp), - ), - const SizedBox( - height: 4, - ), - SizedBox( - height: 42, - child: getTimerText(), - ), - ], - )) + const CustomOptionalTitle( + hint: 'Payment Methods'), + AppSpaces.verticalSmall, + paymentMethod() ], - ) + )), ], ), - const SizedBox( - height: 8, - ), + AppSpaces.verticalLarge, getDiscountAndCalculation() ], ), @@ -874,10 +513,10 @@ class _PaymentOptionPopUpVCState Widget card() { return Visibility( - visible: isCash, + visible: viewModel.isCash, child: Card( child: Container( - padding: const EdgeInsets.all(MyFonts.normal), + padding: EdgeInsets.all(MyFonts.normal), width: double.infinity, child: Column( mainAxisAlignment: MainAxisAlignment.start, @@ -885,60 +524,24 @@ class _PaymentOptionPopUpVCState children: [ Text( AppLocalizations.of(context)!.cash, - style: const TextStyle( - fontSize: 22, - fontWeight: FontWeight.bold, - fontFamily: MyFonts.Bold, - color: MyColors.textColorPopUp), - ), - const SizedBox( - height: MyFonts.normal, + style: ThemeText.textStylePageHeading, ), - isPortrait + AppSpaces.verticalMedium, + viewModel.isPortrait ? Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - AppLocalizations.of(context)!.cash_amount, - style: const TextStyle( - fontSize: MyFonts.normal, - fontWeight: FontWeight.w600, - fontFamily: MyFonts.DMREGULAR, - color: MyColors.textColorPopUp), - ), + MandatoryTitleText( + hint: AppLocalizations.of(context)!.cash_amount), AppSpaces.verticalSmall, - SizedBox( - height: 42, - child: getCashAmountText(), - ), + getCashAmountText(), AppSpaces.verticalMedium, - Text( - AppLocalizations.of(context)!.balance_change, - style: const TextStyle( - fontSize: MyFonts.normal, - fontWeight: FontWeight.w600, - fontFamily: MyFonts.DMREGULAR, - color: MyColors.textColorPopUp), + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.balance_change, ), AppSpaces.verticalSmall, - SizedBox( - height: 42, - child: getEnterBalanceOrChange(), - ), + getEnterBalanceOrChange(), AppSpaces.verticalMedium, - Text( - AppLocalizations.of(context)!.timer, - style: const TextStyle( - fontSize: MyFonts.normal, - fontWeight: FontWeight.w600, - fontFamily: MyFonts.DMREGULAR, - color: MyColors.textColorPopUp), - ), - AppSpaces.verticalSmall, - SizedBox( - height: 42, - child: getTimerText(), - ), ], ) : Row( @@ -947,76 +550,28 @@ class _PaymentOptionPopUpVCState child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - AppLocalizations.of(context)!.cash_amount, - style: const TextStyle( - fontSize: MyFonts.normal, - fontWeight: FontWeight.w600, - fontFamily: MyFonts.DMREGULAR, - color: MyColors.textColorPopUp), - ), - const SizedBox( - height: 4, - ), - SizedBox( - height: 42, - child: getCashAmountText(), - ), + MandatoryTitleText( + hint: AppLocalizations.of(context)! + .cash_amount), + AppSpaces.verticalSmall, + getCashAmountText(), ], )), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - AppLocalizations.of(context)!.balance_change, - style: const TextStyle( - fontSize: MyFonts.normal, - fontWeight: FontWeight.w600, - fontFamily: MyFonts.DMREGULAR, - color: MyColors.textColorPopUp), - ), - const SizedBox( - height: 4, - ), - SizedBox( - height: 42, - child: getEnterBalanceOrChange(), - ), + CustomOptionalTitle( + hint: AppLocalizations.of(context)! + .balance_change), + AppSpaces.verticalSmall, + getEnterBalanceOrChange(), ], )), - const SizedBox( - width: 8, - ), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - AppLocalizations.of(context)!.timer, - style: const TextStyle( - fontSize: MyFonts.normal, - fontWeight: FontWeight.w600, - fontFamily: MyFonts.DMREGULAR, - color: MyColors.textColorPopUp), - ), - const SizedBox( - height: 4, - ), - SizedBox( - height: 42, - child: getTimerText(), - ), - ], - )) ], ), - const SizedBox( - height: MyFonts.normal, - ), + AppSpaces.verticalLarge, getDiscountAndCalculation(), ], ), @@ -1024,132 +579,26 @@ class _PaymentOptionPopUpVCState )); } - Widget getDiscounts(BuildContext context) { - return FutureBuilder( - future: getDiscount(), - builder: (c, s) { - if (s.hasData) { - var itemsList = s.data!; - return Container( - padding: const EdgeInsets.all(4), - child: Material( - color: MyColors.fillColor2, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: 42, - width: double.infinity, - child: DropdownSearch( - popupProps: const PopupProps.menu(), - clearButtonProps: const ClearButtonProps( - alignment: Alignment.centerRight, - padding: EdgeInsets.zero, - icon: Icon(Icons.clear, size: 12), - color: MyColors.black, - isVisible: true, - ), - items: itemsList, - itemAsString: (StoreDiscount u) => u.name!, - onChanged: (StoreDiscount? data) { - setState(() { - if (data == null) { - applyDiscount(sharedPrefs.cartID, ""); - } else { - applyDiscount(sharedPrefs.cartID, data.id!); - } - }); - }, - dropdownDecoratorProps: const DropDownDecoratorProps( - baseStyle: TextStyle( - fontFamily: MyFonts.Bold, - fontSize: 12, - color: MyColors.textColorBlack), - dropdownSearchDecoration: InputDecoration( - border: InputBorder.none, hintText: 'Choose'), - ), - ), - ), - ), - ), - ); + Widget getDiscounts() { + return DiscountDropdown( + onChanged: (data) { + if (isConnected) { + viewModel.applyDiscount(sharedPrefs.cartID, data); } else { - return AppLoader(); + viewModel.calculateDiscount(data); } - }); - } - - Future> getDiscount() async { - var items = []; - - await viewModel - .getData(Constants.GET_DISCOUNT, Constants.getStorePayload()) - .then((value) { - final response = StoreDiscountModel.fromJson(value); - if (response.success!) { - items.addAll(response.storeDiscount!); - } - }).onError((error, stackTrace) { - print(error.toString()); - }); - - return items; - } - - Future applyDiscount(String cartId, String discountId) async { - Map data = {}; - if (discountId.isEmpty) { - data = { - 'cartId': cartId, - }; - } else { - data = { - 'cartId': cartId, - 'discId': discountId, - }; - } - - await viewModel.getData(Constants.APPLY_DISCOUNT, data).then((value) { - final response = ApplyDiscountModel.fromJson(value); - if (response.success!) { - discountAmountController.text = response.discountAmount!.toString(); - totalAmount = subTotalAmount; - totalAmount -= response.discountAmount!; - // totalAmount -= double.tryParse(data.minAmountLimit)!; - if (totalAmount < 0) { - totalAmount = 0.0; - } - } else { - Utils.showMessage(response.message!); - totalAmount = subTotalAmount; - discountAmountController.text = "0.0"; - } - - if (cashAmountController.text.isNotEmpty) { - getChange(cashAmountController.text); - } else { - getChange("0.0"); - } - }).onError((error, stackTrace) { - print(error.toString()); - }); + }, + fillColor: MyColors.fillColor2); } Widget getDiscountAndCalculation() { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - AppLocalizations.of(context)!.discount, - style: const TextStyle( - fontSize: MyFonts.normal, - fontWeight: FontWeight.bold, - fontFamily: MyFonts.Medium, - color: MyColors.textColorPopUp), - ), - const SizedBox( - height: 8, + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.discount, ), + AppSpaces.verticalMedium, Container( decoration: const BoxDecoration( color: MyColors.backColor, @@ -1161,109 +610,44 @@ class _PaymentOptionPopUpVCState child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - AppLocalizations.of(context)!.discount_code, - style: const TextStyle( - fontSize: MyFonts.normal, - fontWeight: FontWeight.w600, - fontFamily: MyFonts.DMREGULAR, - color: MyColors.textColorPopUp), + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.discount_code, ), - const SizedBox( - height: 4, - ), - getDiscounts(context), + AppSpaces.verticalSmall, + getDiscounts(), ], )), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - AppLocalizations.of(context)!.discount, - style: const TextStyle( - fontSize: MyFonts.normal, - fontWeight: FontWeight.w600, - fontFamily: MyFonts.DMREGULAR, - color: MyColors.textColorPopUp), - ), - const SizedBox( - height: 4, - ), - Container( - padding: const EdgeInsets.all(4), - height: 48, - child: TextField( - keyboardType: TextInputType.number, - controller: discountAmountController, - onChanged: (value) { - setState(() { - if (value.isEmpty) { - totalAmount = subTotalAmount; - } else { - totalAmount = subTotalAmount; - var discountValue = double.parse(value); - totalAmount -= discountValue; - if (totalAmount < 0) { - totalAmount = 0.0; - } - } - }); - }, - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normal, - color: MyColors.black), - decoration: InputDecoration( - contentPadding: const EdgeInsets.fromLTRB(8, 0, 8, 0), - hintText: '0.00', - fillColor: MyColors.white, - filled: true, - focusedBorder: OutlineInputBorder( - borderSide: const BorderSide( - color: Colors.transparent, width: 1.0), - borderRadius: BorderRadius.circular(8.0), - ), - enabledBorder: OutlineInputBorder( - borderSide: const BorderSide( - width: 1, - //<-- SEE HERE - color: Colors.transparent, - ), - borderRadius: BorderRadius.circular(8.0), - ), - ), - ), + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.discount, ), + AppSpaces.verticalSmall, + CustomTextFieldForm( + readOnly: true, + initialValue: viewModel.discountAmountController, + key: Key(viewModel.discountAmountController), + keyboardType: TextInputType.number, + onChanged: (value) { + // viewModel.setDiscountOnChange(value); + }, + hintText: '0.00', + ) ], )) ], ), ), - const SizedBox( - height: MyFonts.normal, - ), - Text( - AppLocalizations.of(context)!.delivery_note, - style: const TextStyle( - fontSize: MyFonts.normal, - fontWeight: FontWeight.w600, - fontFamily: MyFonts.DMREGULAR, - color: MyColors.textColorPopUp), - ), - const SizedBox( - height: 4, - ), - SizedBox( - height: 42, - child: getDeliveryNote(), - ), - const SizedBox( - height: 4, + AppSpaces.verticalMedium, + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.delivery_note, ), + AppSpaces.verticalSmall, + getDeliveryNote(), + AppSpaces.verticalSmall, Row( children: [ Expanded( @@ -1274,35 +658,23 @@ class _PaymentOptionPopUpVCState alignment: Alignment.centerLeft, child: Text( AppLocalizations.of(context)!.sub_total, - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.bold, - fontSize: MyFonts.normal, - color: MyColors.textColorBlack20), + style: ThemeText.textStyleAmountHeading, ), )), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, Expanded( child: Align( alignment: Alignment.centerRight, child: Text( - '${subTotalAmount.toStringAsFixed(2)} ${sharedPrefs.currency}', - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.bold, - fontSize: MyFonts.normal, - color: MyColors.textColorBlack20), + '${viewModel.subTotalAmount.toStringAsFixed(2)} ${sharedPrefs.currency}', + style: ThemeText.textStyleAmountValue, ), )), ], )), ], ), - const SizedBox( - height: 4, - ), + AppSpaces.verticalSmall, Row( children: [ Expanded( @@ -1310,37 +682,23 @@ class _PaymentOptionPopUpVCState alignment: Alignment.centerLeft, child: Text( AppLocalizations.of(context)!.discount, - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.bold, - fontSize: MyFonts.normal, - color: MyColors.textColorBlack20), + style: ThemeText.textStyleAmountHeading, ), )), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, Expanded( child: Align( alignment: Alignment.centerRight, child: Text( - "${discountAmountController.text} ${sharedPrefs.currency}", - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.bold, - fontSize: MyFonts.normal, - color: MyColors.textColorBlack20), + "${viewModel.discountAmountController} ${sharedPrefs.currency}", + style: ThemeText.textStyleAmountValue, ), )), ], ), - const SizedBox( - height: MyFonts.normal, - ), + AppSpaces.verticalMedium, const MySeparator(color: Colors.grey), - const SizedBox( - height: MyFonts.normal, - ), + AppSpaces.verticalMedium, Row( children: [ Expanded( @@ -1348,235 +706,276 @@ class _PaymentOptionPopUpVCState alignment: Alignment.centerLeft, child: Text( AppLocalizations.of(context)!.total_amount, - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.bold, - fontSize: MyFonts.bold, - color: MyColors.textColorBlack), + style: ThemeText.textStyleHeadingCart, ), )), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, Expanded( child: Align( alignment: Alignment.centerRight, child: Text( - '${totalAmount.toStringAsFixed(2)} ${sharedPrefs.currency}', - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.bold, - fontSize: MyFonts.bold, - color: MyColors.textColorBlack), + '${viewModel.totalAmount.toStringAsFixed(2)} ${sharedPrefs.currency}', + style: ThemeText.textStyleHeadingCart, ), )), ], ), - const SizedBox( - height: MyFonts.normal, - ), - ElevatedButton( - style: ElevatedButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(28.0), - ), - backgroundColor: MyColors.greenColorEnable, - minimumSize: const Size.fromHeight(48), // NEW - ), - onPressed: () { - var change = 0.0; - if (balanceOrChangeController.text.isNotEmpty) { - change = double.parse(balanceOrChangeController.text); - } else { - change = 0.0; - } - var paymentMode = 'Cash'; - if (isCash) { - paymentMode = 'Cash'; - } else if (isCard) { - paymentMode = 'Card Machine'; - } else if (isCredit) { - paymentMode = 'Cash'; - } - List result = [ - true, - widget.status == "ready" ? 'completed' : Constants.preparing, - change, - deliveryNoteController.text, - int.parse(timerController.text), - subTotalAmount, - totalAmount, - paymentMode - ]; - Navigator.pop(context, result); + AppSpaces.verticalMedium, + CustomSimpleButton( + height: 48, + radius: 24, + textColor: MyColors.white, + backGroundColor: viewModel.enable + ? MyColors.greenColorEnable + : MyColors.greenColorDisable, + onPressed: () async { + var result = await viewModel.sendOrder(widget.status); + checkState(result); }, - child: Text( - widget.status == "ready" - ? AppLocalizations.of(context)!.done - : AppLocalizations.of(context)!.send_to_kitchen, - style: const TextStyle( - fontSize: MyFonts.bold, - color: MyColors.white, - fontFamily: MyFonts.Bold), - ), - ) + heading: widget.status == Constants.ready + ? AppLocalizations.of(context)!.done + : AppLocalizations.of(context)!.send_to_kitchen, + ), + widget.status != Constants.ready + ? AppSpaces.verticalMedium + : Container(), + widget.status != Constants.ready + ? CustomSimpleButton( + height: 48, + radius: 24, + textColor: MyColors.white, + backGroundColor: viewModel.enable + ? MyColors.greenColorEnable + : MyColors.greenColorDisable, + onPressed: () async { + var result = await viewModel.sendOrder(Constants.ready); + checkState(result); + }, + heading: AppLocalizations.of(context)!.completed, + ) + : Container(), ], ); } + Widget paymentMethod() { + return DropdownSearch( + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.paymentMethod!); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: viewModel.paymentMethod, + itemAsString: (PaymentMethod u) => u.paymentMethod!, + onChanged: (PaymentMethod? data) { + viewModel.setPaymentMethod(data); + }, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), + ); + } + Widget getCashAmountText() { - return TextField( + return CustomTextFieldForm( + hintText: 'Enter Cash Amount', keyboardType: TextInputType.number, - controller: cashAmountController, + initialValue: viewModel.cashAmountController, onChanged: (value) { - getChange(value); + viewModel.getChange(value); }, - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normal, - color: MyColors.black), - decoration: InputDecoration( - contentPadding: const EdgeInsets.fromLTRB(8, 0, 8, 0), - hintText: 'Enter Cash Amount', - fillColor: MyColors.fillColor2, - filled: true, - focusedBorder: OutlineInputBorder( - borderSide: const BorderSide(color: Colors.transparent, width: 1.0), - borderRadius: BorderRadius.circular(8.0), - ), - enabledBorder: OutlineInputBorder( - borderSide: const BorderSide( - width: 1, - //<-- SEE HERE - color: Colors.transparent, - ), - borderRadius: BorderRadius.circular(8.0), - ), - ), ); } Widget getEnterBalanceOrChange() { - return TextField( - controller: balanceOrChangeController, - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normal, - color: MyColors.black), - decoration: InputDecoration( - contentPadding: const EdgeInsets.fromLTRB(8, 0, 8, 0), - hintText: 'Balance or Change', - fillColor: MyColors.fillColor2, - filled: true, - focusedBorder: OutlineInputBorder( - borderSide: const BorderSide(color: Colors.transparent, width: 1.0), - borderRadius: BorderRadius.circular(8.0), - ), - enabledBorder: OutlineInputBorder( - borderSide: const BorderSide( - width: 1, - //<-- SEE HERE - color: Colors.transparent, - ), - borderRadius: BorderRadius.circular(8.0), - ), - ), + return CustomTextFieldForm( + key: Key(viewModel.balanceOrChangeController), + hintText: 'Balance or Change', + initialValue: viewModel.balanceOrChangeController, + readOnly: true, + onChanged: (String value) {}, ); } - Widget getTimerText() { - return TextField( - controller: timerController, - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normal, - color: MyColors.black), - decoration: InputDecoration( - contentPadding: const EdgeInsets.fromLTRB(8, 0, 8, 0), - hintText: 'Timer', - fillColor: MyColors.fillColor2, - filled: true, - focusedBorder: OutlineInputBorder( - borderSide: const BorderSide(color: Colors.transparent, width: 1.0), - borderRadius: BorderRadius.circular(8.0), - ), - enabledBorder: OutlineInputBorder( - borderSide: const BorderSide( - width: 1, - //<-- SEE HERE - color: Colors.transparent, - ), - borderRadius: BorderRadius.circular(8.0), - ), - ), + Widget getDeliveryNote() { + return CustomTextFieldForm( + onChanged: (String value) { + viewModel.deliveryNoteController = value; + }, + hintText: 'Enter Delivery Note', ); } - Widget getDeliveryNote() { - return TextField( - controller: deliveryNoteController, - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normal, - color: MyColors.black), - decoration: InputDecoration( - contentPadding: const EdgeInsets.fromLTRB(8, 0, 8, 0), - hintText: 'Enter Delivery Note', - fillColor: MyColors.fillColor2, - filled: true, - focusedBorder: OutlineInputBorder( - borderSide: const BorderSide(color: Colors.transparent, width: 1.0), - borderRadius: BorderRadius.circular(8.0), - ), - enabledBorder: OutlineInputBorder( - borderSide: const BorderSide( - width: 1, - //<-- SEE HERE - color: Colors.transparent, - ), - borderRadius: BorderRadius.circular(8.0), - ), - ), + Widget getCardNumberText() { + return CustomTextFieldForm( + initialValue: viewModel.totalAmount.toStringAsFixed(2), + readOnly: true, + hintText: 'Enter Card number', + onChanged: (String value) {}, ); } - Widget getCardNumberText() { - return TextField( - controller: cardNumberController, - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normal, - color: MyColors.black), - decoration: InputDecoration( - contentPadding: const EdgeInsets.fromLTRB(8, 0, 8, 0), - hintText: 'Enter Card number', - fillColor: MyColors.fillColor2, - filled: true, - focusedBorder: OutlineInputBorder( - borderSide: const BorderSide(color: Colors.transparent, width: 1.0), - borderRadius: BorderRadius.circular(8.0), - ), - enabledBorder: OutlineInputBorder( - borderSide: const BorderSide( - width: 1, - //<-- SEE HERE - color: Colors.transparent, + Widget credit() { + return Visibility( + visible: viewModel.isCredit, + child: Card( + child: Container( + padding: EdgeInsets.all(MyFonts.normal), + width: double.infinity, + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)!.credit, + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + fontFamily: MyFonts.Bold, + color: MyColors.textColorPopUp), + ), + AppSpaces.verticalMedium, + Row( + children: [ + Expanded( + child: Column( + children: [ + Row( + children: [ + Text( + AppLocalizations.of(context)!.credit, + style: TextStyle( + fontSize: MyFonts.normal, + fontWeight: FontWeight.w600, + fontFamily: MyFonts.DMREGULAR, + color: MyColors.textColorPopUp), + ), + const SizedBox( + width: 4, + ), + ], + ), + const SizedBox( + height: 4, + ), + SizedBox( + height: 42, + child: TextField( + style: TextStyle( + fontFamily: MyFonts.DMREGULAR, + fontSize: MyFonts.normal, + color: MyColors.black), + decoration: InputDecoration( + contentPadding: + const EdgeInsets.fromLTRB(8, 0, 8, 0), + hintText: '0.00', + fillColor: MyColors.fillColor2, + filled: true, + focusedBorder: OutlineInputBorder( + borderSide: const BorderSide( + color: Colors.transparent, width: 1.0), + borderRadius: BorderRadius.circular(8.0), + ), + enabledBorder: OutlineInputBorder( + borderSide: const BorderSide( + width: 1, + //<-- SEE HERE + color: Colors.transparent, + ), + borderRadius: BorderRadius.circular(8.0), + ), + ), + ), + ), + ], + )), + const SizedBox( + width: 8, + ), + Expanded( + child: Column( + children: [ + Row( + children: [ + Text( + AppLocalizations.of(context)!.balance_change, + style: TextStyle( + fontSize: MyFonts.normal, + fontWeight: FontWeight.w600, + fontFamily: MyFonts.DMREGULAR, + color: MyColors.textColorPopUp), + ), + const SizedBox( + width: 4, + ), + ], + ), + const SizedBox( + height: 4, + ), + SizedBox( + height: 42, + child: TextField( + style: TextStyle( + fontFamily: MyFonts.DMREGULAR, + fontSize: MyFonts.normal, + color: MyColors.black), + decoration: InputDecoration( + contentPadding: + const EdgeInsets.fromLTRB(8, 0, 8, 0), + hintText: '0.00', + fillColor: MyColors.fillColor2, + filled: true, + focusedBorder: OutlineInputBorder( + borderSide: const BorderSide( + color: Colors.transparent, width: 1.0), + borderRadius: BorderRadius.circular(8.0), + ), + enabledBorder: OutlineInputBorder( + borderSide: const BorderSide( + width: 1, + //<-- SEE HERE + color: Colors.transparent, + ), + borderRadius: BorderRadius.circular(8.0), + ), + ), + ), + ), + ], + )) + ], + ), + AppSpaces.verticalMedium, + ElevatedButton( + style: ElevatedButton.styleFrom( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(28.0), + ), + backgroundColor: viewModel.enable + ? MyColors.greenColorEnable + : MyColors.greenColor10, + minimumSize: const Size.fromHeight(48), // NEW + ), + onPressed: () {}, + child: Text( + widget.status == "ready" + ? AppLocalizations.of(context)!.done + : AppLocalizations.of(context)!.send_to_kitchen, + style: TextStyle( + fontSize: MyFonts.bold, + color: MyColors.white, + fontFamily: MyFonts.Bold), + ), + ) + ], + ), ), - borderRadius: BorderRadius.circular(8.0), - ), - ), - ); + )); } - void getChange(String value) { - setState(() { - final cashAmount = double.parse(value); - if (cashAmount >= totalAmount) { - final changeAmount = cashAmount - totalAmount; - balanceOrChangeController.text = changeAmount.toString(); - } else { - balanceOrChangeController.text = "0.0"; - } - }); + void checkState(result) { + Navigator.pop(context, result); } } diff --git a/lib/application/views/create_order_module/views/popups/RegisterCashVC.dart b/lib/application/views/create_order_module/views/popups/RegisterCashVC.dart index 84427ca..a9567ce 100644 --- a/lib/application/views/create_order_module/views/popups/RegisterCashVC.dart +++ b/lib/application/views/create_order_module/views/popups/RegisterCashVC.dart @@ -3,7 +3,7 @@ import 'package:provider/provider.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/utils/AppLoader.dart'; import 'package:wosull/application/utils/CRUDOperatoinState.dart'; -import 'package:wosull/application/views/authModule/viewModel/CheckInViewModel.dart'; +import 'package:wosull/application/views/authModule/checkinViews/viewModel/CheckInViewModel.dart'; import 'package:wosull/widgets/CustomOptionalTitle.dart'; import 'package:wosull/widgets/CustomSimpleButton.dart'; import 'package:wosull/widgets/CustomTextFieldForm.dart'; @@ -39,82 +39,76 @@ class _RegisterCashVCState extends State { if (viewModel.isGettingData) { viewModel.getCounterById(); } - return WillPopScope( - onWillPop: () { - viewModel.dispose(); - return Future.value(false); - }, - child: Directionality( - textDirection: TextDirection.ltr, - child: Dialog( - elevation: 0, - backgroundColor: const Color(0xffffffff), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(15.0), - ), - child: OrientationBuilder(builder: (c, orientation) { - isPortrait = MediaQuery.of(c).orientation == Orientation.portrait; + return Directionality( + textDirection: TextDirection.ltr, + child: Dialog( + elevation: 0, + backgroundColor: const Color(0xffffffff), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: OrientationBuilder(builder: (c, orientation) { + isPortrait = MediaQuery.of(c).orientation == Orientation.portrait; - return SingleChildScrollView( - child: Container( - width: !isPortrait - ? MediaQuery.of(context).size.width / 1.2 - : double.infinity, - padding: const EdgeInsets.only(bottom: 8), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.end, - mainAxisAlignment: MainAxisAlignment.end, - children: [ - DialogHeader(title: 'Register'), - Padding( - padding: const EdgeInsets.all(12), - child: viewModel.isGettingData - ? AppLoader() - : getCashOutAmount(), - ), - Padding( - padding: const EdgeInsets.only(right: 16), - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - SizedBox( - width: 120, - child: CustomSimpleButton( - textColor: MyColors.white, - isLoading: viewModel.isLoading, - backGroundColor: MyColors.blueThemeColor, - onPressed: () async { - await viewModel.registerParams(); - checkState(); - }, - heading: 'Okay', - ), + return SingleChildScrollView( + child: Container( + width: !isPortrait + ? MediaQuery.of(context).size.width / 1.2 + : double.infinity, + padding: const EdgeInsets.only(bottom: 8), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + DialogHeader(title: 'Register'), + Padding( + padding: const EdgeInsets.all(12), + child: viewModel.isGettingData + ? AppLoader() + : getCashOutAmount(), + ), + Padding( + padding: const EdgeInsets.only(right: 16), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + SizedBox( + width: 120, + child: CustomSimpleButton( + textColor: MyColors.white, + isLoading: viewModel.isLoading, + backGroundColor: MyColors.blueThemeColor, + onPressed: () async { + await viewModel.registerParams(); + checkState(); + }, + heading: 'Okay', ), - const SizedBox( - width: 8, + ), + const SizedBox( + width: 8, + ), + SizedBox( + width: 120, + child: CustomSimpleButton( + textColor: MyColors.white, + backGroundColor: MyColors.blueThemeColor, + onPressed: () { + Navigator.pop(context, false); + }, + heading: 'Cancel', ), - SizedBox( - width: 120, - child: CustomSimpleButton( - textColor: MyColors.white, - backGroundColor: MyColors.blueThemeColor, - onPressed: () { - Navigator.pop(context, false); - }, - heading: 'Cancel', - ), - ) - ], - ), - ) - ], - ), + ) + ], + ), + ) + ], ), - ); - }), - )), - ); + ), + ); + }), + )); } void checkState() { @@ -137,7 +131,7 @@ class _RegisterCashVCState extends State { onChanged: (value) { viewModel.setCashInAmount(value); }, - hintText: '0,0') + hintText: '0.0') ], ); } @@ -156,7 +150,7 @@ class _RegisterCashVCState extends State { onChanged: (value) { viewModel.setCashOutAmount(value); }, - hintText: '0,0') + hintText: '0.0') ], ); } diff --git a/lib/application/views/create_order_module/views/popups/SelectComboPopUp.dart b/lib/application/views/create_order_module/views/popups/SelectComboPopUp.dart index 9f570d6..68914cb 100644 --- a/lib/application/views/create_order_module/views/popups/SelectComboPopUp.dart +++ b/lib/application/views/create_order_module/views/popups/SelectComboPopUp.dart @@ -37,7 +37,7 @@ class _SelectComboPopUpState extends State { elevation: 0, backgroundColor: const Color(0xffffffff), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(15.0), + borderRadius: BorderRadius.circular(8.0), ), child: OrientationBuilder(builder: (c, orientation) { return SingleChildScrollView( diff --git a/lib/application/views/create_order_module/widgets/CartItemView.dart b/lib/application/views/create_order_module/widgets/CartItemView.dart index 1c95577..ea67746 100644 --- a/lib/application/views/create_order_module/widgets/CartItemView.dart +++ b/lib/application/views/create_order_module/widgets/CartItemView.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; import 'package:wosull/application/model/store/StoreItemsResponse.dart'; import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/ThemeImage.dart'; import 'package:wosull/helpers/ThemeText.dart'; import 'package:wosull/helpers/Utils.dart'; @@ -46,13 +47,11 @@ class CartItemView extends StatelessWidget { SizedBox( width: 52, height: 62, - child: storeItems.imageUrl!.isNotEmpty - ? Image.network(storeItems.imageUrl!) + child: storeItems.imageUrl.isNotEmpty + ? Image.network(storeItems.imageUrl) : Image.asset(ThemeImage.wosulLogo), ), - const SizedBox( - width: 4, - ), + AppSpaces.horizontalMedium, Expanded( flex: 2, child: Column( @@ -65,13 +64,11 @@ class CartItemView extends StatelessWidget { child: Align( alignment: Alignment.centerLeft, child: Text( - storeItems.name!, + storeItems.name, style: ThemeText.textStyleNormalMedium, ), )), - const SizedBox( - width: 4, - ), + AppSpaces.horizontalSmall, Container( width: 60, height: 25, @@ -91,7 +88,14 @@ class CartItemView extends StatelessWidget { color: Colors.white, icon: const Icon(Icons.remove, size: 18.0), - onPressed: decreaseItem, + onPressed: sharedPrefs + .billingCounterId + .isNotEmpty + ? decreaseItem + : () { + Utils.showMessage( + 'Please Select Available Billing Counter!'); + }, ))), Expanded( child: Center( @@ -110,7 +114,14 @@ class CartItemView extends StatelessWidget { color: Colors.white, icon: const Icon(Icons.add, size: 18.0), - onPressed: increaseItem, + onPressed: sharedPrefs + .billingCounterId + .isNotEmpty + ? increaseItem + : () { + Utils.showMessage( + 'Please Select Available Billing Counter!'); + }, ))) ], )) @@ -122,9 +133,7 @@ class CartItemView extends StatelessWidget { : '(${lang(context).barcode} N/A)', style: ThemeText.textStyleSmall, ), - const SizedBox( - height: 4, - ), + AppSpaces.verticalSmall, Container( height: 18, decoration: BoxDecoration( @@ -140,9 +149,7 @@ class CartItemView extends StatelessWidget { ), ), ), - const SizedBox( - height: 4, - ), + AppSpaces.verticalSmall, Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ @@ -235,7 +242,7 @@ class CartItemView extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( - "${sharedPrefs.currency} ${storeItems.totalItemPrice!}", + "${sharedPrefs.currency} ${storeItems.totalItemPrice?.toStringAsFixed(2) ?? '0.0'}", style: ThemeText.boldWithBlueColor, ), SizedBox( diff --git a/lib/application/views/create_order_module/widgets/ProductItemView.dart b/lib/application/views/create_order_module/widgets/ProductItemView.dart index 3324378..d90fdba 100644 --- a/lib/application/views/create_order_module/widgets/ProductItemView.dart +++ b/lib/application/views/create_order_module/widgets/ProductItemView.dart @@ -5,6 +5,7 @@ import 'package:wosull/application/model/store/StoreItemsResponse.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/utils/AppLoader.dart'; import 'package:wosull/application/views/create_order_module/viewModels/CreateOrderViewModel.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/ThemeImage.dart'; import 'package:wosull/helpers/ThemeText.dart'; import 'package:wosull/helpers/Utils.dart'; @@ -31,6 +32,14 @@ class ProductItemView extends StatelessWidget { @override Widget build(BuildContext context) { return Container( + foregroundDecoration: !storeItems.isUnlimitedQuantity && + storeItems.totalAddedQuantity <= 0 && + !storeItems.isCombo + ? const BoxDecoration( + color: Colors.grey, + backgroundBlendMode: BlendMode.saturation, + ) + : null, margin: const EdgeInsets.all(8), child: Column( crossAxisAlignment: CrossAxisAlignment.center, @@ -57,7 +66,6 @@ class ProductItemView extends StatelessWidget { visible: !(!storeItems.isCombo && !storeItems.isUnlimitedQuantity && storeItems.stockAlertQuantity == 0), - // visible: storeItems.isCombo , child: Container( margin: const EdgeInsets.only(top: 12), padding: const EdgeInsets.all(2), @@ -66,7 +74,10 @@ class ProductItemView extends StatelessWidget { decoration: BoxDecoration( color: storeItems.isCombo ? MyColors.yellowColor - : MyColors.greenColor, + : !storeItems.isUnlimitedQuantity && + storeItems.totalAddedQuantity <= 0 + ? MyColors.textColorBlack + : MyColors.greenColor, borderRadius: const BorderRadius.only( topLeft: Radius.circular(12), bottomLeft: Radius.circular(12)), @@ -77,7 +88,10 @@ class ProductItemView extends StatelessWidget { ? AppLocalizations.of(context)!.combo : storeItems.isUnlimitedQuantity ? 'Unlimited Quantity' - : '${storeItems.stockAlertQuantity} Stock(s) left', + : !storeItems.isUnlimitedQuantity && + storeItems.totalAddedQuantity <= 0 + ? 'Out of stock' + : '${storeItems.stockAlertQuantity} Stock(s) left', style: ThemeText.textStyleSmallWhite, ), ), @@ -87,50 +101,38 @@ class ProductItemView extends StatelessWidget { child: Visibility( visible: storeItems.deliveryPartner.isNotEmpty, // visible: storeItems.isCombo , - child: Row( - children: [ - Container( - margin: const EdgeInsets.only(top: 12), - padding: const EdgeInsets.fromLTRB(8, 2, 8, 2), - height: 20, - decoration: const BoxDecoration( - color: MyColors.fillRed, - borderRadius: BorderRadius.only( - topRight: Radius.circular(12), - bottomRight: Radius.circular(12)), - ), - child: Center( - child: Text( - storeItems.deliveryPartner, - style: ThemeText.textStyleSmallWhite, - ), - ), - ) - ], + child: Container( + margin: const EdgeInsets.only(top: 12), + padding: const EdgeInsets.fromLTRB(8, 2, 8, 2), + height: 20, + decoration: const BoxDecoration( + color: MyColors.fillRed, + borderRadius: BorderRadius.only( + topRight: Radius.circular(12), + bottomRight: Radius.circular(12)), + ), + child: Text( + storeItems.deliveryPartner, + style: ThemeText.textStyleSmallWhite, + ), )), ) ]), - const SizedBox( - height: 4, - ), + AppSpaces.verticalSmall, Text( storeItems.uniqueIdForStoreData.isNotEmpty ? storeItems.uniqueIdForStoreData : '', style: ThemeText.textStyleSmall, ), - const SizedBox( - height: 4, - ), + AppSpaces.verticalSmall, Text( maxLines: 1, softWrap: true, storeItems.name, style: ThemeText.textStyleH2Black, ), - const SizedBox( - height: 4, - ), + AppSpaces.verticalSmall, SizedBox( height: 35, child: Row( @@ -142,7 +144,7 @@ class ProductItemView extends StatelessWidget { Align( alignment: Alignment.bottomLeft, child: Text( - "${sharedPrefs.currency} ${storeItems.price}", + "${sharedPrefs.currency} ${storeItems.price.toStringAsFixed(2)}", style: ThemeText.textStyleBlueColorSmall, ), ), @@ -152,20 +154,15 @@ class ProductItemView extends StatelessWidget { alignment: Alignment.bottomRight, children: [ FutureBuilder( - future: viewModel.isThere(storeItems.id), + future: viewModel.isThere(storeItems.itemId), builder: (c, s) { if (s.hasData) { var newBool = s.data!; - print(newBool); var quantity = 1; if (newBool) { //TODO issue is coming when we do combo - print('object ' + - viewModel.getQuantity( - viewModel.selectedProductId, - storeItems.id)); quantity = int.parse(viewModel.getQuantity( - viewModel.selectedProductId, storeItems.id)); + storeItems.productId, storeItems.itemId)); } storeItems.quantity = quantity; return Row( @@ -174,23 +171,24 @@ class ProductItemView extends StatelessWidget { children: [ Visibility( visible: storeItems.isCombo, - child: SizedBox( - width: 35, - height: 35, - child: IconButton( - onPressed: showComboInformation, - icon: Icon( + child: Padding( + padding: const EdgeInsets.only(right: 4), + child: GestureDetector( + child: Icon( Icons.info_outline, color: MyColors.blueThemeColor, size: 24, ), + onTap: () { + showComboInformation(); + }, ), )), newBool ? Visibility( visible: true, child: SizedBox( - width: DeviceUtil.isTablet ? 65 : 50, + width: DeviceUtil.isTablet ? 70 : 60, child: Container( height: 25, padding: const EdgeInsets.all(4), @@ -213,8 +211,14 @@ class ProductItemView extends StatelessWidget { icon: const Icon( Icons.remove, size: 18.0), - onPressed: - decreaseItem, + onPressed: sharedPrefs + .billingCounterId + .isNotEmpty + ? decreaseItem + : () { + Utils.showMessage( + 'Please Select Available Billing Counter!'); + }, ))), Expanded( child: Center( @@ -237,8 +241,14 @@ class ProductItemView extends StatelessWidget { icon: const Icon( Icons.add, size: 18.0), - onPressed: - increaseItem, + onPressed: sharedPrefs + .billingCounterId + .isNotEmpty + ? increaseItem + : () { + Utils.showMessage( + 'Please Select Available Billing Counter!'); + }, ))) ], )), @@ -250,7 +260,14 @@ class ProductItemView extends StatelessWidget { height: 25, child: FittedBox( child: FloatingActionButton( - onPressed: addItem, + onPressed: sharedPrefs + .billingCounterId + .isNotEmpty + ? addItem + : () { + Utils.showMessage( + 'Please Select Available Billing Counter!'); + }, backgroundColor: MyColors.blueThemeColor, child: const Icon(Icons.add), diff --git a/lib/application/views/dashboard/HomeVC.dart b/lib/application/views/dashboard/HomeVC.dart index 158c2de..f4ce2f6 100644 --- a/lib/application/views/dashboard/HomeVC.dart +++ b/lib/application/views/dashboard/HomeVC.dart @@ -4,11 +4,10 @@ import 'package:provider/provider.dart'; import 'package:wosull/application/interfaces/DrawerWidgetSelect.dart'; import 'package:wosull/application/model/cart/GetHoldOrderModel.dart'; import 'package:wosull/application/model/customers/GetStoreCustomer.dart'; -import 'package:wosull/application/model/reports/CashierOrderHistory.dart'; +import 'package:wosull/application/model/reports/CashierOrder.dart'; import 'package:wosull/application/model/reports/TopOrderItemsModel.dart'; import 'package:wosull/application/model/suppliers/GetStoreSupplierModel.dart'; import 'package:wosull/application/theme/MyColors.dart'; -import 'package:wosull/application/theme/MyFonts.dart'; import 'package:wosull/application/utils/AppLoader.dart'; import 'package:wosull/application/views/dashboard/viewModel/DashboardViewModel.dart'; import 'package:wosull/application/views/dashboard/widgets/AnimatedProgressBar.dart'; @@ -23,12 +22,13 @@ import 'package:wosull/application/views/dashboard/widgets/POSStatusGraph.dart'; import 'package:wosull/application/views/dashboard/widgets/RevenueGraph.dart'; import 'package:wosull/application/views/dashboard/widgets/TodayPOSSales.dart'; import 'package:wosull/application/views/dashboard/widgets/TodaySaleGraph.dart'; -import 'package:wosull/application/views/settings/reportsViews/BestSuppliersVC.dart'; +import 'package:wosull/application/views/settings/views/reportsViews/BestSuppliersVC.dart'; import 'package:wosull/base/BaseStatefulState.dart'; import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/ThemeText.dart'; import 'package:wosull/helpers/Utils.dart'; import 'package:wosull/widgets/BackHeader.dart'; +import 'package:wosull/widgets/CustomSimpleButton.dart'; import 'package:wosull/widgets/CustomTextButtonIcon.dart'; class HomeVC extends StatefulWidget { @@ -45,377 +45,466 @@ class _HomeVCState extends BaseStatefulState implements ReportsCVS { @override void initState() { + context.read().getService(false); super.initState(); } @override - void didChangeDependencies() {} + void dispose() { + viewModel.disposeData(); + super.dispose(); + } @override Widget build(BuildContext context) { viewModel = context.watch(); - return SafeArea( child: Scaffold( + backgroundColor: MyColors.fillColor, resizeToAvoidBottomInset: true, - body: FutureBuilder( - future: viewModel.getService(), - builder: (c, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return AppLoader(); - } - return OrientationBuilder(builder: (c, orientation) { - viewModel.isPortrait = - MediaQuery.of(c).orientation == Orientation.portrait; - return SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - mainAxisSize: MainAxisSize.min, - children: [ - BackHeader( - onPressed: () { - widget.delegateDrawer.goToHome(); - }, - ), - Container( - padding: const EdgeInsets.all(12), - color: MyColors.fillColor, - child: viewModel.isLoading - ? const Center( - child: CircularProgressIndicator(), - ) - : Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - viewModel.isPortrait - ? Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: - MainAxisAlignment - .start, - children: [ - Text( + body: OrientationBuilder(builder: (c, orientation) { + viewModel.isPortrait = + MediaQuery.of(c).orientation == Orientation.portrait; + return SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + mainAxisSize: MainAxisSize.min, + children: [ + BackHeader( + onPressed: () { + widget.delegateDrawer.goToHome(); + }, + ), + Padding( + padding: const EdgeInsets.all(12), + child: viewModel.isPortrait + ? Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)!.dashboard, + style: MyColors.textStylePageHeading(), + ), + AppSpaces.horizontalSmall, + Flexible( + child: getStartDateButton(), + ) + ], + ), + AppSpaces.verticalMedium, + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Flexible( + child: getEndDateButton(), + ), + AppSpaces.horizontalSmall, + getApplyButton() + ], + ) + ]) + : Row( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)!.dashboard, + style: MyColors.textStylePageHeading(), + ), + ], + ), + Expanded( + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text( + AppLocalizations.of(context)! + .start_date, + style: MyColors.textStyleHeading()), + AppSpaces.horizontalSmall, + SizedBox( + width: 140, + child: getStartDateButton(), + ), + AppSpaces.horizontalSmall, + Text( + AppLocalizations.of(context)! + .end_date, + style: MyColors.textStyleHeading()), + AppSpaces.horizontalSmall, + SizedBox( + width: 140, + child: getEndDateButton(), + ), + AppSpaces.horizontalMedium, + getApplyButton() + ], + ), + ) + ], + ), + ), + Container( + padding: const EdgeInsets.all(12), + child: viewModel.isLoading + ? AppLoader() + : Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + viewModel.isPortrait || !DeviceUtil.isTablet + ? Column(children: [ + Row( + children: [ + Flexible( + child: AnimatedProgressBar( + heading: + AppLocalizations.of( + context)! + .total_sales, + value: viewModel.adminData + .totalSalesReport + ?.toStringAsFixed( + 2) ?? + "0")), + Flexible( + child: AnimatedProgressBar( + heading: + AppLocalizations.of( + context)! + .pos_cancelled, + value: viewModel + .saleCancelOrder + .totalSalesOfCancelledOrder + ?.toStringAsFixed( + 2) ?? + "0.0")), + ], + ), + AppSpaces.verticalMedium, + Row( + children: [ + Flexible( + child: AnimatedProgressBar( + heading: AppLocalizations.of( context)! - .dashboard, - style: MyColors - .textStylePageHeading(), - ), - AppSpaces - .horizontalSmall, - Flexible( - child: - getStartDateButton(), - ) - ], - ), - AppSpaces.verticalMedium, - Row( - mainAxisAlignment: - MainAxisAlignment - .start, - children: [ - Flexible( - child: - getEndDateButton(), - ), - AppSpaces - .horizontalSmall, - getApplyButton() - ], - ) - ]) - : Row( - children: [ - Row( - mainAxisAlignment: - MainAxisAlignment.start, - children: [ - Text( - AppLocalizations.of( - context)! - .dashboard, - style: MyColors - .textStylePageHeading(), - ), - ], - ), - Expanded( - child: Row( - mainAxisAlignment: - MainAxisAlignment.end, - children: [ - Text( - AppLocalizations.of( - context)! - .start_date, - style: MyColors - .textStyleHeading()), - AppSpaces - .horizontalSmall, - SizedBox( - width: 140, - child: - getStartDateButton(), - ), - AppSpaces - .horizontalSmall, - Text( - AppLocalizations.of( - context)! - .end_date, - style: MyColors - .textStyleHeading()), - AppSpaces - .horizontalSmall, - SizedBox( - width: 140, - child: - getEndDateButton(), - ), - AppSpaces - .horizontalMedium, - getApplyButton() - ], - ), - ) - ], - ), - viewModel.isPortrait || - !DeviceUtil.isTablet - ? Column(children: [ - Row( - children: [ - Flexible( - child: AnimatedProgressBar( - heading: - AppLocalizations.of( - context)! - .total_sales, - value: viewModel - .adminData - .totalSalesReport - ?.toStringAsFixed( - 2) ?? - "0")), - Flexible( - child: AnimatedProgressBar( - heading: AppLocalizations - .of( - context)! - .pos_cancelled, - value: viewModel - .saleCancelOrder - .totalSalesOfCancelledOrder - ?.toStringAsFixed( - 2) ?? - "0.0")), - ], - ), - const SizedBox(height: 8), - Row( - children: [ - Flexible( - child: AnimatedProgressBar( - heading: AppLocalizations - .of( - context)! - .total_customer, - value: viewModel - .adminData - .totalCustomer - ?.toString() ?? - "0")), - Flexible( - child: AnimatedProgressBar( - heading: AppLocalizations - .of( - context)! - .total_supplier, - value: viewModel - .adminData - .totalSupplier - ?.toStringAsFixed( - 2) ?? - "0")), - ], - ), - const SizedBox(height: 8), - Row( - children: [ - Flexible( - child: AnimatedProgressBar( - heading: AppLocalizations - .of( - context)! - .total_branches, - value: viewModel - .adminData - .totalBranches - ?.toStringAsFixed( - 2) ?? - "0")), - ], - ), - ]) - : Row( - children: [ - Flexible( - child: AnimatedProgressBar( - heading: - AppLocalizations.of( - context)! - .total_sales, - value: viewModel - .adminData - .totalSalesReport - ?.toStringAsFixed( - 2) ?? - "0")), - Flexible( - child: AnimatedProgressBar( - heading: - AppLocalizations.of( - context)! - .pos_cancelled, - value: viewModel - .saleCancelOrder - .totalSalesOfCancelledOrder - ?.toStringAsFixed( - 2) ?? - "0.0")), - Flexible( - child: AnimatedProgressBar( - heading: AppLocalizations - .of(context)! .total_customer, - value: viewModel - .adminData - .totalCustomer - ?.toString() ?? - "0")), - Flexible( - child: AnimatedProgressBar( - heading: AppLocalizations - .of(context)! + value: viewModel.adminData + .totalCustomer + ?.toString() ?? + "0")), + Flexible( + child: AnimatedProgressBar( + heading: + AppLocalizations.of( + context)! .total_supplier, - value: viewModel - .adminData - .totalSupplier - ?.toStringAsFixed( - 2) ?? - "0")), - Flexible( - child: AnimatedProgressBar( - heading: AppLocalizations - .of(context)! + value: viewModel.adminData + .totalSupplier + ?.toStringAsFixed( + 2) ?? + "0")), + ], + ), + AppSpaces.verticalMedium, + Row( + children: [ + Flexible( + child: AnimatedProgressBar( + heading: + AppLocalizations.of( + context)! .total_branches, - value: viewModel - .adminData - .totalBranches - ?.toStringAsFixed( - 2) ?? - "0")), - ], + value: viewModel.adminData + .totalBranches + ?.toStringAsFixed( + 2) ?? + "0")), + ], + ), + ]) + : Row( + children: [ + Flexible( + child: AnimatedProgressBar( + heading: + AppLocalizations.of( + context)! + .total_sales, + value: viewModel.adminData + .totalSalesReport + ?.toStringAsFixed( + 2) ?? + "0")), + Flexible( + child: AnimatedProgressBar( + heading: + AppLocalizations.of( + context)! + .pos_cancelled, + value: viewModel + .saleCancelOrder + .totalSalesOfCancelledOrder + ?.toStringAsFixed( + 2) ?? + "0.0")), + Flexible( + child: AnimatedProgressBar( + heading: + AppLocalizations.of( + context)! + .total_customer, + value: viewModel.adminData + .totalCustomer + ?.toString() ?? + "0")), + Flexible( + child: AnimatedProgressBar( + heading: + AppLocalizations.of( + context)! + .total_supplier, + value: viewModel.adminData + .totalSupplier + ?.toStringAsFixed( + 2) ?? + "0")), + Flexible( + child: AnimatedProgressBar( + heading: + AppLocalizations.of( + context)! + .total_branches, + value: viewModel.adminData + .totalBranches + ?.toStringAsFixed( + 2) ?? + "0")), + ], + ), + AppSpaces.verticalMedium, + //upper part + viewModel.isPortrait + ? Column(children: [ + OrderDetailsView( + adminData: viewModel.adminData), + AppSpaces.verticalMedium, + InvoiceDetailsView( + invoiceSale: + viewModel.invoiceSale), + ]) + : Row( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Flexible( + child: OrderDetailsView( + adminData: + viewModel.adminData), + ), + AppSpaces.horizontalMedium, + Flexible( + child: InvoiceDetailsView( + invoiceSale: + viewModel.invoiceSale), + ), + ], + ), + + AppSpaces.verticalMedium, + + viewModel.isPortrait + ? Column(children: [ + TodaySaleGraph( + todaySales: viewModel + .graphData.todaySales ?? + [], + ), + AppSpaces.verticalMedium, + TodayPOSSales( + todaySales: viewModel + .graphData.todaySales ?? + [], + ), + AppSpaces.verticalMedium, + RevenueGraph( + data: viewModel.graphData + .totalIncomeExpense ?? + []), + ]) + : Row( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Flexible( + child: TodaySaleGraph( + todaySales: viewModel + .graphData.todaySales ?? + [], + ), + ), + AppSpaces.horizontalMedium, + Flexible( + child: TodayPOSSales( + todaySales: viewModel + .graphData.todaySales ?? + [], ), - //upper part + ), + AppSpaces.horizontalMedium, + Flexible( + child: RevenueGraph( + data: viewModel.graphData + .totalIncomeExpense ?? + []), + ), + ], + ), - AppSpaces.verticalMedium, - TodaySaleGraph(), - AppSpaces.verticalMedium, - TodayPOSSales(), - AppSpaces.verticalMedium, - RevenueGraph( - data: viewModel.graphData - .totalIncomeExpense ?? - []), - AppSpaces.verticalMedium, - InvoiceStatusGraph( + AppSpaces.verticalMedium, + viewModel.isPortrait + ? Column(children: [ + InvoiceStatusGraph( + data: viewModel.graphData + .allInvoiceStatus ?? + []), + AppSpaces.verticalMedium, + POSStatusGraph( + data: viewModel + .graphData.allPosStatus ?? + []), + ]) + : Row( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Flexible( + child: InvoiceStatusGraph( + data: viewModel.graphData + .allInvoiceStatus ?? + []), + ), + AppSpaces.horizontalMedium, + Flexible( + child: POSStatusGraph( + data: viewModel.graphData + .allPosStatus ?? + []), + ), + ], + ), + + AppSpaces.verticalMedium, + + viewModel.isPortrait + ? Column(children: [ + POSOrderCountDayWiseGraph( data: viewModel.graphData - .allInvoiceStatus ?? - []), - AppSpaces.verticalMedium, - POSStatusGraph( - data: viewModel - .graphData.allPosStatus ?? - []), - AppSpaces.verticalMedium, - POSOrderCountDayWiseGraph(), - AppSpaces.verticalMedium, - POSOrderValueDayWise(), - AppSpaces.verticalMedium, - POSOrderCountTimeWiseGraph(), - AppSpaces.verticalMedium, - POSOrderValueTimeWise(), - AppSpaces.verticalMedium, - viewModel.isPortrait - ? Column(children: [ - OrderDetailsView( - adminData: - viewModel.adminData), - AppSpaces.verticalMedium, - InvoiceDetailsView( - invoiceSale: - viewModel.invoiceSale), - ]) - : Row( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Flexible( - child: OrderDetailsView( - adminData: viewModel - .adminData), - ), - AppSpaces.horizontalMedium, - Flexible( - child: InvoiceDetailsView( - invoiceSale: viewModel - .invoiceSale), - ), - ], + .posOrderCountDayWise ?? + [], + ), + AppSpaces.verticalMedium, + POSOrderValueDayWise( + data: viewModel.graphData.array ?? + []), + ]) + : Row( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Flexible( + child: POSOrderCountDayWiseGraph( + data: viewModel.graphData + .posOrderCountDayWise ?? + [], ), - AppSpaces.verticalMedium, - Card( - shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.circular(12.0), + ), + AppSpaces.horizontalMedium, + Flexible( + child: POSOrderValueDayWise( + data: viewModel + .graphData.array ?? + []), + ), + ], + ), + + AppSpaces.verticalMedium, + + viewModel.isPortrait + ? Column(children: [ + POSOrderCountTimeWiseGraph( + data: viewModel.graphData + .posOrderCountTodayTimewise ?? + [], + ), + AppSpaces.verticalMedium, + POSOrderValueTimeWise( + data: viewModel.graphData + .posOrderCountTodayTimewise ?? + [], ), - elevation: 2, - color: MyColors.white, - child: Container( - padding: const EdgeInsets.all(12), - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - AppLocalizations.of( - context)! - .top_order_items, - style: ThemeText - .textStylePageHeading, - ), - AppSpaces.horizontalMedium, - BestSupplierVC( - context: context, - delegate: this, - ) - ], - )), + ]) + : Row( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Flexible( + child: POSOrderCountTimeWiseGraph( + data: viewModel.graphData + .posOrderCountTodayTimewise ?? + [], + ), + ), + AppSpaces.horizontalMedium, + Flexible( + child: POSOrderValueTimeWise( + data: viewModel.graphData + .posOrderCountTodayTimewise ?? + [], + ), + ), + ], ), - ], - )) - ], - ), - ); - }); - }))); + + AppSpaces.verticalMedium, + Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12.0), + ), + elevation: 2, + color: MyColors.white, + child: Container( + padding: const EdgeInsets.all(12), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)! + .top_order_items, + style: ThemeText + .textStylePageHeading, + ), + AppSpaces.horizontalMedium, + BestSupplierVC( + context: context, + delegate: this, + ) + ], + )), + ), + ], + )) + ], + ), + ); + }))); } @override @@ -436,28 +525,21 @@ class _HomeVCState extends BaseStatefulState implements ReportsCVS { Widget getApplyButton() { return SizedBox( width: 100, - child: ElevatedButton( - style: ElevatedButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(6.0), - ), - backgroundColor: MyColors.blueThemeColor, - minimumSize: const Size.fromHeight(38), // NEW - ), + child: CustomSimpleButton( + height: 48, + textColor: MyColors.white, + backGroundColor: MyColors.blueThemeColor, onPressed: () { - viewModel.getService(); + viewModel.getService(true); }, - child: Text( - AppLocalizations.of(context)!.apply, - style: const TextStyle( - fontSize: 12, color: MyColors.white, fontFamily: MyFonts.Bold), - ), + heading: AppLocalizations.of(context)!.apply, ), ); } Widget getEndDateButton() { return CustomTextButtonIcon( + backgroundColor: MyColors.white, icon: Icons.calendar_month, heading: viewModel.endDate.isEmpty ? AppLocalizations.of(context)!.end_date @@ -470,10 +552,11 @@ class _HomeVCState extends BaseStatefulState implements ReportsCVS { Widget getStartDateButton() { return CustomTextButtonIcon( + backgroundColor: MyColors.white, icon: Icons.calendar_month, - heading: viewModel.startDate.isEmpty + heading: context.watch().startDate.isEmpty ? AppLocalizations.of(context)!.start_date - : viewModel.startDate, + : context.watch().startDate, onPressed: () { viewModel.presentDatePicker(context, true); }, diff --git a/lib/application/views/dashboard/repo/DashBoardRepository.dart b/lib/application/views/dashboard/repo/DashBoardRepository.dart new file mode 100644 index 0000000..a23989e --- /dev/null +++ b/lib/application/views/dashboard/repo/DashBoardRepository.dart @@ -0,0 +1,34 @@ +import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/application/model/dashboard/AdminDashboardModel.dart'; +import 'package:wosull/application/model/dashboard/TotalSalesOfCancelledOrderModel.dart'; +import 'package:wosull/application/model/dashboard/graph/GraphData.dart'; +import 'package:wosull/application/model/invoice/InvoiceStatusModel.dart'; +import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/utils/Constants.dart'; + +class DashBoardRepository { + Future getDashboard(Map map) async { + final response = + await APIManager().fetchData(Constants.GET_ADMIN_DASHBOARD, map); + return AdminDashboardModel.fromJson(response); + } + + Future getAdminDashBoardGraph(Map map) async { + final response = await APIManager() + .getResponseAuth(Constants.GET_ADMIN_DASHBOARD_DATA, map); + return GraphData.fromJson(response); + } + + Future getPosSale( + Map map) async { + final response = await APIManager() + .getResponseAuth(Constants.GET_TOP_POS_SALE + sharedPrefs.storeId, map); + return TotalSalesCancelledOrderModel.fromJson(response); + } + + Future getInvoiceSale(Map map) async { + final response = + await APIManager().getResponseAuth(Constants.GET_STORE_INVOICE, map); + return InvoiceStatusModel.fromJson(response); + } +} diff --git a/lib/application/views/dashboard/viewModel/DashboardViewModel.dart b/lib/application/views/dashboard/viewModel/DashboardViewModel.dart index de6c1b0..86b1a9a 100644 --- a/lib/application/views/dashboard/viewModel/DashboardViewModel.dart +++ b/lib/application/views/dashboard/viewModel/DashboardViewModel.dart @@ -4,8 +4,7 @@ import 'package:wosull/application/model/dashboard/AdminDashboardModel.dart'; import 'package:wosull/application/model/dashboard/TotalSalesOfCancelledOrderModel.dart'; import 'package:wosull/application/model/dashboard/graph/GraphData.dart'; import 'package:wosull/application/model/invoice/InvoiceStatusModel.dart'; -import 'package:wosull/application/network/APIManager.dart'; -import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/dashboard/repo/DashBoardRepository.dart'; import '../../../model/converters/DataTimeFormat.dart'; @@ -14,39 +13,52 @@ class DashBoardViewModel with ChangeNotifier { var saleCancelOrder = TotalSalesCancelledOrderModel(); var invoiceSale = InvoiceStatusModel(); var graphData = GraphData(); + + var repository = DashBoardRepository(); + bool isPortrait = true; String startDate = ""; String endDate = ""; - var _isLoading = false; + var _isLoading = true; bool get isLoading => _isLoading; + void disposeData() { + _isLoading = true; + startDate = ""; + endDate = ""; + } + void setLoading(bool value) { - // _isLoading = value; - // notifyListeners(); + _isLoading = value; + notifyListeners(); } - Future getService() async { + Future getService(bool loading) async { + if (loading) { + setLoading(true); + } Map data = { 'store_id': sharedPrefs.storeId, 'start_date': startDate, 'end_date': endDate }; - await APIManager() - .fetchData(Constants.GET_ADMIN_DASHBOARD, data) - .then((value) async { - final response = AdminDashboardModel.fromJson(value); - await getAdminDashBoardGraph(); + + await repository.getDashboard(data).then((response) async { + if (!loading) { + await getAdminDashBoardGraph(); + } + await getPosSale(); await getInvoiceSale(); if (response.success!) { adminData = response; } - //setLoading(false); + setLoading(false); }).onError((error, stackTrace) { - // setLoading(false); + setLoading(false); }); return true; } @@ -57,11 +69,8 @@ class DashBoardViewModel with ChangeNotifier { 'end_date': endDate, 'store_id': sharedPrefs.storeId }; - await APIManager() - .getResponseAuth(Constants.GET_ADMIN_DASHBOARD_DATA, data) - .then((value) { - graphData = GraphData.fromJson(value); - print('lenth' + graphData.totalIncomeExpense!.length.toString()); + await repository.getAdminDashBoardGraph(data).then((value) { + graphData = value; }).onError((error, stackTrace) { setLoading(false); }); @@ -69,10 +78,7 @@ class DashBoardViewModel with ChangeNotifier { Future getPosSale() async { Map data = {'start_date': startDate, 'end_date': endDate}; - await APIManager() - .getResponseAuth(Constants.GET_TOP_POS_SALE + sharedPrefs.storeId, data) - .then((value) { - final response = TotalSalesCancelledOrderModel.fromJson(value); + await repository.getPosSale(data).then((response) { if (response.success!) { saleCancelOrder = response; } @@ -82,15 +88,12 @@ class DashBoardViewModel with ChangeNotifier { } Future getInvoiceSale() async { - Map data = { + Map map = { 'store_id': sharedPrefs.storeId, 'start_date': startDate, 'end_date': endDate }; - await APIManager() - .getResponseAuth(Constants.GET_STORE_INVOICE, data) - .then((value) { - final response = InvoiceStatusModel.fromJson(value); + await repository.getInvoiceSale(map).then((response) { if (response.success!) { invoiceSale = response; } @@ -100,7 +103,7 @@ class DashBoardViewModel with ChangeNotifier { } void presentDatePicker(BuildContext context, bool isStart) { - // showDatePicker is a pre-made funtion of Flutter + // showDatePicker is a pre-made function of Flutter showDatePicker( context: context, initialDate: DateTime.now(), diff --git a/lib/application/views/dashboard/widgets/AnimatedProgressBar.dart b/lib/application/views/dashboard/widgets/AnimatedProgressBar.dart index 16e0c7f..bd5c028 100644 --- a/lib/application/views/dashboard/widgets/AnimatedProgressBar.dart +++ b/lib/application/views/dashboard/widgets/AnimatedProgressBar.dart @@ -22,7 +22,7 @@ class AnimatedProgressBar extends StatelessWidget { children: [ Text( heading, - style: const TextStyle( + style: TextStyle( fontFamily: MyFonts.Bold, fontSize: MyFonts.normal, color: MyColors.textColorBlack), @@ -32,7 +32,7 @@ class AnimatedProgressBar extends StatelessWidget { ), Text( value, - style: const TextStyle( + style: TextStyle( fontFamily: MyFonts.Bold, fontSize: MyFonts.H1, color: MyColors.black), diff --git a/lib/application/views/dashboard/widgets/Indicator.dart b/lib/application/views/dashboard/widgets/Indicator.dart index 6084661..b8a1e90 100644 --- a/lib/application/views/dashboard/widgets/Indicator.dart +++ b/lib/application/views/dashboard/widgets/Indicator.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:wosull/application/theme/MyFonts.dart'; class Indicator extends StatelessWidget { const Indicator({ @@ -33,8 +34,8 @@ class Indicator extends StatelessWidget { Text( text, style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, + fontFamily: MyFonts.Medium, + fontSize: 11, color: textColor, ), ) diff --git a/lib/application/views/dashboard/widgets/InvoiceDetailsView.dart b/lib/application/views/dashboard/widgets/InvoiceDetailsView.dart index 8a157c7..323e7d4 100644 --- a/lib/application/views/dashboard/widgets/InvoiceDetailsView.dart +++ b/lib/application/views/dashboard/widgets/InvoiceDetailsView.dart @@ -24,7 +24,7 @@ class InvoiceDetailsView extends StatelessWidget { padding: const EdgeInsets.only(left: 12, top: 12, right: 12), child: Text( lang(context).invoice_details, - style: const TextStyle( + style: TextStyle( fontSize: MyFonts.H2, fontFamily: MyFonts.Bold, color: MyColors.white), @@ -35,7 +35,7 @@ class InvoiceDetailsView extends StatelessWidget { const EdgeInsets.only(left: 12, bottom: 34, right: 12, top: 4), child: Text( lang(context).recent_invoice_order, - style: const TextStyle( + style: TextStyle( fontSize: MyFonts.normal, fontFamily: MyFonts.DMREGULAR, color: MyColors.white), diff --git a/lib/application/views/dashboard/widgets/InvoiceStatusGraph.dart b/lib/application/views/dashboard/widgets/InvoiceStatusGraph.dart index 069f372..3b144ae 100644 --- a/lib/application/views/dashboard/widgets/InvoiceStatusGraph.dart +++ b/lib/application/views/dashboard/widgets/InvoiceStatusGraph.dart @@ -29,19 +29,19 @@ class InvoiceStatusGraph extends StatelessWidget { children: [ const Indicator( color: MyColors.primary, - text: 'Cancelled Invoices', + text: 'Cancelled', isSquare: true, ), AppSpaces.horizontalSmall, Indicator( color: MyColors.blueThemeColor, - text: 'Open Invoices', + text: 'Open ', isSquare: true, ), AppSpaces.horizontalSmall, const Indicator( color: MyColors.greenColor, - text: 'Paid Invoices', + text: 'Paid ', isSquare: true, ), ], @@ -53,13 +53,13 @@ class InvoiceStatusGraph extends StatelessWidget { children: [ Indicator( color: MyColors.yellowColor, - text: 'Partially Paid Invoices', + text: 'Partially Paid', isSquare: true, ), AppSpaces.horizontalSmall, Indicator( color: MyColors.black, - text: 'Return Invoices', + text: 'Return', isSquare: true, ), ], @@ -75,7 +75,7 @@ class InvoiceStatusGraph extends StatelessWidget { borderData: FlBorderData( show: true, ), - sectionsSpace: 0, + sectionsSpace: 2, centerSpaceRadius: 0, sections: showingSections(), ), diff --git a/lib/application/views/dashboard/widgets/OrderDetailsView.dart b/lib/application/views/dashboard/widgets/OrderDetailsView.dart index 724a1e5..01071bc 100644 --- a/lib/application/views/dashboard/widgets/OrderDetailsView.dart +++ b/lib/application/views/dashboard/widgets/OrderDetailsView.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:wosull/application/model/dashboard/AdminDashboardModel.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/theme/MyFonts.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/Utils.dart'; class OrderDetailsView extends StatelessWidget { @@ -24,7 +25,7 @@ class OrderDetailsView extends StatelessWidget { padding: const EdgeInsets.only(left: 12, top: 12, right: 12), child: Text( lang(context).order_details, - style: const TextStyle( + style: TextStyle( fontSize: MyFonts.H2, fontFamily: MyFonts.Bold, color: MyColors.white), @@ -35,7 +36,7 @@ class OrderDetailsView extends StatelessWidget { const EdgeInsets.only(left: 12, bottom: 34, right: 12, top: 4), child: Text( lang(context).recent_order, - style: const TextStyle( + style: TextStyle( fontSize: MyFonts.normal, fontFamily: MyFonts.DMREGULAR, color: MyColors.white), @@ -57,7 +58,7 @@ class OrderDetailsView extends StatelessWidget { bottomRight: Radius.circular(8)), color: MyColors.white, ), - height: 130), + height: 270), Positioned( right: 0, left: 0, @@ -104,9 +105,7 @@ class OrderDetailsView extends StatelessWidget { ), ), )), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, Flexible( child: Card( child: Container( @@ -185,9 +184,7 @@ class OrderDetailsView extends StatelessWidget { ), ), )), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, Flexible( child: Card( child: Container( @@ -227,6 +224,162 @@ class OrderDetailsView extends StatelessWidget { ), )), ]), + Row(children: [ + Flexible( + child: Card( + child: Container( + padding: const EdgeInsets.all(8), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text( + 'Damaged', + style: TextStyle( + fontFamily: MyFonts.Bold, + fontSize: 12, + color: MyColors.textColorBlack), + ), + AppSpaces.verticalSmall, + Row( + children: [ + Text( + adminData.totalDamagedOrders + ?.toString() ?? + "0", + style: const TextStyle( + fontFamily: MyFonts.Bold, + fontSize: 18, + color: MyColors.black), + ), + const SizedBox( + width: 6, + ), + ], + ), + ], + ), + ), + )), + AppSpaces.horizontalMedium, + Flexible( + child: Card( + child: Container( + padding: const EdgeInsets.all(8), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Returned Orders', + style: const TextStyle( + fontFamily: MyFonts.Bold, + fontSize: 12, + color: MyColors.textColorBlack), + ), + const SizedBox( + height: 4, + ), + Row( + children: [ + Text( + adminData.totalReturnOrders + ?.toString() ?? + "0", + style: const TextStyle( + fontFamily: MyFonts.Bold, + fontSize: 18, + color: MyColors.black), + ), + const SizedBox( + width: 6, + ), + ], + ), + ], + ), + ), + )), + ]), + Row(children: [ + Flexible( + child: Card( + child: Container( + padding: const EdgeInsets.all(8), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text( + 'Partially Returned Orders', + style: TextStyle( + fontFamily: MyFonts.Bold, + fontSize: 12, + color: MyColors.textColorBlack), + ), + const SizedBox( + height: 4, + ), + Row( + children: [ + Text( + adminData.totalPartiallyReturnOrders + ?.toString() ?? + "0", + style: const TextStyle( + fontFamily: MyFonts.Bold, + fontSize: 18, + color: MyColors.black), + ), + const SizedBox( + width: 6, + ), + ], + ), + ], + ), + ), + )), + AppSpaces.horizontalMedium, + Flexible( + child: Card( + child: Container( + padding: const EdgeInsets.all(8), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text( + 'Partially Damaged Orders', + style: TextStyle( + fontFamily: MyFonts.Bold, + fontSize: 12, + color: MyColors.textColorBlack), + ), + const SizedBox( + height: 4, + ), + Row( + children: [ + Text( + adminData.totalPartiallyDamagedOrders + ?.toString() ?? + "0", + style: const TextStyle( + fontFamily: MyFonts.Bold, + fontSize: 18, + color: MyColors.black), + ), + const SizedBox( + width: 6, + ), + ], + ), + ], + ), + ), + )), + ]), ], ), ), diff --git a/lib/application/views/dashboard/widgets/POSOrderCountDayWiseGraph.dart b/lib/application/views/dashboard/widgets/POSOrderCountDayWiseGraph.dart index ed0532c..1deec11 100644 --- a/lib/application/views/dashboard/widgets/POSOrderCountDayWiseGraph.dart +++ b/lib/application/views/dashboard/widgets/POSOrderCountDayWiseGraph.dart @@ -1,34 +1,28 @@ import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/application/model/dashboard/graph/PosOrderCountDayWise.dart'; import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/AppError.dart'; import 'package:wosull/application/views/dashboard/widgets/Indicator.dart'; import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/ThemeText.dart'; class POSOrderCountDayWiseGraph extends StatelessWidget { - POSOrderCountDayWiseGraph({super.key}); + List data; + + POSOrderCountDayWiseGraph({super.key, required this.data}); final Color dark = MyColors.blueThemeColor; - final Color normal = MyColors.blueThemeColor; + final Color normal = Colors.white; final Color light = MyColors.blueThemeColor; Widget bottomTitles(double value, TitleMeta meta) { + print(value); const style = TextStyle(fontSize: 8); String text; switch (value.toInt()) { case 0: - text = 'Apr'; - break; - case 1: - text = 'May'; - break; - case 2: - text = 'Jun'; - break; - case 3: - text = 'Jul'; - break; - case 4: - text = 'Aug'; + text = DataTimeFormat.getDay(data.first.id!); break; default: text = ''; @@ -80,63 +74,68 @@ class POSOrderCountDayWiseGraph extends StatelessWidget { ), ], ), - AspectRatio( - aspectRatio: 1.66, - child: Padding( - padding: const EdgeInsets.only(top: 16), - child: LayoutBuilder( - builder: (context, constraints) { - final barsSpace = 4.0 * constraints.maxWidth / 400; - final barsWidth = 8.0 * constraints.maxWidth / 400; - return BarChart( - BarChartData( - alignment: BarChartAlignment.center, - barTouchData: BarTouchData( - enabled: false, - ), - titlesData: FlTitlesData( - show: true, - bottomTitles: AxisTitles( - sideTitles: SideTitles( - showTitles: true, - reservedSize: 28, - getTitlesWidget: bottomTitles, - ), - ), - leftTitles: AxisTitles( - sideTitles: SideTitles( - showTitles: true, - reservedSize: 40, - getTitlesWidget: leftTitles, + data.isNotEmpty + ? AspectRatio( + aspectRatio: 1.66, + child: Padding( + padding: const EdgeInsets.only(top: 16), + child: LayoutBuilder( + builder: (context, constraints) { + final barsSpace = 4.0 * constraints.maxWidth / 400; + final barsWidth = 8.0 * constraints.maxWidth / 50; + + return BarChart( + BarChartData( + alignment: BarChartAlignment.center, + barTouchData: BarTouchData( + enabled: false, + ), + titlesData: FlTitlesData( + show: true, + bottomTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + reservedSize: 28, + getTitlesWidget: bottomTitles, + ), + ), + leftTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + reservedSize: 40, + getTitlesWidget: leftTitles, + ), + ), + topTitles: const AxisTitles( + sideTitles: SideTitles(showTitles: false), + ), + rightTitles: const AxisTitles( + sideTitles: SideTitles(showTitles: false), + ), + ), + gridData: FlGridData( + show: true, + getDrawingHorizontalLine: (value) => + const FlLine( + color: MyColors.fillColorGray, + strokeWidth: 1, + ), + drawVerticalLine: true, + ), + borderData: FlBorderData( + show: false, + ), + groupsSpace: barsSpace, + barGroups: getData(barsWidth, barsSpace), ), - ), - topTitles: const AxisTitles( - sideTitles: SideTitles(showTitles: false), - ), - rightTitles: const AxisTitles( - sideTitles: SideTitles(showTitles: false), - ), - ), - gridData: FlGridData( - show: true, - checkToShowHorizontalLine: (value) => value % 10 == 0, - getDrawingHorizontalLine: (value) => FlLine( - color: MyColors.blueThemeColor, - strokeWidth: 1, - ), - drawVerticalLine: false, - ), - borderData: FlBorderData( - show: false, - ), - groupsSpace: barsSpace, - barGroups: getData(barsWidth, barsSpace), + ); + }, ), - ); - }, - ), - ), - ), + ), + ) + : AppError( + error: 'No Data Available', + ), ], ), ), @@ -150,220 +149,13 @@ class POSOrderCountDayWiseGraph extends StatelessWidget { barsSpace: barsSpace, barRods: [ BarChartRodData( - toY: 17000000000, - rodStackItems: [ - BarChartRodStackItem(0, 2000000000, dark), - BarChartRodStackItem(2000000000, 12000000000, normal), - BarChartRodStackItem(12000000000, 17000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 24000000000, - rodStackItems: [ - BarChartRodStackItem(0, 13000000000, dark), - BarChartRodStackItem(13000000000, 14000000000, normal), - BarChartRodStackItem(14000000000, 24000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 23000000000.5, - rodStackItems: [ - BarChartRodStackItem(0, 6000000000.5, dark), - BarChartRodStackItem(6000000000.5, 18000000000, normal), - BarChartRodStackItem(18000000000, 23000000000.5, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 29000000000, - rodStackItems: [ - BarChartRodStackItem(0, 9000000000, dark), - BarChartRodStackItem(9000000000, 15000000000, normal), - BarChartRodStackItem(15000000000, 29000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 32000000000, - rodStackItems: [ - BarChartRodStackItem(0, 2000000000.5, dark), - BarChartRodStackItem(2000000000.5, 17000000000.5, normal), - BarChartRodStackItem(17000000000.5, 32000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - ], - ), - BarChartGroupData( - x: 1, - barsSpace: barsSpace, - barRods: [ - BarChartRodData( - toY: 31000000000, - rodStackItems: [ - BarChartRodStackItem(0, 11000000000, dark), - BarChartRodStackItem(11000000000, 18000000000, normal), - BarChartRodStackItem(18000000000, 31000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 35000000000, - rodStackItems: [ - BarChartRodStackItem(0, 14000000000, dark), - BarChartRodStackItem(14000000000, 27000000000, normal), - BarChartRodStackItem(27000000000, 35000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 31000000000, - rodStackItems: [ - BarChartRodStackItem(0, 8000000000, dark), - BarChartRodStackItem(8000000000, 24000000000, normal), - BarChartRodStackItem(24000000000, 31000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 15000000000, - rodStackItems: [ - BarChartRodStackItem(0, 6000000000.5, dark), - BarChartRodStackItem(6000000000.5, 12000000000.5, normal), - BarChartRodStackItem(12000000000.5, 15000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 17000000000, - rodStackItems: [ - BarChartRodStackItem(0, 9000000000, dark), - BarChartRodStackItem(9000000000, 15000000000, normal), - BarChartRodStackItem(15000000000, 17000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - ], - ), - BarChartGroupData( - x: 2, - barsSpace: barsSpace, - barRods: [ - BarChartRodData( - toY: 34000000000, - rodStackItems: [ - BarChartRodStackItem(0, 6000000000, dark), - BarChartRodStackItem(6000000000, 23000000000, normal), - BarChartRodStackItem(23000000000, 34000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 32000000000, - rodStackItems: [ - BarChartRodStackItem(0, 7000000000, dark), - BarChartRodStackItem(7000000000, 24000000000, normal), - BarChartRodStackItem(24000000000, 32000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 14000000000.5, - rodStackItems: [ - BarChartRodStackItem(0, 1000000000.5, dark), - BarChartRodStackItem(1000000000.5, 12000000000, normal), - BarChartRodStackItem(12000000000, 14000000000.5, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 20000000000, - rodStackItems: [ - BarChartRodStackItem(0, 4000000000, dark), - BarChartRodStackItem(4000000000, 15000000000, normal), - BarChartRodStackItem(15000000000, 20000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 24000000000, - rodStackItems: [ - BarChartRodStackItem(0, 4000000000, dark), - BarChartRodStackItem(4000000000, 15000000000, normal), - BarChartRodStackItem(15000000000, 24000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - ], - ), - BarChartGroupData( - x: 3, - barsSpace: barsSpace, - barRods: [ - BarChartRodData( - toY: 14000000000, - rodStackItems: [ - BarChartRodStackItem(0, 1000000000.5, dark), - BarChartRodStackItem(1000000000.5, 12000000000, normal), - BarChartRodStackItem(12000000000, 14000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 27000000000, - rodStackItems: [ - BarChartRodStackItem(0, 7000000000, dark), - BarChartRodStackItem(7000000000, 25000000000, normal), - BarChartRodStackItem(25000000000, 27000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 29000000000, - rodStackItems: [ - BarChartRodStackItem(0, 6000000000, dark), - BarChartRodStackItem(6000000000, 23000000000, normal), - BarChartRodStackItem(23000000000, 29000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 16000000000.5, - rodStackItems: [ - BarChartRodStackItem(0, 9000000000, dark), - BarChartRodStackItem(9000000000, 15000000000, normal), - BarChartRodStackItem(15000000000, 16000000000.5, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 15000000000, + color: Colors.transparent, + toY: data.first.count! + 2, rodStackItems: [ - BarChartRodStackItem(0, 7000000000, dark), - BarChartRodStackItem(7000000000, 12000000000.5, normal), - BarChartRodStackItem(12000000000.5, 15000000000, light), + BarChartRodStackItem( + 0, data.first.count!.toDouble(), dark, BorderSide(width: 0)), ], + borderSide: const BorderSide(width: 0), borderRadius: BorderRadius.zero, width: barsWidth, ), diff --git a/lib/application/views/dashboard/widgets/POSOrderCountTimeWiseGraph.dart b/lib/application/views/dashboard/widgets/POSOrderCountTimeWiseGraph.dart index 84246eb..915fe9e 100644 --- a/lib/application/views/dashboard/widgets/POSOrderCountTimeWiseGraph.dart +++ b/lib/application/views/dashboard/widgets/POSOrderCountTimeWiseGraph.dart @@ -1,12 +1,16 @@ import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/application/model/dashboard/graph/PosOrderCountTodayTimewise.dart'; import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/AppError.dart'; import 'package:wosull/application/views/dashboard/widgets/Indicator.dart'; import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/ThemeText.dart'; class POSOrderCountTimeWiseGraph extends StatelessWidget { - POSOrderCountTimeWiseGraph({super.key}); + List data; + POSOrderCountTimeWiseGraph({super.key, required this.data}); final Color dark = MyColors.blueThemeColor; final Color normal = MyColors.blueThemeColor; @@ -14,27 +18,7 @@ class POSOrderCountTimeWiseGraph extends StatelessWidget { Widget bottomTitles(double value, TitleMeta meta) { const style = TextStyle(fontSize: 8); - String text; - switch (value.toInt()) { - case 0: - text = 'Apr'; - break; - case 1: - text = 'May'; - break; - case 2: - text = 'Jun'; - break; - case 3: - text = 'Jul'; - break; - case 4: - text = 'Aug'; - break; - default: - text = ''; - break; - } + String text = DataTimeFormat.getTimeFormat(data[value.toInt()].sId!); return SideTitleWidget( axisSide: meta.axisSide, child: Text(text, style: style), @@ -81,63 +65,66 @@ class POSOrderCountTimeWiseGraph extends StatelessWidget { ), ], ), - AspectRatio( - aspectRatio: 1.66, - child: Padding( - padding: const EdgeInsets.only(top: 16), - child: LayoutBuilder( - builder: (context, constraints) { - final barsSpace = 4.0 * constraints.maxWidth / 400; - final barsWidth = 8.0 * constraints.maxWidth / 400; - return BarChart( - BarChartData( - alignment: BarChartAlignment.center, - barTouchData: BarTouchData( - enabled: false, - ), - titlesData: FlTitlesData( - show: true, - bottomTitles: AxisTitles( - sideTitles: SideTitles( - showTitles: true, - reservedSize: 28, - getTitlesWidget: bottomTitles, - ), - ), - leftTitles: AxisTitles( - sideTitles: SideTitles( - showTitles: true, - reservedSize: 40, - getTitlesWidget: leftTitles, + data.isNotEmpty + ? AspectRatio( + aspectRatio: 1.66, + child: Padding( + padding: const EdgeInsets.only(top: 16), + child: LayoutBuilder( + builder: (context, constraints) { + final barsSpace = 4.0 * constraints.maxWidth / 400; + final barsWidth = 8.0 * constraints.maxWidth / 50; + return BarChart( + BarChartData( + alignment: BarChartAlignment.center, + barTouchData: BarTouchData( + enabled: false, + ), + titlesData: FlTitlesData( + show: true, + bottomTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + reservedSize: 28, + getTitlesWidget: bottomTitles, + ), + ), + leftTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + reservedSize: 40, + getTitlesWidget: leftTitles, + ), + ), + topTitles: const AxisTitles( + sideTitles: SideTitles(showTitles: false), + ), + rightTitles: const AxisTitles( + sideTitles: SideTitles(showTitles: false), + ), + ), + gridData: FlGridData( + show: true, + getDrawingHorizontalLine: (value) => FlLine( + color: MyColors.fillColorGray, + strokeWidth: 1, + ), + drawVerticalLine: false, + ), + borderData: FlBorderData( + show: false, + ), + groupsSpace: barsSpace, + barGroups: getData(barsWidth, barsSpace), ), - ), - topTitles: const AxisTitles( - sideTitles: SideTitles(showTitles: false), - ), - rightTitles: const AxisTitles( - sideTitles: SideTitles(showTitles: false), - ), - ), - gridData: FlGridData( - show: true, - checkToShowHorizontalLine: (value) => value % 10 == 0, - getDrawingHorizontalLine: (value) => FlLine( - color: MyColors.blueThemeColor, - strokeWidth: 1, - ), - drawVerticalLine: false, - ), - borderData: FlBorderData( - show: false, - ), - groupsSpace: barsSpace, - barGroups: getData(barsWidth, barsSpace), + ); + }, ), - ); - }, - ), - ), - ), + ), + ) + : AppError( + error: 'No Data Available', + ), ], ), ), @@ -145,231 +132,27 @@ class POSOrderCountTimeWiseGraph extends StatelessWidget { } List getData(double barsWidth, double barsSpace) { - return [ - BarChartGroupData( + List groupData = []; + for (var timeData in data) { + groupData.add(BarChartGroupData( x: 0, barsSpace: barsSpace, barRods: [ BarChartRodData( - toY: 17000000000, - rodStackItems: [ - BarChartRodStackItem(0, 2000000000, dark), - BarChartRodStackItem(2000000000, 12000000000, normal), - BarChartRodStackItem(12000000000, 17000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 24000000000, - rodStackItems: [ - BarChartRodStackItem(0, 13000000000, dark), - BarChartRodStackItem(13000000000, 14000000000, normal), - BarChartRodStackItem(14000000000, 24000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 23000000000.5, - rodStackItems: [ - BarChartRodStackItem(0, 6000000000.5, dark), - BarChartRodStackItem(6000000000.5, 18000000000, normal), - BarChartRodStackItem(18000000000, 23000000000.5, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 29000000000, + color: Colors.transparent, + toY: timeData.count! + 2, rodStackItems: [ - BarChartRodStackItem(0, 9000000000, dark), - BarChartRodStackItem(9000000000, 15000000000, normal), - BarChartRodStackItem(15000000000, 29000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 32000000000, - rodStackItems: [ - BarChartRodStackItem(0, 2000000000.5, dark), - BarChartRodStackItem(2000000000.5, 17000000000.5, normal), - BarChartRodStackItem(17000000000.5, 32000000000, light), + BarChartRodStackItem(0, timeData.count!.toDouble(), dark, + const BorderSide(width: 0)) ], + borderSide: const BorderSide(width: 0), borderRadius: BorderRadius.zero, width: barsWidth, ), ], - ), - BarChartGroupData( - x: 1, - barsSpace: barsSpace, - barRods: [ - BarChartRodData( - toY: 31000000000, - rodStackItems: [ - BarChartRodStackItem(0, 11000000000, dark), - BarChartRodStackItem(11000000000, 18000000000, normal), - BarChartRodStackItem(18000000000, 31000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 35000000000, - rodStackItems: [ - BarChartRodStackItem(0, 14000000000, dark), - BarChartRodStackItem(14000000000, 27000000000, normal), - BarChartRodStackItem(27000000000, 35000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 31000000000, - rodStackItems: [ - BarChartRodStackItem(0, 8000000000, dark), - BarChartRodStackItem(8000000000, 24000000000, normal), - BarChartRodStackItem(24000000000, 31000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 15000000000, - rodStackItems: [ - BarChartRodStackItem(0, 6000000000.5, dark), - BarChartRodStackItem(6000000000.5, 12000000000.5, normal), - BarChartRodStackItem(12000000000.5, 15000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 17000000000, - rodStackItems: [ - BarChartRodStackItem(0, 9000000000, dark), - BarChartRodStackItem(9000000000, 15000000000, normal), - BarChartRodStackItem(15000000000, 17000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - ], - ), - BarChartGroupData( - x: 2, - barsSpace: barsSpace, - barRods: [ - BarChartRodData( - toY: 34000000000, - rodStackItems: [ - BarChartRodStackItem(0, 6000000000, dark), - BarChartRodStackItem(6000000000, 23000000000, normal), - BarChartRodStackItem(23000000000, 34000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 32000000000, - rodStackItems: [ - BarChartRodStackItem(0, 7000000000, dark), - BarChartRodStackItem(7000000000, 24000000000, normal), - BarChartRodStackItem(24000000000, 32000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 14000000000.5, - rodStackItems: [ - BarChartRodStackItem(0, 1000000000.5, dark), - BarChartRodStackItem(1000000000.5, 12000000000, normal), - BarChartRodStackItem(12000000000, 14000000000.5, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 20000000000, - rodStackItems: [ - BarChartRodStackItem(0, 4000000000, dark), - BarChartRodStackItem(4000000000, 15000000000, normal), - BarChartRodStackItem(15000000000, 20000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 24000000000, - rodStackItems: [ - BarChartRodStackItem(0, 4000000000, dark), - BarChartRodStackItem(4000000000, 15000000000, normal), - BarChartRodStackItem(15000000000, 24000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - ], - ), - BarChartGroupData( - x: 3, - barsSpace: barsSpace, - barRods: [ - BarChartRodData( - toY: 14000000000, - rodStackItems: [ - BarChartRodStackItem(0, 1000000000.5, dark), - BarChartRodStackItem(1000000000.5, 12000000000, normal), - BarChartRodStackItem(12000000000, 14000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 27000000000, - rodStackItems: [ - BarChartRodStackItem(0, 7000000000, dark), - BarChartRodStackItem(7000000000, 25000000000, normal), - BarChartRodStackItem(25000000000, 27000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 29000000000, - rodStackItems: [ - BarChartRodStackItem(0, 6000000000, dark), - BarChartRodStackItem(6000000000, 23000000000, normal), - BarChartRodStackItem(23000000000, 29000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 16000000000.5, - rodStackItems: [ - BarChartRodStackItem(0, 9000000000, dark), - BarChartRodStackItem(9000000000, 15000000000, normal), - BarChartRodStackItem(15000000000, 16000000000.5, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 15000000000, - rodStackItems: [ - BarChartRodStackItem(0, 7000000000, dark), - BarChartRodStackItem(7000000000, 12000000000.5, normal), - BarChartRodStackItem(12000000000.5, 15000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - ], - ), - ]; + )); + } + + return groupData; } } diff --git a/lib/application/views/dashboard/widgets/POSOrderValueDayWise.dart b/lib/application/views/dashboard/widgets/POSOrderValueDayWise.dart index b234b22..909a6ba 100644 --- a/lib/application/views/dashboard/widgets/POSOrderValueDayWise.dart +++ b/lib/application/views/dashboard/widgets/POSOrderValueDayWise.dart @@ -1,40 +1,20 @@ import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; +import 'package:wosull/application/model/dashboard/graph/POSValueDataWise.dart'; import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/AppError.dart'; import 'package:wosull/application/views/dashboard/widgets/Indicator.dart'; import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/ThemeText.dart'; class POSOrderValueDayWise extends StatelessWidget { - POSOrderValueDayWise({super.key}); - - final Color dark = MyColors.blueThemeColor; - final Color normal = MyColors.blueThemeColor; - final Color light = MyColors.blueThemeColor; + List data; + POSOrderValueDayWise({super.key, required this.data}); Widget bottomTitles(double value, TitleMeta meta) { - const style = TextStyle(fontSize: 8); - String text; - switch (value.toInt()) { - case 0: - text = 'Apr'; - break; - case 1: - text = 'May'; - break; - case 2: - text = 'Jun'; - break; - case 3: - text = 'Jul'; - break; - case 4: - text = 'Aug'; - break; - default: - text = ''; - break; - } + const style = TextStyle(fontSize: 6); + String text = data[value.toInt()].id!; + return SideTitleWidget( axisSide: meta.axisSide, child: Text(text, style: style), @@ -81,63 +61,67 @@ class POSOrderValueDayWise extends StatelessWidget { ), ], ), - AspectRatio( - aspectRatio: 1.66, - child: Padding( - padding: const EdgeInsets.only(top: 16), - child: LayoutBuilder( - builder: (context, constraints) { - final barsSpace = 4.0 * constraints.maxWidth / 400; - final barsWidth = 8.0 * constraints.maxWidth / 400; - return BarChart( - BarChartData( - alignment: BarChartAlignment.center, - barTouchData: BarTouchData( - enabled: false, - ), - titlesData: FlTitlesData( - show: true, - bottomTitles: AxisTitles( - sideTitles: SideTitles( - showTitles: true, - reservedSize: 28, - getTitlesWidget: bottomTitles, + data.isNotEmpty + ? AspectRatio( + aspectRatio: 1.66, + child: Padding( + padding: const EdgeInsets.only(top: 16), + child: LayoutBuilder( + builder: (context, constraints) { + final barsSpace = 4.0 * constraints.maxWidth / 100; + final barsWidth = 8.0 * constraints.maxWidth / 100; + return BarChart( + BarChartData( + alignment: BarChartAlignment.center, + barTouchData: BarTouchData( + enabled: false, + ), + titlesData: FlTitlesData( + show: true, + bottomTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + reservedSize: 28, + getTitlesWidget: bottomTitles, + ), + ), + leftTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + reservedSize: 40, + getTitlesWidget: leftTitles, + ), + ), + topTitles: const AxisTitles( + sideTitles: SideTitles(showTitles: false), + ), + rightTitles: const AxisTitles( + sideTitles: SideTitles(showTitles: false), + ), + ), + gridData: FlGridData( + show: true, + getDrawingHorizontalLine: (value) => + const FlLine( + color: MyColors.fillColorGray, + strokeWidth: 1, + ), + drawVerticalLine: true, + ), + borderData: FlBorderData( + show: false, + ), + groupsSpace: barsSpace, + barGroups: getData(barsWidth, barsSpace), ), - ), - leftTitles: AxisTitles( - sideTitles: SideTitles( - showTitles: true, - reservedSize: 40, - getTitlesWidget: leftTitles, - ), - ), - topTitles: const AxisTitles( - sideTitles: SideTitles(showTitles: false), - ), - rightTitles: const AxisTitles( - sideTitles: SideTitles(showTitles: false), - ), - ), - gridData: FlGridData( - show: true, - checkToShowHorizontalLine: (value) => value % 10 == 0, - getDrawingHorizontalLine: (value) => FlLine( - color: MyColors.blueThemeColor, - strokeWidth: 1, - ), - drawVerticalLine: false, - ), - borderData: FlBorderData( - show: false, - ), - groupsSpace: barsSpace, - barGroups: getData(barsWidth, barsSpace), + ); + }, ), - ); - }, - ), - ), - ), + ), + ) + : AppError( + error: 'No Data Available', + ), ], ), ), @@ -145,231 +129,29 @@ class POSOrderValueDayWise extends StatelessWidget { } List getData(double barsWidth, double barsSpace) { - return [ - BarChartGroupData( - x: 0, - barsSpace: barsSpace, - barRods: [ - BarChartRodData( - toY: 17000000000, - rodStackItems: [ - BarChartRodStackItem(0, 2000000000, dark), - BarChartRodStackItem(2000000000, 12000000000, normal), - BarChartRodStackItem(12000000000, 17000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 24000000000, - rodStackItems: [ - BarChartRodStackItem(0, 13000000000, dark), - BarChartRodStackItem(13000000000, 14000000000, normal), - BarChartRodStackItem(14000000000, 24000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 23000000000.5, - rodStackItems: [ - BarChartRodStackItem(0, 6000000000.5, dark), - BarChartRodStackItem(6000000000.5, 18000000000, normal), - BarChartRodStackItem(18000000000, 23000000000.5, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 29000000000, - rodStackItems: [ - BarChartRodStackItem(0, 9000000000, dark), - BarChartRodStackItem(9000000000, 15000000000, normal), - BarChartRodStackItem(15000000000, 29000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 32000000000, - rodStackItems: [ - BarChartRodStackItem(0, 2000000000.5, dark), - BarChartRodStackItem(2000000000.5, 17000000000.5, normal), - BarChartRodStackItem(17000000000.5, 32000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - ], - ), - BarChartGroupData( - x: 1, + List groupData = []; + for (int i = 0; i < data.length; i++) { + var timeData = data[i]; + groupData.add(BarChartGroupData( + x: i, barsSpace: barsSpace, barRods: [ BarChartRodData( - toY: 31000000000, - rodStackItems: [ - BarChartRodStackItem(0, 11000000000, dark), - BarChartRodStackItem(11000000000, 18000000000, normal), - BarChartRodStackItem(18000000000, 31000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 35000000000, - rodStackItems: [ - BarChartRodStackItem(0, 14000000000, dark), - BarChartRodStackItem(14000000000, 27000000000, normal), - BarChartRodStackItem(27000000000, 35000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 31000000000, + color: Colors.transparent, + toY: timeData.totalAmount! + (timeData.totalAmount! / 2), rodStackItems: [ - BarChartRodStackItem(0, 8000000000, dark), - BarChartRodStackItem(8000000000, 24000000000, normal), - BarChartRodStackItem(24000000000, 31000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 15000000000, - rodStackItems: [ - BarChartRodStackItem(0, 6000000000.5, dark), - BarChartRodStackItem(6000000000.5, 12000000000.5, normal), - BarChartRodStackItem(12000000000.5, 15000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 17000000000, - rodStackItems: [ - BarChartRodStackItem(0, 9000000000, dark), - BarChartRodStackItem(9000000000, 15000000000, normal), - BarChartRodStackItem(15000000000, 17000000000, light), + BarChartRodStackItem(0, timeData.totalAmount!.toDouble(), + MyColors.blueThemeColor, const BorderSide(width: 0)) ], + borderSide: const BorderSide(width: 0), borderRadius: BorderRadius.zero, width: barsWidth, ), ], - ), - BarChartGroupData( - x: 2, - barsSpace: barsSpace, - barRods: [ - BarChartRodData( - toY: 34000000000, - rodStackItems: [ - BarChartRodStackItem(0, 6000000000, dark), - BarChartRodStackItem(6000000000, 23000000000, normal), - BarChartRodStackItem(23000000000, 34000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 32000000000, - rodStackItems: [ - BarChartRodStackItem(0, 7000000000, dark), - BarChartRodStackItem(7000000000, 24000000000, normal), - BarChartRodStackItem(24000000000, 32000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 14000000000.5, - rodStackItems: [ - BarChartRodStackItem(0, 1000000000.5, dark), - BarChartRodStackItem(1000000000.5, 12000000000, normal), - BarChartRodStackItem(12000000000, 14000000000.5, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 20000000000, - rodStackItems: [ - BarChartRodStackItem(0, 4000000000, dark), - BarChartRodStackItem(4000000000, 15000000000, normal), - BarChartRodStackItem(15000000000, 20000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 24000000000, - rodStackItems: [ - BarChartRodStackItem(0, 4000000000, dark), - BarChartRodStackItem(4000000000, 15000000000, normal), - BarChartRodStackItem(15000000000, 24000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - ], - ), - BarChartGroupData( - x: 3, - barsSpace: barsSpace, - barRods: [ - BarChartRodData( - toY: 14000000000, - rodStackItems: [ - BarChartRodStackItem(0, 1000000000.5, dark), - BarChartRodStackItem(1000000000.5, 12000000000, normal), - BarChartRodStackItem(12000000000, 14000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 27000000000, - rodStackItems: [ - BarChartRodStackItem(0, 7000000000, dark), - BarChartRodStackItem(7000000000, 25000000000, normal), - BarChartRodStackItem(25000000000, 27000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 29000000000, - rodStackItems: [ - BarChartRodStackItem(0, 6000000000, dark), - BarChartRodStackItem(6000000000, 23000000000, normal), - BarChartRodStackItem(23000000000, 29000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 16000000000.5, - rodStackItems: [ - BarChartRodStackItem(0, 9000000000, dark), - BarChartRodStackItem(9000000000, 15000000000, normal), - BarChartRodStackItem(15000000000, 16000000000.5, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 15000000000, - rodStackItems: [ - BarChartRodStackItem(0, 7000000000, dark), - BarChartRodStackItem(7000000000, 12000000000.5, normal), - BarChartRodStackItem(12000000000.5, 15000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - ], - ), - ]; + )); + } + + print(groupData.length); + return groupData; } } diff --git a/lib/application/views/dashboard/widgets/POSOrderValueTimeWise.dart b/lib/application/views/dashboard/widgets/POSOrderValueTimeWise.dart index ea70b21..b079bb7 100644 --- a/lib/application/views/dashboard/widgets/POSOrderValueTimeWise.dart +++ b/lib/application/views/dashboard/widgets/POSOrderValueTimeWise.dart @@ -1,40 +1,21 @@ import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/application/model/dashboard/graph/PosOrderCountTodayTimewise.dart'; import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/AppError.dart'; import 'package:wosull/application/views/dashboard/widgets/Indicator.dart'; import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/ThemeText.dart'; class POSOrderValueTimeWise extends StatelessWidget { - POSOrderValueTimeWise({super.key}); + List data; - final Color dark = MyColors.blueThemeColor; - final Color normal = MyColors.blueThemeColor; - final Color light = MyColors.blueThemeColor; + POSOrderValueTimeWise({super.key, required this.data}); Widget bottomTitles(double value, TitleMeta meta) { const style = TextStyle(fontSize: 8); - String text; - switch (value.toInt()) { - case 0: - text = 'Apr'; - break; - case 1: - text = 'May'; - break; - case 2: - text = 'Jun'; - break; - case 3: - text = 'Jul'; - break; - case 4: - text = 'Aug'; - break; - default: - text = ''; - break; - } + String text = DataTimeFormat.getTimeFormat(data[value.toInt()].sId!); return SideTitleWidget( axisSide: meta.axisSide, child: Text(text, style: style), @@ -81,63 +62,66 @@ class POSOrderValueTimeWise extends StatelessWidget { ), ], ), - AspectRatio( - aspectRatio: 1.66, - child: Padding( - padding: const EdgeInsets.only(top: 16), - child: LayoutBuilder( - builder: (context, constraints) { - final barsSpace = 4.0 * constraints.maxWidth / 400; - final barsWidth = 8.0 * constraints.maxWidth / 400; - return BarChart( - BarChartData( - alignment: BarChartAlignment.center, - barTouchData: BarTouchData( - enabled: false, - ), - titlesData: FlTitlesData( - show: true, - bottomTitles: AxisTitles( - sideTitles: SideTitles( - showTitles: true, - reservedSize: 28, - getTitlesWidget: bottomTitles, - ), - ), - leftTitles: AxisTitles( - sideTitles: SideTitles( - showTitles: true, - reservedSize: 40, - getTitlesWidget: leftTitles, + data.isNotEmpty + ? AspectRatio( + aspectRatio: 1.66, + child: Padding( + padding: const EdgeInsets.only(top: 16), + child: LayoutBuilder( + builder: (context, constraints) { + final barsSpace = 4.0 * constraints.maxWidth / 400; + final barsWidth = 8.0 * constraints.maxWidth / 50; + return BarChart( + BarChartData( + alignment: BarChartAlignment.center, + barTouchData: BarTouchData( + enabled: false, + ), + titlesData: FlTitlesData( + show: true, + bottomTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + reservedSize: 28, + getTitlesWidget: bottomTitles, + ), + ), + leftTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + reservedSize: 40, + getTitlesWidget: leftTitles, + ), + ), + topTitles: const AxisTitles( + sideTitles: SideTitles(showTitles: false), + ), + rightTitles: const AxisTitles( + sideTitles: SideTitles(showTitles: false), + ), + ), + gridData: FlGridData( + show: true, + getDrawingHorizontalLine: (value) => FlLine( + color: MyColors.fillColorGray, + strokeWidth: 1, + ), + drawVerticalLine: false, + ), + borderData: FlBorderData( + show: false, + ), + groupsSpace: barsSpace, + barGroups: getData(barsWidth, barsSpace), ), - ), - topTitles: const AxisTitles( - sideTitles: SideTitles(showTitles: false), - ), - rightTitles: const AxisTitles( - sideTitles: SideTitles(showTitles: false), - ), - ), - gridData: FlGridData( - show: true, - checkToShowHorizontalLine: (value) => value % 10 == 0, - getDrawingHorizontalLine: (value) => FlLine( - color: MyColors.blueThemeColor, - strokeWidth: 1, - ), - drawVerticalLine: false, - ), - borderData: FlBorderData( - show: false, - ), - groupsSpace: barsSpace, - barGroups: getData(barsWidth, barsSpace), + ); + }, ), - ); - }, - ), - ), - ), + ), + ) + : AppError( + error: 'No Data Available', + ), ], ), ), @@ -145,231 +129,27 @@ class POSOrderValueTimeWise extends StatelessWidget { } List getData(double barsWidth, double barsSpace) { - return [ - BarChartGroupData( + List groupData = []; + for (var timeData in data) { + groupData.add(BarChartGroupData( x: 0, barsSpace: barsSpace, barRods: [ BarChartRodData( - toY: 17000000000, - rodStackItems: [ - BarChartRodStackItem(0, 2000000000, dark), - BarChartRodStackItem(2000000000, 12000000000, normal), - BarChartRodStackItem(12000000000, 17000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 24000000000, - rodStackItems: [ - BarChartRodStackItem(0, 13000000000, dark), - BarChartRodStackItem(13000000000, 14000000000, normal), - BarChartRodStackItem(14000000000, 24000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 23000000000.5, - rodStackItems: [ - BarChartRodStackItem(0, 6000000000.5, dark), - BarChartRodStackItem(6000000000.5, 18000000000, normal), - BarChartRodStackItem(18000000000, 23000000000.5, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 29000000000, + color: Colors.transparent, + toY: timeData.totalAmount! + (timeData.totalAmount! / 2), rodStackItems: [ - BarChartRodStackItem(0, 9000000000, dark), - BarChartRodStackItem(9000000000, 15000000000, normal), - BarChartRodStackItem(15000000000, 29000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 32000000000, - rodStackItems: [ - BarChartRodStackItem(0, 2000000000.5, dark), - BarChartRodStackItem(2000000000.5, 17000000000.5, normal), - BarChartRodStackItem(17000000000.5, 32000000000, light), + BarChartRodStackItem(0, timeData.totalAmount!.toDouble(), + MyColors.blueThemeColor, const BorderSide(width: 0)) ], + borderSide: const BorderSide(width: 0), borderRadius: BorderRadius.zero, width: barsWidth, ), ], - ), - BarChartGroupData( - x: 1, - barsSpace: barsSpace, - barRods: [ - BarChartRodData( - toY: 31000000000, - rodStackItems: [ - BarChartRodStackItem(0, 11000000000, dark), - BarChartRodStackItem(11000000000, 18000000000, normal), - BarChartRodStackItem(18000000000, 31000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 35000000000, - rodStackItems: [ - BarChartRodStackItem(0, 14000000000, dark), - BarChartRodStackItem(14000000000, 27000000000, normal), - BarChartRodStackItem(27000000000, 35000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 31000000000, - rodStackItems: [ - BarChartRodStackItem(0, 8000000000, dark), - BarChartRodStackItem(8000000000, 24000000000, normal), - BarChartRodStackItem(24000000000, 31000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 15000000000, - rodStackItems: [ - BarChartRodStackItem(0, 6000000000.5, dark), - BarChartRodStackItem(6000000000.5, 12000000000.5, normal), - BarChartRodStackItem(12000000000.5, 15000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 17000000000, - rodStackItems: [ - BarChartRodStackItem(0, 9000000000, dark), - BarChartRodStackItem(9000000000, 15000000000, normal), - BarChartRodStackItem(15000000000, 17000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - ], - ), - BarChartGroupData( - x: 2, - barsSpace: barsSpace, - barRods: [ - BarChartRodData( - toY: 34000000000, - rodStackItems: [ - BarChartRodStackItem(0, 6000000000, dark), - BarChartRodStackItem(6000000000, 23000000000, normal), - BarChartRodStackItem(23000000000, 34000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 32000000000, - rodStackItems: [ - BarChartRodStackItem(0, 7000000000, dark), - BarChartRodStackItem(7000000000, 24000000000, normal), - BarChartRodStackItem(24000000000, 32000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 14000000000.5, - rodStackItems: [ - BarChartRodStackItem(0, 1000000000.5, dark), - BarChartRodStackItem(1000000000.5, 12000000000, normal), - BarChartRodStackItem(12000000000, 14000000000.5, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 20000000000, - rodStackItems: [ - BarChartRodStackItem(0, 4000000000, dark), - BarChartRodStackItem(4000000000, 15000000000, normal), - BarChartRodStackItem(15000000000, 20000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 24000000000, - rodStackItems: [ - BarChartRodStackItem(0, 4000000000, dark), - BarChartRodStackItem(4000000000, 15000000000, normal), - BarChartRodStackItem(15000000000, 24000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - ], - ), - BarChartGroupData( - x: 3, - barsSpace: barsSpace, - barRods: [ - BarChartRodData( - toY: 14000000000, - rodStackItems: [ - BarChartRodStackItem(0, 1000000000.5, dark), - BarChartRodStackItem(1000000000.5, 12000000000, normal), - BarChartRodStackItem(12000000000, 14000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 27000000000, - rodStackItems: [ - BarChartRodStackItem(0, 7000000000, dark), - BarChartRodStackItem(7000000000, 25000000000, normal), - BarChartRodStackItem(25000000000, 27000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 29000000000, - rodStackItems: [ - BarChartRodStackItem(0, 6000000000, dark), - BarChartRodStackItem(6000000000, 23000000000, normal), - BarChartRodStackItem(23000000000, 29000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 16000000000.5, - rodStackItems: [ - BarChartRodStackItem(0, 9000000000, dark), - BarChartRodStackItem(9000000000, 15000000000, normal), - BarChartRodStackItem(15000000000, 16000000000.5, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - BarChartRodData( - toY: 15000000000, - rodStackItems: [ - BarChartRodStackItem(0, 7000000000, dark), - BarChartRodStackItem(7000000000, 12000000000.5, normal), - BarChartRodStackItem(12000000000.5, 15000000000, light), - ], - borderRadius: BorderRadius.zero, - width: barsWidth, - ), - ], - ), - ]; + )); + } + + return groupData; } } diff --git a/lib/application/views/dashboard/widgets/POSStatusGraph.dart b/lib/application/views/dashboard/widgets/POSStatusGraph.dart index 6e266e3..3d0f1d2 100644 --- a/lib/application/views/dashboard/widgets/POSStatusGraph.dart +++ b/lib/application/views/dashboard/widgets/POSStatusGraph.dart @@ -30,19 +30,19 @@ class POSStatusGraph extends StatelessWidget { children: [ const Indicator( color: MyColors.primary, - text: 'Cancelled Orders', + text: 'Cancelled', isSquare: true, ), AppSpaces.horizontalSmall, Indicator( color: MyColors.blueThemeColor, - text: 'Complete Orders', + text: 'Complete', isSquare: true, ), AppSpaces.horizontalSmall, const Indicator( color: MyColors.greenColor, - text: 'Damaged Orders', + text: 'Damaged', isSquare: true, ), ], @@ -54,7 +54,7 @@ class POSStatusGraph extends StatelessWidget { children: [ Indicator( color: MyColors.yellowColor, - text: 'Return Orders', + text: 'Return', isSquare: true, ), ], @@ -70,7 +70,7 @@ class POSStatusGraph extends StatelessWidget { borderData: FlBorderData( show: true, ), - sectionsSpace: 0, + sectionsSpace: 2, centerSpaceRadius: 0, sections: showingSections(), ), diff --git a/lib/application/views/dashboard/widgets/RevenueGraph.dart b/lib/application/views/dashboard/widgets/RevenueGraph.dart index 15704b4..813e6ad 100644 --- a/lib/application/views/dashboard/widgets/RevenueGraph.dart +++ b/lib/application/views/dashboard/widgets/RevenueGraph.dart @@ -2,6 +2,7 @@ import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; import 'package:wosull/application/model/dashboard/graph/TotalIncomeExpense.dart'; import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/AppError.dart'; import 'package:wosull/application/views/dashboard/widgets/Indicator.dart'; import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/ThemeText.dart'; @@ -14,7 +15,6 @@ class RevenueGraph extends StatelessWidget { @override Widget build(BuildContext context) { - print('length ' + data.length.toString()); return Card( child: Padding( padding: const EdgeInsets.all(12), @@ -44,22 +44,27 @@ class RevenueGraph extends StatelessWidget { ], ), AppSpaces.verticalLarge, - AspectRatio( - aspectRatio: 2, - child: PieChart( - PieChartData( - pieTouchData: PieTouchData( - touchCallback: (FlTouchEvent event, pieTouchResponse) {}, + data.isNotEmpty + ? AspectRatio( + aspectRatio: 1.70, + child: PieChart( + PieChartData( + pieTouchData: PieTouchData( + touchCallback: + (FlTouchEvent event, pieTouchResponse) {}, + ), + borderData: FlBorderData( + show: false, + ), + sectionsSpace: 2, + centerSpaceRadius: 40, + sections: showingSections(), + ), + ), + ) + : AppError( + error: 'No Data Available', ), - borderData: FlBorderData( - show: false, - ), - sectionsSpace: 0, - centerSpaceRadius: 40, - sections: showingSections(), - ), - ), - ), ], ), ), @@ -75,15 +80,14 @@ class RevenueGraph extends StatelessWidget { const shadows = [Shadow(color: Colors.black, blurRadius: 2)]; switch (i) { case 0: - print((data[1].totalExpense!)); return PieChartSectionData( color: MyColors.blueThemeColor, value: (data[1].totalExpense! / 100), - title: data[1].totalExpense!.toString(), + title: data[1].totalExpense!.toStringAsFixed(2), radius: radius, titleStyle: TextStyle( fontSize: fontSize, - fontWeight: FontWeight.bold, + fontWeight: FontWeight.w400, color: MyColors.white, shadows: shadows, ), @@ -92,11 +96,11 @@ class RevenueGraph extends StatelessWidget { return PieChartSectionData( color: MyColors.primary, value: data[0].totalIncome! / 100, - title: data[0].totalIncome!.toString(), + title: data[0].totalIncome!.toStringAsFixed(2), radius: radius, titleStyle: TextStyle( fontSize: fontSize, - fontWeight: FontWeight.bold, + fontWeight: FontWeight.w400, color: MyColors.white, shadows: shadows, ), diff --git a/lib/application/views/dashboard/widgets/TodayPOSSales.dart b/lib/application/views/dashboard/widgets/TodayPOSSales.dart index f5097e4..891e78a 100644 --- a/lib/application/views/dashboard/widgets/TodayPOSSales.dart +++ b/lib/application/views/dashboard/widgets/TodayPOSSales.dart @@ -1,17 +1,21 @@ import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/application/model/dashboard/graph/TodaySales.dart'; import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/AppError.dart'; import 'package:wosull/application/views/dashboard/widgets/Indicator.dart'; import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/ThemeText.dart'; class TodayPOSSales extends StatelessWidget { List gradientColors = [ - MyColors.blueThemeColor, + MyColors.backColorBlue50, MyColors.blueThemeColor, ]; + List todaySales = []; - TodayPOSSales({super.key}); + TodayPOSSales({super.key, required this.todaySales}); @override Widget build(BuildContext context) { @@ -45,9 +49,13 @@ class TodayPOSSales extends StatelessWidget { top: 24, bottom: 12, ), - child: LineChart( - mainData(), - ), + child: todaySales.isNotEmpty + ? LineChart( + mainData(), + ) + : AppError( + error: 'No Sales Available', + ), ), ), ], @@ -62,22 +70,13 @@ class TodayPOSSales extends StatelessWidget { fontSize: 8, ); Widget text; - switch (value.toInt()) { - case 1: - text = const Text('JAN', style: style); - break; - case 2: - text = const Text('MAR', style: style); - break; - case 5: - text = const Text('JUN', style: style); - break; - case 8: - text = const Text('SEP', style: style); - break; - default: - text = const Text('', style: style); - break; + + if (value.toInt() <= todaySales.length) { + text = Text( + DataTimeFormat.getDay(todaySales[value.toInt()].id!.createdAt!), + style: style); + } else { + text = const Text('', style: style); } return SideTitleWidget( @@ -86,57 +85,30 @@ class TodayPOSSales extends StatelessWidget { ); } - Widget leftTitleWidgets(double value, TitleMeta meta) { - const style = TextStyle( - fontWeight: FontWeight.bold, - fontSize: 8, - ); - String text; - switch (value.toInt()) { - case 1: - text = '0'; - break; - case 2: - text = '500'; - break; - case 3: - text = '1000'; - break; - case 4: - text = '1500'; - break; - case 5: - text = '2000'; - break; - case 6: - text = '2500'; - break; - default: - return Container(); - } - - return Text(text, style: style, textAlign: TextAlign.left); - } - LineChartData mainData() { return LineChartData( + minY: 0, + minX: 0, gridData: FlGridData( show: true, - drawVerticalLine: true, - horizontalInterval: 1, - verticalInterval: 1, - getDrawingHorizontalLine: (value) { - return const FlLine( - color: MyColors.black, - strokeWidth: 1, - ); - }, + getDrawingHorizontalLine: (value) => const FlLine( + color: MyColors.fillColorGray, + strokeWidth: 1, + ), getDrawingVerticalLine: (value) { return const FlLine( - color: MyColors.black, + color: MyColors.fillColorGray, strokeWidth: 1, ); }, + drawVerticalLine: true, + horizontalInterval: 1, + verticalInterval: 1, + ), + lineTouchData: const LineTouchData(enabled: true), + borderData: FlBorderData( + show: true, + border: Border.all(color: MyColors.fillColorGray2), ), titlesData: FlTitlesData( show: true, @@ -154,42 +126,18 @@ class TodayPOSSales extends StatelessWidget { getTitlesWidget: bottomTitleWidgets, ), ), - leftTitles: AxisTitles( - sideTitles: SideTitles( - showTitles: true, - interval: 1, - getTitlesWidget: leftTitleWidgets, - reservedSize: 42, - ), - ), ), - borderData: FlBorderData( - show: true, - border: Border.all(color: const Color(0xff37434d)), - ), - minX: 0, - maxX: 12, - minY: 0, - maxY: 6, lineBarsData: [ LineChartBarData( - spots: const [ - FlSpot(0, 3), - FlSpot(2.6, 2), - FlSpot(4.9, 5), - FlSpot(6.8, 3.1), - FlSpot(8, 4), - FlSpot(9.5, 3), - FlSpot(11, 4), - ], - isCurved: true, + spots: getSpots(), + isCurved: false, gradient: LinearGradient( colors: gradientColors, ), barWidth: 5, isStrokeCapRound: true, dotData: const FlDotData( - show: false, + show: true, ), belowBarData: BarAreaData( show: true, @@ -203,4 +151,14 @@ class TodayPOSSales extends StatelessWidget { ], ); } + + List getSpots() { + todaySales.reversed; + List spots = []; + + for (int i = 0; i < todaySales.length; i++) { + spots.add(FlSpot(i.toDouble(), todaySales[i].totalAmount!)); + } + return spots; + } } diff --git a/lib/application/views/dashboard/widgets/TodaySaleGraph.dart b/lib/application/views/dashboard/widgets/TodaySaleGraph.dart index 86efefc..38bf81c 100644 --- a/lib/application/views/dashboard/widgets/TodaySaleGraph.dart +++ b/lib/application/views/dashboard/widgets/TodaySaleGraph.dart @@ -1,17 +1,21 @@ import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/application/model/dashboard/graph/TodaySales.dart'; import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/AppError.dart'; import 'package:wosull/application/views/dashboard/widgets/Indicator.dart'; import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/ThemeText.dart'; class TodaySaleGraph extends StatelessWidget { List gradientColors = [ - MyColors.blueThemeColor, + MyColors.backColorBlue50, MyColors.blueThemeColor, ]; + List todaySales = []; - TodaySaleGraph({super.key}); + TodaySaleGraph({super.key, required this.todaySales}); @override Widget build(BuildContext context) { @@ -45,9 +49,13 @@ class TodaySaleGraph extends StatelessWidget { top: 24, bottom: 12, ), - child: LineChart( - mainData(), - ), + child: todaySales.isNotEmpty + ? LineChart( + mainData(), + ) + : AppError( + error: 'No Sales Available', + ), ), ), ], @@ -62,22 +70,14 @@ class TodaySaleGraph extends StatelessWidget { fontSize: 8, ); Widget text; - switch (value.toInt()) { - case 1: - text = const Text('JAN', style: style); - break; - case 2: - text = const Text('MAR', style: style); - break; - case 5: - text = const Text('JUN', style: style); - break; - case 8: - text = const Text('SEP', style: style); - break; - default: - text = const Text('', style: style); - break; + + if (value.toInt() <= todaySales.length) { + text = Text( + DataTimeFormat.getTimeFormat( + todaySales[value.toInt()].id!.createdAt!), + style: style); + } else { + text = const Text('', style: style); } return SideTitleWidget( @@ -86,57 +86,30 @@ class TodaySaleGraph extends StatelessWidget { ); } - Widget leftTitleWidgets(double value, TitleMeta meta) { - const style = TextStyle( - fontWeight: FontWeight.bold, - fontSize: 8, - ); - String text; - switch (value.toInt()) { - case 1: - text = '0'; - break; - case 2: - text = '500'; - break; - case 3: - text = '1000'; - break; - case 4: - text = '1500'; - break; - case 5: - text = '2000'; - break; - case 6: - text = '2500'; - break; - default: - return Container(); - } - - return Text(text, style: style, textAlign: TextAlign.left); - } - LineChartData mainData() { return LineChartData( + minY: 0, + minX: 0, gridData: FlGridData( show: true, - drawVerticalLine: true, - horizontalInterval: 1, - verticalInterval: 1, - getDrawingHorizontalLine: (value) { - return const FlLine( - color: MyColors.black, - strokeWidth: 1, - ); - }, + getDrawingHorizontalLine: (value) => const FlLine( + color: MyColors.fillColorGray, + strokeWidth: 1, + ), getDrawingVerticalLine: (value) { return const FlLine( - color: MyColors.black, + color: MyColors.fillColorGray, strokeWidth: 1, ); }, + drawVerticalLine: true, + horizontalInterval: 1, + verticalInterval: 1, + ), + lineTouchData: const LineTouchData(enabled: true), + borderData: FlBorderData( + show: true, + border: Border.all(color: MyColors.fillColorGray2), ), titlesData: FlTitlesData( show: true, @@ -154,42 +127,20 @@ class TodaySaleGraph extends StatelessWidget { getTitlesWidget: bottomTitleWidgets, ), ), - leftTitles: AxisTitles( - sideTitles: SideTitles( - showTitles: true, - interval: 1, - getTitlesWidget: leftTitleWidgets, - reservedSize: 42, - ), - ), - ), - borderData: FlBorderData( - show: true, - border: Border.all(color: const Color(0xff37434d)), ), - minX: 0, - maxX: 12, - minY: 0, - maxY: 6, lineBarsData: [ LineChartBarData( - spots: const [ - FlSpot(0, 3), - FlSpot(2.6, 2), - FlSpot(4.9, 5), - FlSpot(6.8, 3.1), - FlSpot(8, 4), - FlSpot(9.5, 3), - FlSpot(11, 4), - ], - isCurved: true, + show: true, + spots: getSpots(), + isCurved: false, gradient: LinearGradient( colors: gradientColors, ), barWidth: 5, isStrokeCapRound: true, + isStepLineChart: true, dotData: const FlDotData( - show: false, + show: true, ), belowBarData: BarAreaData( show: true, @@ -203,4 +154,15 @@ class TodaySaleGraph extends StatelessWidget { ], ); } + + List getSpots() { + todaySales.reversed; + List spots = []; + + for (int i = 0; i < todaySales.length; i++) { + spots.add(FlSpot(i.toDouble(), todaySales[i].totalAmount!)); + } + + return spots; + } } diff --git a/lib/application/views/discountModule/DiscoountModuleMainVC.dart b/lib/application/views/discountModule/DiscoountModuleMainVC.dart index 1afdaba..7493a72 100644 --- a/lib/application/views/discountModule/DiscoountModuleMainVC.dart +++ b/lib/application/views/discountModule/DiscoountModuleMainVC.dart @@ -4,6 +4,7 @@ import 'package:wosull/application/interfaces/DrawerWidgetSelect.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/theme/MyFonts.dart'; import 'package:wosull/application/views/discountModule/views/DiscountVC.dart'; +import 'package:wosull/helpers/ThemeText.dart'; class DiscountModuleVC extends StatefulWidget { final DrawerWidgetSelect delegateDrawer; @@ -84,17 +85,9 @@ class _DiscountModuleVCState extends State { ), TabBar( indicatorColor: Colors.white, - labelStyle: TextStyle( - fontSize: MyFonts.normalButton, - fontWeight: FontWeight.w500, - fontFamily: MyFonts.Bold, - color: MyColors.blueThemeColor), + labelStyle: ThemeText.tabLabelStyle, isScrollable: true, - unselectedLabelStyle: const TextStyle( - fontSize: MyFonts.normalButton, - fontWeight: FontWeight.w500, - fontFamily: MyFonts.Medium, - color: MyColors.textColorBlack), + unselectedLabelStyle: ThemeText.unSelectedTabLabelStyle, unselectedLabelColor: MyColors.textColorBlack, labelColor: MyColors.blueThemeColor, tabs: [ diff --git a/lib/application/views/discountModule/repo/DiscountRepository.dart b/lib/application/views/discountModule/repo/DiscountRepository.dart new file mode 100644 index 0000000..d892092 --- /dev/null +++ b/lib/application/views/discountModule/repo/DiscountRepository.dart @@ -0,0 +1,67 @@ +import 'package:wosull/application/model/SimpleResponsModel.dart'; +import 'package:wosull/application/model/discount/StoreDiscountModel.dart'; +import 'package:wosull/application/model/inventory/category/ItemCategory.dart'; +import 'package:wosull/application/model/store/GetItemsByStoreId.dart'; +import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/utils/Constants.dart'; + +class DiscountRepository { + Future addDiscount(Map data) async { + return await APIManager().fetchData(Constants.ADD_STORE_DISCOUNT, data); + } + + Future update(String id, bool status) async { + Map data = { + 'discountId': id, + "status": status ? "Active" : "Inactive" + }; + return await APIManager() + .getResponsePatch(Constants.UPDATE_STORE_DISCOUNT_STATUS, data); + } + + Future> fetch(Map data) async { + var items = []; + await APIManager() + .fetchData(Constants.GET_STORE_DISCOUNT, data) + .then((result) { + final value = StoreDiscountModel.fromJson(result); + if (value.success) { + items.addAll(value.storeDiscount); + } + }).onError((error, stackTrace) {}); + return items; + } + + Future> search(Map data) async { + var items = []; + await APIManager() + .fetchData(Constants.SEARCH_DISCOUNT, data) + .then((result) { + final value = StoreDiscountModel.fromJson(result); + if (value.success) { + items.addAll(value.storeDiscount); + } + }).onError((error, stackTrace) {}); + return items; + } + + Future delete(String id) async { + Map data = {'discountId': id}; + return await APIManager() + .getResponsePatch(Constants.DELETE_STORE_DISCOUNT, data); + } + + Future> getCategoriesListById() async { + var items = []; + await APIManager() + .fetchData( + Constants.GET_STORE_CATEGORY_LIST_ID, Constants.getStorePayload()) + .then((value) { + final response = GetItemsByStoreId.fromJson(value); + if (response.success!) { + items.addAll(response.categories ?? []); + } + }).onError((error, stackTrace) {}); + return items; + } +} diff --git a/lib/application/views/discountModule/viewModels/DiscountViewModel.dart b/lib/application/views/discountModule/viewModels/DiscountViewModel.dart index 18bd395..632637c 100644 --- a/lib/application/views/discountModule/viewModels/DiscountViewModel.dart +++ b/lib/application/views/discountModule/viewModels/DiscountViewModel.dart @@ -1,20 +1,14 @@ import 'package:flutter/cupertino.dart'; import 'package:wosull/application/enum/DataState.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; -import 'package:wosull/application/model/SimpleResponsModel.dart'; import 'package:wosull/application/model/discount/StoreDiscountModel.dart'; -import 'package:wosull/application/model/inventory/category/ItemCategoryResponse.dart'; -import 'package:wosull/application/network/APIManager.dart'; -import 'package:wosull/application/repo/AuthRepository.dart'; -import 'package:wosull/application/utils/Constants.dart'; - -import '../../../model/store/GetItemsByStoreId.dart'; +import 'package:wosull/application/views/discountModule/repo/DiscountRepository.dart'; class DiscountViewModel with ChangeNotifier { int _currentPageNumber = 1; DataState _dataState = DataState.uninitialized; - + int limit = 10; bool _didLastLoad = false; bool _isLoading = false; @@ -27,8 +21,10 @@ class DiscountViewModel with ChangeNotifier { List get dataList => _dataList; List get filteredList => _filteredList; + final repository = DiscountRepository(); - fetch({bool isRefresh = false}) async { + fetch({bool isRefresh = false, int limit = 10}) async { + this.limit = limit; _isLoading = true; if (!isRefresh) { _dataState = (_dataState == DataState.uninitialized) @@ -43,24 +39,22 @@ class DiscountViewModel with ChangeNotifier { Map data = { 'store_id': sharedPrefs.storeId, 'page': _currentPageNumber, + 'limit': this.limit }; try { if (_didLastLoad) { _dataState = DataState.noMoreData; } else { - await APIManager() - .fetchData(Constants.GET_STORE_DISCOUNT, data) - .then((result) { - final value = StoreDiscountModel.fromJson(result); + await repository.fetch(data).then((discounts) { if (_dataState == DataState.refreshing) { _filteredList.clear(); _dataList.clear(); } - if (value.success!) { - _filteredList.addAll(value.storeDiscount!); - _dataList.addAll(value.storeDiscount!); - if (value.storeDiscount!.length < 10) { + if (discounts.isNotEmpty) { + _filteredList.addAll(discounts); + _dataList.addAll(discounts); + if (discounts.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; @@ -95,13 +89,10 @@ class DiscountViewModel with ChangeNotifier { _dataState = DataState.searching; notifyListeners(); try { - await APIManager() - .fetchData(Constants.SEARCH_DISCOUNT, data) - .then((result) { - final value = StoreDiscountModel.fromJson(result); + await repository.search(data).then((discounts) { filteredList.clear(); - if (value.success!) { - filteredList.addAll(value.storeDiscount!); + if (discounts.isNotEmpty) { + filteredList.addAll(discounts); } _dataState = DataState.fetched; }).onError((error, stackTrace) { @@ -116,10 +107,7 @@ class DiscountViewModel with ChangeNotifier { } Future delete(String id) async { - Map data = {'discountId': id}; - await APIManager() - .getResponsePatch(Constants.DELETE_STORE_DISCOUNT, data) - .then((result) { + await repository.delete(id).then((result) { filteredList.removeWhere((element) => element.id! == id); dataList.removeWhere((element) => element.id! == id); notifyListeners(); @@ -129,47 +117,15 @@ class DiscountViewModel with ChangeNotifier { } Future update(String id, bool status) async { - Map data = { - 'discountId': id, - "status": status ? "Active" : "Inactive" - }; - await APIManager() - .getResponsePatch(Constants.UPDATE_STORE_DISCOUNT_STATUS, data) - .then((result) { + await repository.update(id, status).then((result) { + int index = _filteredList.indexWhere((element) => element.id == id); + _filteredList[index].status = status ? "Active" : "Inactive"; + int dataIndex = dataList.indexWhere((element) => element.id == id); + dataList[dataIndex].status = status ? "Active" : "Inactive"; + notifyListeners(); }).onError((error, stackTrace) { notifyListeners(); }); } - - Future addDiscount(Map data) async { - try { - dynamic response = await AuthRepository() - .postResponseAuth(Constants.ADD_STORE_DISCOUNT, data); - print(response); - return SimpleResponseModel.fromJson(response); - } catch (e) { - return SimpleResponseModel(); - } - } - - Future getStoreCategoryItems(Map data) async { - try { - dynamic response = await AuthRepository() - .postResponseAuth(Constants.GET_STORE_CATEGORY_LIST, data); - return ItemCategoryResponse.fromJson(response); - } catch (e) { - return ItemCategoryResponse(success: false, categories: []); - } - } - - Future getStoreItemsById(Map data) async { - try { - dynamic response = await AuthRepository() - .postResponseAuth(Constants.GET_STORE_CATEGORY_LIST_ID, data); - return GetItemsByStoreId.fromJson(response); - } catch (e) { - return GetItemsByStoreId(); - } - } } diff --git a/lib/application/views/discountModule/viewModels/NewDiscountViewModel.dart b/lib/application/views/discountModule/viewModels/NewDiscountViewModel.dart new file mode 100644 index 0000000..3e481c7 --- /dev/null +++ b/lib/application/views/discountModule/viewModels/NewDiscountViewModel.dart @@ -0,0 +1,289 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/application/model/discount/StoreDiscountModel.dart'; +import 'package:wosull/application/model/inventory/category/ItemCategory.dart'; +import 'package:wosull/application/repository/WosulRepository.dart'; +import 'package:wosull/application/utils/CRUDOperatoinState.dart'; +import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/discountModule/repo/DiscountRepository.dart'; +import 'package:wosull/helpers/DatePicker.dart'; +import 'package:wosull/helpers/Utils.dart'; + +class NewDiscountViewModel with ChangeNotifier { + String selectedDiscountType = "Percentage"; + late StoreDiscount storeDiscount; + + var _crudOperation = CRUDOperationState.uninitialized; + + CRUDOperationState get crudOperation => _crudOperation; + + String typesGroupValue = "Manual"; + String verticalGroupValue = ''; + + bool isLoading = false; + bool isGettingItems = false; + bool isTablet = true; + bool isPortrait = true; + + String type = '1'; + + List filteredItems = []; + List data = []; + + final repository = DiscountRepository(); + + disposeData() { + isLoading = false; + isGettingItems = false; + selectedDiscountType = Constants.discountType[0]; + typesGroupValue = Constants.types[0]; + verticalGroupValue = ''; + filteredItems.clear(); + data.clear(); + } + + void setIsGettingData(bool value) { + isGettingItems = value; + notifyListeners(); + } + + void setLoading(bool value) { + isLoading = value; + notifyListeners(); + } + + void initData(bool isEdit, StoreDiscount storeDiscount) { + this.storeDiscount = storeDiscount; + if (isEdit) { + selectedDiscountType = storeDiscount.discountTypeLabel!; + typesGroupValue = storeDiscount.discountType!; + if (storeDiscount.products!.isNotEmpty) { + verticalGroupValue = Constants.discountFilters[1]; + getItems(); + } else if (storeDiscount.categories!.isNotEmpty) { + verticalGroupValue = Constants.discountFilters[2]; + getItems(); + } else if (storeDiscount.categories!.isEmpty && + storeDiscount.products!.isEmpty) { + verticalGroupValue = Constants.discountFilters[0]; + } + } else { + storeDiscount.isMinAmount = false; + storeDiscount.isAlways = false; + storeDiscount.isMaxDiscount = false; + storeDiscount.isUnlimited = false; + storeDiscount.status = "Active"; + storeDiscount.categories = []; + storeDiscount.products = []; + } + } + + Future presentDatePicker(BuildContext context, bool isStart) async { + final pickedDate = await DatePicker.presentDatePicker(context, isStart); + + if (pickedDate == null) { + return; + } + if (isStart) { + storeDiscount.discountStartDate = + DataTimeFormat.formatDateFromPicketINVOICE(pickedDate); + } else { + storeDiscount.discountEndDate = + DataTimeFormat.formatDateFromPicketINVOICE(pickedDate); + } + + notifyListeners(); + } + + Future isValidate() async { + if (storeDiscount.name == null) { + Utils.showMessage('Enter Discount Code'); + } else if (selectedDiscountType == Constants.discountType[0] && + storeDiscount.discountPercentage == null) { + Utils.showMessage('Enter Discount $selectedDiscountType'); + } else { + await addDiscount(); + } + } + + Future addDiscount() async { + setLoading(true); + Map data = { + 'store_id': sharedPrefs.storeId, + 'name': storeDiscount.name ?? '', + 'description': storeDiscount.description ?? '', + 'status': storeDiscount.status, + 'min_amount_limit': storeDiscount.minAmountLimit ?? 0.0, + 'max_discount_limit': storeDiscount.maxDiscountLimit ?? 0.0, + 'discount_percentage': storeDiscount.discountPercentage ?? '', + 'discount_type': typesGroupValue, + 'discount_type_label': selectedDiscountType, + 'limit_of_discount': storeDiscount.limitOfDiscount ?? 0.0, + 'discount_start_date': storeDiscount.discountStartDate ?? '', + 'discount_end_date': storeDiscount.discountEndDate ?? '', + 'type': type, + 'is_deleted': false, + 'products': storeDiscount.products, + 'categories': storeDiscount.categories, + 'is_always': storeDiscount.isAlways ?? false, + 'is_unlimited': storeDiscount.isUnlimited ?? false, + 'is_min_amount': storeDiscount.isMinAmount ?? false, + 'is_max_discount': storeDiscount.isMaxDiscount ?? false, + 'discountId': storeDiscount.id ?? '' + }; + + await repository.addDiscount(data).then((response) { + if (response.success) { + Utils.showMessage(response.message); + _crudOperation = CRUDOperationState.add; + } else { + _crudOperation = CRUDOperationState.error; + Utils.showMessage(response.message); + } + setLoading(false); + }).onError((error, stackTrace) { + _crudOperation = CRUDOperationState.error; + setLoading(false); + }); + } + + void onChangeDiscountType(ItemCategory filteredItem) { + if (verticalGroupValue == Constants.discountFilters.elementAt(2)) { + if (storeDiscount.categories!.isEmpty || + !storeDiscount.categories!.contains(filteredItem.id)) { + storeDiscount.categories!.add(filteredItem.id); + } else if (storeDiscount.categories!.contains(filteredItem.id)) { + storeDiscount.categories!.remove(filteredItem.id); + } + } else { + //product + if (storeDiscount.products!.isEmpty || + !storeDiscount.products!.contains(filteredItem.id)) { + storeDiscount.products!.add(filteredItem.id); + } else if (storeDiscount.products!.contains(filteredItem.id)) { + storeDiscount.products!.remove(filteredItem.id); + } + } + notifyListeners(); + } + + Future> getItems() async { + setIsGettingData(true); + if (verticalGroupValue == Constants.discountFilters.elementAt(0)) { + type = "1"; + filteredItems.clear(); + data.clear(); + } else if (verticalGroupValue == Constants.discountFilters.elementAt(2)) { + type = "3"; + await WosulRepository().getStoreCategoriesData().then((categories) { + if (categories.isNotEmpty) { + filteredItems.clear(); + data.clear(); + filteredItems.addAll(categories); + data.addAll(categories); + } + }).onError((error, stackTrace) {}); + } else { + if (verticalGroupValue == Constants.discountFilters.elementAt(1)) { + type = "2"; + } else if (verticalGroupValue == Constants.discountFilters.elementAt(3)) { + type = "4"; + } + final categories = await repository.getCategoriesListById(); + if (categories.isNotEmpty) { + filteredItems.clear(); + data.clear(); + filteredItems.addAll(categories); + data.addAll(categories); + } + } + setIsGettingData(false); + return filteredItems; + } + + void changeFilter(String? value) { + storeDiscount.categories!.clear(); + storeDiscount.products!.clear(); + verticalGroupValue = value ?? ''; + getItems(); + notifyListeners(); + } + + void changeDiscount(String? value) { + typesGroupValue = value ?? ''; + notifyListeners(); + } + + void updateMaxDiscount(String value) { + if (value.isNotEmpty) { + storeDiscount.maxDiscountLimit = double.parse(value); + } else { + storeDiscount.maxDiscountLimit = 0.0; + } + notifyListeners(); + } + + void updateStatus(bool value) { + storeDiscount.status = value ? "Active" : "Inactive"; + notifyListeners(); + } + + void updateDiscountType(String? data) { + if (data != null) { + selectedDiscountType = data.toString(); + } + notifyListeners(); + } + + void filterItems(String query) { + filteredItems.clear(); + if (query.isNotEmpty) { + filteredItems.addAll(data.where((element) => + element.name.toLowerCase().startsWith(query.toLowerCase()))); + } else { + filteredItems.addAll(data); + } + notifyListeners(); + } + + void updateIsMaxDiscount(bool value) { + storeDiscount.isMaxDiscount = value; + notifyListeners(); + } + + void setIsMinAmount(bool value) { + storeDiscount.isMinAmount = value; + notifyListeners(); + } + + void setMinAmount(String value) { + if (value.isNotEmpty) { + storeDiscount.minAmountLimit = double.parse(value); + } else { + storeDiscount.minAmountLimit = 0.0; + } + } + + void setIsAlways(bool? value) { + storeDiscount.isAlways = value ?? false; + notifyListeners(); + } + + void setIsUnLimited(bool? value) { + storeDiscount.isUnlimited = value; + notifyListeners(); + } + + void setDiscountLimit(String value) { + if (value.isNotEmpty) { + storeDiscount.limitOfDiscount = double.parse(value); + } else { + storeDiscount.limitOfDiscount = 0.0; + } + } + + void setDiscountValue(String value) { + storeDiscount.discountPercentage = value; + } +} diff --git a/lib/application/views/discountModule/views/DiscountVC.dart b/lib/application/views/discountModule/views/DiscountVC.dart index 9b35e3a..0ff8038 100644 --- a/lib/application/views/discountModule/views/DiscountVC.dart +++ b/lib/application/views/discountModule/views/DiscountVC.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:provider/provider.dart'; import 'package:wosull/application/enum/DataState.dart'; -import 'package:wosull/application/model/converters/DataTimeFormat.dart'; import 'package:wosull/application/model/discount/StoreDiscountModel.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/utils/AppError.dart'; @@ -10,15 +9,13 @@ import 'package:wosull/application/utils/AppLoader.dart'; import 'package:wosull/application/views/discountModule/viewModels/DiscountViewModel.dart'; import 'package:wosull/application/views/discountModule/views/NewDiscountVC.dart'; import 'package:wosull/application/views/discountModule/views/ViewDiscountVC.dart'; -import 'package:wosull/application/views/popups/DeleteRecordPopUp.dart'; +import 'package:wosull/application/views/discountModule/widgets/DiscountListView.dart'; import 'package:wosull/base/BaseStatefulState.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/ThemeText.dart'; import 'package:wosull/widgets/CustomSimpleButton.dart'; -import 'package:wosull/widgets/CustomSwitch.dart'; -import 'package:wosull/widgets/EmptyDataWidget.dart'; -import 'package:wosull/widgets/HeadingText.dart'; +import 'package:wosull/widgets/PageLimitDropDown.dart'; import 'package:wosull/widgets/SearchBox.dart'; -import 'package:wosull/widgets/ValueText.dart'; class DiscountVC extends StatefulWidget { const DiscountVC({Key? key}) : super(key: key); @@ -40,11 +37,6 @@ class _DiscountVCState extends BaseStatefulState { _controller = ScrollController()..addListener(_scrollNotification); } - @override - void dispose() { - super.dispose(); - } - @override Widget build(BuildContext context) { return Scaffold( @@ -60,29 +52,51 @@ class _DiscountVCState extends BaseStatefulState { child: Column( children: [ isPortrait - ? Row( - mainAxisAlignment: MainAxisAlignment.start, + ? Column( children: [ - pageLabel(), - const SizedBox( - width: 4, + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + pageLabel(), + AppSpaces.horizontalSmall, + Flexible(child: newDiscountButton()), + AppSpaces.horizontalSmall, + PageLimitDropdown(onChange: (value) { + viewModel.fetch( + isRefresh: true, + limit: int.parse(value!)); + }) + ], ), - newDiscountButton(), + AppSpaces.verticalSmall, + getSearchBar() ], ) : Row( mainAxisAlignment: MainAxisAlignment.start, children: [ pageLabel(), - const SizedBox( - width: 8, + AppSpaces.horizontalSmall, + SizedBox( + width: 110, + child: newDiscountButton(), ), - newDiscountButton(), + AppSpaces.horizontalSmall, + getSearchBar(), + Flexible( + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + PageLimitDropdown(onChange: (value) { + viewModel.fetch( + isRefresh: true, + limit: int.parse(value!)); + }) + ], + )) ], ), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, ChangeNotifierProvider( create: (context) => viewModel, child: Consumer( @@ -93,18 +107,18 @@ class _DiscountVCState extends BaseStatefulState { Future(() { controller.fetch(); }); - return showData(controller.filteredList, true); + return showData(controller.filteredList); case DataState.initialFetching: return AppLoader(); case DataState.moreFetching: case DataState.refreshing: - return showData(controller.filteredList, true); + return showData(controller.filteredList); case DataState.error: return AppError(); case DataState.searching: case DataState.fetched: case DataState.noMoreData: - return showData(controller.filteredList, false); + return showData(controller.filteredList); } }, ), @@ -116,340 +130,32 @@ class _DiscountVCState extends BaseStatefulState { })); } - Widget showData(List data, bool isLoading) { + Widget showData(List data) { return Column( children: [ - data.isEmpty - ? const EmptyDataWidget() - : Column( - children: [ - isPortrait - ? Container() - : Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 50, - color: MyColors.containerBackColor, - child: Row( - children: [ - Expanded( - child: Text( - AppLocalizations.of(context)!.name, - softWrap: false, - style: MyColors.textStyleHeading(), - )), - Expanded( - child: Text( - AppLocalizations.of(context)!.discount_value, - softWrap: false, - style: MyColors.textStyleHeading(), - )), - Expanded( - flex: 1, - child: Text( - AppLocalizations.of(context)! - .minimum_amount_limit, - maxLines: 1, - softWrap: false, - style: MyColors.textStyleHeading(), - )), - Expanded( - child: Align( - alignment: Alignment.center, - child: Text( - AppLocalizations.of(context)!.status, - softWrap: false, - style: MyColors.textStyleHeading(), - ), - )), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: HeadingText( - AppLocalizations.of(context)! - .created_on))), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: HeadingText( - AppLocalizations.of(context)! - .updated_on))), - Expanded( - child: Padding( - padding: const EdgeInsets.only(right: 16), - child: Align( - alignment: Alignment.centerRight, - child: HeadingText( - AppLocalizations.of(context)!.action), - ), - )), - ], - ), - ), - ListView.builder( - physics: const NeverScrollableScrollPhysics(), - padding: EdgeInsets.zero, - scrollDirection: Axis.vertical, - shrinkWrap: true, - itemBuilder: (c, position) { - final discount = data[position]; - if (isPortrait) { - return Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - elevation: 2, - color: MyColors.white, - child: Container( - padding: const EdgeInsets.fromLTRB(8, 0, 0, 8), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Expanded( - child: Container( - padding: const EdgeInsets.only(top: 16), - child: Row( - children: [ - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.start, - children: [ - HeadingText( - AppLocalizations.of(context)! - .name), - const SizedBox( - height: 8, - ), - HeadingText( - AppLocalizations.of(context)! - .discount_value), - const SizedBox( - height: 8, - ), - HeadingText( - AppLocalizations.of(context)! - .minimum_amount_limit), - const SizedBox( - height: 8, - ), - HeadingText( - AppLocalizations.of(context)! - .status), - const SizedBox( - height: 8, - ), - HeadingText( - AppLocalizations.of(context)! - .created_on), - const SizedBox( - height: 8, - ), - HeadingText( - AppLocalizations.of(context)! - .updated_on), - ], - )), - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.end, - mainAxisAlignment: - MainAxisAlignment.start, - children: [ - ValueText(discount.name ?? ''), - const SizedBox( - height: 8, - ), - ValueText(discount.discountType!), - const SizedBox( - height: 8, - ), - ValueText(discount.minAmountLimit! - .toString()), - const SizedBox( - height: 10, - ), - Row( - mainAxisAlignment: - MainAxisAlignment.end, - crossAxisAlignment: - CrossAxisAlignment.end, - children: [ - CustomSwitch( - value: discount.getStatus(), - onToggle: (value) { - setState(() { - if (value) { - discount.status = - "Active"; - } else { - discount.status = - "Inactive"; - } - }); - _updateStatus( - discount.id!, value); - }, - ) - ], - ), - const SizedBox( - height: 10, - ), - ValueText( - DataTimeFormat.getFormatDate( - discount.createdAt!)), - const SizedBox( - height: 8, - ), - ValueText( - DataTimeFormat.getFormatDate( - discount.updatedAt!)), - ], - )), - ], - ), - )), - PopupMenuButton( - icon: const Icon(Icons.more_vert), - itemBuilder: (c) { - return [ - PopupMenuItem( - value: 'edit', - child: ValueText( - AppLocalizations.of(context)!.edit, - ), - ), - PopupMenuItem( - value: 'view', - child: ValueText( - AppLocalizations.of(context)!.view, - ), - ), - PopupMenuItem( - value: 'delete', - child: ValueText( - AppLocalizations.of(context)!.delete, - ), - ) - ]; - }, - onSelected: (String value) => - actionPopUpItemSelected(value, discount), - ) - ], - ), - ), - ); - } else { - return Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - child: Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 56, - color: MyColors.containerBackColor, - child: Row( - children: [ - Expanded(child: ValueText(discount.name!)), - Expanded( - child: - ValueText(discount.discountType ?? '')), - Expanded( - flex: 1, - child: ValueText( - discount.minAmountLimit!.toString() ?? - '')), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: CustomSwitch( - value: discount.getStatus(), - onToggle: (value) { - setState(() { - if (value) { - discount.status = "Active"; - } else { - discount.status = "Inactive"; - } - }); - _updateStatus(discount.id!, value); - }, - ), - )), - Expanded( - child: ValueText( - DataTimeFormat.getFormatDate( - discount.createdAt!))), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: ValueText( - DataTimeFormat.getFormatDate( - discount.updatedAt!)))), - Expanded( - flex: 1, - child: Padding( - padding: const EdgeInsets.all(4), - child: Align( - alignment: Alignment.centerRight, - child: Container( - decoration: BoxDecoration( - borderRadius: - const BorderRadius.all( - Radius.circular(4)), - color: MyColors.backFillColor), - child: PopupMenuButton( - icon: const Icon(Icons.more_vert), - itemBuilder: (c) { - return [ - PopupMenuItem( - value: 'edit', - child: ValueText( - AppLocalizations.of( - context)! - .edit, - ), - ), - PopupMenuItem( - value: 'view', - child: ValueText( - AppLocalizations.of( - context)! - .view, - ), - ), - PopupMenuItem( - value: 'delete', - child: ValueText( - AppLocalizations.of( - context)! - .delete, - ), - ) - ]; - }, - onSelected: (String value) => - actionPopUpItemSelected( - value, discount), - ), - ), - ), - )) - ], - ), - ), - ); - } - }, - itemCount: data.length, - ), - ], - ), + DiscountListView( + data: data, + isPortrait: isPortrait, + onUpdate: (discount, value) { + _updateStatus(discount.id!, value); + }, + onDelete: (discount) { + _deleteDiscount(discount.id!); + }, + onView: (discount) { + showDialog( + barrierColor: Colors.black26, + context: context, + builder: (context) { + return ViewDiscountVC( + discount, + ); + }, + ); + }, + onEdit: (discount) { + toDiscount(true, discount); + }), if (viewModel.dataState == DataState.moreFetching) AppLoader(), ], ); @@ -457,7 +163,7 @@ class _DiscountVCState extends BaseStatefulState { bool _scrollNotification() { if (!viewModel.isLoading && _controller.position.extentAfter < 300) { - viewModel.fetch(); + viewModel.fetch(limit: viewModel.limit); } return true; } @@ -470,15 +176,14 @@ class _DiscountVCState extends BaseStatefulState { Future _deleteDiscount(String id) async { progressDialogue(context); - await viewModel.delete(id); hideProgressBar(); } Widget getSearchBar() { - return Flexible( - child: SizedBox( + return SizedBox( height: 48, + width: isPortrait ? double.infinity : 240, child: SearchBox( hint: AppLocalizations.of(context)!.search, onEditingDone: (text) { @@ -488,7 +193,7 @@ class _DiscountVCState extends BaseStatefulState { filterSearchResults(text); }, ), - )); + ); } Future filterSearchResults(String query) async { @@ -502,29 +207,30 @@ class _DiscountVCState extends BaseStatefulState { } Widget newDiscountButton() { - return SizedBox( - width: 130, - child: CustomSimpleButton( - textColor: MyColors.blueThemeColor, - backGroundColor: MyColors.backColorBlue50, - onPressed: () async { - final result = await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => NewDiscountVC( - isEdit: false, - storeDiscount: - StoreDiscount(products: [], categories: []), - )), - ); - if (!mounted) return; - if (result) { - viewModel.fetch(isRefresh: true); - } - }, - heading: AppLocalizations.of(context)!.new_discount, - ), + return CustomSimpleButton( + height: 38, + textColor: MyColors.blueThemeColor, + backGroundColor: MyColors.backColorBlue50, + onPressed: () async { + toDiscount(false, StoreDiscount()); + }, + heading: AppLocalizations.of(context)!.new_discount, + ); + } + + Future toDiscount(bool isEdit, StoreDiscount discount) async { + final result = await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => NewDiscountVC( + isEdit: isEdit, + storeDiscount: discount, + )), ); + if (!mounted) return; + if (result) { + viewModel.fetch(isRefresh: true); + } } Widget pageLabel() { @@ -533,45 +239,4 @@ class _DiscountVCState extends BaseStatefulState { style: ThemeText.textStylePageHeading, ); } - - void actionPopUpItemSelected( - String value, StoreDiscount storeDiscount) async { - if (value == 'edit') { - final result = await showDialog( - barrierColor: Colors.black26, - context: context, - builder: (context) { - return NewDiscountVC(isEdit: true, storeDiscount: storeDiscount); - }, - ); - - if (!mounted) return; - if (result) { - viewModel.fetch(isRefresh: true); - } - } else if (value == 'delete') { - final result = await showDialog( - barrierColor: Colors.black26, - context: context, - builder: (context) { - return const DeleteRecordPopUp(); - }, - ); - - if (!mounted) return; - if (result) { - _deleteDiscount(storeDiscount.id!); - } - } else { - showDialog( - barrierColor: Colors.black26, - context: context, - builder: (context) { - return ViewDiscountVC( - storeDiscount: storeDiscount, - ); - }, - ); - } - } } diff --git a/lib/application/views/discountModule/views/NewDiscountVC.dart b/lib/application/views/discountModule/views/NewDiscountVC.dart index 16c7e93..4c684f4 100644 --- a/lib/application/views/discountModule/views/NewDiscountVC.dart +++ b/lib/application/views/discountModule/views/NewDiscountVC.dart @@ -1,18 +1,32 @@ +import 'package:dropdown_search/dropdown_search.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:flutter_switch/flutter_switch.dart'; import 'package:group_radio_button/group_radio_button.dart'; -import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:provider/provider.dart'; import 'package:wosull/application/model/converters/DataTimeFormat.dart'; import 'package:wosull/application/model/discount/StoreDiscountModel.dart'; import 'package:wosull/application/model/inventory/category/ItemCategory.dart'; import 'package:wosull/application/theme/MyColors.dart'; -import 'package:wosull/application/theme/MyFonts.dart'; import 'package:wosull/application/utils/AppLoader.dart'; +import 'package:wosull/application/utils/CRUDOperatoinState.dart'; import 'package:wosull/application/utils/Constants.dart'; -import 'package:wosull/application/views/discountModule/viewModels/DiscountViewModel.dart'; +import 'package:wosull/application/views/discountModule/viewModels/NewDiscountViewModel.dart'; +import 'package:wosull/application/views/discountModule/widgets/DiscountFilterItemView.dart'; import 'package:wosull/base/BaseStatefulState.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeDropDown.dart'; +import 'package:wosull/helpers/ThemeText.dart'; import 'package:wosull/helpers/Utils.dart'; +import 'package:wosull/widgets/CustomAppBar.dart'; +import 'package:wosull/widgets/CustomCheckBox.dart'; +import 'package:wosull/widgets/CustomOptionalTitle.dart'; +import 'package:wosull/widgets/CustomSimpleButton.dart'; +import 'package:wosull/widgets/CustomSwitch.dart'; +import 'package:wosull/widgets/CustomTextButtonIcon.dart'; +import 'package:wosull/widgets/CustomTextFieldForm.dart'; +import 'package:wosull/widgets/DropdownItemBuilder.dart'; +import 'package:wosull/widgets/MandatoryTitleText.dart'; +import 'package:wosull/widgets/SearchBox.dart'; class NewDiscountVC extends StatefulWidget { late bool isEdit; @@ -26,107 +40,44 @@ class NewDiscountVC extends StatefulWidget { } class _NewDiscountVCState extends BaseStatefulState { - var items = [ - 'Percentage', - 'Absolute', - ]; - - String selectedDiscountType = "Percentage"; - DiscountViewModel viewModel = DiscountViewModel(); - - List categories = List.empty(growable: true); - - TextEditingController discountCodeController = TextEditingController(); - TextEditingController minimumAmountController = TextEditingController(); - TextEditingController maxDiscountController = TextEditingController(); - TextEditingController discountPerValueController = TextEditingController(); - - TextEditingController descriptionController = TextEditingController(); - TextEditingController limitDiscountController = TextEditingController(); - - final _types = [ - "Manual", - "Automatic", - ]; - String __typesGroupValue = "Manual"; - String _verticalGroupValue = "All Products"; - final _status = [ - "All Products", - "Specific Products", - "Specific Categories of Products", - "All Products except specific products" - ]; - - bool _isLoading = false; - bool isGettingItems = false; - bool isTablet = true; - bool isPortrait = true; - - List filteredItems = []; - List data = []; + var viewModel = NewDiscountViewModel(); @override void initState() { - // TODO: implement initState + context + .read() + .initData(widget.isEdit, widget.storeDiscount); super.initState(); - if (!widget.isEdit) { - widget.storeDiscount.isMinAmount = false; - widget.storeDiscount.isAlways = false; - widget.storeDiscount.isMaxDiscount = false; - widget.storeDiscount.isUnlimited = false; - widget.storeDiscount.status = "Active"; - widget.storeDiscount.categories = List.empty(growable: true); - widget.storeDiscount.products = List.empty(growable: true); - } else { - discountCodeController.text = widget.storeDiscount.name!; - minimumAmountController.text = - widget.storeDiscount.minAmountLimit.toString(); - maxDiscountController.text = - widget.storeDiscount.maxDiscountLimit.toString(); - discountPerValueController.text = - widget.storeDiscount.discountPercentage!; - selectedDiscountType = widget.storeDiscount.discountTypeLabel!; + } - descriptionController.text = widget.storeDiscount.description!; - limitDiscountController.text = - widget.storeDiscount.limitOfDiscount!.toString(); - __typesGroupValue = widget.storeDiscount.discountType!; - } + @override + void dispose() { + viewModel.disposeData(); + super.dispose(); } @override Widget build(BuildContext context) { + viewModel = context.watch(); return Scaffold( + backgroundColor: MyColors.fillColor, resizeToAvoidBottomInset: true, - appBar: AppBar( - leading: BackButton( - color: Colors.black, - onPressed: () { - Navigator.pop(context); - }, // <-- SEE HERE - ), - centerTitle: true, - title: Text( - AppLocalizations.of(context)!.add_discount, - style: const TextStyle( - color: MyColors.textColorBlack, - fontFamily: MyFonts.Bold, - fontSize: 22), - ), - backgroundColor: MyColors.white, - elevation: 5, + appBar: CustomAppBar( + heading: AppLocalizations.of(context)!.add_discount, ), body: OrientationBuilder(builder: (c, orientation) { - isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; - isTablet = DeviceUtil.isTablet; + viewModel.isPortrait = + MediaQuery.of(context).orientation == Orientation.portrait; + viewModel.isTablet = DeviceUtil.isTablet; return SingleChildScrollView( child: Container( - color: MyColors.white, padding: const EdgeInsets.all(8), child: Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ + AppSpaces.verticalLarge, Card( + elevation: 5, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.0), ), @@ -142,493 +93,36 @@ class _NewDiscountVCState extends BaseStatefulState { crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ - Row( - children: [ - Text( - AppLocalizations.of(context)!.discount_code, - style: const TextStyle( - fontSize: MyFonts.normalButton, - fontFamily: MyFonts.Medium, - color: MyColors.textColorPopUp), - ), - const Text( - '*', - style: TextStyle( - fontSize: MyFonts.normalButton, - fontFamily: MyFonts.Medium, - color: MyColors.fillRed), - ), - ], - ), - const SizedBox( - height: 4, - ), - TextField( - controller: discountCodeController, - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normalButton, - color: MyColors.black), - decoration: InputDecoration( - contentPadding: - const EdgeInsets.fromLTRB(8, 0, 8, 0), - hintText: 'Enter Discount Code', - fillColor: MyColors.fillColor2, - filled: true, - focusedBorder: OutlineInputBorder( - borderSide: const BorderSide( - color: Colors.transparent, width: 1.0), - borderRadius: BorderRadius.circular(8.0), - ), - enabledBorder: OutlineInputBorder( - borderSide: const BorderSide( - width: 1, //<-- SEE HERE - color: Colors.transparent, - ), - borderRadius: BorderRadius.circular(8.0), - ), - ), - ), - const SizedBox( - height: 8, - ), - Row( - children: [ - Text( - AppLocalizations.of(context)! - .minimum_amount_limit, - style: const TextStyle( - fontSize: MyFonts.normalButton, - fontFamily: MyFonts.Medium, - color: MyColors.black), - ), - const SizedBox( - width: 8, - ), - FlutterSwitch( - height: 20.0, - width: 40.0, - padding: 4.0, - toggleSize: 15.0, - borderRadius: 10.0, - activeColor: MyColors.blueThemeColor, - value: widget.storeDiscount.isMinAmount ?? - false, - onToggle: (value) { - setState(() { - widget.storeDiscount.isMinAmount = - value; - }); - }, - ), - ], - ), - const SizedBox( - height: 4, - ), - TextField( - keyboardType: TextInputType.number, - controller: minimumAmountController, - enabled: - widget.storeDiscount.isMinAmount ?? false, - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normalButton, - color: MyColors.black), - decoration: InputDecoration( - contentPadding: - const EdgeInsets.fromLTRB(8, 0, 8, 0), - hintText: 'Enter Minimum Amount', - fillColor: MyColors.fillColor2, - filled: true, - focusedBorder: OutlineInputBorder( - borderSide: const BorderSide( - color: Colors.transparent, width: 1.0), - borderRadius: BorderRadius.circular(8.0), - ), - enabledBorder: OutlineInputBorder( - borderSide: const BorderSide( - width: 1, //<-- SEE HERE - color: Colors.transparent, - ), - borderRadius: BorderRadius.circular(8.0), - ), - ), - ), - const SizedBox( - height: 8, - ), - Row( - children: [ - Text( - AppLocalizations.of(context)! - .discount_start_date, - style: const TextStyle( - fontSize: MyFonts.normalButton, - fontFamily: MyFonts.Medium, - color: MyColors.black), - ), - Expanded( - child: Align( - alignment: Alignment.centerRight, - child: Row( - mainAxisAlignment: - MainAxisAlignment.end, - children: [ - SizedBox( - height: 24, - width: 24, - child: Transform.scale( - scale: 1, - child: Checkbox( - value: widget.storeDiscount - .isAlways ?? - false, - side: const BorderSide( - color: MyColors - .fillColorGray2), - onChanged: (bool? value) { - setState(() { - widget.storeDiscount - .isAlways = value; - }); - }, - shape: RoundedRectangleBorder( - // Making around shape - borderRadius: - BorderRadius.circular( - 4)), - activeColor: - MyColors.blueThemeColor, - checkColor: Colors.white, - fillColor: - MaterialStateProperty.all( - MyColors - .blueThemeColor), - tristate: true, - ), - ), - ), - const SizedBox( - width: 4, - ), - Text( - AppLocalizations.of(context)! - .always, - style: const TextStyle( - fontSize: MyFonts.normalButton, - fontFamily: MyFonts.Medium, - color: MyColors.black), - textAlign: TextAlign.center, - ) - ]), - )) - ], - ), - const SizedBox( - height: 4, - ), - Container( - height: 48, - decoration: BoxDecoration( - border: Border.all( - color: Colors.transparent, - width: 1, - ), - color: MyColors.fillColor2, - borderRadius: BorderRadius.circular(8.0), - ), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - crossAxisAlignment: - CrossAxisAlignment.stretch, - children: [ - Expanded( - child: TextButton( - onPressed: () { - _presentDatePicker(true); - }, - child: Align( - alignment: Alignment.centerLeft, - child: Text( - widget.isEdit - ? widget.storeDiscount - .discountStartDate! - : widget.storeDiscount - .discountStartDate ?? - 'dd/mm/yyyy', - textAlign: TextAlign.left, - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normalButton, - color: Colors.black54), - ), - ), - )), - const Icon( - // <-- Icon - Icons.calendar_month_outlined, - size: 24.0, - color: MyColors.black, - ) - ], - ), - ), - const SizedBox( - height: 8, - ), - Row( - children: [ - Text( - AppLocalizations.of(context)! - .limit_of_discount, - style: const TextStyle( - fontSize: MyFonts.normalButton, - fontFamily: MyFonts.Medium, - color: MyColors.black), - ), - Expanded( - child: Align( - alignment: Alignment.centerRight, - child: Row( - mainAxisAlignment: - MainAxisAlignment.end, - children: [ - SizedBox( - height: 24, - width: 24, - child: Transform.scale( - scale: 1, - child: Checkbox( - value: widget.storeDiscount - .isUnlimited ?? - false, - side: const BorderSide( - color: MyColors - .fillColorGray2), - onChanged: (bool? value) { - setState(() { - widget.storeDiscount - .isUnlimited = value; - }); - }, - shape: RoundedRectangleBorder( - // Making around shape - borderRadius: - BorderRadius.circular( - 4)), - activeColor: MyColors.primary, - checkColor: Colors.white, - fillColor: - MaterialStateProperty.all( - MyColors - .blueThemeColor), - tristate: true, - ), - ), - ), - const SizedBox( - width: 4, - ), - Text( - AppLocalizations.of(context)! - .unlimited, - style: const TextStyle( - fontSize: MyFonts.normalButton, - fontFamily: MyFonts.Medium, - color: MyColors.black), - textAlign: TextAlign.center, - ) - ]), - )) - ], - ), - const SizedBox( - height: 4, - ), - TextField( - keyboardType: TextInputType.number, - controller: limitDiscountController, - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normalButton, - color: MyColors.black), - decoration: InputDecoration( - contentPadding: - const EdgeInsets.fromLTRB(8, 0, 8, 0), - hintText: AppLocalizations.of(context)! - .limit_of_discount, - fillColor: MyColors.fillColor2, - filled: true, - focusedBorder: OutlineInputBorder( - borderSide: const BorderSide( - color: Colors.transparent, width: 1.0), - borderRadius: BorderRadius.circular(8.0), - ), - enabledBorder: OutlineInputBorder( - borderSide: const BorderSide( - width: 1, //<-- SEE HERE - color: Colors.transparent, - ), - borderRadius: BorderRadius.circular(8.0), - ), - ), - ), - const SizedBox( - height: 8, - ), - isPortrait + getDiscountCodeWidget(), + AppSpaces.verticalMedium, + getMinimumAmountLimitWidget(), + AppSpaces.verticalMedium, + getDiscountStartDateWidget(), + AppSpaces.verticalMedium, + getLimitDiscountWidget(), + AppSpaces.verticalMedium, + viewModel.isPortrait ? Container() - : Column( - mainAxisAlignment: - MainAxisAlignment.start, - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - AppLocalizations.of(context)! - .discount_filters, - style: const TextStyle( - fontSize: MyFonts.normalButton, - fontFamily: MyFonts.Medium, - color: MyColors.black), - ), - const SizedBox( - height: 8, - ), - getRadioProducts(), - ], - ), - isPortrait + : getDiscountFilterWidget(), + viewModel.isPortrait ? Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Row( - children: [ - Text( - AppLocalizations.of(context)! - .discount_type, - style: const TextStyle( - fontSize: - MyFonts.normalButton, - fontFamily: MyFonts.Medium, - color: - MyColors.textColorPopUp), - ), - const Text( - '*', - style: TextStyle( - fontSize: - MyFonts.normalButton, - fontFamily: MyFonts.Medium, - color: MyColors.fillRed), - ), - ], - ), - const SizedBox( - height: 4, - ), - SizedBox( - height: 48, - child: getDiscountType(), - ), - const SizedBox( - height: 8, - ), + getDiscountTypeWidget(), + AppSpaces.verticalMedium, getMaximumDiscountWidget(), - const SizedBox( - height: 12, - ), + AppSpaces.verticalMedium, getDiscountExpireDate(), - const SizedBox( - height: 12, - ), + AppSpaces.verticalMedium, getStatusWidget(), - const SizedBox( - height: 4, - ), + AppSpaces.verticalSmall, getDiscountPercentage(), - const SizedBox( - height: 12, - ), - Text( - AppLocalizations.of(context)! - .description, - style: const TextStyle( - fontSize: MyFonts.normalButton, - fontFamily: MyFonts.Medium, - color: MyColors.black), - ), - const SizedBox( - height: 4, - ), - SizedBox( - height: 100, - child: TextField( - controller: descriptionController, - maxLines: 5, - keyboardType: - TextInputType.multiline, - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normalButton, - color: MyColors.black), - decoration: InputDecoration( - contentPadding: - const EdgeInsets.fromLTRB( - 8, 12, 8, 12), - hintText: - AppLocalizations.of(context)! - .description, - fillColor: MyColors.fillColor2, - filled: true, - focusedBorder: OutlineInputBorder( - borderSide: const BorderSide( - color: Colors.transparent, - width: 1.0), - borderRadius: - BorderRadius.circular(8.0), - ), - enabledBorder: OutlineInputBorder( - borderSide: const BorderSide( - width: 1, //<-- SEE HERE - color: Colors.transparent, - ), - borderRadius: - BorderRadius.circular(8.0), - ), - ), - ), - ), - const SizedBox( - height: 8, - ), - isPortrait - ? Column( - mainAxisAlignment: - MainAxisAlignment.start, - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - AppLocalizations.of( - context)! - .discount_filters, - style: const TextStyle( - fontSize: MyFonts - .normalButton, - fontFamily: - MyFonts.Medium, - color: MyColors.black), - ), - const SizedBox( - height: 8, - ), - getRadioProducts(), - ], - ) + AppSpaces.verticalMedium, + getDescriptionWidget(), + AppSpaces.verticalMedium, + viewModel.isPortrait + ? getDiscountFilterWidget() : Container(), getProductContainer() ], @@ -637,12 +131,10 @@ class _NewDiscountVCState extends BaseStatefulState { ], ), ), - isPortrait + viewModel.isPortrait ? Container() - : const SizedBox( - width: 8, - ), - isPortrait + : AppSpaces.horizontalMedium, + viewModel.isPortrait ? Container() : Expanded( flex: 2, @@ -663,133 +155,27 @@ class _NewDiscountVCState extends BaseStatefulState { mainAxisAlignment: MainAxisAlignment.start, children: [ - Row( - children: [ - Text( - AppLocalizations.of(context)! - .discount_type, - style: const TextStyle( - fontSize: - MyFonts.normalButton, - fontFamily: - MyFonts.Medium, - color: MyColors - .textColorPopUp), - ), - const Text( - '*', - style: TextStyle( - fontSize: - MyFonts.normalButton, - fontFamily: - MyFonts.Medium, - color: MyColors.fillRed), - ), - ], - ), - const SizedBox( - height: 4, - ), - SizedBox( - height: 48, - child: getDiscountType(), - ), - const SizedBox( - height: 8, - ), + getDiscountTypeWidget(), + AppSpaces.verticalMedium, getMaximumDiscountWidget(), - const SizedBox( - height: 12, - ), + AppSpaces.verticalMedium, getDiscountExpireDate(), - const SizedBox( - height: 12, - ), + AppSpaces.verticalMedium, getStatusWidget() ], )), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, Expanded( child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.start, children: [ getDiscountPercentage(), - const SizedBox( - height: 12, - ), - Text( - AppLocalizations.of(context)! - .description, - style: const TextStyle( - fontSize: - MyFonts.normalButton, - fontFamily: MyFonts.Medium, - color: MyColors.black), - ), - const SizedBox( - height: 4, - ), - SizedBox( - height: 100, - child: TextField( - controller: - descriptionController, - maxLines: 5, - keyboardType: - TextInputType.multiline, - style: const TextStyle( - fontFamily: - MyFonts.DMREGULAR, - fontSize: - MyFonts.normalButton, - color: MyColors.black), - decoration: InputDecoration( - contentPadding: - const EdgeInsets.fromLTRB( - 8, 12, 8, 12), - hintText: AppLocalizations.of( - context)! - .description, - fillColor: - MyColors.fillColor2, - filled: true, - focusedBorder: - OutlineInputBorder( - borderSide: - const BorderSide( - color: Colors - .transparent, - width: 1.0), - borderRadius: - BorderRadius.circular( - 8.0), - ), - enabledBorder: - OutlineInputBorder( - borderSide: - const BorderSide( - width: 1, //<-- SEE HERE - color: Colors.transparent, - ), - borderRadius: - BorderRadius.circular( - 8.0), - ), - ), - ), - ), + AppSpaces.verticalMedium, + getDescriptionWidget() ], )) ], ), - const SizedBox( - height: 6, - ), + AppSpaces.verticalMedium, getProductContainer() ], )) @@ -797,34 +183,19 @@ class _NewDiscountVCState extends BaseStatefulState { ), ), ), - const SizedBox( - height: 12, - ), + AppSpaces.verticalLarge, SizedBox( width: 120, - child: !_isLoading - ? ElevatedButton( - style: ElevatedButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(6.0), - ), - backgroundColor: MyColors.blueThemeColor, - minimumSize: const Size.fromHeight(38), // NEW - ), - onPressed: () { - isValidate(); - }, - child: Text( - AppLocalizations.of(context)!.save, - style: const TextStyle( - fontSize: MyFonts.normalButton, - color: MyColors.white, - fontFamily: MyFonts.Bold), - ), - ) - : const Center( - child: CircularProgressIndicator(), - ), + child: CustomSimpleButton( + textColor: MyColors.white, + backGroundColor: MyColors.blueThemeColor, + isLoading: viewModel.isLoading, + onPressed: () async { + await viewModel.isValidate(); + checkState(); + }, + heading: AppLocalizations.of(context)!.save, + ), ), ], ), @@ -834,33 +205,13 @@ class _NewDiscountVCState extends BaseStatefulState { ); } - void _presentDatePicker(bool isStart) { - // showDatePicker is a pre-made funtion of Flutter - showDatePicker( - context: context, - initialDate: DateTime.now(), - firstDate: DateTime(1965), - lastDate: DateTime(2030)) - .then((pickedDate) { - // Check if no date is selected - if (pickedDate == null) { - return; - } - setState(() { - if (isStart) { - widget.storeDiscount.discountStartDate = - DataTimeFormat.formatDateFromPicket(pickedDate); - } else { - widget.storeDiscount.discountEndDate = - DataTimeFormat.formatDateFromPicket(pickedDate); - } - }); - }); - } - Widget getProductContainer() { + print(!(viewModel.verticalGroupValue.toLowerCase() == + Constants.discountFilters[0].toLowerCase()) || + viewModel.verticalGroupValue.isNotEmpty); return Visibility( - visible: _verticalGroupValue != _status.elementAt(0), + visible: !(viewModel.verticalGroupValue.toLowerCase() == + Constants.discountFilters[0].toLowerCase()), child: Container( height: 200, padding: const EdgeInsets.all(16), @@ -876,149 +227,53 @@ class _NewDiscountVCState extends BaseStatefulState { Row( children: [ Expanded( - flex: 2, + flex: viewModel.isPortrait ? 1 : 2, child: Text( AppLocalizations.of(context)!.choose_product, - style: const TextStyle( - fontSize: 19, - fontFamily: MyFonts.Bold, - color: Colors.black, - fontWeight: FontWeight.bold), + style: ThemeText.textStylePageHeading, )), Expanded( child: SizedBox( height: 38, - child: TextField( - onChanged: (value) { - filterSearchResults(value); - }, - style: const TextStyle( - fontSize: MyFonts.normalButton, - fontFamily: MyFonts.Medium, - color: MyColors.textColorBlack), - decoration: InputDecoration( - contentPadding: const EdgeInsets.fromLTRB(8, 0, 8, 0), - hintText: AppLocalizations.of(context)!.search, - fillColor: MyColors.fillColor2, - filled: true, - prefixIcon: const Icon(Icons.search), - enabledBorder: OutlineInputBorder( - borderSide: const BorderSide( - width: 1, //<-- SEE HERE - color: MyColors.strokeColor, - ), - borderRadius: BorderRadius.circular(8.0), - ), - focusedBorder: OutlineInputBorder( - borderSide: const BorderSide( - color: MyColors.strokeColor, width: 1.0), - borderRadius: BorderRadius.circular(8.0), - ), - )), + child: SearchBox( + onChanged: (value) { + filterSearchResults(value); + }, + hint: AppLocalizations.of(context)!.search, + onEditingDone: (String value) {}, + ), )) ], ), - const SizedBox( - height: 8, - ), - isGettingItems + AppSpaces.verticalMedium, + viewModel.isGettingItems ? AppLoader() : SizedBox( height: 110, child: GridView.builder( physics: const AlwaysScrollableScrollPhysics(), shrinkWrap: true, - itemCount: filteredItems.length, + itemCount: viewModel.filteredItems.length, gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: isPortrait ? 3 : 4, + crossAxisCount: viewModel.isPortrait ? 3 : 4, mainAxisExtent: 38, crossAxisSpacing: 0, mainAxisSpacing: 0, ), itemBuilder: (c, i) { + ItemCategory filteredItem = + viewModel.filteredItems[i]; return GestureDetector( onTap: () { - if (_verticalGroupValue == - _status.elementAt(2)) { - //cate - setState(() { - if (widget.storeDiscount.categories! - .isEmpty || - !widget.storeDiscount.categories! - .contains(filteredItems[i].id)) { - widget.storeDiscount.categories! - .add(filteredItems[i].id); - } else if (widget - .storeDiscount.categories! - .contains(filteredItems[i].id)) { - widget.storeDiscount.categories! - .remove(filteredItems[i].id); - } - }); - } else { - //product - setState(() { - if (widget.storeDiscount.products! - .isEmpty || - !widget.storeDiscount.products! - .contains(filteredItems[i].id)) { - widget.storeDiscount.products! - .add(filteredItems[i].id); - } else if (widget.storeDiscount.products! - .contains(filteredItems[i].id)) { - widget.storeDiscount.products! - .remove(filteredItems[i].id); - } - }); - } + viewModel.onChangeDiscountType(filteredItem); }, - child: Container( - margin: const EdgeInsets.all(4), - padding: const EdgeInsets.all(4), - decoration: BoxDecoration( - color: widget.storeDiscount.products! - .contains( - filteredItems[i].id) || - widget.storeDiscount.categories! - .contains(filteredItems[i].id) - ? MyColors.blueThemeColor - : MyColors.fillColor2, - border: Border.all( - width: 1, color: MyColors.fillColor3), - borderRadius: const BorderRadius.all( - Radius.circular(8))), - child: Row( - children: [ - Expanded( - child: Column( - mainAxisAlignment: - MainAxisAlignment.center, - children: [ - Text( - filteredItems[i].name, - maxLines: 1, - style: TextStyle( - fontSize: 11, - fontFamily: MyFonts.DMREGULAR, - color: widget.storeDiscount - .products! - .contains( - filteredItems[i] - .id) || - widget.storeDiscount - .categories! - .contains( - filteredItems[i] - .id) - ? MyColors.white - : MyColors.textColorBlack, - fontWeight: FontWeight.bold), - ), - ], - )) - ], - ), + child: DiscountFilterItemView( + products: + viewModel.storeDiscount.products ?? [], + categories: + viewModel.storeDiscount.categories ?? [], + filteredItem: filteredItem, )); }), ) @@ -1027,57 +282,15 @@ class _NewDiscountVCState extends BaseStatefulState { )); } - Future> getItems() async { - setState(() { - isGettingItems = true; - }); - if (_verticalGroupValue == _status.elementAt(0)) { - filteredItems.clear(); - data.clear(); - } else if (_verticalGroupValue == _status.elementAt(2)) { - final itemsResponse = - await viewModel.getStoreCategoryItems(Constants.getStorePayload()); - if (itemsResponse.success && itemsResponse.categories.isNotEmpty) { - filteredItems.clear(); - data.clear(); - filteredItems.addAll(itemsResponse.categories); - data.addAll(itemsResponse.categories); - } - } else { - final getItemsByStoreId = - await viewModel.getStoreItemsById(Constants.getStorePayload()); - if (getItemsByStoreId.success! && - getItemsByStoreId.categories!.isNotEmpty) { - filteredItems.clear(); - data.clear(); - filteredItems.addAll(getItemsByStoreId.categories!); - data.addAll(getItemsByStoreId.categories!); - } - } - setState(() { - isGettingItems = false; - }); - return filteredItems; - } - Widget getRadioProducts() { return RadioGroup.builder( horizontalAlignment: MainAxisAlignment.start, - textStyle: const TextStyle( - fontSize: 11, - fontWeight: FontWeight.w500, - fontFamily: MyFonts.Medium, - color: MyColors.textColorPopUp), - groupValue: _verticalGroupValue, + textStyle: ThemeText.textStyleValue, + groupValue: viewModel.verticalGroupValue, onChanged: (value) { - setState(() { - widget.storeDiscount.categories!.clear(); - widget.storeDiscount.products!.clear(); - _verticalGroupValue = value ?? ''; - getItems(); - }); + viewModel.changeFilter(value); }, - items: _status, + items: Constants.discountFilters, itemBuilder: (item) => RadioButtonBuilder( item, ), @@ -1091,18 +304,12 @@ class _NewDiscountVCState extends BaseStatefulState { return RadioGroup.builder( direction: Axis.horizontal, horizontalAlignment: MainAxisAlignment.start, - textStyle: const TextStyle( - fontSize: 11, - fontWeight: FontWeight.w500, - fontFamily: MyFonts.Medium, - color: MyColors.textColorPopUp), - groupValue: __typesGroupValue, + textStyle: ThemeText.textStyleValue, + groupValue: viewModel.typesGroupValue, onChanged: (value) { - setState(() { - __typesGroupValue = value ?? ''; - }); + viewModel.changeDiscount(value); }, - items: _types, + items: Constants.types, itemBuilder: (item) => RadioButtonBuilder( item, ), @@ -1119,61 +326,29 @@ class _NewDiscountVCState extends BaseStatefulState { children: [ Row( children: [ - Text( - AppLocalizations.of(context)!.maximum_discount_limit, - style: const TextStyle( - fontSize: MyFonts.normalButton, - fontFamily: MyFonts.Medium, - color: MyColors.black), - ), - const SizedBox( - width: 8, + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.maximum_discount_limit, ), - FlutterSwitch( - height: 20.0, - width: 40.0, - padding: 4.0, - toggleSize: 15.0, - borderRadius: 10.0, - activeColor: MyColors.blueThemeColor, - value: widget.storeDiscount.isMaxDiscount ?? false, + AppSpaces.horizontalMedium, + CustomSwitch( + value: viewModel.storeDiscount.isMaxDiscount ?? false, onToggle: (value) { - setState(() { - widget.storeDiscount.isMaxDiscount = value; - }); + viewModel.updateIsMaxDiscount(value); }, ), ], ), - const SizedBox( - height: 4, - ), - TextField( + AppSpaces.verticalSmall, + CustomTextFieldForm( + hintText: AppLocalizations.of(context)!.maximum_discount_limit, keyboardType: TextInputType.number, - controller: maxDiscountController, - enabled: widget.storeDiscount.isMaxDiscount ?? false, - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normalButton, - color: MyColors.black), - decoration: InputDecoration( - contentPadding: const EdgeInsets.fromLTRB(8, 0, 8, 0), - hintText: AppLocalizations.of(context)!.maximum_discount_limit, - fillColor: MyColors.fillColor2, - filled: true, - focusedBorder: OutlineInputBorder( - borderSide: - const BorderSide(color: Colors.transparent, width: 1.0), - borderRadius: BorderRadius.circular(8.0), - ), - enabledBorder: OutlineInputBorder( - borderSide: const BorderSide( - width: 1, //<-- SEE HERE - color: Colors.transparent, - ), - borderRadius: BorderRadius.circular(8.0), - ), - ), + initialValue: + viewModel.storeDiscount.maxDiscountLimit?.toStringAsFixed(2) ?? + '', + readOnly: !(viewModel.storeDiscount.isMaxDiscount!), + onChanged: (value) { + viewModel.updateMaxDiscount(value); + }, ), ], ); @@ -1184,39 +359,17 @@ class _NewDiscountVCState extends BaseStatefulState { crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ - Text( - AppLocalizations.of(context)!.status, - style: const TextStyle( - fontSize: MyFonts.normalButton, - fontFamily: MyFonts.Medium, - color: MyColors.black), - ), - const SizedBox( - height: 4, + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.status, ), + AppSpaces.verticalSmall, SizedBox( height: 48, - child: Align( - alignment: Alignment.centerLeft, - child: Row( - children: [ - FlutterSwitch( - height: 20.0, - width: 40.0, - padding: 4.0, - toggleSize: 15.0, - borderRadius: 10.0, - activeColor: MyColors.blueThemeColor, - value: widget.storeDiscount.getStatus(), - onToggle: (value) { - setState(() { - widget.storeDiscount.status = - value ? "Active" : "Inactive"; - }); - }, - ) - ], - ), + child: CustomSwitch( + value: viewModel.storeDiscount.getStatus(), + onToggle: (value) { + viewModel.updateStatus(value); + }, ), ), ], @@ -1228,230 +381,266 @@ class _NewDiscountVCState extends BaseStatefulState { crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ - Text( - AppLocalizations.of(context)!.discount_type, - style: const TextStyle( - fontSize: MyFonts.normalButton, - fontFamily: MyFonts.Medium, - color: MyColors.textColorPopUp), + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.discount_type, ), - const SizedBox( - height: 4, + AppSpaces.verticalSmall, + DropdownSearch( + selectedItem: viewModel.selectedDiscountType, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: Constants.discountType, + itemAsString: (String u) => u, + onChanged: (String? data) { + viewModel.updateDiscountType(data); + }, + dropdownDecoratorProps: + MyColors.dropDownStyle(hint: 'Choose Discount Type'), ), - Material( - color: MyColors.fillColor2, - borderRadius: BorderRadius.circular(8), - child: SizedBox( - height: 48, - width: double.infinity, - child: Padding( - padding: const EdgeInsets.only(left: 8, right: 8), - child: DropdownButton( - hint: Text(selectedDiscountType), - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontSize: 13, - color: MyColors.textColorBlack), - isExpanded: true, - underline: DropdownButtonHideUnderline(child: Container()), - items: items.map((String items) { - return DropdownMenuItem( - value: items, - child: Text(items), - ); - }).toList(), - onChanged: (Object? value) { - setState(() { - selectedDiscountType = value!.toString(); - }); - }, - ), - ), - ), + AppSpaces.verticalMedium, + getDiscountPercentageValueWidget() + ], + ); + } + + Widget getDiscountExpireDate() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.discount_expiry_date, ), - const SizedBox( - height: 8, + AppSpaces.verticalSmall, + getEndDateButton() + ], + ); + } + + Widget getEndDateButton() { + return CustomTextButtonIcon( + backgroundColor: MyColors.backFillColor, + icon: Icons.calendar_month, + heading: widget.isEdit + ? DataTimeFormat.getFormatDate( + viewModel.storeDiscount.discountEndDate ?? '') + : DataTimeFormat.getFormatDate( + viewModel.storeDiscount.discountEndDate ?? ''), + onPressed: () { + viewModel.presentDatePicker(context, false); + }, + ); + } + + Widget getStartDateButton() { + return CustomTextButtonIcon( + backgroundColor: MyColors.backFillColor, + icon: Icons.calendar_month, + heading: widget.isEdit + ? DataTimeFormat.getFormatDate( + viewModel.storeDiscount.discountStartDate ?? '') + : DataTimeFormat.getFormatDate( + viewModel.storeDiscount.discountStartDate ?? '') ?? + 'dd/mm/yyyy', + onPressed: () { + viewModel.presentDatePicker(context, true); + }, + ); + } + + Future filterSearchResults(String query) async { + if (query.isNotEmpty) { + viewModel.filterItems(query); + return; + } else { + Future.delayed(const Duration(milliseconds: 500), () { + viewModel.filterItems(query); + }); + } + } + + Widget getDiscountCodeWidget() { + return Column( + children: [ + MandatoryTitleText( + hint: AppLocalizations.of(context)!.discount_code, ), + AppSpaces.verticalSmall, + CustomTextFieldForm( + hintText: 'Enter Discount Code', + initialValue: viewModel.storeDiscount.name ?? '', + onChanged: (String value) { + viewModel.storeDiscount.name = value; + }, + ) + ], + ); + } + + Widget getMinimumAmountLimitWidget() { + return Column( + children: [ Row( children: [ - Text( - selectedDiscountType == 'Percentage' - ? AppLocalizations.of(context)!.discount_percentage - : AppLocalizations.of(context)!.discount_value, - style: const TextStyle( - fontSize: MyFonts.normalButton, - fontFamily: MyFonts.Medium, - color: MyColors.black), + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.minimum_amount_limit, ), - const Text( - '*', - style: TextStyle( - fontSize: MyFonts.normalButton, - fontFamily: MyFonts.Medium, - color: MyColors.fillRed), + AppSpaces.horizontalMedium, + CustomSwitch( + value: viewModel.storeDiscount.isMinAmount ?? false, + onToggle: (value) { + viewModel.setIsMinAmount(value); + }, ), ], ), - const SizedBox( - height: 4, - ), - TextField( + AppSpaces.verticalSmall, + CustomTextFieldForm( + hintText: 'Enter Minimum Amount', keyboardType: TextInputType.number, - controller: discountPerValueController, - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normalButton, - color: MyColors.black), - decoration: InputDecoration( - contentPadding: const EdgeInsets.fromLTRB(8, 0, 8, 0), - hintText: selectedDiscountType == 'Percentage' - ? 'Enter Discount Percentage' - : 'Enter Discount Value', - fillColor: MyColors.fillColor2, - filled: true, - focusedBorder: OutlineInputBorder( - borderSide: - const BorderSide(color: Colors.transparent, width: 1.0), - borderRadius: BorderRadius.circular(8.0), - ), - enabledBorder: OutlineInputBorder( - borderSide: const BorderSide( - width: 1, //<-- SEE HERE - color: Colors.transparent, - ), - borderRadius: BorderRadius.circular(8.0), - ), - ), + initialValue: + viewModel.storeDiscount.minAmountLimit?.toString() ?? '', + readOnly: !(viewModel.storeDiscount.isMinAmount!), + onChanged: (String value) { + viewModel.setMinAmount(value); + }, ), ], ); } - Widget getDiscountExpireDate() { + Widget getDiscountStartDateWidget() { return Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, children: [ - Text( - AppLocalizations.of(context)!.discount_expiry_date, - style: const TextStyle( - fontSize: MyFonts.normalButton, - fontFamily: MyFonts.Medium, - color: MyColors.black), - ), - const SizedBox( - height: 4, - ), - Container( - height: 48, - decoration: BoxDecoration( - border: Border.all( - color: Colors.transparent, - width: 1, - ), - color: MyColors.fillColor2, - borderRadius: BorderRadius.circular(8.0), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Expanded( - child: TextButton( - onPressed: () { - _presentDatePicker(false); - }, + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.discount_start_date), + Flexible( child: Align( - alignment: Alignment.centerLeft, - child: Text( - widget.isEdit - ? widget.storeDiscount.discountEndDate! - : widget.storeDiscount.discountEndDate ?? 'dd/mm/yyyy', - textAlign: TextAlign.left, - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normalButton, - color: Colors.black54), - ), - ), - )), - const Icon( - // <-- Icon - Icons.calendar_month_outlined, - size: 24.0, - color: MyColors.black, - ) - ], - ), + alignment: Alignment.centerRight, + child: CustomCheckBox( + heading: AppLocalizations.of(context)!.always, + value: viewModel.storeDiscount.isAlways ?? false, + onChange: (value) { + viewModel.setIsAlways(value); + }), + )), + ], ), + AppSpaces.verticalSmall, + getStartDateButton() ], ); } - Future filterSearchResults(String query) async { - if (query.isNotEmpty) { - setState(() { - filteredItems.clear(); - filteredItems.addAll(data.where((element) => - element.name.toLowerCase().startsWith(query.toLowerCase()))); - }); - return; - } else { - Future.delayed(const Duration(milliseconds: 500), () { - setState(() { - filteredItems.clear(); - filteredItems.addAll(data); - }); - }); - } + Widget getDescriptionWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle(hint: AppLocalizations.of(context)!.description), + AppSpaces.verticalSmall, + CustomTextFieldForm( + height: 100, + hintText: AppLocalizations.of(context)!.description, + initialValue: viewModel.storeDiscount.description ?? '', + maxLines: 5, + keyboardType: TextInputType.multiline, + onChanged: (String value) { + viewModel.storeDiscount.description = value; + }, + ), + ], + ); } - isValidate() { - if (discountCodeController.text.isEmpty) { - showMessage('Enter Discount Code'); - } else if (discountPerValueController.text.isEmpty) { - showMessage('Enter Discount $selectedDiscountType'); - } else { - setState(() { - _isLoading = true; - }); - _addDiscount(); - } + Widget getDiscountTypeWidget() { + return Column( + children: [ + MandatoryTitleText(hint: AppLocalizations.of(context)!.discount_type), + AppSpaces.verticalSmall, + getDiscountType() + ], + ); } - Future _addDiscount() async { - Map data = { - 'store_id': sharedPrefs.storeId, - 'name': discountCodeController.text, - 'description': descriptionController.text, - 'status': widget.storeDiscount.status, - 'min_amount_limit': minimumAmountController.text, - 'max_discount_limit': maxDiscountController.text, - 'discount_percentage': discountPerValueController.text, - 'discount_type': __typesGroupValue, - 'discount_type_label': selectedDiscountType, - 'limit_of_discount': limitDiscountController.text, - 'discount_start_date': widget.storeDiscount.discountStartDate ?? '', - 'discount_end_date': widget.storeDiscount.discountEndDate ?? '', - 'type': selectedDiscountType == 'Percentage' ? '1' : '2', - 'is_deleted': false, - 'products': widget.storeDiscount.products, - 'categories': widget.storeDiscount.categories, - 'is_always': widget.storeDiscount.isAlways ?? false, - 'is_unlimited': widget.storeDiscount.isUnlimited ?? false, - 'is_min_amount': widget.storeDiscount.isMinAmount ?? false, - 'is_max_discount': widget.storeDiscount.isMaxDiscount ?? false, - 'discountId': widget.storeDiscount.id ?? '' - }; - final response = await viewModel.addDiscount(data); - setState(() { - _isLoading = false; - }); - if (response.success) { + Widget getDiscountFilterWidget() { + return Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.discount_filters), + AppSpaces.verticalMedium, + getRadioProducts(), + ], + ); + } + + getLimitDiscountWidget() { + return Column( + children: [ + Row( + children: [ + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.limit_of_discount), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: CustomCheckBox( + heading: AppLocalizations.of(context)!.unlimited, + value: viewModel.storeDiscount.isUnlimited ?? false, + onChange: (value) { + viewModel.setIsUnLimited(value); + }), + )), + ], + ), + AppSpaces.verticalSmall, + CustomTextFieldForm( + keyboardType: TextInputType.number, + initialValue: + viewModel.storeDiscount.limitOfDiscount?.toString() ?? '', + hintText: AppLocalizations.of(context)!.limit_of_discount, + onChanged: (value) { + viewModel.setDiscountLimit(value); + }, + ), + ], + ); + } + + getDiscountPercentageValueWidget() { + return Column( + children: [ + MandatoryTitleText( + hint: viewModel.selectedDiscountType == 'Percentage' + ? AppLocalizations.of(context)!.discount_percentage + : 'Discount Amount', + ), + AppSpaces.verticalSmall, + CustomTextFieldForm( + hintText: 'Enter Discount ${viewModel.selectedDiscountType}', + keyboardType: TextInputType.number, + initialValue: viewModel.storeDiscount.discountPercentage ?? '', + onChanged: (value) { + viewModel.setDiscountValue(value); + }, + ), + ], + ); + } + + void checkState() { + if (viewModel.crudOperation == CRUDOperationState.add) { Navigator.pop(context, true); - showMessage(response.message); - } else { - showMessage(response.message); } } } diff --git a/lib/application/views/discountModule/views/ViewDiscountVC.dart b/lib/application/views/discountModule/views/ViewDiscountVC.dart index 62af91c..0373b0a 100644 --- a/lib/application/views/discountModule/views/ViewDiscountVC.dart +++ b/lib/application/views/discountModule/views/ViewDiscountVC.dart @@ -1,22 +1,21 @@ import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:wosull/application/model/converters/DataTimeFormat.dart'; import 'package:wosull/application/model/discount/StoreDiscountModel.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/theme/MyFonts.dart'; import 'package:wosull/application/theme/MySeparator.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/helpers/Utils.dart'; +import 'package:wosull/widgets/DialogHeader.dart'; +import 'package:wosull/widgets/HeadingText.dart'; + +class ViewDiscountVC extends StatelessWidget { + bool isPortrait = true; -class ViewDiscountVC extends StatefulWidget { StoreDiscount storeDiscount; - ViewDiscountVC({Key? key, required this.storeDiscount}) : super(key: key); - - @override - State createState() => _ViewDiscountVCState(); -} - -class _ViewDiscountVCState extends State { - bool isPortrait = true; + ViewDiscountVC(this.storeDiscount, {super.key}); @override Widget build(BuildContext context) { @@ -24,7 +23,7 @@ class _ViewDiscountVCState extends State { elevation: 0, backgroundColor: const Color(0xffffffff), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(15.0), + borderRadius: BorderRadius.circular(8.0), ), child: OrientationBuilder(builder: (c, orientation) { isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; @@ -39,52 +38,19 @@ class _ViewDiscountVCState extends State { crossAxisAlignment: CrossAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end, children: [ - Row( - mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.max, - children: [ - Expanded( - child: Padding( - padding: const EdgeInsets.only(left: 16), - child: Text( - 'Discount Code ', - style: MyColors.textStylePopUpHeading(), - ), - )), - Align( - alignment: Alignment.topRight, - child: IconButton( - onPressed: () { - Navigator.of(context).pop(); - }, - icon: const Icon(Icons.close)), - ), - ], - ), - Container( - height: 2, - color: MyColors.fillColorGray, - ), - const SizedBox( - height: 16, + DialogHeader( + title: 'Discount Code - ${storeDiscount.name}', ), + AppSpaces.verticalLarge, Row( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.end, children: [ - const Text( - 'status', - style: TextStyle( - fontFamily: MyFonts.Medium, - fontSize: MyFonts.normalButton, - color: MyColors.textColorPopUp), - ), - const SizedBox( - width: 6, - ), + HeadingText('Status'), + AppSpaces.horizontalMedium, Container( height: 32, - padding: const EdgeInsets.all(10.0), + padding: const EdgeInsets.all(8.0), margin: const EdgeInsets.only( right: 16, ), @@ -92,19 +58,18 @@ class _ViewDiscountVCState extends State { color: MyColors.greenColor, borderRadius: BorderRadius.all(Radius.circular(6.0))), - child: Text( - widget.storeDiscount.status!, - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.w500, - fontSize: MyFonts.normal, - color: MyColors.white), + child: Center( + child: Text( + storeDiscount.status!, + style: TextStyle( + fontFamily: MyFonts.Medium, + fontSize: MyFonts.normal, + color: MyColors.white), + ), )), ], ), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, Container( margin: const EdgeInsets.all(16), child: isPortrait @@ -118,34 +83,20 @@ class _ViewDiscountVCState extends State { child: Column( children: [ getDiscountCode(), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, getDiscountType(), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, getDiscountAppliedOn(), - const SizedBox( - height: 8, - ), - getDiscountCreatedOn(), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, + getDiscountCreatedOn(context), + AppSpaces.verticalMedium, getDiscountName(), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, getDiscountPercentage(), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, getDiscountLimit(), - const SizedBox( - height: 8, - ), - getDiscountUpdatedOn() + AppSpaces.verticalMedium, + getDiscountUpdatedOn(context) ], ), ) @@ -164,24 +115,16 @@ class _ViewDiscountVCState extends State { child: Column( children: [ getDiscountCode(), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, getDiscountType(), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, getDiscountAppliedOn(), - const SizedBox( - height: 8, - ), - getDiscountCreatedOn() + AppSpaces.verticalMedium, + getDiscountCreatedOn(context) ], ), )), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, Expanded( child: Container( padding: const EdgeInsets.all(16), @@ -193,18 +136,12 @@ class _ViewDiscountVCState extends State { child: Column( children: [ getDiscountName(), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, getDiscountPercentage(), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, getDiscountLimit(), - const SizedBox( - height: 8, - ), - getDiscountUpdatedOn() + AppSpaces.verticalMedium, + getDiscountUpdatedOn(context) ], ), )), @@ -222,28 +159,18 @@ class _ViewDiscountVCState extends State { Widget getDiscountType() { return Row( children: [ - const Text( + Text( 'Discount Type', - style: TextStyle( - fontFamily: MyFonts.Medium, - fontSize: MyFonts.normalButton, - color: MyColors.textColorPopUp), - ), - const SizedBox( - width: 8, + style: ThemeText.labelStyleTextField, ), + AppSpaces.horizontalMedium, const Expanded( child: MySeparator(color: Colors.grey), ), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, Text( - widget.storeDiscount.discountTypeLabel!, - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normalButton, - color: MyColors.textColorGray), + storeDiscount.discountTypeLabel!, + style: ThemeText.textStyleViewValue, ) ], ); @@ -252,28 +179,18 @@ class _ViewDiscountVCState extends State { Widget getDiscountCode() { return Row( children: [ - const Text( + Text( 'Discount Code', - style: TextStyle( - fontFamily: MyFonts.Medium, - fontSize: MyFonts.normalButton, - color: MyColors.textColorPopUp), - ), - const SizedBox( - width: 8, + style: ThemeText.labelStyleTextField, ), + AppSpaces.horizontalMedium, const Expanded( child: MySeparator(color: Colors.grey), ), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, Text( - widget.storeDiscount.name!, - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normalButton, - color: MyColors.textColorGray), + storeDiscount.name!, + style: ThemeText.textStyleViewValue, ) ], ); @@ -282,58 +199,38 @@ class _ViewDiscountVCState extends State { Widget getDiscountAppliedOn() { return Row( children: [ - const Text( + Text( 'Discount Applied On', - style: TextStyle( - fontFamily: MyFonts.Medium, - fontSize: MyFonts.normalButton, - color: MyColors.textColorPopUp), - ), - const SizedBox( - width: 8, + style: ThemeText.labelStyleTextField, ), + AppSpaces.horizontalMedium, const Expanded( child: MySeparator(color: Colors.grey), ), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, Text( - widget.storeDiscount.name!, - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normalButton, - color: MyColors.textColorGray), + storeDiscount.name!, + style: ThemeText.textStyleViewValue, ) ], ); } - Widget getDiscountCreatedOn() { + Widget getDiscountCreatedOn(BuildContext context) { return Row( children: [ Text( - AppLocalizations.of(context)!.created_on, - style: const TextStyle( - fontFamily: MyFonts.Medium, - fontSize: MyFonts.normalButton, - color: MyColors.textColorPopUp), - ), - const SizedBox( - width: 8, + lang(context).created_on, + style: ThemeText.labelStyleTextField, ), + AppSpaces.horizontalMedium, const Expanded( child: MySeparator(color: Colors.grey), ), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, Text( - DataTimeFormat.getFormatDate(widget.storeDiscount.createdAt!), - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normalButton, - color: MyColors.textColorGray), + DataTimeFormat.getFormatDate(storeDiscount.createdAt!), + style: ThemeText.textStyleViewValue, ) ], ); @@ -342,28 +239,18 @@ class _ViewDiscountVCState extends State { Widget getDiscountName() { return Row( children: [ - const Text( + Text( 'Name', - style: TextStyle( - fontFamily: MyFonts.Medium, - fontSize: MyFonts.normalButton, - color: MyColors.textColorPopUp), - ), - const SizedBox( - width: 8, + style: ThemeText.labelStyleTextField, ), + AppSpaces.horizontalMedium, const Expanded( child: MySeparator(color: Colors.grey), ), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, Text( - widget.storeDiscount.name!, - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normalButton, - color: MyColors.textColorGray), + storeDiscount.name!, + style: ThemeText.textStyleViewValue, ) ], ); @@ -372,28 +259,18 @@ class _ViewDiscountVCState extends State { Widget getDiscountPercentage() { return Row( children: [ - const Text( + Text( 'Discount Percentage', - style: TextStyle( - fontFamily: MyFonts.Medium, - fontSize: MyFonts.normalButton, - color: MyColors.textColorPopUp), - ), - const SizedBox( - width: 8, + style: ThemeText.labelStyleTextField, ), + AppSpaces.horizontalMedium, const Expanded( child: MySeparator(color: Colors.grey), ), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, Text( - widget.storeDiscount.discountPercentage!, - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normalButton, - color: MyColors.textColorGray), + storeDiscount.discountPercentage!, + style: ThemeText.textStyleViewValue, ) ], ); @@ -402,58 +279,38 @@ class _ViewDiscountVCState extends State { Widget getDiscountLimit() { return Row( children: [ - const Text( + Text( 'Limit on Discount', - style: TextStyle( - fontFamily: MyFonts.Medium, - fontSize: MyFonts.normalButton, - color: MyColors.textColorPopUp), - ), - const SizedBox( - width: 8, + style: ThemeText.labelStyleTextField, ), + AppSpaces.horizontalMedium, const Expanded( child: MySeparator(color: Colors.grey), ), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, Text( - widget.storeDiscount.limitOfDiscount!.toString(), - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normalButton, - color: MyColors.textColorGray), + storeDiscount.limitOfDiscount!.toString(), + style: ThemeText.textStyleViewValue, ) ], ); } - Widget getDiscountUpdatedOn() { + Widget getDiscountUpdatedOn(BuildContext context) { return Row( children: [ Text( - AppLocalizations.of(context)!.updated_on, - style: const TextStyle( - fontFamily: MyFonts.Medium, - fontSize: MyFonts.normalButton, - color: MyColors.textColorPopUp), - ), - const SizedBox( - width: 8, + lang(context).updated_on, + style: ThemeText.labelStyleTextField, ), + AppSpaces.horizontalMedium, const Expanded( child: MySeparator(color: Colors.grey), ), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, Text( - DataTimeFormat.getFormatDate(widget.storeDiscount.updatedAt!), - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normalButton, - color: MyColors.textColorGray), + DataTimeFormat.getFormatDate(storeDiscount.updatedAt!), + style: ThemeText.textStyleViewValue, ) ], ); diff --git a/lib/application/views/discountModule/widgets/DiscountFilterItemView.dart b/lib/application/views/discountModule/widgets/DiscountFilterItemView.dart new file mode 100644 index 0000000..cbff590 --- /dev/null +++ b/lib/application/views/discountModule/widgets/DiscountFilterItemView.dart @@ -0,0 +1,53 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/model/inventory/category/ItemCategory.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/theme/MyFonts.dart'; + +class DiscountFilterItemView extends StatelessWidget { + List products; + List categories; + ItemCategory filteredItem; + + DiscountFilterItemView( + {super.key, + required this.products, + required this.categories, + required this.filteredItem}); + + @override + Widget build(BuildContext context) { + return Container( + margin: const EdgeInsets.all(4), + padding: const EdgeInsets.all(4), + decoration: BoxDecoration( + color: products.contains(filteredItem.id) || + categories.contains(filteredItem.id) + ? MyColors.blueThemeColor + : MyColors.fillColor2, + border: Border.all(width: 1, color: MyColors.fillColor3), + borderRadius: const BorderRadius.all(Radius.circular(8))), + child: Row( + children: [ + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + filteredItem.name, + maxLines: 1, + style: TextStyle( + fontSize: 11, + fontFamily: MyFonts.DMREGULAR, + color: products.contains(filteredItem.id) || + categories.contains(filteredItem.id) + ? MyColors.white + : MyColors.textColorBlack, + fontWeight: FontWeight.bold), + ), + ], + )) + ], + ), + ); + } +} diff --git a/lib/application/views/discountModule/widgets/DiscountListView.dart b/lib/application/views/discountModule/widgets/DiscountListView.dart new file mode 100644 index 0000000..5a616a4 --- /dev/null +++ b/lib/application/views/discountModule/widgets/DiscountListView.dart @@ -0,0 +1,283 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/application/model/discount/StoreDiscountModel.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/Utils.dart'; +import 'package:wosull/widgets/ActionPopUpContainer.dart'; +import 'package:wosull/widgets/CustomPopuoMenuButton.dart'; +import 'package:wosull/widgets/CustomSwitch.dart'; +import 'package:wosull/widgets/EmptyDataWidget.dart'; +import 'package:wosull/widgets/HeadingText.dart'; +import 'package:wosull/widgets/ListHeadingContainer.dart'; +import 'package:wosull/widgets/ValueText.dart'; + +class DiscountListView extends StatelessWidget { + List data; + bool isPortrait = false; + final void Function(StoreDiscount discount, bool status) onUpdate; + final void Function(StoreDiscount discount) onDelete; + final void Function(StoreDiscount discount) onView; + final void Function(StoreDiscount discount) onEdit; + + DiscountListView( + {super.key, + required this.data, + required this.isPortrait, + required this.onUpdate, + required this.onDelete, + required this.onView, + required this.onEdit}); + + @override + Widget build(BuildContext context) { + return data.isEmpty + ? const EmptyDataWidget() + : Column( + children: [ + isPortrait + ? Container() + : ListHeadingContainer( + child: Row( + children: [ + Expanded( + child: Text( + lang(context).name, + softWrap: false, + style: MyColors.textStyleHeading(), + )), + Expanded( + child: Text( + lang(context).discount_value, + softWrap: false, + style: MyColors.textStyleHeading(), + )), + Expanded( + flex: 1, + child: Text( + lang(context).minimum_amount_limit, + maxLines: 1, + softWrap: false, + style: MyColors.textStyleHeading(), + )), + Expanded( + child: Align( + alignment: Alignment.center, + child: Text( + lang(context).status, + softWrap: false, + style: MyColors.textStyleHeading(), + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: + HeadingText(lang(context).created_on))), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: + HeadingText(lang(context).updated_on))), + Expanded( + child: Padding( + padding: const EdgeInsets.only(right: 16), + child: Align( + alignment: Alignment.centerRight, + child: HeadingText(lang(context).action), + ), + )), + ], + ), + ), + ListView.builder( + physics: const NeverScrollableScrollPhysics(), + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, + shrinkWrap: true, + itemBuilder: (c, position) { + final discount = data[position]; + if (isPortrait) { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + elevation: 2, + color: MyColors.white, + child: Container( + padding: const EdgeInsets.fromLTRB(8, 0, 0, 8), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + child: Container( + padding: const EdgeInsets.only(top: 16), + child: Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + HeadingText(lang(context).name), + AppSpaces.verticalMedium, + HeadingText(lang(context).discount_value), + AppSpaces.verticalMedium, + HeadingText( + lang(context).minimum_amount_limit), + AppSpaces.verticalMedium, + HeadingText(lang(context).status), + AppSpaces.verticalMedium, + HeadingText(lang(context).created_on), + AppSpaces.verticalMedium, + HeadingText(lang(context).updated_on), + ], + )), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + ValueText(discount.name ?? ''), + AppSpaces.verticalMedium, + ValueText(discount.discountType!), + AppSpaces.verticalMedium, + ValueText( + discount.minAmountLimit!.toString()), + AppSpaces.verticalMedium, + Row( + mainAxisAlignment: + MainAxisAlignment.end, + crossAxisAlignment: + CrossAxisAlignment.end, + children: [ + CustomSwitch( + value: discount.getStatus(), + onToggle: (value) { + onUpdate(discount, value); + // setState(() { + // if (value) { + // discount.status = "Active"; + // } else { + // discount.status = "Inactive"; + // } + // }); + // _updateStatus( + // discount.id!, value); + }, + ) + ], + ), + AppSpaces.verticalMedium, + ValueText(DataTimeFormat.getFormatDate( + discount.createdAt!)), + AppSpaces.verticalMedium, + ValueText(DataTimeFormat.getFormatDate( + discount.updatedAt!)), + ], + )), + ], + ), + )), + getPopUpMenuButton(context, discount), + ], + ), + ), + ); + } else { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: ListHeadingContainer( + child: Row( + children: [ + Expanded(child: ValueText(discount.name!)), + Expanded( + child: ValueText(discount.discountType ?? '')), + Expanded( + flex: 1, + child: ValueText( + discount.minAmountLimit!.toString() ?? '')), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: CustomSwitch( + value: discount.getStatus(), + onToggle: (value) { + onUpdate(discount, value); + }, + ), + )), + Expanded( + child: ValueText(DataTimeFormat.getFormatDate( + discount.createdAt!))), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: ValueText( + DataTimeFormat.getFormatDate( + discount.updatedAt!)))), + Expanded( + flex: 1, + child: Padding( + padding: const EdgeInsets.all(4), + child: Align( + alignment: Alignment.centerRight, + child: ActionPopUpContainer( + child: + getPopUpMenuButton(context, discount), + ), + ), + )) + ], + ), + ), + ); + } + }, + itemCount: data.length, + ), + ], + ); + } + + void actionPopUpItemSelected( + String value, StoreDiscount storeDiscount) async { + if (value == 'edit') { + onEdit(storeDiscount); + } else if (value == 'delete') { + onDelete(storeDiscount); + } else { + onView(storeDiscount); + } + } + + Widget getPopUpMenuButton(BuildContext context, StoreDiscount discount) { + return CustomPopupMenuButton( + onSelected: (String value) => actionPopUpItemSelected(value, discount), + items: [ + PopupMenuItem( + value: 'edit', + child: ValueText( + lang(context).edit, + ), + ), + PopupMenuItem( + value: 'view', + child: ValueText( + lang(context).view, + ), + ), + PopupMenuItem( + value: 'delete', + child: ValueText( + lang(context).delete, + ), + ) + ], + ); + } +} diff --git a/lib/application/views/dowloadReports/viewModel/DownloadBestSellerReportViewModel.dart b/lib/application/views/dowloadReports/viewModel/DownloadBestSellerReportViewModel.dart new file mode 100644 index 0000000..9b8441a --- /dev/null +++ b/lib/application/views/dowloadReports/viewModel/DownloadBestSellerReportViewModel.dart @@ -0,0 +1,144 @@ +import 'dart:io'; + +import 'package:csv/csv.dart'; +import 'package:flutter/material.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:permission_handler/permission_handler.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/application/model/reports/TopOrderItemsModel.dart'; +import 'package:wosull/application/views/settings/repo/ReportsRepository.dart'; +import 'package:wosull/helpers/DatePicker.dart'; + +class DownloadBestSellerReportViewModel with ChangeNotifier { + List bestSellers = []; + var repository = ReportsRepository(); + + var stareDate = 'dd/mm/yyyy'; + var endDate = 'dd/mm/yyyy'; + + download() async { + Map data = { + 'start_date': stareDate, + 'end_date': endDate, + }; + + await repository.fetchBestSupplier(data).then((result) async { + bestSellers.clear(); + + if (result.isNotEmpty) { + bestSellers.addAll(result); + print(result); + if (Platform.isIOS || Platform.isAndroid) { + bool status = await Permission.storage.isGranted; + + if (!status) await Permission.storage.request(); + } + + List> list = [[]]; + list.add(bestSellers); + + String csvData = const ListToCsvConverter().convert(list); + String savePath; + if (Platform.isIOS) { + final directory = await getApplicationDocumentsDirectory(); + savePath = '${directory.path}/bestSellerReport${DateTime.now()}'; + } else if (Platform.isAndroid) { + savePath = + '/storage/emulated/0/Download/bestSellerReport${DateTime.now()}'; + } else { + // Handle other platforms if necessary + return; + } + print(savePath); + final File file = File(savePath); + file.writeAsStringSync(csvData); + print('yes'); + // // await file.writeAsString(csvData); + // String? path = await FileSaver.instance.saveFile( + // name: 'bestSellerReport${DateTime.now()}', + // filePath: savePath, + // file: file, + // ext: 'csv', + // + // ///extController.text, + // mimeType: MimeType.csv); + // print(path); + } + }).onError((error, stackTrace) { + print(stackTrace.toString()); + }); + } + + Future saveVideo(String url, String fileName) async { + Directory? directory; + try { + if (Platform.isAndroid) { + if (await _requestPermission(Permission.storage)) { + directory = await getExternalStorageDirectory(); + String newPath = ""; + print(directory); + List paths = directory!.path.split("/"); + for (int x = 1; x < paths.length; x++) { + String folder = paths[x]; + if (folder != "Android") { + newPath += "/$folder"; + } else { + break; + } + } + newPath = "$newPath/Wosul"; + directory = Directory(newPath); + } else { + return false; + } + } else { + if (await _requestPermission(Permission.photos)) { + directory = await getTemporaryDirectory(); + } else { + return false; + } + } + File saveFile = File("${directory.path}/$fileName"); + if (!await directory.exists()) { + await directory.create(recursive: true); + } + if (await directory.exists()) { + if (Platform.isIOS) {} + return true; + } + return false; + } catch (e) { + print(e); + return false; + } + } + + Future _requestPermission(Permission permission) async { + if (await permission.isGranted) { + return true; + } else { + var result = await permission.request(); + if (result == PermissionStatus.granted) { + return true; + } + } + return false; + } + + Future presentDatePicker(BuildContext context, bool isStart) async { + // showDatePicker is a pre-made funtion of Flutter + + final pickedDate = await DatePicker.presentDatePicker(context, isStart); + + if (pickedDate == null) { + return; + } + if (isStart) { + stareDate = DataTimeFormat.formatDateFromPicket(pickedDate); + } else { + endDate = DataTimeFormat.formatDateFromPicket(pickedDate); + } + + notifyListeners(); + } +} diff --git a/lib/application/views/dowloadReports/viewModel/DownloadCategoryReportViewModel.dart b/lib/application/views/dowloadReports/viewModel/DownloadCategoryReportViewModel.dart new file mode 100644 index 0000000..273cdbc --- /dev/null +++ b/lib/application/views/dowloadReports/viewModel/DownloadCategoryReportViewModel.dart @@ -0,0 +1,25 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/helpers/DatePicker.dart'; + +class DownloadCategoryReportViewModel with ChangeNotifier { + var stareDate = 'dd/mm/yyyy'; + var endDate = 'dd/mm/yyyy'; + + Future presentDatePicker(BuildContext context, bool isStart) async { + // showDatePicker is a pre-made funtion of Flutter + + final pickedDate = await DatePicker.presentDatePicker(context, isStart); + + if (pickedDate == null) { + return; + } + if (isStart) { + stareDate = DataTimeFormat.formatDateFromPicket(pickedDate); + } else { + endDate = DataTimeFormat.formatDateFromPicket(pickedDate); + } + + notifyListeners(); + } +} diff --git a/lib/application/views/dowloadReports/viewModel/DownloadPOSCompleteReportViewModel.dart b/lib/application/views/dowloadReports/viewModel/DownloadPOSCompleteReportViewModel.dart new file mode 100644 index 0000000..28a833f --- /dev/null +++ b/lib/application/views/dowloadReports/viewModel/DownloadPOSCompleteReportViewModel.dart @@ -0,0 +1,3 @@ +import 'package:flutter/material.dart'; + +class DownloadPOSCompleteReportViewModel with ChangeNotifier {} diff --git a/lib/application/views/dowloadReports/viewModel/DownloadPOSReturnDamageViewModel.dart b/lib/application/views/dowloadReports/viewModel/DownloadPOSReturnDamageViewModel.dart new file mode 100644 index 0000000..1d26428 --- /dev/null +++ b/lib/application/views/dowloadReports/viewModel/DownloadPOSReturnDamageViewModel.dart @@ -0,0 +1,25 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/helpers/DatePicker.dart'; + +class DownloadPOSReturnDamageViewModel with ChangeNotifier { + var stareDate = 'dd/mm/yyyy'; + var endDate = 'dd/mm/yyyy'; + + Future presentDatePicker(BuildContext context, bool isStart) async { + // showDatePicker is a pre-made funtion of Flutter + + final pickedDate = await DatePicker.presentDatePicker(context, isStart); + + if (pickedDate == null) { + return; + } + if (isStart) { + stareDate = DataTimeFormat.formatDateFromPicket(pickedDate); + } else { + endDate = DataTimeFormat.formatDateFromPicket(pickedDate); + } + + notifyListeners(); + } +} diff --git a/lib/application/views/dowloadReports/viewModel/DownloadProductViewModel.dart b/lib/application/views/dowloadReports/viewModel/DownloadProductViewModel.dart new file mode 100644 index 0000000..1fe850a --- /dev/null +++ b/lib/application/views/dowloadReports/viewModel/DownloadProductViewModel.dart @@ -0,0 +1,25 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/helpers/DatePicker.dart'; + +class DownloadProductViewModel with ChangeNotifier { + var stareDate = 'dd/mm/yyyy'; + var endDate = 'dd/mm/yyyy'; + + Future presentDatePicker(BuildContext context, bool isStart) async { + // showDatePicker is a pre-made funtion of Flutter + + final pickedDate = await DatePicker.presentDatePicker(context, isStart); + + if (pickedDate == null) { + return; + } + if (isStart) { + stareDate = DataTimeFormat.formatDateFromPicket(pickedDate); + } else { + endDate = DataTimeFormat.formatDateFromPicket(pickedDate); + } + + notifyListeners(); + } +} diff --git a/lib/application/views/dowloadReports/views/DownloadReportMainVC.dart b/lib/application/views/dowloadReports/views/DownloadReportMainVC.dart new file mode 100644 index 0000000..f46578e --- /dev/null +++ b/lib/application/views/dowloadReports/views/DownloadReportMainVC.dart @@ -0,0 +1,56 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:wosull/application/interfaces/DrawerWidgetSelect.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/views/dowloadReports/views/DownloadReports.dart'; +import 'package:wosull/widgets/BackTabBarContainer.dart'; + +class DownloadReportsMainVC extends StatefulWidget { + final DrawerWidgetSelect delegateDrawer; + + const DownloadReportsMainVC({Key? key, required this.delegateDrawer}) + : super(key: key); + + @override + State createState() => _DownloadReportsMainVCState(); +} + +class _DownloadReportsMainVCState extends State { + @override + Widget build(BuildContext context) { + return DefaultTabController( + length: 1, + child: Scaffold( + body: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + mainAxisSize: MainAxisSize.min, + children: [ + Container( + margin: const EdgeInsets.only(left: 6.0, right: 6.0), + height: 0.5, + width: double.infinity, + color: MyColors.fillColorGray2, + ), + BackTabBarContainer( + onPressed: () { + widget.delegateDrawer.goToHome(); + }, + tabs: [ + Tab( + text: AppLocalizations.of(context)!.reports, + ), + ], + ), + const Expanded( + child: TabBarView( + children: [ + DownloadReports(), + ], + )) + ], + ), + ), + ); + } +} diff --git a/lib/application/views/dowloadReports/views/DownloadReports.dart b/lib/application/views/dowloadReports/views/DownloadReports.dart new file mode 100644 index 0000000..4633de5 --- /dev/null +++ b/lib/application/views/dowloadReports/views/DownloadReports.dart @@ -0,0 +1,96 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/views/dowloadReports/widgets/BestSellerReportView.dart'; +import 'package:wosull/application/views/dowloadReports/widgets/DownloadCategoriesView.dart'; +import 'package:wosull/application/views/dowloadReports/widgets/DownloadDiscountView.dart'; +import 'package:wosull/application/views/dowloadReports/widgets/DownloadInventoryReport.dart'; +import 'package:wosull/application/views/dowloadReports/widgets/DownloadInvoiceView.dart'; +import 'package:wosull/application/views/dowloadReports/widgets/DownloadOrderReportView.dart'; +import 'package:wosull/application/views/dowloadReports/widgets/DownloadPOSCompleteView.dart'; +import 'package:wosull/application/views/dowloadReports/widgets/DownloadPOSReturnAndDamage.dart'; +import 'package:wosull/application/views/dowloadReports/widgets/DownloadProductsView.dart'; +import 'package:wosull/application/views/dowloadReports/widgets/DownloadQuotationView.dart'; +import 'package:wosull/application/views/dowloadReports/widgets/DownloadStockStatusView.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeText.dart'; + +class DownloadReports extends StatefulWidget { + const DownloadReports({super.key}); + + @override + State createState() => _DownloadReportsState(); +} + +class _DownloadReportsState extends State { + bool isPortrait = false; + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: MyColors.fillColor, + resizeToAvoidBottomInset: true, + body: OrientationBuilder(builder: (c, orientation) { + isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; + + return SingleChildScrollView( + child: Container( + padding: const EdgeInsets.all(8), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Download Reports', + style: ThemeText.textStylePageHeading, + ), + AppSpaces.verticalLarge, + BestSellerReportView( + isPortrait: isPortrait, + ), + AppSpaces.verticalLarge, + DownloadPOSCompleteView( + isPortrait: isPortrait, + ), + AppSpaces.verticalLarge, + DownloadPOSReturnAndDamage( + isPortrait: isPortrait, + ), + AppSpaces.verticalLarge, + DownloadCategoriesView( + isPortrait: isPortrait, + ), + AppSpaces.verticalLarge, + DownloadProductsView( + isPortrait: isPortrait, + ), + AppSpaces.verticalLarge, + DownloadInvoiceView( + isPortrait: isPortrait, + ), + AppSpaces.verticalLarge, + DownloadDiscountView( + isPortrait: isPortrait, + ), + AppSpaces.verticalLarge, + DownloadQuotationView( + isPortrait: isPortrait, + ), + AppSpaces.verticalLarge, + DownloadOrderReportView( + isPortrait: isPortrait, + ), + AppSpaces.verticalLarge, + DownloadStockStatusView( + isPortrait: isPortrait, + ), + AppSpaces.verticalLarge, + DownloadInventoryReport( + isPortrait: isPortrait, + ) + ], + ), + ), + ); + }), + ); + } +} diff --git a/lib/application/views/dowloadReports/widgets/BestSellerReportView.dart b/lib/application/views/dowloadReports/widgets/BestSellerReportView.dart new file mode 100644 index 0000000..dd080ca --- /dev/null +++ b/lib/application/views/dowloadReports/widgets/BestSellerReportView.dart @@ -0,0 +1,110 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/views/dowloadReports/viewModel/DownloadBestSellerReportViewModel.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/widgets/CustomOptionalTitle.dart'; +import 'package:wosull/widgets/CustomTextButtonIcon.dart'; +import 'package:wosull/widgets/IconButton.dart'; + +class BestSellerReportView extends StatelessWidget { + var viewModel = DownloadBestSellerReportViewModel(); + bool isPortrait = false; + + BestSellerReportView({super.key, required this.isPortrait}); + + @override + Widget build(BuildContext context) { + viewModel = context.watch(); + return Card( + elevation: 5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: Padding( + padding: const EdgeInsets.all(15), + child: Column( + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Text( + 'Best Sellers', + style: ThemeText.textStyleHeadingCart, + ), + SizedBox( + width: 130, + child: CustomIconButton( + textColor: MyColors.blueThemeColor, + backgroundColor: MyColors.backColorBlue50, + heading: 'Download', + onPressed: () { + viewModel.download(); + }, + iconColor: MyColors.blueThemeColor, + icon: Icons.download), + ) + ], + ), + isPortrait + ? Container() + : Row( + children: [ + Flexible(child: getFromDateWidget(context)), + AppSpaces.horizontalMedium, + Flexible(child: getToDateWidget(context)) + ], + ), + isPortrait + ? Column( + children: [ + getFromDateWidget(context), + AppSpaces.verticalMedium, + getToDateWidget(context) + ], + ) + : Container() + ], + ), + ), + ); + } + + getFromDateWidget(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle(hint: 'From Date'), + AppSpaces.verticalSmall, + CustomTextButtonIcon( + backgroundColor: MyColors.backFillColor, + icon: Icons.calendar_month, + heading: viewModel.stareDate, + onPressed: () { + viewModel.presentDatePicker(context, true); + }, + ) + ], + ); + } + + getToDateWidget(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle(hint: 'To Date'), + AppSpaces.verticalSmall, + CustomTextButtonIcon( + backgroundColor: MyColors.backFillColor, + icon: Icons.calendar_month, + heading: viewModel.endDate, + onPressed: () { + viewModel.presentDatePicker(context, false); + }, + ) + ], + ); + } +} diff --git a/lib/application/views/dowloadReports/widgets/DownloadCategoriesView.dart b/lib/application/views/dowloadReports/widgets/DownloadCategoriesView.dart new file mode 100644 index 0000000..594a0de --- /dev/null +++ b/lib/application/views/dowloadReports/widgets/DownloadCategoriesView.dart @@ -0,0 +1,143 @@ +import 'package:dropdown_search/dropdown_search.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/settings/viewModels/POSCompleteViewModel.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeDropDown.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/widgets/CustomOptionalTitle.dart'; +import 'package:wosull/widgets/CustomTextButtonIcon.dart'; +import 'package:wosull/widgets/DropdownItemBuilder.dart'; +import 'package:wosull/widgets/IconButton.dart'; + +class DownloadCategoriesView extends StatelessWidget { + var viewModel = POSCompleteViewModel(); + bool isPortrait = false; + + DownloadCategoriesView({super.key, required this.isPortrait}); + + @override + Widget build(BuildContext context) { + viewModel = context.watch(); + return Card( + elevation: 5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: Padding( + padding: const EdgeInsets.all(15), + child: Column( + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Text( + 'Categories', + style: ThemeText.textStyleHeadingCart, + ), + SizedBox( + width: 130, + child: CustomIconButton( + textColor: MyColors.blueThemeColor, + backgroundColor: MyColors.backColorBlue50, + heading: 'Download', + onPressed: () {}, + iconColor: MyColors.blueThemeColor, + icon: Icons.download), + ) + ], + ), + isPortrait + ? Container() + : Row( + children: [ + Flexible(child: getFromDateWidget(context)), + AppSpaces.horizontalMedium, + Flexible(child: getToDateWidget(context)), + AppSpaces.horizontalMedium, + Flexible(child: getStatusWidget()) + ], + ), + isPortrait + ? Column( + children: [ + getFromDateWidget(context), + AppSpaces.horizontalMedium, + getToDateWidget(context), + AppSpaces.horizontalMedium, + getStatusWidget() + ], + ) + : Container() + ], + ), + ), + ); + } + + getFromDateWidget(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle(hint: 'From Date'), + AppSpaces.verticalSmall, + CustomTextButtonIcon( + backgroundColor: MyColors.backFillColor, + icon: Icons.calendar_month, + heading: viewModel.stareDate, + onPressed: () { + viewModel.presentDatePicker(context, true); + }, + ) + ], + ); + } + + getToDateWidget(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle(hint: 'To Date'), + AppSpaces.verticalSmall, + CustomTextButtonIcon( + backgroundColor: MyColors.backFillColor, + icon: Icons.calendar_month, + heading: viewModel.endDate, + onPressed: () { + viewModel.presentDatePicker(context, false); + }, + ) + ], + ); + } + + getStatusWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle(hint: 'Status'), + AppSpaces.verticalSmall, + DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: Constants.activeStatus, + itemAsString: (String u) => u, + onChanged: (category) {}, + dropdownDecoratorProps: MyColors.dropDownStyle( + hint: 'Choose Status', + ), + ) + ], + ); + } +} diff --git a/lib/application/views/dowloadReports/widgets/DownloadDiscountView.dart b/lib/application/views/dowloadReports/widgets/DownloadDiscountView.dart new file mode 100644 index 0000000..c6e8a90 --- /dev/null +++ b/lib/application/views/dowloadReports/widgets/DownloadDiscountView.dart @@ -0,0 +1,139 @@ +import 'package:dropdown_search/dropdown_search.dart'; +import 'package:flutter/material.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeDropDown.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/widgets/CustomOptionalTitle.dart'; +import 'package:wosull/widgets/CustomTextButtonIcon.dart'; +import 'package:wosull/widgets/DropdownItemBuilder.dart'; +import 'package:wosull/widgets/IconButton.dart'; + +class DownloadDiscountView extends StatelessWidget { + bool isPortrait = false; + + DownloadDiscountView({super.key, required this.isPortrait}); + + @override + Widget build(BuildContext context) { + return Card( + elevation: 5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: Padding( + padding: const EdgeInsets.all(15), + child: isPortrait + ? Column( + children: [ + getHeaderWidget(), + AppSpaces.verticalLarge, + getFromDateWidget(context), + AppSpaces.verticalMedium, + getToDateWidget(), + AppSpaces.verticalMedium, + getStatusWidget() + ], + ) + : Column( + children: [ + getHeaderWidget(), + AppSpaces.verticalLarge, + Row( + children: [ + Flexible(child: getFromDateWidget(context)), + AppSpaces.horizontalMedium, + Flexible(child: getToDateWidget()), + AppSpaces.horizontalMedium, + Flexible(child: getStatusWidget()) + ], + ) + ], + ), + ), + ); + } + + getFromDateWidget(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle(hint: 'From Date'), + AppSpaces.verticalSmall, + CustomTextButtonIcon( + backgroundColor: MyColors.backFillColor, + icon: Icons.calendar_month, + heading: 'dd/mm/yyyy', + onPressed: () {}, + ) + ], + ); + } + + getToDateWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle(hint: 'To Date'), + AppSpaces.verticalSmall, + CustomTextButtonIcon( + backgroundColor: MyColors.backFillColor, + icon: Icons.calendar_month, + heading: 'dd/mm/yyyy', + onPressed: () {}, + ) + ], + ); + } + + getStatusWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle(hint: 'Status'), + AppSpaces.verticalSmall, + DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: Constants.activeStatus, + itemAsString: (String u) => u, + onChanged: (category) {}, + dropdownDecoratorProps: MyColors.dropDownStyle( + hint: 'Choose Status', + ), + ) + ], + ); + } + + getHeaderWidget() { + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Text( + 'Discounts', + style: ThemeText.textStyleHeadingCart, + ), + SizedBox( + width: 130, + child: CustomIconButton( + textColor: MyColors.blueThemeColor, + backgroundColor: MyColors.backColorBlue50, + heading: 'Download', + onPressed: () {}, + iconColor: MyColors.blueThemeColor, + icon: Icons.download), + ) + ], + ); + } +} diff --git a/lib/application/views/dowloadReports/widgets/DownloadInventoryReport.dart b/lib/application/views/dowloadReports/widgets/DownloadInventoryReport.dart new file mode 100644 index 0000000..0f9593d --- /dev/null +++ b/lib/application/views/dowloadReports/widgets/DownloadInventoryReport.dart @@ -0,0 +1,139 @@ +import 'package:dropdown_search/dropdown_search.dart'; +import 'package:flutter/material.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeDropDown.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/widgets/CustomOptionalTitle.dart'; +import 'package:wosull/widgets/CustomTextButtonIcon.dart'; +import 'package:wosull/widgets/DropdownItemBuilder.dart'; +import 'package:wosull/widgets/IconButton.dart'; + +class DownloadInventoryReport extends StatelessWidget { + bool isPortrait = false; + + DownloadInventoryReport({super.key, required this.isPortrait}); + + @override + Widget build(BuildContext context) { + return Card( + elevation: 5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: Padding( + padding: const EdgeInsets.all(15), + child: isPortrait + ? Column( + children: [ + getHeaderWidget(), + AppSpaces.verticalLarge, + getFromDateWidget(context), + AppSpaces.verticalMedium, + getToDateWidget(), + AppSpaces.verticalMedium, + getStatusWidget() + ], + ) + : Column( + children: [ + getHeaderWidget(), + AppSpaces.verticalLarge, + Row( + children: [ + Flexible(child: getFromDateWidget(context)), + AppSpaces.horizontalMedium, + Flexible(child: getToDateWidget()), + AppSpaces.horizontalMedium, + Flexible(child: getStatusWidget()) + ], + ) + ], + ), + ), + ); + } + + getFromDateWidget(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle(hint: 'From Date'), + AppSpaces.verticalSmall, + CustomTextButtonIcon( + backgroundColor: MyColors.backFillColor, + icon: Icons.calendar_month, + heading: 'dd/mm/yyyy', + onPressed: () {}, + ) + ], + ); + } + + getToDateWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle(hint: 'To Date'), + AppSpaces.verticalSmall, + CustomTextButtonIcon( + backgroundColor: MyColors.backFillColor, + icon: Icons.calendar_month, + heading: 'dd/mm/yyyy', + onPressed: () {}, + ) + ], + ); + } + + getStatusWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle(hint: 'Status'), + AppSpaces.verticalSmall, + DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: Constants.activeStatus, + itemAsString: (String u) => u, + onChanged: (category) {}, + dropdownDecoratorProps: MyColors.dropDownStyle( + hint: 'Choose Status', + ), + ) + ], + ); + } + + getHeaderWidget() { + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Text( + 'Inventory Report', + style: ThemeText.textStyleHeadingCart, + ), + SizedBox( + width: 130, + child: CustomIconButton( + textColor: MyColors.blueThemeColor, + backgroundColor: MyColors.backColorBlue50, + heading: 'Download', + onPressed: () {}, + iconColor: MyColors.blueThemeColor, + icon: Icons.download), + ) + ], + ); + } +} diff --git a/lib/application/views/dowloadReports/widgets/DownloadInvoiceView.dart b/lib/application/views/dowloadReports/widgets/DownloadInvoiceView.dart new file mode 100644 index 0000000..c41a99c --- /dev/null +++ b/lib/application/views/dowloadReports/widgets/DownloadInvoiceView.dart @@ -0,0 +1,139 @@ +import 'package:dropdown_search/dropdown_search.dart'; +import 'package:flutter/material.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeDropDown.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/widgets/CustomOptionalTitle.dart'; +import 'package:wosull/widgets/CustomTextButtonIcon.dart'; +import 'package:wosull/widgets/DropdownItemBuilder.dart'; +import 'package:wosull/widgets/IconButton.dart'; + +class DownloadInvoiceView extends StatelessWidget { + bool isPortrait = false; + + DownloadInvoiceView({super.key, required this.isPortrait}); + + @override + Widget build(BuildContext context) { + return Card( + elevation: 5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: Padding( + padding: const EdgeInsets.all(15), + child: isPortrait + ? Column( + children: [ + getHeaderWidget(), + AppSpaces.verticalLarge, + getFromDateWidget(context), + AppSpaces.verticalMedium, + getToDateWidget(), + AppSpaces.verticalMedium, + getStatusWidget() + ], + ) + : Column( + children: [ + getHeaderWidget(), + AppSpaces.verticalLarge, + Row( + children: [ + Flexible(child: getFromDateWidget(context)), + AppSpaces.horizontalMedium, + Flexible(child: getToDateWidget()), + AppSpaces.horizontalMedium, + Flexible(child: getStatusWidget()) + ], + ) + ], + ), + ), + ); + } + + getHeaderWidget() { + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Text( + 'Invoices', + style: ThemeText.textStyleHeadingCart, + ), + SizedBox( + width: 130, + child: CustomIconButton( + textColor: MyColors.blueThemeColor, + backgroundColor: MyColors.backColorBlue50, + heading: 'Download', + onPressed: () {}, + iconColor: MyColors.blueThemeColor, + icon: Icons.download), + ) + ], + ); + } + + getFromDateWidget(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle(hint: 'From Date'), + AppSpaces.verticalSmall, + CustomTextButtonIcon( + backgroundColor: MyColors.backFillColor, + icon: Icons.calendar_month, + heading: 'dd/mm/yyyy', + onPressed: () {}, + ) + ], + ); + } + + getToDateWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle(hint: 'To Date'), + AppSpaces.verticalSmall, + CustomTextButtonIcon( + backgroundColor: MyColors.backFillColor, + icon: Icons.calendar_month, + heading: 'dd/mm/yyyy', + onPressed: () {}, + ) + ], + ); + } + + getStatusWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle(hint: 'Status'), + AppSpaces.verticalSmall, + DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: Constants.activeStatus, + itemAsString: (String u) => u, + onChanged: (category) {}, + dropdownDecoratorProps: MyColors.dropDownStyle( + hint: 'Choose Status', + ), + ) + ], + ); + } +} diff --git a/lib/application/views/dowloadReports/widgets/DownloadOrderReportView.dart b/lib/application/views/dowloadReports/widgets/DownloadOrderReportView.dart new file mode 100644 index 0000000..ddd878d --- /dev/null +++ b/lib/application/views/dowloadReports/widgets/DownloadOrderReportView.dart @@ -0,0 +1,173 @@ +import 'package:dropdown_search/dropdown_search.dart'; +import 'package:flutter/material.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeDropDown.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/widgets/CustomOptionalTitle.dart'; +import 'package:wosull/widgets/CustomTextButtonIcon.dart'; +import 'package:wosull/widgets/DropdownItemBuilder.dart'; +import 'package:wosull/widgets/IconButton.dart'; + +class DownloadOrderReportView extends StatelessWidget { + bool isPortrait = false; + + DownloadOrderReportView({super.key, required this.isPortrait}); + + @override + Widget build(BuildContext context) { + return Card( + elevation: 5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: Padding( + padding: const EdgeInsets.all(15), + child: isPortrait + ? Column( + children: [ + getHeaderWidget(), + AppSpaces.verticalLarge, + getFromDateWidget(context), + AppSpaces.verticalMedium, + getToDateWidget(), + AppSpaces.verticalMedium, + getStatusWidget(), + AppSpaces.verticalMedium, + getPaymentMode(), + ], + ) + : Column( + children: [ + getHeaderWidget(), + Row( + children: [ + Flexible(child: getFromDateWidget(context)), + AppSpaces.horizontalMedium, + Flexible(child: getToDateWidget()), + ], + ), + AppSpaces.verticalLarge, + Row( + children: [ + Flexible(child: getStatusWidget()), + AppSpaces.horizontalMedium, + Flexible(child: getPaymentMode()), + ], + ), + ], + ), + ), + ); + } + + getFromDateWidget(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle(hint: 'From Date'), + AppSpaces.verticalSmall, + CustomTextButtonIcon( + backgroundColor: MyColors.backFillColor, + icon: Icons.calendar_month, + heading: 'dd/mm/yyyy', + onPressed: () {}, + ) + ], + ); + } + + getToDateWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle(hint: 'To Date'), + AppSpaces.verticalSmall, + CustomTextButtonIcon( + backgroundColor: MyColors.backFillColor, + icon: Icons.calendar_month, + heading: 'dd/mm/yyyy', + onPressed: () {}, + ) + ], + ); + } + + getStatusWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle(hint: 'Select Branch'), + AppSpaces.verticalSmall, + DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: Constants.activeStatus, + itemAsString: (String u) => u, + onChanged: (category) {}, + dropdownDecoratorProps: MyColors.dropDownStyle( + hint: 'Choose Status', + ), + ) + ], + ); + } + + getPaymentMode() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle(hint: 'Payment Mode'), + AppSpaces.verticalSmall, + DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: Constants.activeStatus, + itemAsString: (String u) => u, + onChanged: (category) {}, + dropdownDecoratorProps: MyColors.dropDownStyle( + hint: 'Choose Payment Mode', + ), + ) + ], + ); + } + + getHeaderWidget() { + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Text( + 'Order Report', + style: ThemeText.textStyleHeadingCart, + ), + SizedBox( + width: 130, + child: CustomIconButton( + textColor: MyColors.blueThemeColor, + backgroundColor: MyColors.backColorBlue50, + heading: 'Download', + onPressed: () {}, + iconColor: MyColors.blueThemeColor, + icon: Icons.download), + ) + ], + ); + } +} diff --git a/lib/application/views/dowloadReports/widgets/DownloadPOSCompleteView.dart b/lib/application/views/dowloadReports/widgets/DownloadPOSCompleteView.dart new file mode 100644 index 0000000..8b30566 --- /dev/null +++ b/lib/application/views/dowloadReports/widgets/DownloadPOSCompleteView.dart @@ -0,0 +1,108 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/views/settings/viewModels/POSCompleteViewModel.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/widgets/CustomOptionalTitle.dart'; +import 'package:wosull/widgets/CustomTextButtonIcon.dart'; +import 'package:wosull/widgets/IconButton.dart'; + +class DownloadPOSCompleteView extends StatelessWidget { + var viewModel = POSCompleteViewModel(); + bool isPortrait = false; + + DownloadPOSCompleteView({super.key, required this.isPortrait}); + + @override + Widget build(BuildContext context) { + viewModel = context.watch(); + return Card( + elevation: 5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: Padding( + padding: const EdgeInsets.all(15), + child: Column( + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Text( + 'POS Complete', + style: ThemeText.textStyleHeadingCart, + ), + SizedBox( + width: 130, + child: CustomIconButton( + textColor: MyColors.blueThemeColor, + backgroundColor: MyColors.backColorBlue50, + heading: 'Download', + onPressed: () {}, + iconColor: MyColors.blueThemeColor, + icon: Icons.download), + ) + ], + ), + isPortrait + ? Container() + : Row( + children: [ + Flexible(child: getFromDateWidget(context)), + AppSpaces.horizontalMedium, + Flexible(child: getToDateWidget(context)) + ], + ), + isPortrait + ? Column( + children: [ + getFromDateWidget(context), + AppSpaces.verticalMedium, + getToDateWidget(context) + ], + ) + : Container() + ], + ), + ), + ); + } + + getFromDateWidget(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle(hint: 'From Date'), + AppSpaces.verticalSmall, + CustomTextButtonIcon( + backgroundColor: MyColors.backFillColor, + icon: Icons.calendar_month, + heading: viewModel.stareDate, + onPressed: () { + viewModel.presentDatePicker(context, true); + }, + ) + ], + ); + } + + getToDateWidget(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle(hint: 'To Date'), + AppSpaces.verticalSmall, + CustomTextButtonIcon( + backgroundColor: MyColors.backFillColor, + icon: Icons.calendar_month, + heading: viewModel.endDate, + onPressed: () { + viewModel.presentDatePicker(context, false); + }, + ) + ], + ); + } +} diff --git a/lib/application/views/dowloadReports/widgets/DownloadPOSReturnAndDamage.dart b/lib/application/views/dowloadReports/widgets/DownloadPOSReturnAndDamage.dart new file mode 100644 index 0000000..012b256 --- /dev/null +++ b/lib/application/views/dowloadReports/widgets/DownloadPOSReturnAndDamage.dart @@ -0,0 +1,143 @@ +import 'package:dropdown_search/dropdown_search.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/settings/viewModels/POSCompleteViewModel.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeDropDown.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/widgets/CustomOptionalTitle.dart'; +import 'package:wosull/widgets/CustomTextButtonIcon.dart'; +import 'package:wosull/widgets/DropdownItemBuilder.dart'; +import 'package:wosull/widgets/IconButton.dart'; + +class DownloadPOSReturnAndDamage extends StatelessWidget { + var viewModel = POSCompleteViewModel(); + bool isPortrait = false; + + DownloadPOSReturnAndDamage({super.key, required this.isPortrait}); + + @override + Widget build(BuildContext context) { + viewModel = context.watch(); + return Card( + elevation: 5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: Padding( + padding: const EdgeInsets.all(15), + child: Column( + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Text( + 'POS Return & Damage', + style: ThemeText.textStyleHeadingCart, + ), + SizedBox( + width: 130, + child: CustomIconButton( + textColor: MyColors.blueThemeColor, + backgroundColor: MyColors.backColorBlue50, + heading: 'Download', + onPressed: () {}, + iconColor: MyColors.blueThemeColor, + icon: Icons.download), + ) + ], + ), + isPortrait + ? Container() + : Row( + children: [ + Flexible(child: getFromDateWidget(context)), + AppSpaces.horizontalMedium, + Flexible(child: getToDateWidget(context)), + AppSpaces.horizontalMedium, + Flexible(child: getStatusWidget()) + ], + ), + isPortrait + ? Column( + children: [ + getFromDateWidget(context), + AppSpaces.horizontalMedium, + getToDateWidget(context), + AppSpaces.horizontalMedium, + getStatusWidget() + ], + ) + : Container() + ], + ), + ), + ); + } + + getFromDateWidget(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle(hint: 'From Date'), + AppSpaces.verticalSmall, + CustomTextButtonIcon( + backgroundColor: MyColors.backFillColor, + icon: Icons.calendar_month, + heading: viewModel.stareDate, + onPressed: () { + viewModel.presentDatePicker(context, true); + }, + ) + ], + ); + } + + getToDateWidget(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle(hint: 'To Date'), + AppSpaces.verticalSmall, + CustomTextButtonIcon( + backgroundColor: MyColors.backFillColor, + icon: Icons.calendar_month, + heading: viewModel.endDate, + onPressed: () { + viewModel.presentDatePicker(context, false); + }, + ) + ], + ); + } + + getStatusWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle(hint: 'Status'), + AppSpaces.verticalSmall, + DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: Constants.posStatus, + itemAsString: (String u) => u, + onChanged: (category) {}, + dropdownDecoratorProps: MyColors.dropDownStyle( + hint: 'Choose Status', + ), + ) + ], + ); + } +} diff --git a/lib/application/views/dowloadReports/widgets/DownloadProductsView.dart b/lib/application/views/dowloadReports/widgets/DownloadProductsView.dart new file mode 100644 index 0000000..8992d20 --- /dev/null +++ b/lib/application/views/dowloadReports/widgets/DownloadProductsView.dart @@ -0,0 +1,204 @@ +import 'package:dropdown_search/dropdown_search.dart'; +import 'package:flutter/material.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeDropDown.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/widgets/CustomOptionalTitle.dart'; +import 'package:wosull/widgets/CustomTextButtonIcon.dart'; +import 'package:wosull/widgets/DropdownItemBuilder.dart'; +import 'package:wosull/widgets/IconButton.dart'; + +class DownloadProductsView extends StatelessWidget { + bool isPortrait = false; + + DownloadProductsView({super.key, required this.isPortrait}); + + @override + Widget build(BuildContext context) { + return Card( + elevation: 5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: Padding( + padding: const EdgeInsets.all(15), + child: isPortrait + ? Column( + children: [ + getHeaderWidget(), + AppSpaces.verticalLarge, + getFromDateWidget(context), + AppSpaces.verticalMedium, + getToDateWidget(), + AppSpaces.verticalMedium, + getCategoryWidget(), + AppSpaces.verticalMedium, + getProductWidget(), + AppSpaces.verticalMedium, + getStatusWidget(), + ], + ) + : Column( + children: [ + getHeaderWidget(), + Row( + children: [ + Flexible(child: getFromDateWidget(context)), + AppSpaces.horizontalMedium, + Flexible(child: getToDateWidget()), + AppSpaces.horizontalMedium, + Flexible(child: getCategoryWidget()) + ], + ), + AppSpaces.verticalLarge, + Row( + children: [ + Flexible(child: getProductWidget()), + AppSpaces.horizontalMedium, + Flexible(child: getStatusWidget()), + ], + ), + ], + ), + ), + ); + } + + getFromDateWidget(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle(hint: 'From Date'), + AppSpaces.verticalSmall, + CustomTextButtonIcon( + backgroundColor: MyColors.backFillColor, + icon: Icons.calendar_month, + heading: 'dd/mm/yyyy', + onPressed: () {}, + ) + ], + ); + } + + getToDateWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle(hint: 'To Date'), + AppSpaces.verticalSmall, + CustomTextButtonIcon( + backgroundColor: MyColors.backFillColor, + icon: Icons.calendar_month, + heading: 'dd/mm/yyyy', + onPressed: () {}, + ) + ], + ); + } + + getCategoryWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle(hint: 'Categories'), + AppSpaces.verticalSmall, + DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: Constants.activeStatus, + itemAsString: (String u) => u, + onChanged: (category) {}, + dropdownDecoratorProps: MyColors.dropDownStyle( + hint: 'Choose Status', + ), + ) + ], + ); + } + + getProductWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle(hint: 'Product'), + AppSpaces.verticalSmall, + DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: Constants.activeStatus, + itemAsString: (String u) => u, + onChanged: (category) {}, + dropdownDecoratorProps: MyColors.dropDownStyle( + hint: 'Choose Status', + ), + ) + ], + ); + } + + getStatusWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle(hint: 'Categories'), + AppSpaces.verticalSmall, + DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: Constants.activeStatus, + itemAsString: (String u) => u, + onChanged: (category) {}, + dropdownDecoratorProps: MyColors.dropDownStyle( + hint: 'Choose Status', + ), + ) + ], + ); + } + + getHeaderWidget() { + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Text( + 'Products', + style: ThemeText.textStyleHeadingCart, + ), + SizedBox( + width: 130, + child: CustomIconButton( + textColor: MyColors.blueThemeColor, + backgroundColor: MyColors.backColorBlue50, + heading: 'Download', + onPressed: () {}, + iconColor: MyColors.blueThemeColor, + icon: Icons.download), + ) + ], + ); + } +} diff --git a/lib/application/views/dowloadReports/widgets/DownloadQuotationView.dart b/lib/application/views/dowloadReports/widgets/DownloadQuotationView.dart new file mode 100644 index 0000000..e2efe92 --- /dev/null +++ b/lib/application/views/dowloadReports/widgets/DownloadQuotationView.dart @@ -0,0 +1,138 @@ +import 'package:dropdown_search/dropdown_search.dart'; +import 'package:flutter/material.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeDropDown.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/widgets/CustomOptionalTitle.dart'; +import 'package:wosull/widgets/CustomTextButtonIcon.dart'; +import 'package:wosull/widgets/DropdownItemBuilder.dart'; +import 'package:wosull/widgets/IconButton.dart'; + +class DownloadQuotationView extends StatelessWidget { + bool isPortrait = false; + + DownloadQuotationView({super.key, required this.isPortrait}); + + @override + Widget build(BuildContext context) { + return Card( + elevation: 5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: Padding( + padding: const EdgeInsets.all(15), + child: isPortrait + ? Column( + children: [ + getHeaderWidget(), + AppSpaces.verticalLarge, + getFromDateWidget(context), + AppSpaces.horizontalMedium, + getToDateWidget(), + AppSpaces.horizontalMedium, + getStatusWidget() + ], + ) + : Column( + children: [ + getHeaderWidget(), + Row( + children: [ + Flexible(child: getFromDateWidget(context)), + AppSpaces.horizontalMedium, + Flexible(child: getToDateWidget()), + AppSpaces.horizontalMedium, + Flexible(child: getStatusWidget()) + ], + ) + ], + ), + ), + ); + } + + getFromDateWidget(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle(hint: 'From Date'), + AppSpaces.verticalSmall, + CustomTextButtonIcon( + backgroundColor: MyColors.backFillColor, + icon: Icons.calendar_month, + heading: 'dd/mm/yyyy', + onPressed: () {}, + ) + ], + ); + } + + getToDateWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle(hint: 'To Date'), + AppSpaces.verticalSmall, + CustomTextButtonIcon( + backgroundColor: MyColors.backFillColor, + icon: Icons.calendar_month, + heading: 'dd/mm/yyyy', + onPressed: () {}, + ) + ], + ); + } + + getStatusWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle(hint: 'Status'), + AppSpaces.verticalSmall, + DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: Constants.activeStatus, + itemAsString: (String u) => u, + onChanged: (category) {}, + dropdownDecoratorProps: MyColors.dropDownStyle( + hint: 'Choose Status', + ), + ) + ], + ); + } + + getHeaderWidget() { + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Text( + 'Quotation', + style: ThemeText.textStyleHeadingCart, + ), + SizedBox( + width: 130, + child: CustomIconButton( + textColor: MyColors.blueThemeColor, + backgroundColor: MyColors.backColorBlue50, + heading: 'Download', + onPressed: () {}, + iconColor: MyColors.blueThemeColor, + icon: Icons.download), + ) + ], + ); + } +} diff --git a/lib/application/views/dowloadReports/widgets/DownloadReportView.dart b/lib/application/views/dowloadReports/widgets/DownloadReportView.dart new file mode 100644 index 0000000..e749c10 --- /dev/null +++ b/lib/application/views/dowloadReports/widgets/DownloadReportView.dart @@ -0,0 +1,180 @@ +import 'package:dropdown_search/dropdown_search.dart'; +import 'package:flutter/material.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeDropDown.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/widgets/CustomOptionalTitle.dart'; +import 'package:wosull/widgets/CustomTextButtonIcon.dart'; +import 'package:wosull/widgets/DropdownItemBuilder.dart'; +import 'package:wosull/widgets/IconButton.dart'; + +class DownloadReportView extends StatelessWidget { + const DownloadReportView({super.key}); + + @override + Widget build(BuildContext context) { + return Card( + elevation: 5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: Padding( + padding: const EdgeInsets.all(15), + child: Column( + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Text( + 'Order Report', + style: ThemeText.textStyleHeadingCart, + ), + SizedBox( + width: 130, + child: CustomIconButton( + textColor: MyColors.blueThemeColor, + backgroundColor: MyColors.backColorBlue50, + heading: 'Download', + onPressed: () {}, + iconColor: MyColors.blueThemeColor, + icon: Icons.download), + ) + ], + ), + Row( + children: [ + Flexible(child: getFromDateWidget(context)), + AppSpaces.horizontalMedium, + Flexible(child: getToDateWidget()), + ], + ), + AppSpaces.verticalLarge, + Row( + children: [ + Flexible(child: getStatusWidget()), + AppSpaces.horizontalMedium, + Flexible(child: getPaymentMode()), + ], + ), + ], + ), + ), + ); + } + + getFromDateWidget(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle(hint: 'From Date'), + AppSpaces.verticalSmall, + CustomTextButtonIcon( + backgroundColor: MyColors.backFillColor, + icon: Icons.calendar_month, + heading: 'dd/mm/yyyy', + onPressed: () {}, + ) + ], + ); + } + + getToDateWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle(hint: 'To Date'), + AppSpaces.verticalSmall, + CustomTextButtonIcon( + backgroundColor: MyColors.backFillColor, + icon: Icons.calendar_month, + heading: 'dd/mm/yyyy', + onPressed: () {}, + ) + ], + ); + } + + getCategoryWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle(hint: 'Categories'), + AppSpaces.verticalSmall, + DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: Constants.activeStatus, + itemAsString: (String u) => u, + onChanged: (category) {}, + dropdownDecoratorProps: MyColors.dropDownStyle( + hint: 'Choose Status', + ), + ) + ], + ); + } + + getPaymentMode() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle(hint: 'Payment Mode'), + AppSpaces.verticalSmall, + DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: Constants.activeStatus, + itemAsString: (String u) => u, + onChanged: (category) {}, + dropdownDecoratorProps: MyColors.dropDownStyle( + hint: 'Choose Status', + ), + ) + ], + ); + } + + getStatusWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle(hint: 'Categories'), + AppSpaces.verticalSmall, + DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: Constants.activeStatus, + itemAsString: (String u) => u, + onChanged: (category) {}, + dropdownDecoratorProps: MyColors.dropDownStyle( + hint: 'Choose Status', + ), + ) + ], + ); + } +} diff --git a/lib/application/views/dowloadReports/widgets/DownloadStockStatusView.dart b/lib/application/views/dowloadReports/widgets/DownloadStockStatusView.dart new file mode 100644 index 0000000..00df180 --- /dev/null +++ b/lib/application/views/dowloadReports/widgets/DownloadStockStatusView.dart @@ -0,0 +1,173 @@ +import 'package:dropdown_search/dropdown_search.dart'; +import 'package:flutter/material.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeDropDown.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/widgets/CustomOptionalTitle.dart'; +import 'package:wosull/widgets/CustomTextButtonIcon.dart'; +import 'package:wosull/widgets/DropdownItemBuilder.dart'; +import 'package:wosull/widgets/IconButton.dart'; + +class DownloadStockStatusView extends StatelessWidget { + bool isPortrait = false; + + DownloadStockStatusView({super.key, required this.isPortrait}); + + @override + Widget build(BuildContext context) { + return Card( + elevation: 5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: Padding( + padding: const EdgeInsets.all(15), + child: isPortrait + ? Column( + children: [ + getHeaderWidget(), + AppSpaces.verticalLarge, + getFromDateWidget(context), + AppSpaces.verticalMedium, + getToDateWidget(), + AppSpaces.verticalMedium, + getBranchWidget(), + AppSpaces.verticalMedium, + getStatusWidget(), + ], + ) + : Column( + children: [ + getHeaderWidget(), + Row( + children: [ + Flexible(child: getFromDateWidget(context)), + AppSpaces.horizontalMedium, + Flexible(child: getToDateWidget()), + ], + ), + AppSpaces.verticalLarge, + Row( + children: [ + Flexible(child: getBranchWidget()), + AppSpaces.horizontalMedium, + Flexible(child: getStatusWidget()), + ], + ), + ], + ), + ), + ); + } + + getFromDateWidget(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle(hint: 'From Date'), + AppSpaces.verticalSmall, + CustomTextButtonIcon( + backgroundColor: MyColors.backFillColor, + icon: Icons.calendar_month, + heading: 'dd/mm/yyyy', + onPressed: () {}, + ) + ], + ); + } + + getToDateWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle(hint: 'To Date'), + AppSpaces.verticalSmall, + CustomTextButtonIcon( + backgroundColor: MyColors.backFillColor, + icon: Icons.calendar_month, + heading: 'dd/mm/yyyy', + onPressed: () {}, + ) + ], + ); + } + + getStatusWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle(hint: 'Select Branch'), + AppSpaces.verticalSmall, + DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: Constants.activeStatus, + itemAsString: (String u) => u, + onChanged: (category) {}, + dropdownDecoratorProps: MyColors.dropDownStyle( + hint: 'Choose Status', + ), + ) + ], + ); + } + + getBranchWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle(hint: 'Select Branch'), + AppSpaces.verticalSmall, + DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: Constants.activeStatus, + itemAsString: (String u) => u, + onChanged: (category) {}, + dropdownDecoratorProps: MyColors.dropDownStyle( + hint: 'Choose Status', + ), + ) + ], + ); + } + + getHeaderWidget() { + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Text( + 'Stock Status Report', + style: ThemeText.textStyleHeadingCart, + ), + SizedBox( + width: 130, + child: CustomIconButton( + textColor: MyColors.blueThemeColor, + backgroundColor: MyColors.backColorBlue50, + heading: 'Download', + onPressed: () {}, + iconColor: MyColors.blueThemeColor, + icon: Icons.download), + ) + ], + ); + } +} diff --git a/lib/application/views/home/HomePage.dart b/lib/application/views/home/HomePage.dart index 2ad9341..ebe0f7c 100644 --- a/lib/application/views/home/HomePage.dart +++ b/lib/application/views/home/HomePage.dart @@ -3,38 +3,40 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_svg/svg.dart'; import 'package:internet_connection_checker/internet_connection_checker.dart'; import 'package:provider/provider.dart'; +import 'package:sizer/sizer.dart'; import 'package:wosull/application/interfaces/DrawerWidgetSelect.dart'; -import 'package:wosull/application/language/AppLanguage.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/theme/MyFonts.dart'; -import 'package:wosull/application/views/authModule/loginViews/CheckInPopUp.dart'; +import 'package:wosull/application/utils/AppLoader.dart'; +import 'package:wosull/application/views/authModule/checkinViews/CheckInPopUp.dart'; import 'package:wosull/application/views/authModule/loginViews/LoginVC.dart'; +import 'package:wosull/application/views/billingCounterDashboard/BillingCounterMainVC.dart'; +import 'package:wosull/application/views/businessAccounts/BusinessAccountMainVC.dart'; import 'package:wosull/application/views/create_order_module/CartVC.dart'; import 'package:wosull/application/views/create_order_module/HoldOrderVC.dart'; import 'package:wosull/application/views/create_order_module/views/TabBarHomeVC.dart'; import 'package:wosull/application/views/create_order_module/views/popups/CashOutVC.dart'; +import 'package:wosull/application/views/create_order_module/views/popups/CounterCloseVC.dart'; import 'package:wosull/application/views/create_order_module/views/popups/LogoutVC.dart'; import 'package:wosull/application/views/create_order_module/views/popups/RegisterCashVC.dart'; import 'package:wosull/application/views/dashboard/HomeVC.dart'; import 'package:wosull/application/views/discountModule/DiscoountModuleMainVC.dart'; import 'package:wosull/application/views/home/HomePageViewModel.dart'; import 'package:wosull/application/views/inventorymodule/InventoryModuleMainVC.dart'; -import 'package:wosull/application/views/kitchenmodule/views/KitchenMainTableVC.dart'; import 'package:wosull/application/views/kitchenmodule/views/KitchenMainVC.dart'; import 'package:wosull/application/views/salesandordermodule/SalesAndOrderMainVC.dart'; import 'package:wosull/application/views/settings/SettingsMainVC.dart'; import 'package:wosull/base/BaseStatefulState.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeDropDown.dart'; import 'package:wosull/helpers/ThemeImage.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/main.dart'; +import 'package:wosull/widgets/CustomIconButton.dart'; import 'package:wosull/widgets/CustomListTIle.dart'; -import 'package:wosull/widgets/IconButton.dart'; - -class DrawerItem { - String title; - IconData icon; - - DrawerItem(this.title, this.icon); -} +import 'package:wosull/widgets/LanguageDropdown.dart'; +import 'package:wosull/widgets/ValueText.dart'; class HomePage extends StatefulWidget { const HomePage({Key? key}) : super(key: key); @@ -50,7 +52,11 @@ class _HomePageState extends BaseStatefulState @override void initState() { super.initState(); - viewModel.setContext(context); + context.read().setContext(context); + //context.read().setHomeMenus(); + // + // viewModel.setHomeMenus(); + // viewModel.setContext(context); } @override @@ -62,12 +68,13 @@ class _HomePageState extends BaseStatefulState @override Widget build(BuildContext context) { viewModel = context.watch(); - viewModel.setContext(context); + // viewModel.setContext(context); viewModel.setHomeMenus(); - viewModel.setCashierMenus(); - viewModel.dropdownValue = AppLanguage.languages().first; + viewModel.setDropDownValue(); return StreamProvider( - initialData: InternetConnectionStatus.connected, + initialData: isConnected + ? InternetConnectionStatus.connected + : InternetConnectionStatus.disconnected, create: (_) { return InternetConnectionChecker().onStatusChange; }, @@ -86,140 +93,43 @@ class _HomePageState extends BaseStatefulState mainAxisSize: MainAxisSize.min, children: [ getLangDropdown(), - const SizedBox( - width: 12, - ), + AppSpaces.horizontalMedium, + getSyncButton(), + AppSpaces.horizontalMedium, SizedBox( - width: 100, + width: 110, child: CustomIconButton( - iconColor: MyColors.blueThemeColor, - backgroundColor: MyColors.backFillColor, - height: 38, - textColor: MyColors.blueThemeColor, - isLoading: viewModel.isInSync, - heading: 'Sync', - onPressed: () { - viewModel.syncData(); - }, - icon: Icons.sync, - ), - ), - const SizedBox( - width: 12, - ), - SizedBox( - width: 130, - child: ElevatedButton.icon( - style: ElevatedButton.styleFrom( - elevation: 0, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - backgroundColor: MyColors.backFillColor, - minimumSize: const Size.fromHeight(38), // NEW - ), onPressed: () { viewModel.setSelectedDrawer(0); }, - label: Text( - AppLocalizations.of(context)!.cashier, - style: TextStyle( - fontSize: 13, - color: MyColors.blueThemeColor, - fontFamily: MyFonts.Medium), - ), - icon: ImageIcon( - color: MyColors.blueThemeColor, - const AssetImage('images/cashier.png'), - size: 18, - ), + heading: AppLocalizations.of(context)!.cashier, + svgIconPath: ThemeImage.cashierImage, ), ), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, SizedBox( - width: 120, - child: ElevatedButton.icon( - style: ElevatedButton.styleFrom( - elevation: 0, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - backgroundColor: MyColors.backFillColor, - minimumSize: const Size.fromHeight(38), // NEW - ), - onPressed: () { - viewModel.setSelectedDrawer(8); - }, - label: Text( - AppLocalizations.of(context)!.kitchen, - style: TextStyle( - fontSize: 13, - color: MyColors.blueThemeColor, - fontFamily: MyFonts.Medium), - ), - icon: ImageIcon( - color: MyColors.blueThemeColor, - const AssetImage('images/kitchen.png'), - size: 18, - ), - ), - ), - const SizedBox( - width: 8, - ), - PopupMenuButton( - padding: EdgeInsets.zero, - child: Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular(22)), - color: MyColors.backFillColor), - height: 44, - child: Row( - children: [ - Padding( - padding: const EdgeInsets.all(4), - child: CircleAvatar( - backgroundColor: - MyColors.blueThemeColor, - child: Padding( - padding: const EdgeInsets.fromLTRB( - 0, 0, 0, 0), // Border radius - child: ClipOval( - child: SizedBox( - width: 24, - height: 24, - child: SvgPicture.asset( - 'images/account_profile.svg'), - )), - ), - ), - ), - Text( - sharedPrefs.store_name, - style: const TextStyle( - fontSize: MyFonts.normalButton, - fontFamily: MyFonts.Medium, - color: MyColors.textColorBlack), - ), - const Icon( - Icons.keyboard_arrow_down, - color: MyColors.textColorBlack, - ) - ], - ), - ), - itemBuilder: (context) { - return getPopUpMenu(); - }, - onSelected: (String value) => - actionPopUpItemSelected(value), + width: 110, + child: CustomIconButton( + onPressed: () { + showCloseCounter(); + }, + heading: 'Counter', + svgIconPath: ThemeImage.cashierImage), ), - const SizedBox( - width: 8, + AppSpaces.horizontalMedium, + SizedBox( + width: 110, + child: CustomIconButton( + onPressed: () { + viewModel.setSelectedDrawer(7); + }, + heading: + AppLocalizations.of(context)!.kitchen, + svgIconPath: ThemeImage.kitchenImage), ), + AppSpaces.horizontalMedium, + getPopupButton(), + AppSpaces.horizontalMedium, ], )) : Expanded( @@ -228,78 +138,11 @@ class _HomePageState extends BaseStatefulState mainAxisSize: MainAxisSize.min, children: [ getLangDropdown(), - const SizedBox( - width: 8, - ), - SizedBox( - width: 100, - child: CustomIconButton( - iconColor: MyColors.blueThemeColor, - backgroundColor: MyColors.backFillColor, - height: 38, - textColor: MyColors.blueThemeColor, - isLoading: viewModel.isInSync, - heading: 'Sync', - onPressed: () { - viewModel.syncData(); - }, - icon: Icons.sync, - ), - ), - const SizedBox( - width: 8, - ), - PopupMenuButton( - padding: EdgeInsets.zero, - child: Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular(22)), - color: MyColors.backFillColor), - height: 44, - child: Row( - children: [ - Padding( - padding: const EdgeInsets.all(4), - child: CircleAvatar( - backgroundColor: - MyColors.blueThemeColor, - child: Padding( - padding: const EdgeInsets.fromLTRB( - 0, 0, 0, 0), // Border radius - child: ClipOval( - child: SizedBox( - width: 24, - height: 24, - child: SvgPicture.asset( - 'images/account_profile.svg'), - )), - ), - ), - ), - Text( - sharedPrefs.store_name, - style: const TextStyle( - fontSize: MyFonts.normalButton, - fontFamily: MyFonts.Medium, - color: MyColors.textColorBlack), - ), - const Icon( - Icons.keyboard_arrow_down, - color: MyColors.textColorBlack, - ) - ], - ), - ), - itemBuilder: (context) { - return getPopUpMenu(); - }, - onSelected: (String value) => - actionPopUpItemSelected(value), - ), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalSmall, + getSyncButton(), + AppSpaces.horizontalSmall, + getPopupButton(), + AppSpaces.horizontalSmall, ], )) ], @@ -325,37 +168,86 @@ class _HomePageState extends BaseStatefulState } List> getPopUpMenu() { - return [ - PopupMenuItem( - value: 'mystore', - child: Text(AppLocalizations.of(context)!.my_store), - ), - PopupMenuItem( - value: 'register', - child: Text(AppLocalizations.of(context)!.register), - ), - const PopupMenuItem( - value: 'cashout', - child: Text('Cash Out'), - ), - PopupMenuItem( - value: 'logout', - child: Text(AppLocalizations.of(context)!.logout), - ), - ]; + return SizerUtil.deviceType == DeviceType.mobile + ? [ + PopupMenuItem( + value: 'counter', + child: ValueText('Counter'), + ), + // PopupMenuItem( + // value: 'mystore', + // child: ValueText(AppLocalizations.of(context)!.my_store), + // ), + // PopupMenuItem( + // value: 'register', + // child: ValueText(AppLocalizations.of(context)!.register), + // ), + // PopupMenuItem( + // value: 'cashout', + // child: ValueText('Cash Out'), + // ), + PopupMenuItem( + value: 'logout', + child: ValueText(AppLocalizations.of(context)!.logout), + ), + ] + : [ + // PopupMenuItem( + // value: 'mystore', + // child: ValueText(AppLocalizations.of(context)!.my_store), + // ), + // PopupMenuItem( + // value: 'register', + // child: ValueText(AppLocalizations.of(context)!.register), + // ), + // PopupMenuItem( + // value: 'cashout', + // child: ValueText('Cash Out'), + // ), + PopupMenuItem( + value: 'logout', + child: ValueText(AppLocalizations.of(context)!.logout), + ), + ]; } Future actionPopUpItemSelected(String value) async { if (value == 'mystore') { + } else if (value == 'counter') { + showCloseCounter(); } else if (value == 'register') { showRegister(); } else if (value == 'cashout') { showCashout(); } else if (value == 'logout') { - logout(); + //logout(); + clearData(); + } else if (value == 'fetch') { + viewModel.syncData(); + } else if (value == 'upload') { + viewModel.uploadOrders(); } } + List> getSyncMenu() { + return [ + PopupMenuItem( + value: 'fetch', + child: Text( + 'Fetch Data', + style: ThemeDropDown.dropDownTextStyle, + ), + ), + PopupMenuItem( + value: 'upload', + child: Text( + 'Upload Order', + style: ThemeDropDown.dropDownTextStyle, + ), + ), + ]; + } + Future logout() async { final result = await showDialog( barrierColor: Colors.black26, @@ -369,11 +261,7 @@ class _HomePageState extends BaseStatefulState if (result != null) { final updated = result; if (updated) { - sharedPrefs.isLoggedIn = false; - Navigator.pushReplacement( - context, - MaterialPageRoute(builder: (context) => LoginVC()), - ); + clearData(); } } } @@ -388,6 +276,26 @@ class _HomePageState extends BaseStatefulState ); } + Future showCloseCounter() async { + if (sharedPrefs.billingCounterId.isEmpty) { + showCounters(); + } else { + final result = await showDialog( + barrierColor: Colors.black26, + context: context, + builder: (context) { + return const CounterCloseVC(); + }, + ); + + if (!mounted) return; + if (result != null) { + viewModel.clearCounterData(); + showCounters(); + } + } + } + Future showRegister() async { final result = await showDialog( barrierColor: Colors.black26, @@ -411,7 +319,7 @@ class _HomePageState extends BaseStatefulState barrierColor: Colors.black26, context: context, builder: (context) { - return CheckInPopUp(); + return const CheckInPopUp(); }, ); @@ -447,49 +355,70 @@ class _HomePageState extends BaseStatefulState ), ), CustomListTile( - path: 'images/home_icon.svg', - title: AppLocalizations.of(context)!.dashboard, + wasTaped: viewModel.isTaped[0], + path: ThemeImage.homeImage, + title: 'Master Dashboard', + onTap: () { + viewModel.onSelectItem(0); + }), + CustomListTile( + wasTaped: viewModel.isTaped[1], + path: ThemeImage.createOrderImage, + title: 'Billing Counter Dashboard', onTap: () { - viewModel.onSelectItem(12); + viewModel.onSelectItem(1); }), CustomListTile( - path: 'images/create-order.svg', + wasTaped: viewModel.isTaped[2], + path: ThemeImage.createOrderImage, title: AppLocalizations.of(context)!.create_order, onTap: () { - viewModel.onSelectItem(0); + viewModel.onSelectItem(2); }), CustomListTile( - path: 'images/inven.svg', + wasTaped: viewModel.isTaped[3], + path: ThemeImage.inventoryImage, title: AppLocalizations.of(context)!.inventory, onTap: () { - viewModel.onSelectItem(1); + viewModel.onSelectItem(3); }), CustomListTile( - path: 'images/dis.svg', + wasTaped: viewModel.isTaped[4], + path: ThemeImage.discountImage, title: AppLocalizations.of(context)!.discount, onTap: () { - viewModel.onSelectItem(2); + viewModel.onSelectItem(4); }), CustomListTile( - path: 'images/sales_order.svg', + wasTaped: viewModel.isTaped[5], + path: ThemeImage.salesImage, + title: 'Business Accounts', + onTap: () { + viewModel.onSelectItem(5); + }), + CustomListTile( + wasTaped: viewModel.isTaped[6], + path: ThemeImage.salesImage, title: AppLocalizations.of(context)!.sales_and_orders, onTap: () { - viewModel.onSelectItem(7); + viewModel.onSelectItem(6); }), CustomListTile( - path: 'images/kitchen.svg', + wasTaped: viewModel.isTaped[7], + path: ThemeImage.kitchenIcon, title: AppLocalizations.of(context)!.kitchen, onTap: () { viewModel.tableIndex = 0; - viewModel.onSelectItem(8); + viewModel.onSelectItem(7); }), Align( alignment: FractionalOffset.bottomCenter, child: CustomListTile( - path: 'images/setting.svg', + wasTaped: viewModel.isTaped[8], + path: ThemeImage.settingIcon, title: AppLocalizations.of(context)!.settings, onTap: () { - viewModel.onSelectItem(14); + viewModel.onSelectItem(8); }), ) ], @@ -499,73 +428,165 @@ class _HomePageState extends BaseStatefulState @override void goToHome() { - viewModel.setSelectedDrawer(0); + viewModel.setSelectedDrawer(2); } @override void changeBottomNavigation(int index) { - if (viewModel.isCashier) { - viewModel.onItemTapped(1); - } + viewModel.onItemTapped(index); } Widget getLangDropdown() { - return DropdownButton( - value: viewModel.dropdownValue, - iconSize: 12, - style: const TextStyle(fontSize: 12, color: MyColors.black), - onChanged: (AppLanguage? language) { - viewModel.dropdownValue = language!; - viewModel.setLanguage(language); - }, - items: AppLanguage.languages() - .map>( - (e) => DropdownMenuItem( - value: e, - child: Text( - e.name, - )), - ) - .toList(), - ); + return LanguageDropdown( + fillColor: MyColors.backFillColor, + dropdownValue: viewModel.dropdownValue, + onChange: (language) { + viewModel.dropdownValue = language!; + viewModel.setLanguage(language); + }); } _getDrawerItemWidget(int pos) { switch (pos) { case 0: - return const TabBarHomeVC(); + return HomeVC(delegateDrawer: this); case 1: + return BillingCounterMainVC(delegateDrawer: this); + case 2: + viewModel.currentIndex = 1; + return const TabBarHomeVC(); + case 3: return InventoryModuleMainVC( delegateDrawer: this, ); - case 2: + case 4: return DiscountModuleVC( delegateDrawer: this, ); - - case 7: + case 5: + return BusinessAccountMainVC( + delegateDrawer: this, + ); + case 6: return SalesAndOrderMainVC( delegateDrawer: this, ); - case 8: + case 7: return KitchenMainVC( delegateDrawer: this, initialIndex: 0, ); + case 8: + return SettingsMainVC(delegateDrawer: this); + case 9: + return HomeVC(delegateDrawer: this); case 10: - return CartVC(); + return CartVC(delegateDrawer: this); case 11: return HoldOrderVC( delegateDrawer: this, ); - case 12: - return HomeVC(delegateDrawer: this); - case 13: - return KitchenMainTableVC(delegateDrawer: this); - case 14: - return SettingsMainVC(delegateDrawer: this); default: return const Text("Error"); } } + + Widget getSyncButton() { + return PopupMenuButton( + padding: EdgeInsets.zero, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: Container( + padding: const EdgeInsets.only(left: 8, right: 8), + decoration: BoxDecoration( + borderRadius: const BorderRadius.all(Radius.circular(8)), + color: MyColors.backFillColor), + height: 38, + child: viewModel.isInSync + ? AppLoader() + : Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SizedBox( + width: 24, + height: 24, + child: Icon( + Icons.sync, + size: 18, + color: MyColors.blueThemeColor, + ), + ), + Text( + 'Sync', + style: ThemeText.textStyleBlueMedium, + ), + ], + ), + ), + itemBuilder: (context) { + return getSyncMenu(); + }, + onSelected: (String value) => actionPopUpItemSelected(value), + ); + } + + void clearData() { + viewModel.clearLogoutData(); + Navigator.pushReplacement( + context, + MaterialPageRoute(builder: (context) => const LoginVC()), + ); + } + + getPopupButton() { + return PopupMenuButton( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + padding: EdgeInsets.zero, + child: Container( + decoration: BoxDecoration( + borderRadius: const BorderRadius.all(Radius.circular(22)), + color: MyColors.backFillColor), + height: 44, + child: Row( + children: [ + Padding( + padding: const EdgeInsets.all(4), + child: CircleAvatar( + backgroundColor: MyColors.blueThemeColor, + child: Padding( + padding: + const EdgeInsets.fromLTRB(0, 0, 0, 0), // Border radius + child: ClipOval( + child: SizedBox( + width: 24, + height: 24, + child: SvgPicture.asset(ThemeImage.accountProfileImage), + )), + ), + ), + ), + Text( + sharedPrefs.store_name, + style: TextStyle( + fontSize: MyFonts.mediumText, + fontFamily: MyFonts.Medium, + color: MyColors.textColorBlack), + ), + const Icon( + Icons.keyboard_arrow_down, + color: MyColors.textColorBlack, + ) + ], + ), + ), + itemBuilder: (context) { + return getPopUpMenu(); + }, + onSelected: (String value) => actionPopUpItemSelected(value), + ); + } } diff --git a/lib/application/views/home/HomePageViewModel.dart b/lib/application/views/home/HomePageViewModel.dart index 17f1c2c..f92f744 100644 --- a/lib/application/views/home/HomePageViewModel.dart +++ b/lib/application/views/home/HomePageViewModel.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:flutter_svg/flutter_svg.dart'; import 'package:internet_connection_checker/internet_connection_checker.dart'; import 'package:provider/provider.dart'; import 'package:wosull/application/language/AppLanguage.dart'; @@ -9,107 +10,151 @@ import 'package:wosull/database/SyncDatabase.dart'; import 'package:wosull/helpers/Utils.dart'; class HomePageViewModel with ChangeNotifier { - late AppLanguage dropdownValue; + AppLanguage dropdownValue = AppLanguage.languages().first; late BuildContext context; List homeItems = []; - List cashierItems = []; var _appLocale; - late String currentDefaultSystemLocale; - bool _isInSync = false; bool get isInSync => _isInSync; - int currentIndex = 0; + int currentIndex = 1; bool isCashier = true; - int selectedDrawerIndex = 0; + int selectedDrawerIndex = 2; late int tableIndex; + final List isTaped = [ + false, + false, + true, + false, + false, + false, + false, + false, + false, + ]; // the first is true because when the app + + void changeHighlight(int index) { + for (int indexTap = 0; indexTap < isTaped.length; indexTap++) { + if (indexTap == index) { + isTaped[index] = true; //used to change the value of the bool list + } else { + isTaped[indexTap] = false; + } + } + } + void setLanguage(AppLanguage language) { sharedPrefs.isChanged = true; _appLocale ??= Provider.of(context, listen: false); _appLocale.changeLocale(Locale(language.languageCode)); - setFlag(); sharedPrefs.setLocale(language.languageCode); + notifyListeners(); } void onDepChange() { if (sharedPrefs.isChanged) { - _appLocale = Provider.of(context); sharedPrefs.isChanged = false; + _appLocale = Provider.of(context); sharedPrefs.getLocale().then((locale) { _appLocale.changeLocale(Locale(locale.languageCode)); dropdownValue = AppLanguage.languages().firstWhere( (element) => element.languageCode == locale.languageCode); - setFlag(); }); } } - void setFlag() { - currentDefaultSystemLocale = _appLocale.locale.languageCode.split('_')[0]; - // setState(() { - // selectedLangIndex = _getLangIndex(currentDefaultSystemLocale); - // }); - } - - int _getLangIndex(String currentDefaultSystemLocale) { - int _langIndex = 0; - switch (currentDefaultSystemLocale) { - case 'en': - _langIndex = 0; - break; - case 'ar': - _langIndex = 1; - break; - } - return _langIndex; + void setDropDownValue() { + sharedPrefs.getLocale().then((locale) { + _appLocale ??= Provider.of(context, listen: false); + if (locale.languageCode == 'en') { + dropdownValue = AppLanguage.languages().first; + } else { + _appLocale.changeLocale(Locale(locale.languageCode)); + dropdownValue = AppLanguage.languages().firstWhere( + (element) => element.languageCode == locale.languageCode); + } + }); } void setHomeMenus() { homeItems = [ - const BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'), - BottomNavigationBarItem( - icon: const Icon(Icons.money), - label: AppLocalizations.of(context)!.cashier), - BottomNavigationBarItem( - icon: const Icon(Icons.kitchen), - label: AppLocalizations.of(context)!.cart), BottomNavigationBarItem( - icon: const Icon(Icons.pending_actions), - label: AppLocalizations.of(context)!.hold_order) - ]; - } - - void setCashierMenus() { - cashierItems = [ + icon: SvgPicture.asset( + 'images/home.svg', + width: 24, + ), + activeIcon: SvgPicture.asset( + 'images/home_active.svg', + width: 24, + ), + label: 'Home'), BottomNavigationBarItem( - icon: const Icon(Icons.money), + icon: SvgPicture.asset( + 'images/cashier.svg', + width: 24, + ), + activeIcon: SvgPicture.asset( + 'images/active_cashier.svg', + width: 24, + ), label: AppLocalizations.of(context)!.cashier), BottomNavigationBarItem( - icon: const Icon(Icons.kitchen), + icon: SvgPicture.asset( + 'images/cart.svg', + width: 24, + ), + activeIcon: SvgPicture.asset( + 'images/active_cart.svg', + width: 24, + ), label: AppLocalizations.of(context)!.cart), BottomNavigationBarItem( - icon: const Icon(Icons.pending_actions), + icon: SvgPicture.asset( + 'images/hold_order.svg', + width: 24, + ), + activeIcon: SvgPicture.asset( + 'images/active_hold.svg', + width: 24, + ), label: AppLocalizations.of(context)!.hold_order) ]; } + // void setCashierMenus() { + // cashierItems = [ + // BottomNavigationBarItem( + // icon: const Icon(Icons.money), + // label: AppLocalizations.of(context)!.cashier), + // BottomNavigationBarItem( + // icon: const Icon(Icons.kitchen), + // label: AppLocalizations.of(context)!.cart), + // BottomNavigationBarItem( + // icon: const Icon(Icons.pending_actions), + // label: AppLocalizations.of(context)!.hold_order) + // ]; + // } + void setContext(BuildContext c) { context = c; } void setSelectedDrawer(int i) { + changeHighlight(i); selectedDrawerIndex = i; notifyListeners(); } onSelectItem(int index) { - if (index == 12) { - isCashier = false; - currentIndex = 0; + if (index == 0 || index == 2) { + currentIndex = index; + if (index == 2) { + currentIndex = 1; + } } setSelectedDrawer(index); Navigator.of(context).pop(); // close the drawer @@ -117,14 +162,10 @@ class HomePageViewModel with ChangeNotifier { void onItemTapped(int index) async { currentIndex = index; - if (index == 0) { - isCashier = false; - setSelectedDrawer(12); - } else if (index == 1) { - isCashier = true; - currentIndex = 0; setSelectedDrawer(0); + } else if (index == 1) { + setSelectedDrawer(2); } else if (index == 2) { setSelectedDrawer(10); } else if (index == 3) { @@ -147,9 +188,34 @@ class HomePageViewModel with ChangeNotifier { } } + Future uploadOrders() async { + if (!isInSync) { + var sync = SyncDatabase(); + if (await InternetConnectionChecker().hasConnection) { + setSync(true); + await sync.uploadOrders(); + setSync(false); + } else { + Utils.showMessage('Internet not connected'); + } + } else { + Utils.showMessage('Sync is already in progress'); + } + } + void setSync(bool value) { _isInSync = value; - notifyListeners(); } + + void clearCounterData() { + sharedPrefs.businessRegisterId = ''; + sharedPrefs.billingCounterId = ''; + } + + void clearLogoutData() { + sharedPrefs.isLoggedIn = false; + sharedPrefs.storeId = ''; + sharedPrefs.store_name = ''; + } } diff --git a/lib/application/views/inventorymodule/InventoryModuleMainVC.dart b/lib/application/views/inventorymodule/InventoryModuleMainVC.dart index 70777d6..6e2cacc 100644 --- a/lib/application/views/inventorymodule/InventoryModuleMainVC.dart +++ b/lib/application/views/inventorymodule/InventoryModuleMainVC.dart @@ -2,14 +2,16 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:wosull/application/interfaces/DrawerWidgetSelect.dart'; import 'package:wosull/application/theme/MyColors.dart'; -import 'package:wosull/application/theme/MyFonts.dart'; import 'package:wosull/application/views/inventorymodule/comboviews/InventoryComboVC.dart'; import 'package:wosull/application/views/inventorymodule/ingredientsViews/IngredientsVC.dart'; import 'package:wosull/application/views/inventorymodule/measurementviews/InventoryMeasurementVC.dart'; +import 'package:wosull/application/views/inventorymodule/modiferOption/views/ModiferOptionVC.dart'; import 'package:wosull/application/views/inventorymodule/modifierviews/InventoryModifierVC.dart'; import 'package:wosull/application/views/inventorymodule/productviews/InventoryProductVC.dart'; +import 'package:wosull/application/views/inventorymodule/stockReturn/views/StockReturnVC.dart'; import 'package:wosull/application/views/inventorymodule/stockTransferViews/InventoryStockTransferVC.dart'; import 'package:wosull/application/views/inventorymodule/subCategoryViews/SubCategoryVC.dart'; +import 'package:wosull/widgets/BackTabBarContainer.dart'; import 'categoryviews/InventoryCategoriesModule.dart'; import 'deliveryPartnerViews/InventoryDeliveryPartnerPriceVC.dart'; @@ -28,7 +30,7 @@ class _InventoryModuleMainVCState extends State { @override Widget build(BuildContext context) { return DefaultTabController( - length: 9, + length: 11, child: Scaffold( body: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -41,105 +43,45 @@ class _InventoryModuleMainVCState extends State { width: double.infinity, color: MyColors.fillColorGray2, ), - Container( - width: double.infinity, - margin: const EdgeInsets.only(bottom: 6.0), - //Same as `blurRadius` i guess - decoration: const BoxDecoration( - color: Colors.white, - boxShadow: [ - BoxShadow( - color: Colors.grey, - offset: Offset(0.0, 1.0), //(x,y) - blurRadius: 6.0, - ), - ], - ), - child: Row( - children: [ - Container( - margin: const EdgeInsets.only(left: 8), - child: ElevatedButton.icon( - onPressed: () { - widget.delegateDrawer.goToHome(); - }, - icon: const Icon( - size: 16, - Icons.arrow_back_ios, - color: MyColors.textColorBlack, - ), - label: Text( - AppLocalizations.of(context)!.back, - style: const TextStyle( - color: MyColors.textColorBlack, - fontFamily: MyFonts.Medium, - fontSize: 14), - ), - style: ElevatedButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(5.0), - ), - elevation: 0, - backgroundColor: MyColors.backFillColor, - ), - ), - ), - const SizedBox(width: 8), - Container( - margin: const EdgeInsets.only(bottom: 6.0, top: 6.0), - height: 25, - width: 1, - color: MyColors.fillColorGray2, - ), - Flexible( - child: TabBar( - indicatorColor: Colors.white, - labelStyle: TextStyle( - fontSize: MyFonts.normalButton, - fontWeight: FontWeight.w500, - fontFamily: MyFonts.Bold, - color: MyColors.blueThemeColor), - isScrollable: true, - unselectedLabelStyle: const TextStyle( - fontSize: MyFonts.normalButton, - fontWeight: FontWeight.w500, - fontFamily: MyFonts.Medium, - color: MyColors.textColorBlack), - unselectedLabelColor: MyColors.textColorBlack, - labelColor: MyColors.blueThemeColor, - tabs: [ - Tab( - text: AppLocalizations.of(context)!.categories, - ), - const Tab( - text: 'Sub Categories', - ), - Tab( - text: AppLocalizations.of(context)!.measurements, - ), - Tab( - text: AppLocalizations.of(context)!.modifiers, - ), - Tab( - text: AppLocalizations.of(context)!.product, - ), - Tab( - text: 'Ingredient', - ), - Tab( - text: AppLocalizations.of(context)!.stock_transfer, - ), - Tab( - text: AppLocalizations.of(context)!.combo, - ), - Tab( - text: AppLocalizations.of(context)! - .delivery_partner_price, - ), - ], - )) - ], - ), + BackTabBarContainer( + onPressed: () { + widget.delegateDrawer.goToHome(); + }, + tabs: [ + Tab( + text: AppLocalizations.of(context)!.categories, + ), + const Tab( + text: 'Sub Categories', + ), + Tab( + text: AppLocalizations.of(context)!.measurements, + ), + const Tab( + text: 'Modifier Options', + ), + Tab( + text: AppLocalizations.of(context)!.modifiers, + ), + Tab( + text: AppLocalizations.of(context)!.product, + ), + const Tab( + text: 'Ingredient', + ), + const Tab( + text: 'Stock Return', + ), + Tab( + text: AppLocalizations.of(context)!.stock_transfer, + ), + Tab( + text: AppLocalizations.of(context)!.combo, + ), + Tab( + text: AppLocalizations.of(context)!.delivery_partner_price, + ), + ], ), const Expanded( child: TabBarView( @@ -147,9 +89,11 @@ class _InventoryModuleMainVCState extends State { InventoryCategoriesModule(), SubCategoryVC(), InventoryMeasurementVC(), + ModifierOptionVC(), InventoryModifierVC(), InventoryProductVC(), IngredientsVC(), + StockReturnVC(), InventoryStockTransferVC(), InventoryComboVC(), InventoryDeliveryPartnerPriceVC(), diff --git a/lib/application/views/inventorymodule/categoryviews/InventoryAddCategoryVC.dart b/lib/application/views/inventorymodule/categoryviews/InventoryAddCategoryVC.dart index 8ea8342..a55fb71 100644 --- a/lib/application/views/inventorymodule/categoryviews/InventoryAddCategoryVC.dart +++ b/lib/application/views/inventorymodule/categoryviews/InventoryAddCategoryVC.dart @@ -13,6 +13,7 @@ import 'package:wosull/base/BaseStatefulState.dart'; import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/ThemeText.dart'; import 'package:wosull/widgets/AlertDialogForPicture.dart'; +import 'package:wosull/widgets/CustomAppBar.dart'; import 'package:wosull/widgets/CustomOptionalTitle.dart'; import 'package:wosull/widgets/CustomSimpleButton.dart'; import 'package:wosull/widgets/CustomSwitch.dart'; @@ -47,34 +48,21 @@ class _InventoryAddCategoryVCState @override void initState() { + context.read().setDataOnEdit(widget.item); super.initState(); } @override Widget build(BuildContext context) { viewModel = context.watch(); - if (widget.isEdit) { - viewModel.setDataOnEdit(widget.item); - } - // else { - // viewModel.setStoreIds(widget.stores); - // } + return Directionality( textDirection: TextDirection.ltr, child: Scaffold( resizeToAvoidBottomInset: true, - appBar: AppBar( - leading: BackButton( - color: Colors.black, - onPressed: () { - Navigator.pop(context); - }, // <-- SEE HERE - ), - centerTitle: true, - backgroundColor: MyColors.white, - elevation: 5, - title: Text(AppLocalizations.of(context)!.category, - style: ThemeText.textStylePopUpHeading), + backgroundColor: MyColors.white, + appBar: CustomAppBar( + heading: AppLocalizations.of(context)!.category, ), body: OrientationBuilder(builder: (context, orientation) { isPortrait = @@ -151,7 +139,7 @@ class _InventoryAddCategoryVCState child: Container( padding: const EdgeInsets.only( bottom: 10, left: 10, right: 10), - color: Colors.transparent, + color: Colors.white, child: Text( AppLocalizations.of(context)! .product_image, @@ -303,12 +291,6 @@ class _InventoryAddCategoryVCState textStyle: ThemeText.textStyleValue, groupValue: viewModel.selectedType, onChanged: (value) { - // if (value == viewModel.types[0]) { - // widget.item.categoryAppliedOn = Constants.appliedTypes[0]; - // } else { - // widget.item.categoryAppliedOn = Constants.appliedTypes[1]; - // } - viewModel.setSelectedType(value); }, items: viewModel.types, diff --git a/lib/application/views/inventorymodule/categoryviews/InventoryCategoriesModule.dart b/lib/application/views/inventorymodule/categoryviews/InventoryCategoriesModule.dart index f84ec20..a64bb42 100644 --- a/lib/application/views/inventorymodule/categoryviews/InventoryCategoriesModule.dart +++ b/lib/application/views/inventorymodule/categoryviews/InventoryCategoriesModule.dart @@ -18,6 +18,7 @@ import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/ThemeText.dart'; import 'package:wosull/helpers/Utils.dart'; import 'package:wosull/widgets/CustomSimpleButton.dart'; +import 'package:wosull/widgets/PageLimitDropDown.dart'; import 'package:wosull/widgets/SearchBox.dart'; //view @@ -37,89 +38,40 @@ class _InventoryCategoriesModuleState @override void dispose() { - // TODO: implement dispose categoryViewModel.disposeData(); super.dispose(); } @override Widget build(BuildContext context) { - //not doing watch because using state to get the data - //and listener - // categoryViewModel = CategoryViewModel(); - //scroll state for pagination _controller = ScrollController()..addListener(_scrollNotification); - return WillPopScope( - child: Scaffold( - backgroundColor: MyColors.fillColor, - resizeToAvoidBottomInset: true, - body: OrientationBuilder(builder: (c, orientation) { - isPortrait = - MediaQuery.of(context).orientation == Orientation.portrait; - return SingleChildScrollView( - controller: _controller, - child: Container( - padding: const EdgeInsets.all(12), - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - isPortrait - ? Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Text( - AppLocalizations.of(context)!.categories, - style: ThemeText.textStylePageHeading, - ), - const SizedBox( - width: 4, - ), - SizedBox( - width: 120, - child: CustomSimpleButton( - textColor: MyColors.blueThemeColor, - backGroundColor: - MyColors.backColorBlue50, - heading: AppLocalizations.of(context)! - .new_categories, - onPressed: () { - showPopUP(false, ItemCategory()); - }, - ), - ), - ], - ), - AppSpaces.verticalSmall, - SizedBox( - height: 48, - child: SearchBox( - onEditingDone: (text) { - filterSearchResults(text); - }, - onChanged: (text) { - filterSearchResults(text); - }, - hint: AppLocalizations.of(context)!.search, - ), - ) - ], - ) - : Row( + return Scaffold( + backgroundColor: MyColors.fillColor, + resizeToAvoidBottomInset: true, + body: OrientationBuilder(builder: (c, orientation) { + isPortrait = + MediaQuery.of(context).orientation == Orientation.portrait; + return SingleChildScrollView( + controller: _controller, + child: Container( + padding: const EdgeInsets.all(12), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + isPortrait + ? Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( mainAxisAlignment: MainAxisAlignment.start, children: [ Text( AppLocalizations.of(context)!.categories, style: ThemeText.textStylePageHeading, ), - const SizedBox( - width: 4, - ), - SizedBox( - width: 120, + AppSpaces.horizontalSmall, + Flexible( child: CustomSimpleButton( textColor: MyColors.blueThemeColor, backGroundColor: MyColors.backColorBlue50, @@ -130,79 +82,127 @@ class _InventoryCategoriesModuleState }, ), ), - Expanded( - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - SizedBox( - width: SizerUtil.deviceType == - DeviceType.mobile - ? 240 - : 200, - height: 48, - child: SearchBox( - onEditingDone: (text) { - filterSearchResults(text); - }, - onChanged: (text) { - filterSearchResults(text); - }, - hint: AppLocalizations.of(context)! - .search, - ), - ), - ], - )) + AppSpaces.horizontalSmall, + PageLimitDropdown( + value: categoryViewModel.limit.toString(), + onChange: (value) { + categoryViewModel.fetchCategories( + isRefresh: true, + limit: int.parse(value!)); + }, + ) ], ), - const SizedBox( - height: 8, - ), - ChangeNotifierProvider( - create: (context) => categoryViewModel, - child: Consumer( - builder: (BuildContext context, - CategoryViewModel controller, Widget? _) { - switch (controller.dataState) { - case DataState.uninitialized: - Future(() { - controller.fetchCategories(); - }); - return categoryListViewWidget( - controller.filteredList); - case DataState.initialFetching: - return AppLoader(); - case DataState.moreFetching: - case DataState.refreshing: - return categoryListViewWidget( - controller.filteredList); - case DataState.error: - return AppError(); - case DataState.searching: - case DataState.fetched: - case DataState.noMoreData: - return categoryListViewWidget( - controller.filteredList); - } - }, + AppSpaces.verticalSmall, + SizedBox( + height: 48, + child: SearchBox( + onEditingDone: (text) { + filterSearchResults(text); + }, + onChanged: (text) { + filterSearchResults(text); + }, + hint: AppLocalizations.of(context)!.search, + ), + ), + ], + ) + : Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)!.categories, + style: ThemeText.textStylePageHeading, + ), + AppSpaces.horizontalSmall, + SizedBox( + width: 120, + child: CustomSimpleButton( + textColor: MyColors.blueThemeColor, + backGroundColor: MyColors.backColorBlue50, + heading: AppLocalizations.of(context)! + .new_categories, + onPressed: () { + showPopUP(false, ItemCategory()); + }, + ), + ), + Expanded( + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + SizedBox( + width: + SizerUtil.deviceType == DeviceType.mobile + ? 200 + : 200, + height: 48, + child: SearchBox( + onEditingDone: (text) { + filterSearchResults(text); + }, + onChanged: (text) { + filterSearchResults(text); + }, + hint: AppLocalizations.of(context)!.search, + ), + ), + AppSpaces.horizontalSmall, + PageLimitDropdown( + value: categoryViewModel.limit.toString(), + onChange: (value) { + categoryViewModel.fetchCategories( + isRefresh: true, + limit: int.parse(value!)); + }, + ) + ], + )) + ], ), - ), - ], + AppSpaces.verticalMedium, + ChangeNotifierProvider( + create: (context) => categoryViewModel, + child: Consumer( + builder: (BuildContext context, + CategoryViewModel controller, Widget? _) { + switch (controller.dataState) { + case DataState.uninitialized: + Future(() { + controller.fetchCategories( + limit: categoryViewModel.limit); + }); + return showData(controller.filteredList); + case DataState.initialFetching: + return AppLoader(); + case DataState.moreFetching: + case DataState.refreshing: + return showData(controller.filteredList); + case DataState.error: + return AppError(); + case DataState.searching: + case DataState.fetched: + case DataState.noMoreData: + return showData(controller.filteredList); + } + }, + ), ), - ), - ); - })), - onWillPop: () { - categoryViewModel.dispose(); - return Future.value(false); - }); + ], + ), + ), + ); + })); } - Widget categoryListViewWidget(List data) { + Widget showData(List data) { return Column( children: [ CategoryListView( data: data, + isPortrait: isPortrait, onUpdate: (item, status) { update(item.id, status); }, @@ -223,7 +223,7 @@ class _InventoryCategoriesModuleState bool _scrollNotification() { if (!categoryViewModel.isLoading && _controller.position.extentAfter < 300) { - categoryViewModel.fetchCategories(); + categoryViewModel.fetchCategories(limit: categoryViewModel.limit); } return true; } diff --git a/lib/application/views/inventorymodule/categoryviews/ViewInventoryCategoriesVC.dart b/lib/application/views/inventorymodule/categoryviews/ViewInventoryCategoriesVC.dart index 82d3294..ad61a10 100644 --- a/lib/application/views/inventorymodule/categoryviews/ViewInventoryCategoriesVC.dart +++ b/lib/application/views/inventorymodule/categoryviews/ViewInventoryCategoriesVC.dart @@ -4,7 +4,6 @@ import 'package:wosull/application/model/inventory/category/ViewItemCategory.dar import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/theme/MySeparator.dart'; import 'package:wosull/helpers/AppSpaces.dart'; -import 'package:wosull/helpers/ThemeText.dart'; import 'package:wosull/helpers/Utils.dart'; import 'package:wosull/widgets/DialogHeader.dart'; import 'package:wosull/widgets/HeadingText.dart'; @@ -23,7 +22,7 @@ class ViewInventoryCategoriesVC extends StatelessWidget { elevation: 0, backgroundColor: const Color(0xffffffff), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(15.0), + borderRadius: BorderRadius.circular(8.0), ), child: OrientationBuilder(builder: (c, orientation) { isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; @@ -192,18 +191,16 @@ class ViewInventoryCategoriesVC extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ - Text( + HeadingText( lang(context).category_applied_on, - style: ThemeText.labelStyleTextField, ), AppSpaces.horizontalMedium, const Expanded( child: MySeparator(color: Colors.grey), ), AppSpaces.horizontalMedium, - Text( + ValueText( item.storeIds.length > 1 ? "All Stores" : "Specific Stores", - style: ThemeText.textStyleViewValue, ) ], ); diff --git a/lib/application/views/inventorymodule/categoryviews/repo/CategoryRepository.dart b/lib/application/views/inventorymodule/categoryviews/repo/CategoryRepository.dart new file mode 100644 index 0000000..c8753df --- /dev/null +++ b/lib/application/views/inventorymodule/categoryviews/repo/CategoryRepository.dart @@ -0,0 +1,98 @@ +import 'package:dio/dio.dart'; +import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/application/model/SimpleResponsModel.dart'; +import 'package:wosull/application/model/inventory/category/ItemCategory.dart'; +import 'package:wosull/application/model/inventory/category/ItemCategoryResponse.dart'; +import 'package:wosull/application/model/inventory/category/ViewItemCategoryResponse.dart'; +import 'package:wosull/application/model/store/GetSpecificStores.dart'; +import 'package:wosull/application/model/store/WosulStore.dart'; +import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/utils/Constants.dart'; + +class CategoryRepository { + final dio = Dio(); + + Future> fetchCategories(Map data) async { + var categories = []; + await APIManager() + .fetchData(Constants.ITEM_TYPE_CATEGORIES_URL, data) + .then((result) { + final value = ItemCategoryResponse.fromJson(result); + if (value.success) { + categories.addAll(value.categories); + } + }).onError((error, stackTrace) {}); + return categories; + } + + Future> searchCategory(Map data) async { + var categories = []; + await APIManager() + .fetchData(Constants.SEARCH_CATEGORY, data) + .then((result) { + final value = ItemCategoryResponse.fromJson(result); + if (value.success) { + categories.addAll(value.categories); + } + }).onError((error, stackTrace) {}); + return categories; + } + + Future addNewCategory(FormData formData) async { + dio.options.headers['content-Type'] = 'application/json'; + dio.options.headers["Authorization"] = Constants.auth; + final response = await dio.post(Constants.baseURL + Constants.ADD_CATEGORY, + data: formData); + return SimpleResponse.fromJson(response.data); + } + + Future updateCategoryData(FormData formData) async { + dio.options.headers['content-Type'] = 'application/json'; + dio.options.headers["Authorization"] = Constants.auth; + final response = await dio + .post(Constants.baseURL + Constants.UPDATE_CATEGORY, data: formData); + return SimpleResponse.fromJson(response.data); + } + + Future getCategoryById(String id) async { + dynamic response = await APIManager() + .getResponseAuth('${Constants.GET_CATEGORY_BY_ID}$id'); + return ViewItemCategoryResponse.fromJson(response); + } + + Future> getStores() async { + var stores = []; + Map data = { + 'is_included': true, + 'store_id': sharedPrefs.storeId, + }; + await APIManager() + .fetchData(Constants.GET_SPECIFIC_STORES, data) + .then((response) { + final value = GetSpecificStores.fromJson(response); + if (value.success) { + stores.clear(); + stores.addAll(value.stores); + } + }).onError((error, stackTrace) {}); + + return stores; + } + + Future deleteCategory(String id) async { + Map data = {'categoryId': id}; + final response = + await APIManager().getResponsePatch(Constants.DELETE_CATEGORY, data); + return response; + } + + Future updateCategory(String id, bool value) async { + Map data = { + 'categoryId': id, + 'is_visible_in_store': value + }; + final response = await APIManager() + .getResponsePatch(Constants.UPDATE_CATEGORY_STATUS, data); + return response; + } +} diff --git a/lib/application/views/inventorymodule/categoryviews/viewModels/AddCategoryViewModel.dart b/lib/application/views/inventorymodule/categoryviews/viewModels/AddCategoryViewModel.dart index 51b6c10..2497016 100644 --- a/lib/application/views/inventorymodule/categoryviews/viewModels/AddCategoryViewModel.dart +++ b/lib/application/views/inventorymodule/categoryviews/viewModels/AddCategoryViewModel.dart @@ -4,16 +4,16 @@ import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'package:image_picker/image_picker.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; -import 'package:wosull/application/model/SimpleResponsModel.dart'; import 'package:wosull/application/model/inventory/category/ItemCategory.dart'; -import 'package:wosull/application/model/store/GetSpecificStores.dart'; import 'package:wosull/application/model/store/WosulStore.dart'; -import 'package:wosull/application/network/APIManager.dart'; import 'package:wosull/application/utils/CRUDOperatoinState.dart'; import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/inventorymodule/categoryviews/repo/CategoryRepository.dart'; import 'package:wosull/helpers/Utils.dart'; class AddCategoryViewModel with ChangeNotifier { + var repository = CategoryRepository(); + var categoryName = ''; var arabicName = ''; @@ -48,7 +48,6 @@ class AddCategoryViewModel with ChangeNotifier { String getStoresName() { String name = ""; - print('here'); for (var storeName in _selectedStoreObject) { if (name.isEmpty) { name = storeName.name; @@ -120,24 +119,14 @@ class AddCategoryViewModel with ChangeNotifier { } Future> getStores(ItemCategory itemCategory) async { - var stores = []; - Map data = { - 'is_included': true, - 'store_id': sharedPrefs.storeId, - }; - await APIManager() - .fetchData(Constants.GET_SPECIFIC_STORES, data) - .then((response) { - final value = GetSpecificStores.fromJson(response); - if (value.success) { - stores.clear(); - stores.addAll(value.stores); + await repository.getStores().then((value) { + if (value.isNotEmpty) { if (isEdit) { if (itemCategory.store_id!.isNotEmpty && itemCategory.categoryAppliedOn == Constants.appliedTypes[1]) { storeIds.clear(); _selectedStoreObject.clear(); - Future.forEach(stores, (element) { + Future.forEach(value, (element) { if (itemCategory.store_id!.contains(element.id)) { _selectedStoreObject.add(element); storeIds.add(element.id); @@ -145,13 +134,11 @@ class AddCategoryViewModel with ChangeNotifier { }); } } - allStoresData.clear(); - allStoresData.addAll(stores); + allStoresData.addAll(value); } }).onError((error, stackTrace) {}); - - return stores; + return allStoresData; } getFromGallery() async { @@ -212,7 +199,7 @@ class AddCategoryViewModel with ChangeNotifier { types[0] == selectedType ? 'allStores' : 'specificStore', 'is_special_category': false, 'is_visible_in_store': activeInActiveStatus, - 'category_arabic_description': 'filter', + 'category_arabic_description': '', 'category_arabic_name': arabicName, 'description': 'none', 'image_url': @@ -225,6 +212,7 @@ class AddCategoryViewModel with ChangeNotifier { 'name': categoryName, 'store_id': storeIds, 'category_id': id, + 'store_id': sharedPrefs.storeId, 'category_applied_on': types[0] == selectedType ? 'allStores' : 'specificStore', 'is_special_category': false, @@ -293,12 +281,8 @@ class AddCategoryViewModel with ChangeNotifier { formData = getParams(); } - addHeaders(); - await dio - .post(Constants.baseURL + Constants.ADD_CATEGORY, data: formData) - .then((value) { + await repository.addNewCategory(formData).then((response) { setLoading(false); - final response = SimpleResponse.fromJson(value.data); if (response.success!) { Utils.showMessage('Added Successfully'); setState(CRUDOperationState.saved); @@ -314,17 +298,27 @@ class AddCategoryViewModel with ChangeNotifier { setLoading(true); FormData formData; if (imageFile != null) { - formData = getUpdateParamsWithImage(id) as FormData; + formData = FormData.fromMap({ + 'name': categoryName, + 'store_id': sharedPrefs.storeId, + 'store_id': storeIds, + 'category_id': id, + 'category_applied_on': + types[0] == selectedType ? 'allStores' : 'specificStore', + 'is_special_category': false, + 'is_visible_in_store': activeInActiveStatus, + 'category_arabic_description': '', + 'category_arabic_name': arabicName, + 'description': 'none', + 'image_url': + await MultipartFile.fromFile(imageFile!.path, filename: 'wosul'), + }); } else { formData = getUpdateParams(id); } - addHeaders(); - await dio - .post(Constants.baseURL + Constants.UPDATE_CATEGORY, data: formData) - .then((value) { + await repository.updateCategoryData(formData).then((response) { setLoading(false); - final response = SimpleResponse.fromJson(value.data); if (response.success!) { Utils.showMessage('Updated Successfully'); setState(CRUDOperationState.update); @@ -337,7 +331,6 @@ class AddCategoryViewModel with ChangeNotifier { } void setSelectedStore(List data) { - print('length ' + data.length.toString()); _selectedStoreObject.clear(); _selectedStoreObject.addAll(data); storeIds.clear(); @@ -346,9 +339,4 @@ class AddCategoryViewModel with ChangeNotifier { } notifyListeners(); } - - void addHeaders() { - dio.options.headers['content-Type'] = 'application/json'; - dio.options.headers["Authorization"] = Constants.auth; - } } diff --git a/lib/application/views/inventorymodule/categoryviews/viewModels/CategoryViewModel.dart b/lib/application/views/inventorymodule/categoryviews/viewModels/CategoryViewModel.dart index 3419235..a5455e0 100644 --- a/lib/application/views/inventorymodule/categoryviews/viewModels/CategoryViewModel.dart +++ b/lib/application/views/inventorymodule/categoryviews/viewModels/CategoryViewModel.dart @@ -2,13 +2,10 @@ import 'package:flutter/material.dart'; import 'package:wosull/application/enum/DataState.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; import 'package:wosull/application/model/inventory/category/ItemCategory.dart'; -import 'package:wosull/application/model/inventory/category/ItemCategoryResponse.dart'; import 'package:wosull/application/model/inventory/category/ViewItemCategory.dart'; -import 'package:wosull/application/model/inventory/category/ViewItemCategoryResponse.dart'; -import 'package:wosull/application/network/APIManager.dart'; import 'package:wosull/application/network/WosulError.dart'; import 'package:wosull/application/utils/CRUDOperatoinState.dart'; -import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/inventorymodule/categoryviews/repo/CategoryRepository.dart'; class CategoryViewModel extends ChangeNotifier { int _currentPageNumber = 1; @@ -36,6 +33,9 @@ class CategoryViewModel extends ChangeNotifier { List get filteredList => _filteredList; + var repository = CategoryRepository(); + + int limit = 10; var wosulError = WosulError(message: ''); late ViewItemCategory category; @@ -46,7 +46,8 @@ class CategoryViewModel extends ChangeNotifier { _currentPageNumber = 1; } - fetchCategories({bool isRefresh = false}) async { + fetchCategories({bool isRefresh = false, int limit = 10}) async { + this.limit = limit; _isLoading = true; if (!isRefresh) { _dataState = (_dataState == DataState.uninitialized) @@ -61,24 +62,21 @@ class CategoryViewModel extends ChangeNotifier { Map data = { 'store_id': sharedPrefs.storeId, 'page': _currentPageNumber, + 'limit': this.limit }; - try { if (_didLastLoad) { _dataState = DataState.noMoreData; } else { - await APIManager() - .fetchData(Constants.ITEM_TYPE_CATEGORIES_URL, data) - .then((result) { - final value = ItemCategoryResponse.fromJson(result); + await repository.fetchCategories(data).then((value) { if (_dataState == DataState.refreshing) { _filteredList.clear(); _dataList.clear(); } - if (value.success) { - _filteredList.addAll(value.categories); - _dataList.addAll(value.categories); - if (value.categories.length < 10) { + if (value.isNotEmpty) { + _filteredList.addAll(value); + _dataList.addAll(value); + if (value.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; @@ -102,10 +100,7 @@ class CategoryViewModel extends ChangeNotifier { } Future deleteCategory(String id) async { - Map data = {'categoryId': id}; - await APIManager() - .getResponsePatch(Constants.DELETE_CATEGORY, data) - .then((result) { + await repository.deleteCategory(id).then((result) { if (result.success) { _filteredList.removeWhere((element) => element.id == id); _dataList.removeWhere((element) => element.id == id); @@ -122,13 +117,7 @@ class CategoryViewModel extends ChangeNotifier { } Future updateCategory(String id, bool value) async { - Map data = { - 'categoryId': id, - 'is_visible_in_store': value - }; - await APIManager() - .getResponsePatch(Constants.UPDATE_CATEGORY_STATUS, data) - .then((result) { + await repository.updateCategory(id, value).then((result) { if (result.success) { int index = _filteredList.indexWhere((element) => element.id == id); _filteredList[index].isVisibleInStore = value; @@ -160,13 +149,10 @@ class CategoryViewModel extends ChangeNotifier { _dataState = DataState.searching; notifyListeners(); try { - await APIManager() - .fetchData(Constants.SEARCH_CATEGORY, data) - .then((result) { - final value = ItemCategoryResponse.fromJson(result); + await repository.searchCategory(data).then((value) { _filteredList.clear(); - if (value.success) { - _filteredList.addAll(value.categories); + if (value.isNotEmpty) { + _filteredList.addAll(value); } _dataState = DataState.fetched; }).onError((error, stackTrace) { @@ -180,15 +166,8 @@ class CategoryViewModel extends ChangeNotifier { } } - Future getCategoryById(String id) async { - dynamic response = await APIManager() - .getResponseAuth('${Constants.GET_CATEGORY_BY_ID}$id'); - - return ViewItemCategoryResponse.fromJson(response); - } - Future viewCategory(String id) async { - await getCategoryById(id).then((value) { + await repository.getCategoryById(id).then((value) { if (value.success) { category = value.categories; _crudOperationState = CRUDOperationState.view; diff --git a/lib/application/views/inventorymodule/categoryviews/widgets/CategoryListView.dart b/lib/application/views/inventorymodule/categoryviews/widgets/CategoryListView.dart index 0f72f18..2d7cc8f 100644 --- a/lib/application/views/inventorymodule/categoryviews/widgets/CategoryListView.dart +++ b/lib/application/views/inventorymodule/categoryviews/widgets/CategoryListView.dart @@ -2,15 +2,19 @@ import 'package:flutter/material.dart'; import 'package:wosull/application/model/converters/DataTimeFormat.dart'; import 'package:wosull/application/model/inventory/category/ItemCategory.dart'; import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/Utils.dart'; +import 'package:wosull/widgets/ActionPopUpContainer.dart'; +import 'package:wosull/widgets/CustomPopuoMenuButton.dart'; import 'package:wosull/widgets/CustomSwitch.dart'; import 'package:wosull/widgets/EmptyDataWidget.dart'; import 'package:wosull/widgets/HeadingText.dart'; +import 'package:wosull/widgets/ListHeadingContainer.dart'; import 'package:wosull/widgets/ValueText.dart'; class CategoryListView extends StatelessWidget { List data; - + bool isPortrait = false; final void Function(ItemCategory itemCategory, bool status) onUpdate; final void Function(ItemCategory itemCategory) onDelete; final void Function(ItemCategory itemCategory) onView; @@ -18,6 +22,7 @@ class CategoryListView extends StatelessWidget { CategoryListView( {super.key, + required this.isPortrait, required this.data, required this.onUpdate, required this.onDelete, @@ -30,122 +35,166 @@ class CategoryListView extends StatelessWidget { ? const EmptyDataWidget() : Column( children: [ - Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 50, - color: MyColors.containerBackColor, - child: Row( - children: [ - Expanded(child: HeadingText(lang(context).name)), - Expanded( - child: Align( - alignment: Alignment.center, - child: HeadingText( - lang(context).status, - ), - )), - Expanded( - child: HeadingText( - lang(context).created_on, - )), - Expanded( - child: HeadingText( - lang(context).updated_on, - )), - Expanded( - child: Padding( - padding: const EdgeInsets.only(right: 16), - child: Align( - alignment: Alignment.centerRight, - child: HeadingText( - lang(context).action, - ), - ), - )), - ], - ), - ), - ListView.builder( - physics: const NeverScrollableScrollPhysics(), - padding: EdgeInsets.zero, - scrollDirection: Axis.vertical, - shrinkWrap: true, - itemBuilder: (c, position) { - return Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - child: Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 56, - color: MyColors.containerBackColor, + isPortrait + ? Container() + : ListHeadingContainer( child: Row( children: [ - Expanded( - child: ValueText( - data[position].name, - )), + Expanded(child: HeadingText(lang(context).name)), Expanded( child: Align( alignment: Alignment.centerLeft, - child: CustomSwitch( - value: data[position].isVisibleInStore, - onToggle: (value) { - onUpdate(data[position], value); - }), + child: HeadingText( + lang(context).status, + ), )), Expanded( - child: ValueText( - DataTimeFormat.getFormatDate( - data[position].createdAt), + child: HeadingText( + lang(context).created_on, )), Expanded( - child: ValueText( - DataTimeFormat.getFormatDate( - data[position].updatedAt), + child: HeadingText( + lang(context).updated_on, )), Expanded( child: Padding( - padding: const EdgeInsets.all(4), + padding: const EdgeInsets.only(right: 16), child: Align( alignment: Alignment.centerRight, - child: Container( - width: 42, - height: 42, - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular(4)), - color: MyColors.backFillColor), - child: PopupMenuButton( - padding: EdgeInsets.zero, - icon: const Icon(Icons.more_vert), - itemBuilder: (c) { - return [ - PopupMenuItem( - value: 'edit', - child: ValueText(lang(context)!.edit), - ), - PopupMenuItem( - value: 'view', - child: ValueText(lang(context).view), - ), - PopupMenuItem( - value: 'delete', - child: ValueText(lang(context)!.delete), - ) - ]; - }, - onSelected: (String value) => - actionPopUpItemSelected( - value, data[position], position), - ), + child: HeadingText( + lang(context).action, ), ), - )) + )), ], ), ), - ); + ListView.builder( + physics: const NeverScrollableScrollPhysics(), + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, + shrinkWrap: true, + itemBuilder: (c, position) { + if (isPortrait) { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + elevation: 2, + color: MyColors.white, + child: Container( + padding: const EdgeInsets.fromLTRB(8, 0, 0, 8), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + child: Container( + padding: const EdgeInsets.only(top: 16), + child: Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + HeadingText( + lang(context).category_name, + ), + AppSpaces.verticalMedium, + HeadingText(lang(context).created_on), + AppSpaces.verticalMedium, + HeadingText(lang(context).updated_on), + AppSpaces.verticalMedium, + HeadingText(lang(context).status), + ], + )), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + ValueText(data[position].name), + AppSpaces.verticalMedium, + ValueText(DataTimeFormat.getFormatDate( + data[position].createdAt)), + AppSpaces.verticalMedium, + ValueText(DataTimeFormat.getFormatDate( + data[position].updatedAt)), + AppSpaces.verticalSmall, + Row( + mainAxisAlignment: + MainAxisAlignment.end, + crossAxisAlignment: + CrossAxisAlignment.end, + children: [ + CustomSwitch( + value: + data[position].isVisibleInStore, + onToggle: (value) { + onUpdate(data[position], value); + }, + ) + ], + ), + ], + )), + ], + ), + )), + getMenuBuilder(context, position) + ], + ), + ), + ); + } else { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: ListHeadingContainer( + child: Row( + children: [ + Expanded( + child: ValueText( + data[position].name, + )), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: CustomSwitch( + value: data[position].isVisibleInStore, + onToggle: (value) { + onUpdate(data[position], value); + }), + )), + Expanded( + child: ValueText( + DataTimeFormat.getFormatDate( + data[position].createdAt), + )), + Expanded( + child: ValueText( + DataTimeFormat.getFormatDate( + data[position].updatedAt), + )), + Expanded( + child: Padding( + padding: const EdgeInsets.all(4), + child: Align( + alignment: Alignment.centerRight, + child: ActionPopUpContainer( + child: getMenuBuilder(context, position), + ), + ), + )) + ], + ), + ), + ); + } }, itemCount: data.length, ) @@ -154,7 +203,7 @@ class CategoryListView extends StatelessWidget { } Future actionPopUpItemSelected( - String value, ItemCategory itemCategory, int position) async { + String value, ItemCategory itemCategory) async { if (value == 'edit') { onEdit(itemCategory); } else if (value == 'delete') { @@ -163,4 +212,29 @@ class CategoryListView extends StatelessWidget { onView(itemCategory); } } + + getMenuBuilder(BuildContext context, int position) { + return CustomPopupMenuButton( + onSelected: (String value) => + actionPopUpItemSelected(value, data[position]), + items: getMenuList(context), + ); + } + + List> getMenuList(context) { + return [ + PopupMenuItem( + value: 'edit', + child: ValueText(lang(context).edit), + ), + PopupMenuItem( + value: 'view', + child: ValueText(lang(context).view), + ), + PopupMenuItem( + value: 'delete', + child: ValueText(lang(context).delete), + ) + ]; + } } diff --git a/lib/application/views/inventorymodule/comboviews/ComboAddSizesVC.dart b/lib/application/views/inventorymodule/comboviews/ComboAddSizesVC.dart index df3b3eb..161a9af 100644 --- a/lib/application/views/inventorymodule/comboviews/ComboAddSizesVC.dart +++ b/lib/application/views/inventorymodule/comboviews/ComboAddSizesVC.dart @@ -1,347 +1,187 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:wosull/application/ViewModel/InventoryViewModel.dart'; -import 'package:wosull/application/model/Combo/GetComboSizes.dart'; -import 'package:wosull/application/model/SimpleResponsModel.dart'; +import 'package:provider/provider.dart'; import 'package:wosull/application/theme/MyColors.dart'; -import 'package:wosull/application/theme/MyFonts.dart'; -import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/utils/AppLoader.dart'; +import 'package:wosull/application/utils/CRUDOperatoinState.dart'; +import 'package:wosull/application/views/inventorymodule/comboviews/viewModels/AddComboSizeViewModel.dart'; import 'package:wosull/base/BaseStatefulState.dart'; import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/widgets/CustomSimpleButton.dart'; +import 'package:wosull/widgets/CustomTextFieldForm.dart'; +import 'package:wosull/widgets/DialogHeader.dart'; +import 'package:wosull/widgets/MandatoryTitleText.dart'; class ComboAddSizesVC extends StatefulWidget { - late ComboSize comboSize; - - ComboAddSizesVC({Key? key, required this.comboSize}) : super(key: key); + const ComboAddSizesVC({ + Key? key, + }) : super(key: key); @override State createState() => _ComboAddSizesVCState(); } class _ComboAddSizesVCState extends BaseStatefulState { - List _controller = List.empty(growable: true); - bool isPortrait = true; - bool isLoading = false; - TextEditingController newSizeController = TextEditingController(); + var viewModel = AddComboSizeViewModel(); + + @override + void dispose() { + viewModel.disposeData(); + super.dispose(); + } @override void initState() { - // TODO: implement initState + context.read().getComboSizes(); super.initState(); - if (widget.comboSize.sizes != null) { - for (var size in widget.comboSize.sizes!) { - _controller.add(TextEditingController(text: size)); - } - } else { - _controller.add(TextEditingController(text: "")); - } } @override Widget build(BuildContext context) { + viewModel = context.watch(); return Directionality( textDirection: TextDirection.ltr, child: Dialog( elevation: 0, backgroundColor: const Color(0xffffffff), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(15.0), + borderRadius: BorderRadius.circular(8.0), ), child: OrientationBuilder(builder: (context, orientation) { - isPortrait = + viewModel.isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; return SingleChildScrollView( - child: Container( - width: !isPortrait - ? MediaQuery.of(context).size.width / 1.2 - : double.infinity, - padding: const EdgeInsets.only(bottom: 8), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.end, - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.max, - children: [ - Expanded( - child: Padding( - padding: const EdgeInsets.only(left: 16), - child: Text( - AppLocalizations.of(context)!.sizes, - style: MyColors.textStylePopUpHeading(), - ), - )), - Align( - alignment: Alignment.topRight, - child: IconButton( - onPressed: () { - Navigator.of(context).pop(); - }, - icon: const Icon(Icons.close)), - ), - ], - ), - Container( - height: 2, - color: MyColors.fillColorGray, - ), - Padding( - padding: const EdgeInsets.all(16), + child: viewModel.crudOperation == CRUDOperationState.uninitialized + ? AppLoader() + : Container( + width: !viewModel.isPortrait + ? MediaQuery.of(context).size.width / 1.2 + : double.infinity, + padding: const EdgeInsets.only(bottom: 8), child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, children: [ - AppSpaces.verticalSmall, - ListView.builder( - padding: EdgeInsets.zero, - scrollDirection: Axis.vertical, - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - itemBuilder: (context, position) { - return Column( - crossAxisAlignment: CrossAxisAlignment.end, - mainAxisAlignment: MainAxisAlignment.end, - children: [ - const SizedBox( - height: 4, - ), - Row( - children: [ - Text( - AppLocalizations.of(context)!.size_name, - style: const TextStyle( - fontSize: MyFonts.normalButton, - fontFamily: MyFonts.Medium, - color: MyColors.black), - ), - const Text( - '*', - style: TextStyle( - fontSize: MyFonts.normalButton, - fontFamily: MyFonts.Medium, - color: MyColors.fillRed), - ), - ], - ), - Row( - children: [ - Flexible( - child: SizedBox( - height: 42, - child: TextField( - controller: _controller[position], - onChanged: (value) { - widget.comboSize.sizes![position] = - value; - }, - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normalButton, - color: MyColors.black), - decoration: InputDecoration( - contentPadding: - const EdgeInsets.fromLTRB( - 8, 0, 8, 0), - fillColor: MyColors.fillColor2, - filled: true, - focusedBorder: OutlineInputBorder( - borderSide: const BorderSide( - color: Colors.transparent, - width: 1.0), - borderRadius: - BorderRadius.circular(8.0), - ), - enabledBorder: OutlineInputBorder( - borderSide: const BorderSide( - width: 1, //<-- SEE HERE - color: Colors.transparent, + DialogHeader( + title: AppLocalizations.of(context)!.sizes), + Padding( + padding: const EdgeInsets.all(12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ListView.builder( + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (context, position) { + return Column( + crossAxisAlignment: + CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + AppSpaces.verticalSmall, + MandatoryTitleText( + hint: AppLocalizations.of(context)! + .size_name), + Row( + children: [ + Flexible( + child: CustomTextFieldForm( + initialValue: viewModel + .controller[position], + onChanged: (value) { + viewModel.controller[position] = + value; + }, + hintText: '', + )), + AppSpaces.horizontalMedium, + SizedBox( + width: 100, + child: CustomSimpleButton( + textColor: + MyColors.textColorBlack20, + backGroundColor: + MyColors.fillColorGray2, + onPressed: () { + viewModel + .removeSize(position); + }, + heading: AppLocalizations.of( + context)! + .remove, ), - borderRadius: - BorderRadius.circular(8.0), - ), - ), - ), - )), - const SizedBox( - width: 8, + ) + ], + ) + ], + ); + }, + itemCount: viewModel.controller.length, + ), + AppSpaces.verticalMedium, + Row( + children: [ + Flexible( + child: SizedBox( + height: 42, + child: CustomTextFieldForm( + hintText: 'Enter Size Name', + key: Key(viewModel.newSizeController), + initialValue: + viewModel.newSizeController, + onChanged: (String value) { + viewModel.newSizeController = value; + }, ), - SizedBox( + )), + AppSpaces.horizontalMedium, + SizedBox( width: 100, - child: ElevatedButton( - style: ElevatedButton.styleFrom( - elevation: 0, - shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.circular(8.0), - ), - backgroundColor: - MyColors.fillColorGray2, - minimumSize: const Size.fromHeight( - 38), // NEW - ), + child: CustomSimpleButton( + textColor: MyColors.textColorBlack20, + backGroundColor: + MyColors.fillColorGray2, onPressed: () { - setState(() { - _controller.removeAt(position); - widget.comboSize.sizes! - .removeAt(position); - }); + viewModel.addNewSizeToList(); }, - child: Text( - AppLocalizations.of(context)! - .remove, - style: const TextStyle( - fontSize: MyFonts.normal, - fontWeight: FontWeight.w500, - color: MyColors.textColorBlack, - fontFamily: MyFonts.Bold), - ), - ), - ) - ], - ) - ], - ); - }, - itemCount: widget.comboSize.sizes == null - ? 0 - : widget.comboSize.sizes!.length, + heading: + AppLocalizations.of(context)!.add, + )) + ], + ) + ], + ), ), - AppSpaces.verticalMedium, - Row( - children: [ - Flexible( - child: SizedBox( - height: 42, - child: TextField( - controller: newSizeController, - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normalButton, - color: MyColors.black), - decoration: InputDecoration( - contentPadding: - const EdgeInsets.fromLTRB(8, 0, 8, 0), - hintText: 'Enter Size Name', - fillColor: MyColors.fillColor2, - filled: true, - focusedBorder: OutlineInputBorder( - borderSide: const BorderSide( - color: Colors.transparent, - width: 1.0), - borderRadius: BorderRadius.circular(8.0), - ), - enabledBorder: OutlineInputBorder( - borderSide: const BorderSide( - width: 1, //<-- SEE HERE - color: Colors.transparent, - ), - borderRadius: BorderRadius.circular(8.0), - ), - ), - ), - )), - const SizedBox( - width: 8, + Padding( + padding: const EdgeInsets.all(16), + child: SizedBox( + width: 120, + child: CustomSimpleButton( + isLoading: viewModel.isLoading, + textColor: MyColors.white, + backGroundColor: MyColors.blueThemeColor, + onPressed: () async { + await viewModel.isValidate(); + checkState(); + }, + heading: AppLocalizations.of(context)!.save, ), - SizedBox( - width: 100, - child: ElevatedButton( - style: ElevatedButton.styleFrom( - elevation: 0, - shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.circular(8.0), - ), - backgroundColor: MyColors.fillColorGray2, - minimumSize: - const Size.fromHeight(38), // NEW - ), - onPressed: () { - setState(() { - if (newSizeController.text.isNotEmpty) { - widget.comboSize.sizes ??= []; - - _controller.add(TextEditingController( - text: newSizeController.text)); - widget.comboSize.sizes! - .add(newSizeController.text); - newSizeController.text = ""; - } else { - showMessage('Enter Size name'); - } - }); - }, - child: Text( - AppLocalizations.of(context)!.add, - style: const TextStyle( - fontSize: MyFonts.normal, - fontWeight: FontWeight.w500, - color: MyColors.textColorBlack, - fontFamily: MyFonts.Bold), - ), - )) - ], + ), ) ], ), ), - Padding( - padding: const EdgeInsets.all(16), - child: SizedBox( - child: isLoading - ? const Center( - child: CircularProgressIndicator(), - ) - : ElevatedButton( - style: ElevatedButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(6.0), - ), - backgroundColor: MyColors.blueThemeColor, - minimumSize: const Size.fromHeight(38), // NEW - ), - onPressed: () { - if (widget.comboSize.sizes!.isNotEmpty) { - addUpdateSize(); - } else { - showMessage('Add Atleast One Size'); - } - }, - child: Text( - AppLocalizations.of(context)!.save, - style: const TextStyle( - fontSize: MyFonts.normalButton, - color: MyColors.white, - fontFamily: MyFonts.Bold), - ), - ), - width: 120, - ), - ) - ], - ), - ), ); }), )); } - void addUpdateSize() async { - setState(() { - isLoading = true; - }); - - InventoryViewModel viewModel = InventoryViewModel(); - await viewModel - .getData(Constants.ADD_COMBO_SIZES, widget.comboSize.toJson()) - .then((value) { - final response = SimpleResponseModel.fromJson(value); - - if (response.success!) { - showMessage(response.message!); - Navigator.pop(context, true); - } else {} - }).onError((error, stackTrace) {}); + void checkState() { + if (viewModel.crudOperation == CRUDOperationState.add) { + Navigator.pop(context, true); + } } } diff --git a/lib/application/views/inventorymodule/comboviews/ComboInformationPopup.dart b/lib/application/views/inventorymodule/comboviews/ComboInformationPopup.dart index 01b64e0..013beef 100644 --- a/lib/application/views/inventorymodule/comboviews/ComboInformationPopup.dart +++ b/lib/application/views/inventorymodule/comboviews/ComboInformationPopup.dart @@ -25,7 +25,7 @@ class _ComboInformationPopupState extends State { elevation: 0, backgroundColor: const Color(0xffffffff), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(15.0), + borderRadius: BorderRadius.circular(8.0), ), child: OrientationBuilder(builder: (c, orientation) { isPortrait = diff --git a/lib/application/views/inventorymodule/comboviews/CreateComboGroupVC.dart b/lib/application/views/inventorymodule/comboviews/CreateComboGroupVC.dart index 24724e2..bbd2ef2 100644 --- a/lib/application/views/inventorymodule/comboviews/CreateComboGroupVC.dart +++ b/lib/application/views/inventorymodule/comboviews/CreateComboGroupVC.dart @@ -1,13 +1,20 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:wosull/application/ViewModel/InventoryViewModel.dart'; -import 'package:wosull/application/model/Combo/GetComboModel.dart'; -import 'package:wosull/application/model/SimpleResponsModel.dart'; +import 'package:provider/provider.dart'; import 'package:wosull/application/theme/MyColors.dart'; -import 'package:wosull/application/theme/MyFonts.dart'; -import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/utils/CRUDOperatoinState.dart'; +import 'package:wosull/application/views/inventorymodule/comboviews/viewModels/AddComboGroupViewModel.dart'; import 'package:wosull/base/BaseStatefulState.dart'; import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/widgets/BorderContainer.dart'; +import 'package:wosull/widgets/ChildContainer.dart'; +import 'package:wosull/widgets/CustomOptionalTitle.dart'; +import 'package:wosull/widgets/CustomRemoveItemButton.dart'; +import 'package:wosull/widgets/CustomSimpleButton.dart'; +import 'package:wosull/widgets/CustomTextFieldForm.dart'; +import 'package:wosull/widgets/DialogHeader.dart'; +import 'package:wosull/widgets/HeadingContainer.dart'; +import 'package:wosull/widgets/WrapHeightContainer.dart'; class CreateComboGroupVC extends StatefulWidget { const CreateComboGroupVC({Key? key}) : super(key: key); @@ -17,36 +24,31 @@ class CreateComboGroupVC extends StatefulWidget { } class _CreateComboGroupVCState extends BaseStatefulState { - bool isPortrait = true; - bool isLoading = false; - AddComboGroup addComboGroup = AddComboGroup(); - List _subGroupNameController = []; - TextEditingController groupName = TextEditingController(); + var viewModel = AddComboGroupViewModel(); @override void initState() { - // TODO: implement initState + context.read().init(); super.initState(); - addComboGroup.subGroups = List.empty(growable: true); - addComboGroup.subGroups!.add(ComboSubGroup(name: "")); } @override Widget build(BuildContext context) { + viewModel = context.watch(); return Directionality( textDirection: TextDirection.ltr, child: Dialog( elevation: 0, backgroundColor: const Color(0xffffffff), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(15.0), + borderRadius: BorderRadius.circular(8.0), ), child: OrientationBuilder(builder: (context, orientation) { - isPortrait = + viewModel.isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; return SingleChildScrollView( child: Container( - width: !isPortrait + width: !viewModel.isPortrait ? MediaQuery.of(context).size.width / 1.2 : double.infinity, padding: const EdgeInsets.only(bottom: 8), @@ -55,136 +57,37 @@ class _CreateComboGroupVCState extends BaseStatefulState { crossAxisAlignment: CrossAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end, children: [ - Row( - mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.max, - children: [ - Expanded( - child: Padding( - padding: const EdgeInsets.only(left: 16), - child: Text( - AppLocalizations.of(context)!.create_combo_group, - style: MyColors.textStylePopUpHeading(), - ), - )), - Align( - alignment: Alignment.topRight, - child: IconButton( - onPressed: () { - Navigator.of(context).pop(); - }, - icon: const Icon(Icons.close)), - ), - ], - ), - Container( - height: 2, - color: MyColors.fillColorGray, - ), + DialogHeader( + title: + AppLocalizations.of(context)!.create_combo_group), Padding( - padding: const EdgeInsets.all(16), + padding: const EdgeInsets.all(12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - AppLocalizations.of(context)!.group_name, - style: TextStyle( - fontSize: MyFonts.normalButton, - fontWeight: FontWeight.w600, - fontFamily: MyFonts.DMREGULAR, - color: MyColors.textColorPopUp), + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.group_name, ), AppSpaces.verticalSmall, - SizedBox( - height: 42, - child: TextField( - controller: groupName, - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normalButton, - color: MyColors.black), - decoration: InputDecoration( - contentPadding: - const EdgeInsets.fromLTRB(8, 0, 8, 0), - hintText: 'Enter Group Name', - fillColor: MyColors.fillColor2, - filled: true, - focusedBorder: OutlineInputBorder( - borderSide: const BorderSide( - color: Colors.transparent, width: 1.0), - borderRadius: BorderRadius.circular(8.0), - ), - enabledBorder: OutlineInputBorder( - borderSide: const BorderSide( - width: 1, //<-- SEE HERE - color: Colors.transparent, - ), - borderRadius: BorderRadius.circular(8.0), - ), - ), - ), + CustomTextFieldForm( + onChanged: (value) { + viewModel.groupName = value; + }, + hintText: 'Enter Group Name', ), - AppSpaces.verticalSmall, - Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all( - width: 1, color: MyColors.fillColorGray2), - color: MyColors.containerBackColor, - ), - height: 48, + AppSpaces.verticalLarge, + BorderContainer( child: Row( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ Expanded( - child: Container( - padding: - const EdgeInsets.only(left: 4, right: 4), - height: 48, - decoration: BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .sub_group_name, - style: TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.bold, - fontSize: MyFonts.normal, - color: MyColors.textColorBlack20), - ), - ), - )), - Container( + child: HeadingContainer( + heading: AppLocalizations.of(context)! + .sub_group_name)), + HeadingContainer( width: 80, - height: 48, - decoration: BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: Text( - AppLocalizations.of(context)!.action, - style: TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.bold, - fontSize: MyFonts.normal, - color: MyColors.textColorBlack20), - ), - ), + heading: AppLocalizations.of(context)!.action, ) ], ), @@ -195,150 +98,61 @@ class _CreateComboGroupVCState extends BaseStatefulState { physics: const NeverScrollableScrollPhysics(), shrinkWrap: true, itemBuilder: (context, position) { - _subGroupNameController - .add(TextEditingController()); - return Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all( - width: 1, color: MyColors.fillColorGray2), - color: MyColors.white, - ), - height: 48, + // viewModel.subGroupNameController.add(''); + return WrapHeightContainer( child: Row( children: [ Expanded( - child: Container( - padding: const EdgeInsets.all(4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: TextField( - controller: - _subGroupNameController[position], - onChanged: (value) { - addComboGroup.subGroups![position] - .name = value; - }, - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normal, - color: MyColors.black), - decoration: InputDecoration( - contentPadding: - const EdgeInsets.fromLTRB( - 4, 0, 4, 0), - hintText: - AppLocalizations.of(context)! - .name, - fillColor: MyColors.fillColor2, - filled: true, - focusedBorder: OutlineInputBorder( - borderSide: const BorderSide( - color: Colors.transparent, - width: 1.0), - borderRadius: - BorderRadius.circular(8.0), - ), - enabledBorder: OutlineInputBorder( - borderSide: const BorderSide( - width: 1, //<-- SEE HERE - color: Colors.transparent, - ), - borderRadius: - BorderRadius.circular(4.0), - ), - ), - ), + child: ChildContainer( + child: CustomTextFieldForm( + hintText: '', + initialValue: viewModel.addComboGroup + .subGroups![position].name ?? + '', + onChanged: (value) { + viewModel + .addComboGroup + .subGroups![position] + .name = value; + }, ), )), SizedBox( width: 80, - height: 48, - child: Center( - child: Container( - width: 32, - height: 32, - decoration: const BoxDecoration( - borderRadius: BorderRadius.all( - Radius.circular(4)), - color: MyColors.fillColorGray2), - child: IconButton( - icon: const Icon( - size: 18, - Icons.close, - color: - MyColors.textColorBlack, - ), - onPressed: () { - setState(() { - _subGroupNameController - .removeAt(position); - addComboGroup.subGroups! - .removeAt(position); - }); - }), + child: Padding( + padding: + const EdgeInsets.only(right: 4), + child: Align( + alignment: Alignment.centerRight, + child: CustomRemoveItemButton( + onPressed: () { + viewModel.removeGroup(position); + }, + ), ), )), ], ), ); }, - itemCount: addComboGroup.subGroups!.length, + itemCount: + viewModel.addComboGroup.subGroups!.length, ), - Container( - padding: EdgeInsets.all(8), - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all( - width: 1, color: MyColors.fillColorGray2), - color: Colors.white, - ), - height: 48, + BorderContainer( + backgroundColor: MyColors.white, child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ SizedBox( width: 120, - child: ElevatedButton( - style: ElevatedButton.styleFrom( - elevation: 0, - shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.circular(8.0), - ), - backgroundColor: - MyColors.fillColorGray2, - minimumSize: - const Size.fromHeight(38), // NEW - ), + child: CustomSimpleButton( + backGroundColor: MyColors.fillColorGray2, + textColor: MyColors.textColorBlack20, onPressed: () { - setState(() { - addComboGroup.subGroups! - .add(ComboSubGroup(name: '')); - }); + viewModel.addNewComboGroup(); }, - child: Text( - AppLocalizations.of(context)! - .add_option, - style: TextStyle( - fontSize: MyFonts.normal, - fontWeight: FontWeight.w500, - color: MyColors.textColorBlack, - fontFamily: MyFonts.Bold), - ), + heading: AppLocalizations.of(context)! + .add_option, )) ], ), @@ -347,32 +161,20 @@ class _CreateComboGroupVCState extends BaseStatefulState { ), ), Padding( - padding: const EdgeInsets.all(16), + padding: const EdgeInsets.all(12), child: SizedBox( - child: isLoading - ? Center( - child: CircularProgressIndicator(), - ) - : ElevatedButton( - style: ElevatedButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(6.0), - ), - backgroundColor: MyColors.blueThemeColor, - minimumSize: const Size.fromHeight(38), // NEW - ), - onPressed: () { - isValidate(); - }, - child: Text( - AppLocalizations.of(context)!.add_combo_group, - style: TextStyle( - fontSize: MyFonts.normalButton, - color: MyColors.white, - fontFamily: MyFonts.Bold), - ), - ), width: 160, + child: CustomSimpleButton( + isLoading: viewModel.isLoading, + textColor: MyColors.white, + backGroundColor: MyColors.blueThemeColor, + onPressed: () async { + await viewModel.isValidate(); + checkState(); + }, + heading: + AppLocalizations.of(context)!.add_combo_group, + ), ), ) ], @@ -383,36 +185,9 @@ class _CreateComboGroupVCState extends BaseStatefulState { )); } - void isValidate() { - if (groupName.text.isEmpty) { - showMessage('Please enter group name'); - } else if (addComboGroup.subGroups!.isEmpty) { - showMessage('Please enter sub group name'); - } else if (addComboGroup.subGroups!.first.name!.isEmpty) { - showMessage('Please enter sub group name'); - } else { - _addComboGroup(); + void checkState() { + if (viewModel.crudOperation == CRUDOperationState.add) { + Navigator.pop(context, true); } } - - Future _addComboGroup() async { - setState(() { - isLoading = true; - }); - addComboGroup.groupName = groupName.text; - InventoryViewModel viewModel = InventoryViewModel(); - await viewModel - .getData(Constants.ADD_COMBO_GROUP, addComboGroup.toJson()) - .then((value) { - final response = SimpleResponseModel.fromJson(value); - if (response.success!) { - showMessage(response.message!); - Navigator.pop(context, true); - } else { - showMessage(response.message!); - } - }) - .onError((error, stackTrace) {}) - .timeout(const Duration(minutes: 1)); - } } diff --git a/lib/application/views/inventorymodule/comboviews/InventoryComboVC.dart b/lib/application/views/inventorymodule/comboviews/InventoryComboVC.dart index 1195fc3..ca9ecbd 100644 --- a/lib/application/views/inventorymodule/comboviews/InventoryComboVC.dart +++ b/lib/application/views/inventorymodule/comboviews/InventoryComboVC.dart @@ -1,10 +1,10 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:provider/provider.dart'; +import 'package:sizer/sizer.dart'; import 'package:wosull/application/enum/DataState.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; import 'package:wosull/application/model/Combo/GetComboModel.dart'; -import 'package:wosull/application/model/Combo/GetComboSizes.dart'; import 'package:wosull/application/model/inventory/category/ItemCategoryResponse.dart'; import 'package:wosull/application/network/APIManager.dart'; import 'package:wosull/application/theme/MyColors.dart'; @@ -21,6 +21,7 @@ import 'package:wosull/base/BaseStatefulState.dart'; import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/ThemeText.dart'; import 'package:wosull/widgets/CustomSimpleButton.dart'; +import 'package:wosull/widgets/PageLimitDropDown.dart'; import 'package:wosull/widgets/SearchBox.dart'; class InventoryComboVC extends StatefulWidget { @@ -66,59 +67,45 @@ class _InventoryComboVCState extends BaseStatefulState { AppLocalizations.of(context)!.combos, style: ThemeText.textStylePageHeading, ), - const SizedBox( - width: 4, - ), - SizedBox( - width: 120, + AppSpaces.horizontalSmall, + Flexible( child: newComboGroup(), ), - const SizedBox( - width: 4, - ), - SizedBox( - width: 115, + AppSpaces.horizontalSmall, + Flexible( child: addGroupButton(), ), - // const SizedBox( - // width: 4, - // ), - // Padding( - // padding: const EdgeInsets.all(4), - // child: Align( - // alignment: Alignment.centerRight, - // child: Container( - // height: 42, - // width: 40, - // decoration: BoxDecoration( - // borderRadius: BorderRadius.all( - // Radius.circular(8)), - // color: MyColors.backColorBlue50), - // child: IconButton( - // icon: Icon( - // Icons.filter_alt_sharp, - // color: MyColors.blueThemeColor, - // ), - // onPressed: () { - // showDialog( - // barrierColor: Colors.black26, - // context: context, - // builder: (c) { - // return const FilterViewVC(); - // }, - // ); - // }), - // ), - // ), - // ), ], ), - const SizedBox( - height: 4, + AppSpaces.verticalSmall, + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Flexible( + child: addSizesButton(), + ), + AppSpaces.horizontalSmall, + PageLimitDropdown( + onChange: (value) { + viewModel.fetch( + isRefresh: true, + limit: int.parse(value!)); + }, + ) + ], ), + AppSpaces.verticalSmall, SizedBox( - width: 120, - child: addSizesButton(), + height: 48, + child: SearchBox( + onEditingDone: (text) { + filterSearchResults(text); + }, + onChanged: (text) { + filterSearchResults(text); + }, + hint: AppLocalizations.of(context)!.search, + ), ), ], ) @@ -129,27 +116,50 @@ class _InventoryComboVCState extends BaseStatefulState { AppLocalizations.of(context)!.combos, style: ThemeText.textStylePageHeading, ), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalSmall, SizedBox( width: 130, child: newComboGroup(), ), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalSmall, SizedBox( width: 120, child: addGroupButton(), ), - const SizedBox( - width: 4, - ), + AppSpaces.horizontalSmall, SizedBox( width: 120, child: addSizesButton(), - ) + ), + AppSpaces.horizontalSmall, + SizedBox( + width: SizerUtil.deviceType == DeviceType.mobile + ? 200 + : 200, + height: 48, + child: SearchBox( + onEditingDone: (text) { + filterSearchResults(text); + }, + onChanged: (text) { + filterSearchResults(text); + }, + hint: AppLocalizations.of(context)!.search, + ), + ), + Flexible( + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + PageLimitDropdown( + onChange: (value) { + viewModel.fetch( + isRefresh: true, + limit: int.parse(value!)); + }, + ) + ], + )) ], ), AppSpaces.verticalMedium, @@ -202,7 +212,7 @@ class _InventoryComboVCState extends BaseStatefulState { bool _scrollNotification() { if (!viewModel.isLoading && _controller.position.extentAfter < 300) { - viewModel.fetch(); + viewModel.fetch(limit: viewModel.limit); } return true; } @@ -225,7 +235,7 @@ class _InventoryComboVCState extends BaseStatefulState { Future _delete(String id) async { progressDialogue(context); - viewModel.delete(id); + await viewModel.delete(id); hideProgressBar(); } @@ -256,40 +266,13 @@ class _InventoryComboVCState extends BaseStatefulState { textColor: MyColors.blueThemeColor, backGroundColor: MyColors.backColorBlue50, onPressed: () async { - progressDialogue(context); - Map data = { - 'store_id': sharedPrefs.storeId, - }; - await APIManager() - .fetchData(Constants.GET_COMBO_SIZES, data) - .then((value) { - hideProgressBar(); - final response = GetComboSizes.fromJson(value); - if (response.success!) { - showDialog( - barrierColor: Colors.black26, - context: context, - builder: (context) { - return ComboAddSizesVC( - comboSize: response.comboSizes!, - ); - }, - ); - } else { - showDialog( - barrierColor: Colors.black26, - context: context, - builder: (context) { - return ComboAddSizesVC( - comboSize: ComboSize(), - ); - }, - ); - } - }).onError((error, stackTrace) { - hideProgressBar(); - print(stackTrace.toString()); - }).timeout(const Duration(minutes: 1)); + showDialog( + barrierColor: Colors.black26, + context: context, + builder: (context) { + return const ComboAddSizesVC(); + }, + ); }, heading: AppLocalizations.of(context)!.add_sizes, ); @@ -300,7 +283,7 @@ class _InventoryComboVCState extends BaseStatefulState { textColor: MyColors.blueThemeColor, backGroundColor: MyColors.backColorBlue50, onPressed: () async { - getCategory(); + newCombo(); }, heading: AppLocalizations.of(context)!.new_combos, ); @@ -318,18 +301,6 @@ class _InventoryComboVCState extends BaseStatefulState { hideProgressBar(); if (itemCategoryResponse.success && itemCategoryResponse.categories.isNotEmpty) { - final result = await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => InventoryNewComboVC( - itemCategories: itemCategoryResponse.categories, - )), - ); - - if (!mounted) return; - if (result != null) { - viewModel.fetch(isRefresh: true); - } } else { showMessage('Something went wrong while getting categories'); } @@ -351,4 +322,18 @@ class _InventoryComboVCState extends BaseStatefulState { heading: AppLocalizations.of(context)!.add_groups, ); } + + Future newCombo() async { + final result = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => const InventoryNewComboVC()), + ); + + if (!mounted) return; + if (result != null) { + if (result) { + viewModel.fetch(isRefresh: true); + } + } + } } diff --git a/lib/application/views/inventorymodule/comboviews/InventoryNewComboVC.dart b/lib/application/views/inventorymodule/comboviews/InventoryNewComboVC.dart index 1c594b9..1364c02 100644 --- a/lib/application/views/inventorymodule/comboviews/InventoryNewComboVC.dart +++ b/lib/application/views/inventorymodule/comboviews/InventoryNewComboVC.dart @@ -1,1704 +1,563 @@ import 'package:dropdown_search/dropdown_search.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:wosull/application/ViewModel/InventoryViewModel.dart'; -import 'package:wosull/application/localdb/SharedPrefs.dart'; -import 'package:wosull/application/model/Combo/AddNewComboModel.dart'; -import 'package:wosull/application/model/Combo/ComboProduct.dart'; +import 'package:provider/provider.dart'; import 'package:wosull/application/model/Combo/GetComboGroupModel.dart'; import 'package:wosull/application/model/Combo/GetComboMeasurementModel.dart'; import 'package:wosull/application/model/Combo/GetComboModel.dart'; -import 'package:wosull/application/model/Combo/GetComboProuctItem.dart'; -import 'package:wosull/application/model/Combo/GetComboSizes.dart'; -import 'package:wosull/application/model/SimpleResponsModel.dart'; import 'package:wosull/application/model/StockTransfer/ProductItemCategoryModel.dart'; import 'package:wosull/application/model/inventory/category/ItemCategory.dart'; import 'package:wosull/application/theme/MyColors.dart'; -import 'package:wosull/application/theme/MyFonts.dart'; -import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/utils/AppLoader.dart'; +import 'package:wosull/application/utils/CRUDOperatoinState.dart'; +import 'package:wosull/application/views/inventorymodule/comboviews/viewModels/AddNewComboViewModel.dart'; import 'package:wosull/base/BaseStatefulState.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeDropDown.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/widgets/BorderContainer.dart'; +import 'package:wosull/widgets/ChildContainer.dart'; +import 'package:wosull/widgets/CustomAddButton.dart'; +import 'package:wosull/widgets/CustomAppBar.dart'; +import 'package:wosull/widgets/CustomRemoveItemButton.dart'; +import 'package:wosull/widgets/CustomSimpleButton.dart'; +import 'package:wosull/widgets/CustomTextFieldForm.dart'; +import 'package:wosull/widgets/DropdownItemBuilder.dart'; +import 'package:wosull/widgets/HeadingContainer.dart'; +import 'package:wosull/widgets/HeadingText.dart'; +import 'package:wosull/widgets/MandatoryTitleText.dart'; +import 'package:wosull/widgets/PortraitContainer.dart'; +import 'package:wosull/widgets/WrapHeightContainer.dart'; class InventoryNewComboVC extends StatefulWidget { - List itemCategories; - - InventoryNewComboVC({Key? key, required this.itemCategories}) - : super(key: key); + const InventoryNewComboVC({Key? key}) : super(key: key); @override State createState() => _InventoryNewComboVCState(); } class _InventoryNewComboVCState extends BaseStatefulState { - var viewModel = InventoryViewModel(); - var isLoadingFirst = true; - var isLoadingData = false; - var addCombo = AddNewComboModel(); - - bool isPortrait = true; - - TextEditingController comboNameController = TextEditingController(); - TextEditingController comboTotalPriceController = TextEditingController(); - - List comboProduct = List.empty(growable: true); - List comboGroups = List.empty(growable: true); - List comboMeasurement = List.empty(growable: true); - List subGroup = []; - List comboSize = []; - List priceController = List.empty(growable: true); - List quantityController = List.empty(growable: true); - var selectedItemCategory; - - List selectedSizeValue = List.empty(growable: true); - List selectedGroup = List.empty(growable: true); - List selectedSubGroup = List.empty(growable: true); - List selectedProduct = List.empty(growable: true); - List selectedMeasurement = List.empty(growable: true); + var viewModel = AddNewComboViewModel(); @override void initState() { - // TODO: implement initState + context.read().initData(); super.initState(); - selectedItemCategory = widget.itemCategories[0]; - addCombo.comboProducts = List.empty(growable: true); - addCombo.comboProducts.add(ComboProducts()); - addCombo.categoryId = widget.itemCategories[0].id!; - loadSizes(); + } + + @override + void dispose() { + viewModel.disposeData(); + super.dispose(); } @override Widget build(BuildContext context) { - return MaterialApp( - debugShowCheckedModeBanner: false, - home: Scaffold( - resizeToAvoidBottomInset: true, - appBar: AppBar( - leading: BackButton( - color: Colors.black, - onPressed: () { - Navigator.pop(context); - }, // <-- SEE HERE - ), - centerTitle: true, - title: const Text( - 'Create Combo', - style: TextStyle( - color: MyColors.textColorBlack, - fontFamily: MyFonts.Bold, - fontSize: 22), - ), - backgroundColor: MyColors.white, - elevation: 5, - ), - body: OrientationBuilder(builder: (c, orientation) { - isPortrait = - MediaQuery.of(context).orientation == Orientation.portrait; - return SingleChildScrollView( - child: Container( - margin: isLoadingFirst - ? const EdgeInsets.only(top: 16) - : EdgeInsets.zero, - padding: const EdgeInsets.only(bottom: 8), - child: isLoadingFirst - ? const Center( - child: CircularProgressIndicator(), - ) - : Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.end, - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Row( - children: [ - Text( - 'Select Category', - style: TextStyle( - fontSize: 16, - fontFamily: MyFonts.Medium, - color: MyColors.black), - ), - Text( - '*', - style: TextStyle( - fontSize: 16, - fontFamily: MyFonts.Medium, - color: MyColors.fillRed), - ), - ], - ), - const SizedBox( - height: 4, - ), - Material( - color: MyColors.fillColor2, - borderRadius: BorderRadius.circular(8), - child: SizedBox( - height: 42, - width: double.infinity, - child: Padding( - padding: const EdgeInsets.only( - left: 8, right: 8), - child: DropdownButton( - value: selectedItemCategory, - hint: Text( - widget.itemCategories[0].name!), - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontSize: 13, - color: MyColors.textColorBlack), - isExpanded: true, - underline: DropdownButtonHideUnderline( - child: Container()), - items: widget.itemCategories - .map((ItemCategory items) { - return DropdownMenuItem( - value: items, - child: Text(items.name!), - ); - }).toList(), - onChanged: (Object? value) { - setState(() { - selectedItemCategory = value!; - loadProduct(); - }); - }, - ), - ), - ), - ), - const SizedBox( - height: 8, - ), - Row( - children: [ - Text( - AppLocalizations.of(context)!.combo_name, - style: const TextStyle( - fontSize: 16, - fontFamily: MyFonts.Medium, - color: MyColors.black), - ), - const Text( - '*', - style: TextStyle( - fontSize: 16, - fontFamily: MyFonts.Medium, - color: MyColors.fillRed), - ), - ], - ), - const SizedBox( - height: 4, - ), - SizedBox( - height: 42, - child: TextField( - controller: comboNameController, - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normalButton, - color: MyColors.black), - decoration: InputDecoration( - contentPadding: - const EdgeInsets.fromLTRB(8, 0, 8, 0), - hintText: 'Enter Combo Name', - fillColor: MyColors.fillColor2, - filled: true, - focusedBorder: OutlineInputBorder( - borderSide: const BorderSide( - color: Colors.transparent, - width: 1.0), - borderRadius: - BorderRadius.circular(8.0), - ), - enabledBorder: OutlineInputBorder( - borderSide: const BorderSide( - width: 1, //<-- SEE HERE - color: Colors.transparent, - ), - borderRadius: - BorderRadius.circular(8.0), - ), - ), - ), - ), - const SizedBox( - height: 8, - ), - Row( - children: [ - Text( - AppLocalizations.of(context)!.price, - style: const TextStyle( - fontSize: 16, - fontFamily: MyFonts.Medium, - color: MyColors.black), - ), - const Text( - '*', - style: TextStyle( - fontSize: 16, - fontFamily: MyFonts.Medium, - color: MyColors.fillRed), - ), - ], - ), - const SizedBox( - height: 4, - ), - SizedBox( - height: 42, - child: TextField( - keyboardType: TextInputType.number, - controller: comboTotalPriceController, - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normalButton, - color: MyColors.black), - decoration: InputDecoration( - contentPadding: - const EdgeInsets.fromLTRB(8, 0, 8, 0), - hintText: 'Enter Combo Price', - fillColor: MyColors.fillColor2, - filled: true, - focusedBorder: OutlineInputBorder( - borderSide: const BorderSide( - color: Colors.transparent, - width: 1.0), - borderRadius: - BorderRadius.circular(8.0), - ), - enabledBorder: OutlineInputBorder( - borderSide: const BorderSide( - width: 1, //<-- SEE HERE - color: Colors.transparent, - ), - borderRadius: - BorderRadius.circular(8.0), - ), - ), - ), - ), - const SizedBox( - height: 16, - ), - getProductContainer() - ], + viewModel = context.watch(); + return Scaffold( + backgroundColor: MyColors.white, + resizeToAvoidBottomInset: true, + appBar: CustomAppBar( + heading: 'Create Combo', + ), + body: OrientationBuilder(builder: (c, orientation) { + viewModel.isPortrait = + MediaQuery.of(context).orientation == Orientation.portrait; + return SingleChildScrollView( + child: Container( + margin: viewModel.isLoadingFirst + ? const EdgeInsets.only(top: 16) + : EdgeInsets.zero, + padding: const EdgeInsets.only(bottom: 8), + child: viewModel.isLoadingFirst + ? AppLoader() + : Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const MandatoryTitleText(hint: 'Select Category'), + AppSpaces.verticalSmall, + getCategoriesDropdown(), + AppSpaces.verticalLarge, + MandatoryTitleText( + hint: AppLocalizations.of(context)!.combo_name), + AppSpaces.verticalSmall, + CustomTextFieldForm( + initialValue: viewModel.comboNameController, + onChanged: (value) { + viewModel.comboNameController = value; + }, + hintText: 'Enter Combo Name', ), - ), - SizedBox( - width: 150, - child: Padding( - padding: const EdgeInsets.only(right: 16), - child: isLoadingData - ? const Center( - child: CircularProgressIndicator(), - ) - : ElevatedButton( - style: ElevatedButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.circular(6.0), - ), - backgroundColor: - MyColors.blueThemeColor, - minimumSize: - const Size.fromHeight(38), // NEW - ), - onPressed: () { - isValidate(); - }, - child: Text( - AppLocalizations.of(context)!.save, - style: const TextStyle( - fontSize: MyFonts.normalButton, - color: MyColors.white, - fontFamily: MyFonts.Bold), - ), - ), + AppSpaces.verticalMedium, + MandatoryTitleText( + hint: AppLocalizations.of(context)!.price), + AppSpaces.verticalSmall, + CustomTextFieldForm( + hintText: 'Enter Combo Price', + keyboardType: TextInputType.number, + initialValue: viewModel.comboTotalPriceController, + onChanged: (String value) { + viewModel.comboTotalPriceController = value; + }, ), + AppSpaces.verticalLarge, + getProductContainer() + ], + ), + ), + SizedBox( + width: 150, + child: Padding( + padding: const EdgeInsets.only(right: 16), + child: CustomSimpleButton( + isLoading: viewModel.isLoadingData, + textColor: MyColors.white, + backGroundColor: MyColors.blueThemeColor, + onPressed: () async { + await viewModel.isValidate(); + checkState(); + }, + heading: AppLocalizations.of(context)!.save, ), - ], + ), ), - ), - ); - }), - )); - } - - void isValidate() { - if (comboNameController.text.isEmpty) { - showMessage('Please enter combo name'); - } else if (addCombo.comboProducts.isEmpty) { - showMessage('Please fill at least one combo product'); - } else if (addCombo.comboProducts.first.product == null || - addCombo.comboProducts.first.price == null || - addCombo.comboProducts.first.subGroup == null || - addCombo.comboProducts.first.size == null || - addCombo.comboProducts.first.measurementId == null) { - showMessage('Please fill at least one combo '); - } else { - addUpdateCombo(); - } + ], + ), + ), + ); + }), + ); } - void addUpdateCombo() async { - addCombo.comboPrice = double.parse(comboTotalPriceController.text); - addCombo.comboName = comboNameController.text; - - setState(() { - isLoadingData = true; - }); - - await viewModel - .getData(Constants.NEW_COMBO, addCombo.toJson()) - .then((value) { - final response = SimpleResponseModel.fromJson(value); - if (response.success!) { - showMessage(response.message!); - Navigator.pop(context, true); - } - }) - .onError((error, stackTrace) {}) - .timeout(const Duration(seconds: 60)); + Widget getCategoriesDropdown() { + return DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + selectedItem: viewModel.selectedItemCategory, + items: viewModel.categoriesList, + itemAsString: (ItemCategory u) => u.name, + onChanged: (category) { + viewModel.setSelectedCategory(category); + }, + dropdownDecoratorProps: MyColors.dropDownStyle( + hint: 'Choose', + ), + ); } Widget getProductContainer() { - return Container( - width: double.infinity, - padding: const EdgeInsets.fromLTRB(8, 16, 8, 16), - decoration: BoxDecoration( - border: Border.all( - color: MyColors.fillColorGray, - width: 1, - ), + return Card( + elevation: 5, + shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.0), ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'Combo Products', - style: TextStyle( - fontSize: 16, - fontFamily: MyFonts.Bold, - color: Colors.black, - fontWeight: FontWeight.bold), - ), - const SizedBox( - height: 16, - ), - isPortrait - ? Container() - : Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius.all(Radius.circular( - 1.0) // <--- border radius here - ), - border: - Border.all(width: 1, color: MyColors.fillColorGray2), - color: MyColors.fillColor2, - ), - height: 48, - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Expanded( - child: Container( - padding: const EdgeInsets.only(left: 4, right: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, color: MyColors.fillColorGray2), - ), - ), - child: Align( - alignment: Alignment.centerLeft, - child: Text( - 'Size', - style: MyColors.textStylePopUpHeading(), - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.only(left: 4, right: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, color: MyColors.fillColorGray2), - ), - ), - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)!.group, - style: MyColors.textStylePopUpHeading(), - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.only(left: 4, right: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, color: MyColors.fillColorGray2), - ), - ), - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)!.sub_group, - style: MyColors.textStylePopUpHeading(), - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.only(left: 4, right: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, color: MyColors.fillColorGray2), - ), - ), - child: Align( - alignment: Alignment.centerLeft, - child: Text( - 'Product', - style: MyColors.textStylePopUpHeading(), - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.only(left: 4, right: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, color: MyColors.fillColorGray2), - ), - ), - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)!.measurement, - style: MyColors.textStylePopUpHeading(), - ), - ), - )), - Container( - padding: const EdgeInsets.only(left: 4, right: 4), - width: 100, - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, color: MyColors.fillColorGray2), - ), - ), - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)!.quantity, - style: MyColors.textStylePopUpHeading(), - ), - ), - ), - Container( - padding: const EdgeInsets.only(left: 4, right: 4), - width: 100, - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, color: MyColors.fillColorGray2), - ), - ), - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)!.price, - style: MyColors.textStylePopUpHeading(), - ), - ), - ), - Container( - width: 48, - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, color: MyColors.fillColorGray2), - ), - ), - child: const Center( - child: Text( - '', - style: TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.bold, - fontSize: MyFonts.normal, - color: MyColors.textColorBlack20), - ), + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text( + 'Combo Products', + style: ThemeText.textStyleHeadingCart, + ), + AppSpaces.verticalLarge, + viewModel.isPortrait + ? Container() + : BorderContainer( + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded(child: HeadingContainer(heading: 'Size')), + Expanded( + child: HeadingContainer( + heading: AppLocalizations.of(context)!.group, + )), + Expanded( + child: HeadingContainer( + heading: AppLocalizations.of(context)!.sub_group, + )), + Expanded( + child: HeadingContainer( + heading: 'Product', + )), + Expanded( + child: HeadingContainer( + heading: AppLocalizations.of(context)!.measurement, + )), + HeadingContainer( + width: 100, + height: 48, + heading: AppLocalizations.of(context)!.quantity, ), - ) - ], - ), - ), - ListView.builder( - padding: EdgeInsets.zero, - scrollDirection: Axis.vertical, - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - itemBuilder: (c, position) { - selectedSizeValue.add('Choose'); - selectedGroup - .add(ComboGroup(name: 'Choose', id: '', subGroups: [])); - selectedSubGroup.add(ComboSubGroup(name: 'Choose')); - selectedProduct.add(ProductItem( - name: 'Choose', - id: '', - price: 0, - total_quantity: 0, - uniqueIdForStoreData: '', - details: '')); - selectedMeasurement.add(ComboMeasurement(id: '', name: 'Choose')); - quantityController.add(TextEditingController(text: '0')); - priceController.add(TextEditingController(text: '0')); - - if (isPortrait) { - return Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius.all(Radius.circular( - 1.0) // <--- border radius here + HeadingContainer( + width: 100, + height: 48, + heading: AppLocalizations.of(context)!.price, ), - border: - Border.all(width: 1, color: MyColors.fillColorGray2), - color: MyColors.white, + HeadingContainer( + width: 48, + height: 48, + heading: '', + ) + ], + ), ), - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: Column( - children: [ - Row( - children: [ - Expanded( - child: Container( - padding: - const EdgeInsets.only(left: 4, right: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Align( - alignment: Alignment.centerLeft, - child: Text( - 'Size', - style: MyColors.textStylePopUpHeading(), - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.all(4), - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Material( - color: MyColors.fillColor2, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only( - left: 6, right: 0), - child: SizedBox( - height: 42, - width: double.infinity, - child: DropdownSearch( - popupProps: const PopupProps.menu( - showSelectedItems: true, - ), - items: comboSize, - itemAsString: (String u) => u, - onChanged: (String? data) { - setState(() { - selectedSizeValue[position] = data!; - addCombo.comboProducts[position] - .size = data; - }); - }, - selectedItem: - selectedSizeValue[position], - dropdownDecoratorProps: - const DropDownDecoratorProps( - baseStyle: TextStyle( - fontFamily: MyFonts.Bold, - fontSize: 11, - color: MyColors.textColorBlack), - dropdownSearchDecoration: - InputDecoration( - border: InputBorder.none, - hintText: 'Choose'), - ), - ), + ListView.builder( + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (c, position) { + if (viewModel.isPortrait) { + return WrapHeightContainer( + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Column( + children: [ + Row( + children: [ + Expanded( + child: PortraitContainer( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + 'Size', ), ), - ), - )) - ], - ), - Row( - children: [ - Expanded( - child: Container( - padding: - const EdgeInsets.only(left: 4, right: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)!.group, - style: MyColors.textStylePopUpHeading(), - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.all(4), - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Material( - color: MyColors.fillColor2, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only( - left: 6, right: 0), - child: SizedBox( - height: 42, - width: double.infinity, - child: DropdownSearch( - items: comboGroups, - itemAsString: (ComboGroup u) => u.name!, - onChanged: (ComboGroup? data) { - setState(() { - selectedGroup[position] = data!; - addCombo.comboProducts[position] - .group = data.name!; - subGroup.clear(); - subGroup.addAll(data.subGroups!); - }); - }, - selectedItem: selectedGroup[position], - dropdownDecoratorProps: - const DropDownDecoratorProps( - baseStyle: TextStyle( - fontFamily: MyFonts.Bold, - fontSize: 11, - color: MyColors.textColorBlack), - dropdownSearchDecoration: - InputDecoration( - border: InputBorder.none, - hintText: 'Choose'), - ), - ), + )), + Expanded( + child: PortraitContainer( + child: getSizesDropdown(position), + )) + ], + ), + Row( + children: [ + Expanded( + child: PortraitContainer( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + AppLocalizations.of(context)!.group, ), ), - ), - )) - ], - ), - Row( - children: [ - Expanded( - child: Container( - padding: - const EdgeInsets.only(left: 4, right: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)!.sub_group, - style: MyColors.textStylePopUpHeading(), - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.all(4), - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Material( - color: MyColors.fillColor2, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only( - left: 6, right: 0), - child: SizedBox( - height: 42, - width: double.infinity, - child: DropdownSearch( - items: subGroup, - itemAsString: (ComboSubGroup u) => - u.name!, - onChanged: (ComboSubGroup? data) { - setState(() { - selectedSubGroup[position] = data!; - addCombo.comboProducts[position] - .subGroup = data.name!; - }); - }, - selectedItem: - selectedSubGroup[position], - dropdownDecoratorProps: - const DropDownDecoratorProps( - baseStyle: TextStyle( - fontFamily: MyFonts.Bold, - fontSize: 11, - color: MyColors.textColorBlack), - dropdownSearchDecoration: - InputDecoration( - border: InputBorder.none, - hintText: 'Choose'), - ), - ), + )), + Expanded( + child: PortraitContainer( + child: getComboGroupDropdown(position), + )) + ], + ), + Row( + children: [ + Expanded( + child: PortraitContainer( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + AppLocalizations.of(context)!.sub_group, ), ), - ), - )) - ], - ), - Row( - children: [ - Expanded( - child: Container( - padding: - const EdgeInsets.only(left: 4, right: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Align( - alignment: Alignment.centerLeft, - child: Text( - 'Product', - style: MyColors.textStylePopUpHeading(), - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.all(4), - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Material( - color: MyColors.fillColor2, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only( - left: 6, right: 0), - child: SizedBox( - height: 42, - width: double.infinity, - child: DropdownSearch( - items: comboProduct, - selectedItem: selectedProduct[position], - itemAsString: (ProductItem u) => - u.name!, - onChanged: (ProductItem? data) { - setState(() { - selectedProduct[position] = data!; - priceController[position].text = - data.price.toString(); - - if (comboTotalPriceController - .text.isNotEmpty) { - var price = double.parse( - comboTotalPriceController - .text) + - data.price!; - comboTotalPriceController.text = - price.toString(); - } else { - comboTotalPriceController.text = - data.price.toString(); - } - addCombo.comboProducts[position] - .price = data.price!; - addCombo.comboProducts[position] - .product = data.name!; - }); - }, - dropdownDecoratorProps: - const DropDownDecoratorProps( - baseStyle: TextStyle( - fontFamily: MyFonts.Bold, - fontSize: 11, - color: MyColors.textColorBlack), - dropdownSearchDecoration: - InputDecoration( - border: InputBorder.none, - hintText: 'Choose'), - ), - ), + )), + Expanded( + child: PortraitContainer( + child: getSubGroupDropdown(position), + )) + ], + ), + Row( + children: [ + Expanded( + child: PortraitContainer( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + 'Product', ), ), - ), - )) - ], - ), - Row( - children: [ - Expanded( - child: Container( - padding: - const EdgeInsets.only(left: 4, right: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)!.measurement, - style: MyColors.textStylePopUpHeading(), - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.all(4), - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Material( - color: MyColors.fillColor2, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only( - left: 6, right: 0), - child: SizedBox( - height: 42, - width: double.infinity, - child: DropdownSearch( - items: comboMeasurement, - itemAsString: (ComboMeasurement u) => - u.name!, - onChanged: (ComboMeasurement? data) { - setState(() { - selectedMeasurement[position] = - data!; - addCombo.comboProducts[position] - .measurementId = data.name!; - }); - }, - dropdownDecoratorProps: - const DropDownDecoratorProps( - baseStyle: TextStyle( - fontFamily: MyFonts.Bold, - fontSize: 11, - color: MyColors.textColorBlack), - dropdownSearchDecoration: - InputDecoration( - border: InputBorder.none, - hintText: 'Choose'), - ), - ), + )), + Expanded( + child: PortraitContainer( + child: getProductDropdown(position), + )) + ], + ), + Row( + children: [ + Expanded( + child: PortraitContainer( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + AppLocalizations.of(context)!.measurement, ), ), - ), - )) - ], - ), - Row( - children: [ - Expanded( - child: Container( - padding: - const EdgeInsets.only(left: 4, right: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)!.quantity, - style: MyColors.textStylePopUpHeading(), - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.all(4), - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: TextField( - keyboardType: TextInputType.number, - controller: quantityController[position], - onChanged: (value) { - if (value.isNotEmpty) { - setState(() { - addCombo.comboProducts[position] - .quantity = value; - ProductItem product = - selectedProduct[position]; - priceController[position].text = - (int.parse(value) * product.price!) - .toString(); - - var totalPrice = 0.0; - for (var price in priceController) { - totalPrice = totalPrice + - double.parse(price.text); - } - comboTotalPriceController.text = - totalPrice.toString(); - }); - } - }, - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normal, - color: MyColors.black), - decoration: InputDecoration( - contentPadding: - const EdgeInsets.fromLTRB(4, 0, 4, 0), - hintText: '0.0', - fillColor: MyColors.fillColor2, - filled: true, - focusedBorder: OutlineInputBorder( - borderSide: const BorderSide( - color: Colors.transparent, - width: 1.0), - borderRadius: BorderRadius.circular(8.0), - ), - enabledBorder: OutlineInputBorder( - borderSide: const BorderSide( - width: 1, //<-- SEE HERE - color: Colors.transparent, - ), - borderRadius: BorderRadius.circular(4.0), + )), + Expanded( + child: PortraitContainer( + child: getMeasurementDropdown(position), + )) + ], + ), + Row( + children: [ + Expanded( + child: PortraitContainer( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + AppLocalizations.of(context)!.quantity, ), ), - ), - )) - ], - ), - Row( - children: [ - Expanded( - child: Container( - padding: - const EdgeInsets.only(left: 4, right: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)!.price, - style: MyColors.textStylePopUpHeading(), - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.all(4), - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: TextField( - controller: priceController[position], - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normal, - color: MyColors.black), - decoration: InputDecoration( - contentPadding: - const EdgeInsets.fromLTRB(4, 0, 4, 0), - hintText: '0.0', - fillColor: MyColors.fillColor2, - filled: true, - focusedBorder: OutlineInputBorder( - borderSide: const BorderSide( - color: Colors.transparent, - width: 1.0), - borderRadius: BorderRadius.circular(8.0), - ), - enabledBorder: OutlineInputBorder( - borderSide: const BorderSide( - width: 1, //<-- SEE HERE - color: Colors.transparent, - ), - borderRadius: BorderRadius.circular(4.0), + )), + Expanded( + child: PortraitContainer( + child: quantityTextField(position), + )) + ], + ), + Row( + children: [ + Expanded( + child: PortraitContainer( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + AppLocalizations.of(context)!.price, ), ), - ), - )) - ], - ), - ], - )), - SizedBox( - width: 48, + )), + Expanded( + child: PortraitContainer( + child: getPriceTextField(position), + )) + ], + ), + ], + )), + getRemoveButton(position) + ], + ), + ); + } else { + return BorderContainer( + child: Row( + children: [ + Expanded( + child: ChildContainer( + child: getSizesDropdown(position), + )), + Expanded( + child: ChildContainer( + child: getComboGroupDropdown(position), + )), + Expanded( + child: ChildContainer( + child: getSubGroupDropdown(position), + )), + Expanded( + child: ChildContainer( + child: getProductDropdown(position), + )), + Expanded( + child: ChildContainer( + child: getMeasurementDropdown(position), + )), + ChildContainer( + width: 100, height: 48, child: Center( - child: Container( - width: 32, - height: 32, - decoration: const BoxDecoration( - borderRadius: - BorderRadius.all(Radius.circular(4)), - color: MyColors.fillColor2), - child: IconButton( - icon: const Icon( - size: 18, - Icons.close, - color: MyColors.textColorBlack, - ), - onPressed: () { - setState(() { - if (comboTotalPriceController - .text.isNotEmpty) { - var price = - priceController[position].text; - price = (double.parse( - comboTotalPriceController - .text) - - double.parse(price)) - .toString(); - comboTotalPriceController.text = - price.toString(); - } - - selectedSizeValue.removeAt(position); - selectedGroup.removeAt(position); - selectedSubGroup.removeAt(position); - selectedProduct.removeAt(position); - selectedMeasurement.removeAt(position); - - quantityController.removeAt(position); - priceController.removeAt(position); - addCombo.comboProducts.removeAt(position); - }); - }), - ), - )), - ], - ), - ); - } else { - return Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius.all(Radius.circular( - 1.0) // <--- border radius here - ), - border: - Border.all(width: 1, color: MyColors.fillColorGray2), - color: MyColors.white, - ), - child: Row( - children: [ - Expanded( - child: Container( - padding: const EdgeInsets.all(4), - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, color: MyColors.fillColorGray2), - ), - ), - child: Material( - color: MyColors.fillColor2, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: 42, - width: double.infinity, - child: DropdownSearch( - popupProps: const PopupProps.menu( - showSelectedItems: true, - ), - items: comboSize, - itemAsString: (String u) => u, - onChanged: (String? data) { - setState(() { - selectedSizeValue[position] = data!; - addCombo.comboProducts[position].size = - data; - }); - }, - selectedItem: selectedSizeValue[position], - dropdownDecoratorProps: - const DropDownDecoratorProps( - baseStyle: TextStyle( - fontFamily: MyFonts.Bold, - fontSize: 11, - color: MyColors.textColorBlack), - dropdownSearchDecoration: InputDecoration( - border: InputBorder.none, - hintText: 'Choose'), - ), - ), - ), - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.all(4), - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, color: MyColors.fillColorGray2), - ), - ), - child: Material( - color: MyColors.fillColor2, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: 42, - width: double.infinity, - child: DropdownSearch( - items: comboGroups, - itemAsString: (ComboGroup u) => u.name!, - onChanged: (ComboGroup? data) { - setState(() { - selectedGroup[position] = data!; - addCombo.comboProducts[position].group = - data.name!; - subGroup.clear(); - subGroup.addAll(data.subGroups!); - }); - }, - selectedItem: selectedGroup[position], - dropdownDecoratorProps: - const DropDownDecoratorProps( - baseStyle: TextStyle( - fontFamily: MyFonts.Bold, - fontSize: 11, - color: MyColors.textColorBlack), - dropdownSearchDecoration: InputDecoration( - border: InputBorder.none, - hintText: 'Choose'), - ), - ), - ), - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.all(4), - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, color: MyColors.fillColorGray2), + child: quantityTextField(position), ), ), - child: Material( - color: MyColors.fillColor2, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: 42, - width: double.infinity, - child: DropdownSearch( - items: subGroup, - itemAsString: (ComboSubGroup u) => u.name!, - onChanged: (ComboSubGroup? data) { - setState(() { - selectedSubGroup[position] = data!; - addCombo.comboProducts[position].subGroup = - data.name!; - }); - }, - selectedItem: selectedSubGroup[position], - dropdownDecoratorProps: - const DropDownDecoratorProps( - baseStyle: TextStyle( - fontFamily: MyFonts.Bold, - fontSize: 11, - color: MyColors.textColorBlack), - dropdownSearchDecoration: InputDecoration( - border: InputBorder.none, - hintText: 'Choose'), - ), - ), - ), - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.all(4), - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, color: MyColors.fillColorGray2), + ChildContainer( + width: 100, + height: 48, + child: Center( + child: getPriceTextField(position), ), ), - child: Material( - color: MyColors.fillColor2, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: 42, - width: double.infinity, - child: DropdownSearch( - items: comboProduct, - selectedItem: selectedProduct[position], - itemAsString: (ProductItem u) => u.name!, - onChanged: (ProductItem? data) { - setState(() { - selectedProduct[position] = data!; - priceController[position].text = - data.price.toString(); + getRemoveButton(position) + ], + ), + ); + } + }, + itemCount: viewModel.addCombo.comboProducts.length, + ), + BorderContainer( + backgroundColor: MyColors.white, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [getAddComboButton()], + ), + ), + ], + ), + ), + ); + } - if (comboTotalPriceController - .text.isNotEmpty) { - var price = double.parse( - comboTotalPriceController.text) + - data.price!; - comboTotalPriceController.text = - price.toString(); - } else { - comboTotalPriceController.text = - data.price.toString(); - } - addCombo.comboProducts[position].price = - data.price!; - addCombo.comboProducts[position].product = - data.name!; - }); - }, - dropdownDecoratorProps: - const DropDownDecoratorProps( - baseStyle: TextStyle( - fontFamily: MyFonts.Bold, - fontSize: 11, - color: MyColors.textColorBlack), - dropdownSearchDecoration: InputDecoration( - border: InputBorder.none, - hintText: 'Choose'), - ), - ), - ), - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.all(4), - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, color: MyColors.fillColorGray2), - ), - ), - child: Material( - color: MyColors.fillColor2, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: 42, - width: double.infinity, - child: DropdownSearch( - items: comboMeasurement, - itemAsString: (ComboMeasurement u) => u.name!, - onChanged: (ComboMeasurement? data) { - setState(() { - selectedMeasurement[position] = data!; - addCombo.comboProducts[position] - .measurementId = data.name!; - }); - }, - dropdownDecoratorProps: - const DropDownDecoratorProps( - baseStyle: TextStyle( - fontFamily: MyFonts.Bold, - fontSize: 11, - color: MyColors.textColorBlack), - dropdownSearchDecoration: InputDecoration( - border: InputBorder.none, - hintText: 'Choose'), - ), - ), - ), - ), - ), - )), - Container( - padding: const EdgeInsets.all(4), - width: 100, - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: TextField( - keyboardType: TextInputType.number, - controller: quantityController[position], - onChanged: (value) { - if (value.isNotEmpty) { - setState(() { - addCombo.comboProducts[position].quantity = - value; - ProductItem product = - selectedProduct[position]; - priceController[position].text = - (int.parse(value) * product.price!) - .toString(); + Widget getSizesDropdown(int position) { + return DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: viewModel.comboSize, + itemAsString: (String u) => u, + onChanged: (String? data) { + viewModel.setSelectedSize(data, position); + }, + selectedItem: viewModel.selectedSizeValue[position], + dropdownDecoratorProps: MyColors.dropDownStyleAddProduct(hint: 'Choose'), + ); + } - var totalPrice = 0.0; - for (var price in priceController) { - totalPrice = - totalPrice + double.parse(price.text); - } - comboTotalPriceController.text = - totalPrice.toString(); - }); - } - }, - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normal, - color: MyColors.black), - decoration: InputDecoration( - contentPadding: - const EdgeInsets.fromLTRB(4, 0, 4, 0), - hintText: '0.0', - fillColor: MyColors.fillColor2, - filled: true, - focusedBorder: OutlineInputBorder( - borderSide: const BorderSide( - color: Colors.transparent, width: 1.0), - borderRadius: BorderRadius.circular(8.0), - ), - enabledBorder: OutlineInputBorder( - borderSide: const BorderSide( - width: 1, //<-- SEE HERE - color: Colors.transparent, - ), - borderRadius: BorderRadius.circular(4.0), - ), - ), - ), - ), - ), - Container( - padding: const EdgeInsets.all(4), - width: 100, - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: TextField( - controller: priceController[position], - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normal, - color: MyColors.black), - decoration: InputDecoration( - contentPadding: - const EdgeInsets.fromLTRB(4, 0, 4, 0), - hintText: '0.0', - fillColor: MyColors.fillColor2, - filled: true, - focusedBorder: OutlineInputBorder( - borderSide: const BorderSide( - color: Colors.transparent, width: 1.0), - borderRadius: BorderRadius.circular(8.0), - ), - enabledBorder: OutlineInputBorder( - borderSide: const BorderSide( - width: 1, //<-- SEE HERE - color: Colors.transparent, - ), - borderRadius: BorderRadius.circular(4.0), - ), - ), - ), - ), - ), - SizedBox( - width: 48, - height: 48, - child: Center( - child: Container( - width: 32, - height: 32, - decoration: const BoxDecoration( - borderRadius: - BorderRadius.all(Radius.circular(4)), - color: MyColors.fillColor2), - child: IconButton( - icon: const Icon( - size: 18, - Icons.close, - color: MyColors.textColorBlack, - ), - onPressed: () { - setState(() { - if (comboTotalPriceController - .text.isNotEmpty) { - var price = - priceController[position].text; - price = (double.parse( - comboTotalPriceController - .text) - - double.parse(price)) - .toString(); - comboTotalPriceController.text = - price.toString(); - } + Widget getComboGroupDropdown(int position) { + return DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name ?? ''); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: viewModel.comboGroups, + itemAsString: (ComboGroup u) => u.name!, + onChanged: (ComboGroup? data) { + viewModel.setSelectedComboGroup(data, position); + }, + selectedItem: viewModel.selectedGroup[position], + dropdownDecoratorProps: MyColors.dropDownStyleAddProduct(hint: 'Choose'), + ); + } - selectedSizeValue.removeAt(position); - selectedGroup.removeAt(position); - selectedSubGroup.removeAt(position); - selectedProduct.removeAt(position); - selectedMeasurement.removeAt(position); + Widget getSubGroupDropdown(int position) { + return DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name ?? ''); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: viewModel.subGroup, + itemAsString: (ComboSubGroup u) => u.name!, + onChanged: (ComboSubGroup? data) { + viewModel.setSelectedSubGroup(data, position); + }, + selectedItem: viewModel.selectedSubGroup[position], + dropdownDecoratorProps: MyColors.dropDownStyleAddProduct(hint: 'Choose'), + ); + } - quantityController.removeAt(position); - priceController.removeAt(position); - addCombo.comboProducts.removeAt(position); - }); - }), - ), - )), - ], - ), - ); - } - }, - itemCount: addCombo.comboProducts.length, - ), - Container( - padding: const EdgeInsets.all(8), - decoration: BoxDecoration( - borderRadius: const BorderRadius.all(Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all(width: 1, color: MyColors.fillColorGray2), - color: Colors.white, - ), - height: 48, - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - SizedBox( - width: 48, - height: 48, - child: Center( - child: Container( - width: 32, - height: 32, - decoration: const BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(4)), - color: MyColors.fillColor2), - child: IconButton( - icon: const Icon( - size: 18, - Icons.add, - color: MyColors.textColorBlack, - ), - onPressed: () { - setState(() { - addCombo.comboProducts.add(ComboProducts()); - }); - }), - ), - )) - ], - ), - ), - ], - ), + Widget getProductDropdown(int position) { + return DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name ?? ''); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: viewModel.comboProduct, + selectedItem: viewModel.selectedProduct[position], + itemAsString: (ProductItem u) => u.name!, + onChanged: (ProductItem? data) { + viewModel.onChangeProduct(data, position); + }, + dropdownDecoratorProps: MyColors.dropDownStyleAddProduct(hint: 'Choose'), ); } - void loadSizes() async { - await viewModel - .getData(Constants.GET_COMBO_SIZES, Constants.getStorePayload()) - .then((value) { - final response = GetComboSizes.fromJson(value); - if (response.success!) { - comboSize.addAll(response.comboSizes!.sizes!); - loadGroups(); - } else { - setState(() { - isLoadingFirst = false; - }); - } - }).onError((error, stackTrace) { - print('size' + error.toString()); - setState(() { - isLoadingFirst = false; - }); - }); + Widget getMeasurementDropdown(int position) { + return DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name ?? ''); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: viewModel.comboMeasurement, + itemAsString: (ComboMeasurement u) => u.name!, + onChanged: (ComboMeasurement? data) { + viewModel.onChangeMeasurement(data, position); + }, + dropdownDecoratorProps: MyColors.dropDownStyleAddProduct(hint: 'Choose'), + ); } - void loadGroups() async { - await viewModel - .getData(Constants.GET_COMBO_GROUPS, Constants.getStorePayload()) - .then((value) { - final response = GetComboGroupModel.fromJson(value); - if (response.success!) { - comboGroups.addAll(response.comboGroup!); - loadMeasurement(); - } else { - setState(() { - isLoadingFirst = false; - }); - } - }).onError((error, stackTrace) { - setState(() { - isLoadingFirst = false; - }); - print(error.toString()); - }); + Widget quantityTextField(int position) { + return CustomTextFieldForm( + hintText: '0.0', + keyboardType: TextInputType.number, + initialValue: viewModel.quantityController[position], + onChanged: (value) { + viewModel.onChangeQuantity(value, position); + }, + ); } - void loadMeasurement() async { - await viewModel - .getData(Constants.GET_MEASUREMENT, Constants.getStorePayload()) - .then((value) { - final response = GetComboMeasurementModel.fromJson(value); - if (response.success!) { - comboMeasurement.addAll(response.measurements!); - loadProduct(); - } else { - setState(() { - isLoadingFirst = false; - }); - } - }).onError((error, stackTrace) { - setState(() { - isLoadingFirst = false; - }); - }); + Widget getPriceTextField(int position) { + return CustomTextFieldForm( + key: Key(viewModel.priceController[position]), + onChanged: (value) { + viewModel.priceController[position] = value; + }, + keyboardType: TextInputType.number, + hintText: '0.0', + initialValue: viewModel.priceController[position], + ); } - void loadProduct() async { - ItemCategory itemCategory = selectedItemCategory; - Map data = { - 'store_id': sharedPrefs.storeId, - 'category_id': itemCategory.id!, - }; - await viewModel - .getData(Constants.GET_PRODUCT_ITEM_BY_CATEGORY, data) - .then((value) { - final response = GetComboProductItem.fromJson(value); - if (response.success!) { - comboProduct.clear(); - comboProduct.addAll(response.products!); + Widget getRemoveButton(int position) { + return CustomRemoveItemButton(onPressed: () { + viewModel.removeComboProduct(position); + }); + } - setState(() { - isLoadingFirst = false; - }); - } else { - setState(() { - isLoadingFirst = false; - }); - } - }).onError((error, stackTrace) { - setState(() { - isLoadingFirst = false; - }); + Widget getAddComboButton() { + return CustomAddButton(onPressed: () { + viewModel.addNewCombo(); }); } + + void checkState() { + if (viewModel.crudOperation == CRUDOperationState.add) { + Navigator.pop(context, true); + } + } } diff --git a/lib/application/views/inventorymodule/comboviews/repo/ComboRepository.dart b/lib/application/views/inventorymodule/comboviews/repo/ComboRepository.dart new file mode 100644 index 0000000..eb24ba7 --- /dev/null +++ b/lib/application/views/inventorymodule/comboviews/repo/ComboRepository.dart @@ -0,0 +1,44 @@ +import 'package:wosull/application/model/Combo/GetComboModel.dart'; +import 'package:wosull/application/model/Combo/GetComboSizes.dart'; +import 'package:wosull/application/model/SimpleResponsModel.dart'; +import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/utils/Constants.dart'; + +class ComboRepository { + Future fetch(Map map) async { + final result = await APIManager().fetchData(Constants.GET_COMBOS, map); + return GetComboModel.fromJson(result); + } + + Future search(Map data) async { + final result = await APIManager().fetchData(Constants.SEARCH_COMBO, data); + return GetComboModel.fromJson(result); + } + + Future delete(String id) async { + Map data = {'comboId': id}; + return await APIManager().getResponsePatch(Constants.DELETE_COMBO, data); + } + + Future addGroup(Map map) async { + final response = + await APIManager().fetchData(Constants.ADD_COMBO_GROUP, map); + return SimpleResponseModel.fromJson(response); + } + + Future addUpdateSize(Map map) async { + final response = + await APIManager().fetchData(Constants.ADD_COMBO_SIZES, map); + return SimpleResponseModel.fromJson(response); + } + + Future getComboSizes() async { + final response = await APIManager() + .fetchData(Constants.GET_COMBO_SIZES, Constants.getStorePayload()); + return GetComboSizes.fromJson(response); + } + + Future addUpdateCombo(Map map) async { + return await APIManager().fetchData(Constants.NEW_COMBO, map); + } +} diff --git a/lib/application/views/inventorymodule/comboviews/viewModels/AddComboGroupViewModel.dart b/lib/application/views/inventorymodule/comboviews/viewModels/AddComboGroupViewModel.dart new file mode 100644 index 0000000..1509e7a --- /dev/null +++ b/lib/application/views/inventorymodule/comboviews/viewModels/AddComboGroupViewModel.dart @@ -0,0 +1,75 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/model/Combo/GetComboModel.dart'; +import 'package:wosull/application/utils/CRUDOperatoinState.dart'; +import 'package:wosull/application/views/inventorymodule/comboviews/repo/ComboRepository.dart'; +import 'package:wosull/helpers/Utils.dart'; + +class AddComboGroupViewModel with ChangeNotifier { + bool isPortrait = true; + bool _isLoading = false; + + bool get isLoading => _isLoading; + var addComboGroup = AddComboGroup(); + final repository = ComboRepository(); + var groupName = ''; + + var _crudOperation = CRUDOperationState.uninitialized; + + CRUDOperationState get crudOperation => _crudOperation; + + void init() { + addComboGroup.subGroups = []; + addComboGroup.subGroups!.add(ComboSubGroup(name: "")); + } + + void disposeData() { + _isLoading = false; + groupName = ''; + } + + void setLoading(bool value) { + _isLoading = value; + notifyListeners(); + } + + Future isValidate() async { + if (groupName.isEmpty) { + Utils.showMessage('Please enter group name'); + } else if (addComboGroup.subGroups!.isEmpty) { + Utils.showMessage('Please enter sub group name'); + } else if (addComboGroup.subGroups!.first.name!.isEmpty) { + Utils.showMessage('Please enter sub group name'); + } else { + await addGroup(); + } + } + + Future addGroup() async { + setLoading(true); + addComboGroup.groupName = groupName; + + await repository.addGroup(addComboGroup.toJson()).then((response) { + if (response.success) { + Utils.showMessage(response.message); + _crudOperation = CRUDOperationState.add; + } else { + Utils.showMessage(response.message); + _crudOperation = CRUDOperationState.error; + } + setLoading(false); + }).onError((error, stackTrace) { + _crudOperation = CRUDOperationState.error; + setLoading(false); + }); + } + + void removeGroup(int position) { + addComboGroup.subGroups!.removeAt(position); + notifyListeners(); + } + + void addNewComboGroup() { + addComboGroup.subGroups!.add(ComboSubGroup(name: '')); + notifyListeners(); + } +} diff --git a/lib/application/views/inventorymodule/comboviews/viewModels/AddComboSizeViewModel.dart b/lib/application/views/inventorymodule/comboviews/viewModels/AddComboSizeViewModel.dart new file mode 100644 index 0000000..8661aa2 --- /dev/null +++ b/lib/application/views/inventorymodule/comboviews/viewModels/AddComboSizeViewModel.dart @@ -0,0 +1,97 @@ +import 'package:flutter/cupertino.dart'; +import 'package:wosull/application/model/Combo/GetComboSizes.dart'; +import 'package:wosull/application/utils/CRUDOperatoinState.dart'; +import 'package:wosull/application/views/inventorymodule/comboviews/repo/ComboRepository.dart'; +import 'package:wosull/helpers/Utils.dart'; + +class AddComboSizeViewModel with ChangeNotifier { + List controller = []; + bool isPortrait = true; + + bool _isLoading = false; + + bool get isLoading => _isLoading; + + var newSizeController = ''; + + var _crudOperation = CRUDOperationState.uninitialized; + + CRUDOperationState get crudOperation => _crudOperation; + + final repository = ComboRepository(); + + void disposeData() { + controller.clear(); + _crudOperation = CRUDOperationState.uninitialized; + _isLoading = false; + newSizeController = ''; + } + + void setLoading(bool value) { + _isLoading = value; + notifyListeners(); + } + + Future addUpdateSize() async { + _crudOperation = CRUDOperationState.update; + setLoading(true); + var comboSizes = ComboSize(id: '', sizes: controller); + await repository.addUpdateSize(comboSizes.toJson()).then((response) { + if (response.success) { + _crudOperation = CRUDOperationState.add; + Utils.showMessage(response.message); + } + notifyListeners(); + }).onError((error, stackTrace) {}); + } + + void setSizes(ComboSize comboSize) { + if (comboSize.sizes != null) { + for (var size in comboSize.sizes!) { + controller.add(size); + } + } else { + controller.add(''); + } + } + + void addNewSizeToList() { + if (newSizeController.isNotEmpty) { + controller.add(newSizeController); + newSizeController = ''; + notifyListeners(); + } else { + Utils.showMessage('Enter Size name'); + } + } + + void removeSize(int position) { + controller.removeAt(position); + notifyListeners(); + } + + Future isValidate() async { + if (controller.isNotEmpty) { + await addUpdateSize(); + } else { + Utils.showMessage('Add At least One Size'); + } + } + + void getComboSizes() async { + await repository.getComboSizes().then((response) { + if (response.success!) { + if (response.comboSizes != null) { + for (var size in response.comboSizes!.sizes!) { + controller.add(size); + } + } + } + _crudOperation = CRUDOperationState.update; + notifyListeners(); + }).onError((error, stackTrace) { + _crudOperation = CRUDOperationState.error; + notifyListeners(); + }); + } +} diff --git a/lib/application/views/inventorymodule/comboviews/viewModels/AddNewComboViewModel.dart b/lib/application/views/inventorymodule/comboviews/viewModels/AddNewComboViewModel.dart new file mode 100644 index 0000000..a6646b8 --- /dev/null +++ b/lib/application/views/inventorymodule/comboviews/viewModels/AddNewComboViewModel.dart @@ -0,0 +1,309 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/application/model/Combo/AddNewComboModel.dart'; +import 'package:wosull/application/model/Combo/ComboProduct.dart'; +import 'package:wosull/application/model/Combo/GetComboGroupModel.dart'; +import 'package:wosull/application/model/Combo/GetComboMeasurementModel.dart'; +import 'package:wosull/application/model/Combo/GetComboModel.dart'; +import 'package:wosull/application/model/StockTransfer/ProductItemCategoryModel.dart'; +import 'package:wosull/application/model/inventory/category/ItemCategory.dart'; +import 'package:wosull/application/repository/WosulRepository.dart'; +import 'package:wosull/application/utils/CRUDOperatoinState.dart'; +import 'package:wosull/application/views/inventorymodule/comboviews/repo/ComboRepository.dart'; +import 'package:wosull/helpers/Utils.dart'; + +class AddNewComboViewModel with ChangeNotifier { + var isLoadingFirst = true; + var isLoadingData = false; + + bool isPortrait = true; + + var comboNameController = ''; + var comboTotalPriceController = ''; + + List comboProduct = []; + List comboGroups = []; + List categoriesList = []; + List comboMeasurement = []; + List subGroup = []; + List comboSize = []; + List priceController = []; + List quantityController = []; + var selectedItemCategory; + var addCombo = AddNewComboModel(); + List selectedSizeValue = []; + List selectedGroup = []; + List selectedSubGroup = []; + List selectedProduct = []; + List selectedMeasurement = []; + + var _crudOperation = CRUDOperationState.uninitialized; + + CRUDOperationState get crudOperation => _crudOperation; + + final repository = ComboRepository(); + final wosulRepository = WosulRepository(); + + void disposeData() { + addCombo = AddNewComboModel(); + selectedItemCategory = null; + selectedSizeValue.clear(); + comboTotalPriceController = ''; + comboNameController = ''; + comboProduct.clear(); + comboGroups.clear(); + categoriesList.clear(); + comboMeasurement.clear(); + subGroup.clear(); + comboSize.clear(); + priceController.clear(); + quantityController.clear(); + isLoadingFirst = true; + selectedGroup.clear(); + selectedSubGroup.clear(); + selectedProduct.clear(); + selectedMeasurement.clear(); + priceController.clear(); + comboSize.clear(); + quantityController.clear(); + } + + void setLoading(bool value) { + isLoadingData = value; + notifyListeners(); + } + + void setLoadingFirst(bool value) { + isLoadingFirst = value; + notifyListeners(); + } + + Future initData() async { + isLoadingFirst = true; + addCombo.comboProducts = []; + emptyProduct(); + await loadCategories(); + } + + Future loadCategories() async { + final response = await WosulRepository().getCategoriesData(); + categoriesList.clear(); + categoriesList.addAll(response); + if (categoriesList.isNotEmpty) { + selectedItemCategory = categoriesList.first; + addCombo.categoryId = categoriesList.first.id; + } + loadSizes(); + } + + Future loadSizes() async { + await repository.getComboSizes().then((response) { + if (response.success!) { + comboSize.addAll(response.comboSizes!.sizes!); + loadGroups(); + } else { + setLoadingFirst(false); + } + }).onError((error, stackTrace) { + setLoading(false); + }); + } + + Future loadGroups() async { + await wosulRepository.loadGroups().then((value) { + if (value.isNotEmpty) { + comboGroups.addAll(value); + loadMeasurement(); + } else { + setLoadingFirst(false); + } + }).onError((error, stackTrace) { + setLoadingFirst(false); + }); + } + + Future loadMeasurement() async { + await wosulRepository.loadMeasurement().then((value) { + if (value.isNotEmpty) { + comboMeasurement.addAll(value); + if (categoriesList.isNotEmpty) { + loadProduct(); + } + } else { + setLoadingFirst(false); + } + }).onError((error, stackTrace) { + setLoadingFirst(false); + }); + } + + Future loadProduct() async { + ItemCategory itemCategory = selectedItemCategory; + Map map = { + 'store_id': sharedPrefs.storeId, + 'category_id': itemCategory.id, + }; + await wosulRepository.loadProduct(map).then((value) { + if (value.isNotEmpty) { + comboProduct.clear(); + comboProduct.addAll(value); + setLoadingFirst(false); + } else { + setLoadingFirst(false); + } + }).onError((error, stackTrace) { + setLoadingFirst(false); + }); + } + + Future isValidate() async { + if (comboNameController.isEmpty) { + Utils.showMessage('Please enter combo name'); + } else if (addCombo.comboProducts.isEmpty) { + Utils.showMessage('Please fill at least one combo product'); + } else if (addCombo.comboProducts.first.product == null || + addCombo.comboProducts.first.price == null || + addCombo.comboProducts.first.subGroup == null || + addCombo.comboProducts.first.size == null || + addCombo.comboProducts.first.measurementId == null) { + Utils.showMessage('Please fill at least one combo '); + } else { + await addUpdateCombo(); + } + } + + Future addUpdateCombo() async { + addCombo.comboPrice = double.parse(comboTotalPriceController); + addCombo.comboName = comboNameController; + setLoading(true); + await repository.addUpdateCombo(addCombo.toJson()).then((response) { + if (response.success) { + _crudOperation = CRUDOperationState.add; + Utils.showMessage(response.message); + } + setLoading(false); + }).onError((error, stackTrace) { + setLoading(false); + _crudOperation = CRUDOperationState.error; + }); + } + + void setSelectedCategory(ItemCategory? data) { + if (data != null) { + selectedItemCategory = data; + addCombo.categoryId = data.id; + loadProduct(); + } + } + + void setSelectedSize(String? data, int position) { + if (data != null) { + selectedSizeValue[position] = data; + addCombo.comboProducts[position].size = data; + } + + notifyListeners(); + } + + void setSelectedComboGroup(ComboGroup? data, int position) { + if (data != null) { + selectedGroup[position] = data; + addCombo.comboProducts[position].group = data.name!; + subGroup.clear(); + subGroup.addAll(data.subGroups!); + } + notifyListeners(); + } + + void setSelectedSubGroup(ComboSubGroup? data, int position) { + if (data != null) { + selectedSubGroup[position] = data; + addCombo.comboProducts[position].subGroup = data.name!; + } + notifyListeners(); + } + + void onChangeProduct(ProductItem? data, position) { + if (data != null) { + selectedProduct[position] = data; + priceController[position] = data.price.toString(); + + if (comboTotalPriceController.isNotEmpty) { + var price = double.parse(comboTotalPriceController) + data.price!; + comboTotalPriceController = price.toString(); + } else { + comboTotalPriceController = data.price.toString(); + } + addCombo.comboProducts[position].price = data.price!; + addCombo.comboProducts[position].product = data.name!; + } + notifyListeners(); + } + + void onChangeMeasurement(ComboMeasurement? data, position) { + if (data != null) { + selectedMeasurement[position] = data; + addCombo.comboProducts[position].measurementId = data.name!; + } + notifyListeners(); + } + + void onChangeQuantity(String value, int position) { + if (value.isNotEmpty) { + addCombo.comboProducts[position].quantity = value; + ProductItem product = selectedProduct[position]; + priceController[position] = + (int.parse(value) * product.price!).toString(); + + var totalPrice = 0.0; + for (var price in priceController) { + totalPrice = totalPrice + double.parse(price); + } + comboTotalPriceController = totalPrice.toString(); + } + notifyListeners(); + } + + void removeComboProduct(int position) { + if (comboTotalPriceController.isNotEmpty) { + var price = priceController[position]; + price = (double.parse(comboTotalPriceController) - double.parse(price)) + .toString(); + comboTotalPriceController = price.toString(); + } + + selectedSizeValue.removeAt(position); + selectedGroup.removeAt(position); + selectedSubGroup.removeAt(position); + selectedProduct.removeAt(position); + selectedMeasurement.removeAt(position); + + quantityController.removeAt(position); + priceController.removeAt(position); + addCombo.comboProducts.removeAt(position); + + notifyListeners(); + } + + void addNewCombo() { + emptyProduct(); + notifyListeners(); + } + + void emptyProduct() { + addCombo.comboProducts.add(ComboProducts()); + selectedSizeValue.add('Choose'); + selectedGroup.add(ComboGroup(name: 'Choose', id: '', subGroups: [])); + selectedSubGroup.add(ComboSubGroup(name: 'Choose')); + selectedProduct.add(ProductItem( + name: 'Choose', + id: '', + price: 0, + total_quantity: 0, + uniqueIdForStoreData: '', + details: '')); + selectedMeasurement.add(ComboMeasurement(id: '', name: 'Choose')); + quantityController.add('0'); + priceController.add('0'); + } +} diff --git a/lib/application/views/inventorymodule/comboviews/viewModels/ComboViewModel.dart b/lib/application/views/inventorymodule/comboviews/viewModels/ComboViewModel.dart index 118e12f..337ace0 100644 --- a/lib/application/views/inventorymodule/comboviews/viewModels/ComboViewModel.dart +++ b/lib/application/views/inventorymodule/comboviews/viewModels/ComboViewModel.dart @@ -2,17 +2,19 @@ import 'package:flutter/cupertino.dart'; import 'package:wosull/application/enum/DataState.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; import 'package:wosull/application/model/Combo/GetComboModel.dart'; -import 'package:wosull/application/network/APIManager.dart'; -import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/inventorymodule/comboviews/repo/ComboRepository.dart'; class ComboViewModel with ChangeNotifier { + final repository = ComboRepository(); int _currentPageNumber = 1; DataState _dataState = DataState.uninitialized; - + int limit = 10; bool _didLastLoad = false; bool _isLoading = false; + bool get isLoading => _isLoading; + DataState get dataState => _dataState; List _dataList = []; List _filteredList = []; @@ -21,7 +23,8 @@ class ComboViewModel with ChangeNotifier { List get filteredList => _filteredList; - fetch({bool isRefresh = false}) async { + fetch({bool isRefresh = false, int limit = 10}) async { + this.limit = limit; _isLoading = true; if (!isRefresh) { _dataState = (_dataState == DataState.uninitialized) @@ -36,14 +39,13 @@ class ComboViewModel with ChangeNotifier { Map data = { 'store_id': sharedPrefs.storeId, 'page': _currentPageNumber, + 'limit': this.limit }; - try { if (_didLastLoad) { _dataState = DataState.noMoreData; } else { - await APIManager().fetchData(Constants.GET_COMBOS, data).then((result) { - final value = GetComboModel.fromJson(result); + await repository.fetch(data).then((value) { if (_dataState == DataState.refreshing) { _filteredList.clear(); _dataList.clear(); @@ -51,7 +53,7 @@ class ComboViewModel with ChangeNotifier { if (value.success!) { _filteredList.addAll(value.combos!); _dataList.addAll(value.combos!); - if (value.combos!.length < 10) { + if (value.combos!.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; @@ -60,8 +62,6 @@ class ComboViewModel with ChangeNotifier { _dataState = DataState.fetched; _currentPageNumber += 1; }).onError((error, stackTrace) { - print(error.toString()); - print(stackTrace.toString()); _dataState = DataState.error; }); } @@ -88,10 +88,7 @@ class ComboViewModel with ChangeNotifier { _dataState = DataState.searching; notifyListeners(); try { - await APIManager() - .fetchData(Constants.SEARCH_COMBO, data) - .then((result) { - final value = GetComboModel.fromJson(result); + await repository.search(data).then((value) { filteredList.clear(); if (value.success!) { filteredList.addAll(value.combos!); @@ -109,10 +106,7 @@ class ComboViewModel with ChangeNotifier { } Future delete(String id) async { - Map data = {'comboId': id}; - await APIManager() - .getResponsePatch(Constants.DELETE_COMBO, data) - .then((result) { + await repository.delete(id).then((result) { filteredList.removeWhere((element) => element.id! == id); dataList.removeWhere((element) => element.id! == id); notifyListeners(); diff --git a/lib/application/views/inventorymodule/comboviews/widgets/ComboListView.dart b/lib/application/views/inventorymodule/comboviews/widgets/ComboListView.dart index 1cc16d9..d4627cd 100644 --- a/lib/application/views/inventorymodule/comboviews/widgets/ComboListView.dart +++ b/lib/application/views/inventorymodule/comboviews/widgets/ComboListView.dart @@ -4,8 +4,11 @@ import 'package:wosull/application/model/converters/DataTimeFormat.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/Utils.dart'; +import 'package:wosull/widgets/ActionPopUpContainer.dart'; +import 'package:wosull/widgets/CustomPopuoMenuButton.dart'; import 'package:wosull/widgets/EmptyDataWidget.dart'; import 'package:wosull/widgets/HeadingText.dart'; +import 'package:wosull/widgets/ListHeadingContainer.dart'; import 'package:wosull/widgets/ValueText.dart'; class ComboListView extends StatelessWidget { @@ -29,10 +32,7 @@ class ComboListView extends StatelessWidget { children: [ isPortrait ? Container() - : Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 50, - color: MyColors.containerBackColor, + : ListHeadingContainer( child: Row( children: [ Expanded( @@ -132,21 +132,7 @@ class ComboListView extends StatelessWidget { ], ), )), - PopupMenuButton( - icon: const Icon(Icons.more_vert), - itemBuilder: (c) { - return [ - PopupMenuItem( - value: 'delete', - child: ValueText( - lang(context).delete, - ), - ) - ]; - }, - onSelected: (String value) => - actionPopUpItemSelected(value, combo), - ) + getPopMenuButton(context, position) ], ), ), @@ -156,10 +142,7 @@ class ComboListView extends StatelessWidget { shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.0), ), - child: Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 56, - color: MyColors.containerBackColor, + child: ListHeadingContainer( child: Row( children: [ Expanded(child: ValueText(combo.comboName!)), @@ -177,29 +160,8 @@ class ComboListView extends StatelessWidget { padding: const EdgeInsets.all(4), child: Align( alignment: Alignment.centerRight, - child: Container( - width: 42, - height: 42, - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular(4)), - color: MyColors.backFillColor), - child: PopupMenuButton( - padding: EdgeInsets.zero, - icon: const Icon(Icons.more_vert), - itemBuilder: (context) { - return [ - PopupMenuItem( - value: 'delete', - child: ValueText( - lang(context).delete, - ), - ) - ]; - }, - onSelected: (String value) => - actionPopUpItemSelected(value, combo), - ), + child: ActionPopUpContainer( + child: getPopMenuButton(context, position), ), ), )) @@ -256,4 +218,19 @@ class ComboListView extends StatelessWidget { onDelete(combo); } } + + getPopMenuButton(BuildContext context, int position) { + return CustomPopupMenuButton( + onSelected: (String value) => + actionPopUpItemSelected(value, data[position]), + items: [ + PopupMenuItem( + value: 'delete', + child: ValueText( + lang(context).delete, + ), + ) + ], + ); + } } diff --git a/lib/application/views/inventorymodule/deliveryPartnerViews/InventoryDeliveryPartnerPriceVC.dart b/lib/application/views/inventorymodule/deliveryPartnerViews/InventoryDeliveryPartnerPriceVC.dart index c6b38e1..b7b8e54 100644 --- a/lib/application/views/inventorymodule/deliveryPartnerViews/InventoryDeliveryPartnerPriceVC.dart +++ b/lib/application/views/inventorymodule/deliveryPartnerViews/InventoryDeliveryPartnerPriceVC.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:provider/provider.dart'; +import 'package:sizer/sizer.dart'; import 'package:wosull/application/enum/DataState.dart'; import 'package:wosull/application/model/DeliveryPartner/GetDeliveryPartner.dart'; import 'package:wosull/application/theme/MyColors.dart'; @@ -15,6 +16,8 @@ import 'package:wosull/base/BaseStatefulState.dart'; import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/ThemeText.dart'; import 'package:wosull/widgets/CustomSimpleButton.dart'; +import 'package:wosull/widgets/PageLimitDropDown.dart'; +import 'package:wosull/widgets/SearchBox.dart'; class InventoryDeliveryPartnerPriceVC extends StatefulWidget { const InventoryDeliveryPartnerPriceVC({Key? key}) : super(key: key); @@ -26,7 +29,6 @@ class InventoryDeliveryPartnerPriceVC extends StatefulWidget { class _InventoryDeliveryPartnerPriceVCState extends BaseStatefulState { - bool isPortrait = true; final viewModel = DeliveryPartnerPriceViewModel(); late ScrollController _controller; @@ -42,7 +44,7 @@ class _InventoryDeliveryPartnerPriceVCState backgroundColor: MyColors.fillColor, resizeToAvoidBottomInset: true, body: OrientationBuilder(builder: (c, orientation) { - isPortrait = + viewModel.isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; return SingleChildScrollView( @@ -51,19 +53,47 @@ class _InventoryDeliveryPartnerPriceVCState padding: const EdgeInsets.all(12), child: Column( children: [ - isPortrait - ? Row( - mainAxisAlignment: MainAxisAlignment.start, + viewModel.isPortrait + ? Column( children: [ - Text( - AppLocalizations.of(context)! - .delivery_partner_price, - style: ThemeText.textStylePageHeading, + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)! + .delivery_partner_price, + style: ThemeText.textStylePageHeading, + ), + AppSpaces.horizontalSmall, + toNewDeliveryPrice(), + ], ), - const SizedBox( - width: 4, - ), - toNewDeliveryPrice(), + Row( + children: [ + Flexible( + child: SizedBox( + height: 48, + child: SearchBox( + onEditingDone: (text) { + filterSearchResults(text); + }, + onChanged: (text) { + filterSearchResults(text); + }, + hint: + AppLocalizations.of(context)!.search, + ), + ), + ), + PageLimitDropdown( + onChange: (value) { + viewModel.fetch( + isRefresh: true, + limit: int.parse(value!)); + }, + ) + ], + ) ], ) : Row( @@ -74,10 +104,37 @@ class _InventoryDeliveryPartnerPriceVCState .delivery_partner_price, style: ThemeText.textStylePageHeading, ), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalSmall, toNewDeliveryPrice(), + AppSpaces.horizontalSmall, + SizedBox( + width: SizerUtil.deviceType == DeviceType.mobile + ? 200 + : 200, + height: 48, + child: SearchBox( + onEditingDone: (text) { + filterSearchResults(text); + }, + onChanged: (text) { + filterSearchResults(text); + }, + hint: AppLocalizations.of(context)!.search, + ), + ), + Flexible( + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + PageLimitDropdown( + onChange: (value) { + viewModel.fetch( + isRefresh: true, + limit: int.parse(value!)); + }, + ) + ], + )) ], ), AppSpaces.verticalMedium, @@ -119,7 +176,7 @@ class _InventoryDeliveryPartnerPriceVCState children: [ DeliveryPartnerPriceListView( data: data, - isPortrait: isPortrait, + isPortrait: viewModel.isPortrait, onUpdate: (partner, value) { _updateStatus(partner.id, value); }, @@ -139,7 +196,7 @@ class _InventoryDeliveryPartnerPriceVCState bool _scrollNotification() { if (!viewModel.isLoading && _controller.position.extentAfter < 300) { - viewModel.fetch(); + viewModel.fetch(limit: viewModel.limit); } return true; } @@ -209,7 +266,7 @@ class _InventoryDeliveryPartnerPriceVCState Widget toNewDeliveryPrice() { return SizedBox( - width: 120, + width: 110, child: CustomSimpleButton( textColor: MyColors.blueThemeColor, backGroundColor: MyColors.backColorBlue50, diff --git a/lib/application/views/inventorymodule/deliveryPartnerViews/ViewInventoryDeliveryPricesVC.dart b/lib/application/views/inventorymodule/deliveryPartnerViews/ViewInventoryDeliveryPricesVC.dart index 5719027..f4606ad 100644 --- a/lib/application/views/inventorymodule/deliveryPartnerViews/ViewInventoryDeliveryPricesVC.dart +++ b/lib/application/views/inventorymodule/deliveryPartnerViews/ViewInventoryDeliveryPricesVC.dart @@ -5,6 +5,7 @@ import 'package:wosull/application/model/converters/DataTimeFormat.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/theme/MyFonts.dart'; import 'package:wosull/application/theme/MySeparator.dart'; +import 'package:wosull/widgets/DialogHeader.dart'; class ViewInventoryDeliveryPricesVC extends StatefulWidget { late DeliveryPartner deliveryPartner; @@ -26,62 +27,33 @@ class _ViewInventoryDeliveryPricesVCState elevation: 0, backgroundColor: const Color(0xffffffff), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(15.0), + borderRadius: BorderRadius.circular(8.0), ), child: OrientationBuilder(builder: (c, orientation) { isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; return SingleChildScrollView( - child: Container( + child: SizedBox( width: !isPortrait ? MediaQuery.of(context).size.width / 1.2 : double.infinity, - padding: const EdgeInsets.only(bottom: 8), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end, children: [ - Row( - mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.max, - children: [ - Expanded( - child: Padding( - padding: const EdgeInsets.only(left: 16), - child: Text( - 'View Prices', - style: MyColors.textStylePopUpHeading(), - ), - )), - Align( - alignment: Alignment.topRight, - child: IconButton( - onPressed: () { - Navigator.of(context).pop(); - }, - icon: const Icon(Icons.close)), - ), - ], - ), - const SizedBox( - height: 8, - ), + DialogHeader(title: 'View Prices'), Container( - height: 2, - color: MyColors.fillColorGray, - ), - Container( - margin: const EdgeInsets.all(16), + margin: const EdgeInsets.all(12), decoration: const BoxDecoration( color: MyColors.fillColor2, borderRadius: BorderRadius.all(Radius.circular(8.0)), ), - padding: const EdgeInsets.all(16), + padding: const EdgeInsets.all(12), child: Column( children: [ Row( children: [ - const Text( + Text( 'Name', style: TextStyle( fontFamily: MyFonts.Medium, @@ -99,7 +71,7 @@ class _ViewInventoryDeliveryPricesVCState ), Text( widget.deliveryPartner.name!, - style: const TextStyle( + style: TextStyle( fontFamily: MyFonts.DMREGULAR, fontSize: MyFonts.normalButton, color: MyColors.textColorGray), @@ -113,7 +85,7 @@ class _ViewInventoryDeliveryPricesVCState children: [ Text( AppLocalizations.of(context)!.created_on, - style: const TextStyle( + style: TextStyle( fontFamily: MyFonts.Medium, fontSize: MyFonts.normalButton, color: MyColors.textColorPopUp), @@ -130,7 +102,7 @@ class _ViewInventoryDeliveryPricesVCState Text( DataTimeFormat.getFormatDate( widget.deliveryPartner.createdAt!), - style: const TextStyle( + style: TextStyle( fontFamily: MyFonts.DMREGULAR, fontSize: MyFonts.normalButton, color: MyColors.textColorGray), @@ -144,7 +116,7 @@ class _ViewInventoryDeliveryPricesVCState children: [ Text( AppLocalizations.of(context)!.updated_on, - style: const TextStyle( + style: TextStyle( fontFamily: MyFonts.Medium, fontSize: MyFonts.normalButton, color: MyColors.textColorPopUp), @@ -161,7 +133,7 @@ class _ViewInventoryDeliveryPricesVCState Text( DataTimeFormat.getFormatDate( widget.deliveryPartner.updatedAt!), - style: const TextStyle( + style: TextStyle( fontFamily: MyFonts.DMREGULAR, fontSize: MyFonts.normalButton, color: MyColors.textColorGray), diff --git a/lib/application/views/inventorymodule/deliveryPartnerViews/inventoryAddDeliveryPriceVC.dart b/lib/application/views/inventorymodule/deliveryPartnerViews/inventoryAddDeliveryPriceVC.dart index def890b..7292b56 100644 --- a/lib/application/views/inventorymodule/deliveryPartnerViews/inventoryAddDeliveryPriceVC.dart +++ b/lib/application/views/inventorymodule/deliveryPartnerViews/inventoryAddDeliveryPriceVC.dart @@ -1,16 +1,22 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:flutter_switch/flutter_switch.dart'; -import 'package:wosull/application/ViewModel/InventoryViewModel.dart'; -import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:provider/provider.dart'; import 'package:wosull/application/model/DeliveryPartner/GetDeliveryPartner.dart'; -import 'package:wosull/application/model/SimpleResponsModel.dart'; import 'package:wosull/application/model/store/WosulStore.dart'; import 'package:wosull/application/theme/MyColors.dart'; -import 'package:wosull/application/theme/MyFonts.dart'; -import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/utils/CRUDOperatoinState.dart'; +import 'package:wosull/application/views/inventorymodule/deliveryPartnerViews/viewModels/NewDeliveryPartnerViewModel.dart'; import 'package:wosull/application/views/popups/SelectMultiStoresPopUp.dart'; import 'package:wosull/base/BaseStatefulState.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/widgets/CustomAppBar.dart'; +import 'package:wosull/widgets/CustomOptionalTitle.dart'; +import 'package:wosull/widgets/CustomSimpleButton.dart'; +import 'package:wosull/widgets/CustomSwitch.dart'; +import 'package:wosull/widgets/CustomTextButtonIcon.dart'; +import 'package:wosull/widgets/CustomTextFieldForm.dart'; +import 'package:wosull/widgets/MandatoryTitleText.dart'; +import 'package:wosull/widgets/TransprentBorderContainer.dart'; //ignore: must_be_immutable class InventoryAddDeliveryPriceVC extends StatefulWidget { @@ -28,406 +34,141 @@ class InventoryAddDeliveryPriceVC extends StatefulWidget { class _InventoryAddDeliveryPriceVCState extends BaseStatefulState { - bool isPortrait = true; - final List _selectedStoreObject = []; - List stores = List.empty(growable: true); - bool _isInAsyncCall = true; - TextEditingController nameController = TextEditingController(); - TextEditingController arabicNameController = TextEditingController(); + var viewModel = NewDeliveryPartnerViewModel(); - InventoryViewModel viewModel = InventoryViewModel(); + @override + void dispose() { + viewModel.disposeData(); + super.dispose(); + } @override void initState() { - // TODO: implement initState super.initState(); - - if (widget.isEdit) { - nameController.text = widget.deliveryPartner.name; - arabicNameController.text = widget.deliveryPartner.nameArabic; - } else { - widget.deliveryPartner.status = "Active"; - } - - getAllStores(); - } - - getAllStores() async { - Map data = { - 'store_id': sharedPrefs.storeId, - 'is_included': true, - }; - - final response = await viewModel.getSpecificStoresById(data); - - if (response.success) { - setState(() { - _isInAsyncCall = false; - stores.clear(); - stores.addAll(response.stores); - - if (widget.isEdit) { - for (var store in stores) { - if (widget.deliveryPartner.stores!.contains(store.id)) { - _selectedStoreObject.add(store); - } - } - } - }); - } else {} + context + .read() + .initPartner(widget.isEdit, widget.deliveryPartner); } @override Widget build(BuildContext context) { - return MaterialApp( - debugShowCheckedModeBanner: false, - home: Scaffold( - resizeToAvoidBottomInset: true, - appBar: AppBar( - leading: BackButton( - color: Colors.black, - onPressed: () { - Navigator.pop(context); - }, // <-- SEE HERE - ), - centerTitle: true, - title: Text( - widget.isEdit - ? 'Edit Prices' - : AppLocalizations.of(context)!.add_prices, - style: const TextStyle( - color: MyColors.textColorBlack, - fontFamily: MyFonts.Bold, - fontSize: 22), - ), - backgroundColor: MyColors.white, - elevation: 5, - ), - body: OrientationBuilder(builder: (c, orientation) { - isPortrait = - MediaQuery.of(context).orientation == Orientation.portrait; - return SingleChildScrollView( - child: _isInAsyncCall - ? const Center( - child: CircularProgressIndicator(), - ) - : Container( - padding: const EdgeInsets.only(bottom: 8), - child: Padding( - padding: const EdgeInsets.all(16), - child: Column( - mainAxisAlignment: MainAxisAlignment.end, - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Row( - children: [ - Text( - AppLocalizations.of(context)!.name, - style: const TextStyle( - fontSize: 16, - fontFamily: MyFonts.Medium, - color: MyColors.black), - ), - const Text( - '*', - style: TextStyle( - fontSize: 16, - fontFamily: MyFonts.Medium, - color: MyColors.fillRed), - ), - ], - ), - const SizedBox( - height: 4, - ), - SizedBox( - height: 42, - child: TextField( - controller: nameController, - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normalButton, - color: MyColors.black), - decoration: InputDecoration( - contentPadding: - const EdgeInsets.fromLTRB(8, 0, 8, 0), - hintText: 'Enter Name', - fillColor: MyColors.fillColor2, - filled: true, - focusedBorder: OutlineInputBorder( - borderSide: const BorderSide( - color: Colors.transparent, width: 1.0), - borderRadius: BorderRadius.circular(8.0), - ), - enabledBorder: OutlineInputBorder( - borderSide: const BorderSide( - width: 1, //<-- SEE HERE - color: Colors.transparent, - ), - borderRadius: BorderRadius.circular(8.0), - ), - ), - ), - ), - const SizedBox( - height: 8, - ), - Row( - children: [ - Text( - AppLocalizations.of(context)!.name_ar, - style: const TextStyle( - fontSize: 16, - fontFamily: MyFonts.Medium, - color: MyColors.black), - ), - ], - ), - const SizedBox( - height: 4, - ), - SizedBox( - height: 42, - child: TextField( - controller: arabicNameController, - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normalButton, - color: MyColors.black), - decoration: InputDecoration( - contentPadding: - const EdgeInsets.fromLTRB(8, 0, 8, 0), - hintText: 'Enter Name (Arabic)', - fillColor: MyColors.fillColor2, - filled: true, - focusedBorder: OutlineInputBorder( - borderSide: const BorderSide( - color: Colors.transparent, width: 1.0), - borderRadius: BorderRadius.circular(8.0), - ), - enabledBorder: OutlineInputBorder( - borderSide: const BorderSide( - width: 1, //<-- SEE HERE - color: Colors.transparent, - ), - borderRadius: BorderRadius.circular(8.0), - ), - ), - ), - ), - const SizedBox( - height: 8, - ), - Row( - children: [ - Text( - AppLocalizations.of(context)!.status, - style: const TextStyle( - fontSize: MyFonts.normalButton, - fontWeight: FontWeight.w600, - fontFamily: MyFonts.DMREGULAR, - color: MyColors.textColorPopUp), - ), - ], - ), - const SizedBox( - height: 12, - ), - Row( - children: [ - FlutterSwitch( - height: 20.0, - width: 40.0, - padding: 4.0, - toggleSize: 15.0, - borderRadius: 10.0, - activeColor: MyColors.blueThemeColor, - value: widget.deliveryPartner.getStatus(), - onToggle: (value) { - setState(() { - if (value) { - widget.deliveryPartner.status = - "Active"; - } else { - widget.deliveryPartner.status = - "Inactive"; - } - }); - }, - ), - ], - ), - const SizedBox( - height: 8, - ), - Row( - children: [ - Text( - AppLocalizations.of(context)!.choose_store, - style: const TextStyle( - fontSize: 16, - fontFamily: MyFonts.Medium, - color: MyColors.black), - ), - const Text( - '*', - style: TextStyle( - fontSize: 16, - fontFamily: MyFonts.Medium, - color: MyColors.fillRed), - ), - ], - ), - const SizedBox( - height: 4, - ), - Container( - height: 48, - padding: const EdgeInsets.only(right: 8), - decoration: BoxDecoration( - border: Border.all( - color: Colors.transparent, - width: 1, - ), - color: MyColors.fillColor2, - borderRadius: BorderRadius.circular(8.0), - ), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Expanded( - child: TextButton( - onPressed: () async { - List result = - await showDialog( - barrierColor: Colors.black26, - context: context, - builder: (c) { - return SelectMultiStoresPopUp( - selectedStore: widget - .deliveryPartner.stores!); - }, - ); - - if (!mounted) return; - setState(() { - widget.deliveryPartner.stores!.clear(); - _selectedStoreObject.clear(); - _selectedStoreObject.addAll(result); - for (var item in _selectedStoreObject) { - widget.deliveryPartner.stores! - .add(item.id); - } - }); - }, - child: Align( - alignment: Alignment.centerLeft, - child: Text( - widget.deliveryPartner.stores! - .isNotEmpty - ? getStores() - : AppLocalizations.of(context)! - .choose_store, - textAlign: TextAlign.left, - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normalButton, - color: Colors.black), - ), - ), - )), - const Icon( - // <-- Icon - Icons.arrow_drop_down, - size: 24.0, - color: MyColors.black, - ) - ], - ), - ), - SizedBox( - width: 100, - child: Padding( - padding: const EdgeInsets.only(right: 16), - child: ElevatedButton( - style: ElevatedButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(6.0), - ), - backgroundColor: MyColors.blueThemeColor, - minimumSize: - const Size.fromHeight(38), // NEW - ), - onPressed: () { - isValidate(); - }, - child: Text( - AppLocalizations.of(context)!.save, - style: const TextStyle( - fontSize: MyFonts.normalButton, - color: MyColors.white, - fontFamily: MyFonts.Bold), - ), - ), - ), - ), - ], + viewModel = context.watch(); + return Scaffold( + resizeToAvoidBottomInset: true, + backgroundColor: MyColors.white, + appBar: CustomAppBar( + heading: viewModel.isEdit + ? 'Edit Prices' + : AppLocalizations.of(context)!.add_prices, + ), + body: OrientationBuilder(builder: (c, orientation) { + viewModel.isPortrait = + MediaQuery.of(context).orientation == Orientation.portrait; + return SingleChildScrollView( + child: Container( + padding: const EdgeInsets.only(bottom: 8), + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + MandatoryTitleText( + hint: AppLocalizations.of(context)!.name, + ), + AppSpaces.verticalSmall, + CustomTextFieldForm( + initialValue: viewModel.nameController, + hintText: 'Enter Name', + onChanged: (String value) { + viewModel.nameController = value; + }, + ), + AppSpaces.verticalLarge, + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.name_ar, + ), + AppSpaces.verticalSmall, + CustomTextFieldForm( + initialValue: viewModel.arabicNameController, + hintText: 'Enter Name (Arabic)', + onChanged: (String value) { + viewModel.arabicNameController = value; + }, + ), + AppSpaces.verticalLarge, + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.status, + ), + AppSpaces.verticalLarge, + Row( + children: [ + CustomSwitch( + value: viewModel.deliveryPartner.getStatus(), + onToggle: (value) { + viewModel.updateStatus(value); + }, ), + ], + ), + AppSpaces.verticalMedium, + MandatoryTitleText( + hint: AppLocalizations.of(context)!.choose_store), + AppSpaces.verticalSmall, + TransparentBorderContainer( + height: 48, + child: CustomTextButtonIcon( + backgroundColor: MyColors.backFillColor, + heading: viewModel.deliveryPartner.stores!.isNotEmpty + ? viewModel.getStores() + : AppLocalizations.of(context)!.choose_store, + onPressed: () { + showStoresPopUp(); + }, ), ), - ); - })), - ); + AppSpaces.verticalMedium, + Align( + alignment: Alignment.centerRight, + child: SizedBox( + width: 100, + child: CustomSimpleButton( + isLoading: viewModel.isLoading, + textColor: MyColors.white, + backGroundColor: MyColors.blueThemeColor, + onPressed: () async { + await viewModel.isValidate(); + checkState(); + }, + heading: AppLocalizations.of(context)!.save, + ), + ), + ), + ], + ), + ), + ), + ); + })); } - Future isValidate() async { - if (nameController.text.isEmpty) { - showMessage('Enter Name'); - } else if (widget.deliveryPartner.stores!.isEmpty) { - showMessage('Choose Store'); - } else { - addUpdatePrice(); - } - } + Future showStoresPopUp() async { + List result = await showDialog( + barrierColor: Colors.black26, + context: context, + builder: (c) { + return SelectMultiStoresPopUp( + selectedStore: viewModel.deliveryPartner.stores!); + }, + ); - String getStores() { - String name = ""; - for (var storeName in _selectedStoreObject) { - if (name.isEmpty) { - name = storeName.name; - } else { - name = "$name, ${storeName.name}"; - } - } - return name; + if (!mounted) return; + viewModel.setStores(result); } - Future addUpdatePrice() async { - progressDialogue(context); - - Map data = { - 'name': nameController.text, - 'arabic_name': arabicNameController.text, - 'status': widget.deliveryPartner.status, - 'store_id': widget.deliveryPartner.stores, - 'delivery_id': widget.deliveryPartner.id, - }; - - await viewModel - .getData(Constants.ADD_DELIVERY_PARTNER, data) - .then((response) async { - final value = SimpleResponseModel.fromJson(response); - if (value.success) { - showMessage(value.message); - hideProgressBar(); - Navigator.pop(context, true); - } - }).onError((error, stackTrace) { - setState(() { - hideProgressBar(); - }); - }); + void checkState() { + if (viewModel.crudOperation == CRUDOperationState.add) { + Navigator.pop(context, true); + } } } diff --git a/lib/application/views/inventorymodule/deliveryPartnerViews/repository/DeliveryPartnerRepository.dart b/lib/application/views/inventorymodule/deliveryPartnerViews/repository/DeliveryPartnerRepository.dart new file mode 100644 index 0000000..70f1ace --- /dev/null +++ b/lib/application/views/inventorymodule/deliveryPartnerViews/repository/DeliveryPartnerRepository.dart @@ -0,0 +1,67 @@ +import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/application/model/DeliveryPartner/GetDeliveryPartner.dart'; +import 'package:wosull/application/model/SimpleResponsModel.dart'; +import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/utils/Constants.dart'; + +class DeliveryPartnerRepository { + Future> getAllPartners() async { + var items = []; + var data = { + 'is_item_included': true, + }; + await APIManager() + .getResponseAuth( + Constants.getStoreDeliveryPartner + sharedPrefs.storeId, data) + .then((value) { + final response = GetDeliveryPartner.fromJson(value); + if (response.success!) { + items.addAll(response.deliveries!); + } + }).onError((error, stackTrace) {}); + + return items; + } + + Future> fetch(data) async { + var items = []; + await APIManager() + .fetchData(Constants.GET_DELIVERY_PARTNER, data) + .then((result) { + final value = GetDeliveryPartner.fromJson(result); + if (value.success!) { + items.addAll(value.deliveries!); + } + }).onError((error, stackTrace) {}); + return items; + } + + Future> search({String searchValue = ""}) async { + var items = []; + var data = {'store_id': sharedPrefs.storeId, 'searchTerm': searchValue}; + await APIManager() + .fetchData(Constants.SEARCH_PARTNER_PRICE, data) + .then((result) { + final value = SearchDeliveryPartner.fromJson(result); + if (value.success!) { + items.addAll(value.deliveries!); + } + }).onError((error, stackTrace) {}); + return items; + } + + Future delete(String id) async { + Map data = {'deliveryId': id}; + return await APIManager() + .getResponsePatch(Constants.DELETE_DELIVERY_PARTNER, data); + } + + Future update(String id, bool value) async { + Map data = { + 'deliveryId': id, + 'status': value ? 'Active' : 'Inactive' + }; + return await APIManager() + .getResponsePatch(Constants.UPDATE_DELIVERY_PARTNER_STATUS, data); + } +} diff --git a/lib/application/views/inventorymodule/deliveryPartnerViews/viewModels/DeliveryPartnerPriceViewModel.dart b/lib/application/views/inventorymodule/deliveryPartnerViews/viewModels/DeliveryPartnerPriceViewModel.dart index 29201ce..b4c08b2 100644 --- a/lib/application/views/inventorymodule/deliveryPartnerViews/viewModels/DeliveryPartnerPriceViewModel.dart +++ b/lib/application/views/inventorymodule/deliveryPartnerViews/viewModels/DeliveryPartnerPriceViewModel.dart @@ -2,18 +2,18 @@ import 'package:flutter/material.dart'; import 'package:wosull/application/enum/DataState.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; import 'package:wosull/application/model/DeliveryPartner/GetDeliveryPartner.dart'; -import 'package:wosull/application/network/APIManager.dart'; -import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/inventorymodule/deliveryPartnerViews/repository/DeliveryPartnerRepository.dart'; class DeliveryPartnerPriceViewModel with ChangeNotifier { int _currentPageNumber = 1; - + final repository = DeliveryPartnerRepository(); DataState _dataState = DataState.uninitialized; - + int limit = 10; bool _didLastLoad = false; bool _isLoading = false; bool get isLoading => _isLoading; + bool isPortrait = true; DataState get dataState => _dataState; final List _dataList = []; @@ -23,33 +23,35 @@ class DeliveryPartnerPriceViewModel with ChangeNotifier { List get filteredList => _filteredList; - late DeliveryPartner __typesGroupValue = DeliveryPartner(); + late DeliveryPartner _selectedDeliveryPartner; + + DeliveryPartner get selectedDeliveryPartner => _selectedDeliveryPartner; - DeliveryPartner get selectedType => __typesGroupValue; + int selectedItem = -1; + + void disposeData() { + selectedItem = -1; + } - void changeSelectedType(DeliveryPartner? value) { - __typesGroupValue = value!; + void changeSelectedType(DeliveryPartner? value, int selectedItem) { + _selectedDeliveryPartner = value!; + this.selectedItem = selectedItem; notifyListeners(); } Future> getAllPartners() async { var items = []; - await APIManager() - .getResponseAuth( - Constants.getStoreDeliveryPartner + sharedPrefs.storeId) - .then((value) { - final response = GetDeliveryPartner.fromJson(value); - if (response.success!) { - items.addAll(response.deliveries!); - } - }) - .onError((error, stackTrace) {}) - .timeout(const Duration(minutes: 1)); + await repository.getAllPartners().then((response) { + if (response.isNotEmpty) { + items.addAll(response); + } + }).onError((error, stackTrace) {}); return items; } - fetch({bool isRefresh = false}) async { + fetch({bool isRefresh = false, int limit = 10}) async { + this.limit = limit; _isLoading = true; if (!isRefresh) { _dataState = (_dataState == DataState.uninitialized) @@ -64,24 +66,22 @@ class DeliveryPartnerPriceViewModel with ChangeNotifier { Map data = { 'store_id': sharedPrefs.storeId, 'page': _currentPageNumber, + 'limit': this.limit }; try { if (_didLastLoad) { _dataState = DataState.noMoreData; } else { - await APIManager() - .fetchData(Constants.GET_DELIVERY_PARTNER, data) - .then((result) { - final value = GetDeliveryPartner.fromJson(result); + await repository.fetch(data).then((value) { if (_dataState == DataState.refreshing) { _filteredList.clear(); _dataList.clear(); } - if (value.success!) { - _filteredList.addAll(value.deliveries!); - _dataList.addAll(value.deliveries!); - if (value.deliveries!.length < 10) { + if (value.isNotEmpty) { + _filteredList.addAll(value); + _dataList.addAll(value); + if (value.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; @@ -109,20 +109,13 @@ class DeliveryPartnerPriceViewModel with ChangeNotifier { _filteredList.addAll(_dataList); notifyListeners(); } else { - Map data = { - 'store_id': sharedPrefs.storeId, - 'searchTerm': searchValue - }; _dataState = DataState.searching; notifyListeners(); try { - await APIManager() - .fetchData(Constants.SEARCH_PARTNER_PRICE, data) - .then((result) { - final value = SearchDeliveryPartner.fromJson(result); + await repository.search(searchValue: searchValue).then((value) { filteredList.clear(); - if (value.success!) { - filteredList.addAll(value.deliveries!); + if (value.isNotEmpty) { + filteredList.addAll(value); } _dataState = DataState.fetched; }).onError((error, stackTrace) { @@ -137,10 +130,7 @@ class DeliveryPartnerPriceViewModel with ChangeNotifier { } Future delete(String id) async { - Map data = {'deliveryId': id}; - await APIManager() - .getResponsePatch(Constants.DELETE_DELIVERY_PARTNER, data) - .then((result) { + await repository.delete(id).then((result) { filteredList.removeWhere((element) => element.id == id); dataList.removeWhere((element) => element.id == id); notifyListeners(); @@ -150,18 +140,11 @@ class DeliveryPartnerPriceViewModel with ChangeNotifier { } Future update(String id, bool value) async { - String status = ''; - if (value) { - status = "Active"; - } else { - status = "Inactive"; - } - Map data = {'deliveryId': id, 'status': status}; - await APIManager() - .getResponsePatch(Constants.UPDATE_DELIVERY_PARTNER_STATUS, data) - .then((result) { - _filteredList.singleWhere((element) => element.id == id).status = status; - _dataList.singleWhere((element) => element.id == id).status = status; + await repository.update(id, value).then((result) { + _filteredList.singleWhere((element) => element.id == id).status = + value ? 'Active' : 'Inactive'; + _dataList.singleWhere((element) => element.id == id).status = + value ? 'Active' : 'Inactive'; notifyListeners(); }).onError((error, stackTrace) { notifyListeners(); diff --git a/lib/application/views/inventorymodule/deliveryPartnerViews/viewModels/NewDeliveryPartnerViewModel.dart b/lib/application/views/inventorymodule/deliveryPartnerViews/viewModels/NewDeliveryPartnerViewModel.dart new file mode 100644 index 0000000..736eb3b --- /dev/null +++ b/lib/application/views/inventorymodule/deliveryPartnerViews/viewModels/NewDeliveryPartnerViewModel.dart @@ -0,0 +1,145 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/application/model/DeliveryPartner/GetDeliveryPartner.dart'; +import 'package:wosull/application/model/SimpleResponsModel.dart'; +import 'package:wosull/application/model/store/GetSpecificStores.dart'; +import 'package:wosull/application/model/store/WosulStore.dart'; +import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/utils/CRUDOperatoinState.dart'; +import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/helpers/Utils.dart'; + +class NewDeliveryPartnerViewModel with ChangeNotifier { + bool isPortrait = true; + final List selectedStoreObject = []; + List stores = []; + bool _isLoading = false; + + bool get isLoading => _isLoading; + + var _crudOperation = CRUDOperationState.uninitialized; + + CRUDOperationState get crudOperation => _crudOperation; + + var nameController = ''; + var arabicNameController = ''; + late DeliveryPartner deliveryPartner; + var isEdit = false; + + void disposeData() { + nameController = ''; + arabicNameController = ''; + selectedStoreObject.clear(); + stores.clear(); + } + + void setLoading(bool value) { + _isLoading = value; + notifyListeners(); + } + + Future initPartner(bool isEdit, DeliveryPartner deliveryPartner) async { + this.isEdit = isEdit; + this.deliveryPartner = deliveryPartner; + if (isEdit) { + nameController = deliveryPartner.name; + arabicNameController = deliveryPartner.nameArabic; + } else { + deliveryPartner.status = "Active"; + } + await getAllStores(); + } + + Future getAllStores() async { + Map data = { + 'store_id': sharedPrefs.storeId, + 'is_included': true, + }; + // getSpecificStoresById(data); + await APIManager() + .fetchData(Constants.GET_SPECIFIC_STORES, data) + .then((value) { + final response = GetSpecificStores.fromJson(value); + + stores.clear(); + stores.addAll(response.stores); + + if (isEdit) { + for (var store in stores) { + if (deliveryPartner.stores!.contains(store.id)) { + selectedStoreObject.add(store); + } + } + } + notifyListeners(); + }).onError((error, stackTrace) {}); + } + + Future isValidate() async { + if (nameController.isEmpty) { + Utils.showMessage('Enter Name'); + } else if (deliveryPartner.stores!.isEmpty) { + Utils.showMessage('Choose Store'); + } else { + await addUpdatePrice(); + } + } + + String getStores() { + String name = ""; + for (var storeName in selectedStoreObject) { + if (name.isEmpty) { + name = storeName.name; + } else { + name = "$name, ${storeName.name}"; + } + } + return name; + } + + Future addUpdatePrice() async { + setLoading(true); + Map data = { + 'name': nameController, + 'arabic_name': arabicNameController, + 'status': deliveryPartner.status, + 'store_id': deliveryPartner.stores, + 'delivery_id': deliveryPartner.id, + }; + + await APIManager() + .fetchData(Constants.ADD_DELIVERY_PARTNER, data) + .then((response) async { + final value = SimpleResponseModel.fromJson(response); + if (value.success) { + Utils.showMessage(value.message); + _crudOperation = CRUDOperationState.add; + } else { + _crudOperation = CRUDOperationState.error; + } + setLoading(false); + }).onError((error, stackTrace) { + _crudOperation = CRUDOperationState.error; + setLoading(false); + }); + } + + void setStores(List result) { + deliveryPartner.stores!.clear(); + selectedStoreObject.clear(); + selectedStoreObject.addAll(result); + for (var item in selectedStoreObject) { + deliveryPartner.stores!.add(item.id); + } + notifyListeners(); + } + + void updateStatus(bool value) { + if (value) { + deliveryPartner.status = "Active"; + } else { + deliveryPartner.status = "Inactive"; + } + notifyListeners(); + } +} diff --git a/lib/application/views/inventorymodule/deliveryPartnerViews/widgets/DeliveryPartnerPriceListView.dart b/lib/application/views/inventorymodule/deliveryPartnerViews/widgets/DeliveryPartnerPriceListView.dart index 4e473fe..35568e0 100644 --- a/lib/application/views/inventorymodule/deliveryPartnerViews/widgets/DeliveryPartnerPriceListView.dart +++ b/lib/application/views/inventorymodule/deliveryPartnerViews/widgets/DeliveryPartnerPriceListView.dart @@ -4,9 +4,12 @@ import 'package:wosull/application/model/converters/DataTimeFormat.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/Utils.dart'; +import 'package:wosull/widgets/ActionPopUpContainer.dart'; +import 'package:wosull/widgets/CustomPopuoMenuButton.dart'; import 'package:wosull/widgets/CustomSwitch.dart'; import 'package:wosull/widgets/EmptyDataWidget.dart'; import 'package:wosull/widgets/HeadingText.dart'; +import 'package:wosull/widgets/ListHeadingContainer.dart'; import 'package:wosull/widgets/ValueText.dart'; class DeliveryPartnerPriceListView extends StatelessWidget { @@ -34,48 +37,39 @@ class DeliveryPartnerPriceListView extends StatelessWidget { children: [ isPortrait ? Container() - : Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 50, - color: MyColors.containerBackColor, + : ListHeadingContainer( child: Row( children: [ Expanded( - child: Text( + child: HeadingText( lang(context).name, - style: MyColors.textStyleHeading(), )), Expanded( - child: Text( + child: HeadingText( lang(context).name_ar, - style: MyColors.textStyleHeading(), )), Expanded( child: Align( - alignment: Alignment.center, - child: Text( + alignment: Alignment.centerLeft, + child: HeadingText( lang(context).status, - style: MyColors.textStyleHeading(), ), )), Expanded( - child: Text( + child: HeadingText( lang(context).created_on, - style: MyColors.textStyleHeading(), )), Expanded( - child: Text( + child: HeadingText( lang(context).updated_on, - style: MyColors.textStyleHeading(), )), Expanded( child: Padding( padding: const EdgeInsets.only(right: 16), child: Align( alignment: Alignment.centerRight, - child: Text( + child: HeadingText( lang(context).action, - style: MyColors.textStyleHeading(), ), ), )), @@ -143,13 +137,6 @@ class DeliveryPartnerPriceListView extends StatelessWidget { CustomSwitch( value: price.getStatus(), onToggle: (value) { - // setState(() { - // if (value) { - // price.status = "Active"; - // } else { - // price.status = "Inactive"; - // } - // }); onUpdate(price, value); }, ) @@ -166,33 +153,7 @@ class DeliveryPartnerPriceListView extends StatelessWidget { ], ), )), - PopupMenuButton( - icon: const Icon(Icons.more_vert), - itemBuilder: (c) { - return [ - PopupMenuItem( - value: 'edit', - child: ValueText( - lang(context).edit, - ), - ), - PopupMenuItem( - value: 'view', - child: Text( - lang(context).view, - ), - ), - PopupMenuItem( - value: 'delete', - child: ValueText( - lang(context).delete, - ), - ) - ]; - }, - onSelected: (String value) => - actionPopUpItemSelected(value, price), - ) + getPopupMenuButton(context, position) ], ), ), @@ -202,10 +163,7 @@ class DeliveryPartnerPriceListView extends StatelessWidget { shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.0), ), - child: Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 56, - color: MyColors.containerBackColor, + child: ListHeadingContainer( child: Row( children: [ Expanded(child: ValueText(price.name)), @@ -234,41 +192,8 @@ class DeliveryPartnerPriceListView extends StatelessWidget { padding: const EdgeInsets.all(4), child: Align( alignment: Alignment.centerRight, - child: Container( - width: 42, - height: 42, - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular(4)), - color: MyColors.backFillColor), - child: PopupMenuButton( - padding: EdgeInsets.zero, - icon: const Icon(Icons.more_vert), - itemBuilder: (c) { - return [ - PopupMenuItem( - value: 'edit', - child: ValueText( - lang(context).edit, - ), - ), - PopupMenuItem( - value: 'view', - child: ValueText( - lang(context).view, - ), - ), - PopupMenuItem( - value: 'delete', - child: ValueText( - lang(context).delete, - ), - ) - ]; - }, - onSelected: (String value) => - actionPopUpItemSelected(value, price), - ), + child: ActionPopUpContainer( + child: getPopupMenuButton(context, position), ), ), )) @@ -294,4 +219,31 @@ class DeliveryPartnerPriceListView extends StatelessWidget { onView(deliveryPartner); } } + + getPopupMenuButton(BuildContext context, int position) { + return CustomPopupMenuButton( + onSelected: (String value) => + actionPopUpItemSelected(value, data[position]), + items: [ + PopupMenuItem( + value: 'edit', + child: ValueText( + lang(context).edit, + ), + ), + PopupMenuItem( + value: 'view', + child: ValueText( + lang(context).view, + ), + ), + PopupMenuItem( + value: 'delete', + child: ValueText( + lang(context).delete, + ), + ) + ], + ); + } } diff --git a/lib/application/views/inventorymodule/ingredientsViews/AddProductIngredientVC.dart b/lib/application/views/inventorymodule/ingredientsViews/AddProductIngredientVC.dart index 95ae3e4..0fc22d0 100644 --- a/lib/application/views/inventorymodule/ingredientsViews/AddProductIngredientVC.dart +++ b/lib/application/views/inventorymodule/ingredientsViews/AddProductIngredientVC.dart @@ -2,24 +2,29 @@ import 'package:dropdown_search/dropdown_search.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:provider/provider.dart'; +import 'package:wosull/application/model/Measurement/InventoryMeasurementModel.dart'; import 'package:wosull/application/model/brands/GetBrandsModel.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; import 'package:wosull/application/model/discount/StoreDiscountModel.dart'; -import 'package:wosull/application/model/inventory/AddIngredientModel.dart'; -import 'package:wosull/application/model/inventory/GetMeasurementCategory.dart'; +import 'package:wosull/application/model/ingredients/AddIngredient.dart'; import 'package:wosull/application/model/inventory/category/ItemCategory.dart'; import 'package:wosull/application/model/store/StoreInvoicesModel.dart'; import 'package:wosull/application/theme/MyColors.dart'; -import 'package:wosull/application/theme/MyFonts.dart'; import 'package:wosull/application/utils/AppLoader.dart'; import 'package:wosull/application/utils/CRUDOperatoinState.dart'; -import 'package:wosull/application/views/inventorymodule/productviews/viewModels/AddIngredientViewModel.dart'; +import 'package:wosull/application/views/inventorymodule/ingredientsViews/viewModels/AddIngredientViewModel.dart'; +import 'package:wosull/application/views/inventorymodule/productviews/widgets/GenerateBarCodeButton.dart'; import 'package:wosull/base/BaseStatefulState.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/ThemeDropDown.dart'; import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/widgets/CustomAppBar.dart'; import 'package:wosull/widgets/CustomOptionalTitle.dart'; import 'package:wosull/widgets/CustomSimpleButton.dart'; import 'package:wosull/widgets/CustomSwitch.dart'; +import 'package:wosull/widgets/CustomTextButtonIcon.dart'; import 'package:wosull/widgets/CustomTextFieldForm.dart'; +import 'package:wosull/widgets/DropdownItemBuilder.dart'; import 'package:wosull/widgets/MandatoryTitleText.dart'; class AddProductIngredientVC extends StatefulWidget { @@ -45,6 +50,10 @@ class _AddProductIngredientVCState @override void initState() { + if (widget.isView || widget.isEdit) { + context.read().setData(widget.ingredient); + } + super.initState(); } @@ -57,41 +66,24 @@ class _AddProductIngredientVCState @override Widget build(BuildContext context) { viewModel = context.watch(); - // viewModel.setIsEditView(widget.isEdit, widget.isView); - if (widget.isView || widget.isEdit) { - viewModel.setData(widget.ingredient); - } return Scaffold( + backgroundColor: MyColors.fillColor, resizeToAvoidBottomInset: true, - appBar: AppBar( - leading: BackButton( - color: Colors.black, - onPressed: () { - Navigator.pop(context); - }, // <-- SEE HERE - ), - centerTitle: true, - title: const Text( - 'Add Ingredient', - style: TextStyle( - color: MyColors.textColorBlack, - fontFamily: MyFonts.Bold, - fontSize: 22), - ), - backgroundColor: MyColors.white, - elevation: 5, + appBar: CustomAppBar( + heading: 'Add Ingredient', ), body: OrientationBuilder(builder: (c, orientation) { isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; return SingleChildScrollView( child: Container( - color: MyColors.white, padding: const EdgeInsets.all(8), child: Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ + AppSpaces.verticalLarge, Card( + elevation: 5, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.0), ), @@ -103,11 +95,9 @@ class _AddProductIngredientVCState children: [ const Text( 'Ingredient Information', - style: ThemeText.textStylePageHeading, - ), - const SizedBox( - height: 12, + style: ThemeText.textStyleHeadingCart, ), + AppSpaces.verticalLarge, Row( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, @@ -121,48 +111,41 @@ class _AddProductIngredientVCState MandatoryTitleText( hint: AppLocalizations.of(context)!.name, ), - const SizedBox( - height: 4, - ), + AppSpaces.verticalSmall, CustomTextFieldForm( - key: Key(viewModel.nameController), + key: Key(viewModel.addIngredient.name), readOnly: widget.isView, hintText: 'Enter Ingredient name', - initialValue: viewModel.nameController, + initialValue: viewModel.addIngredient.name, onChanged: (value) { - viewModel.nameController = value; + viewModel.addIngredient.name = value; }, ), ], ), ), - const SizedBox( - width: 12, - ), + AppSpaces.horizontalMedium, Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const CustomOptionalTitle(hint: 'Product Code'), - const SizedBox( - height: 4, - ), + AppSpaces.verticalSmall, CustomTextFieldForm( - key: Key(viewModel.productCode), + key: Key(viewModel.addIngredient.productCode), readOnly: widget.isView, hintText: 'Enter Product Code', - initialValue: viewModel.productCode, + initialValue: + viewModel.addIngredient.productCode, onChanged: (String value) { - viewModel.productCode = value; + viewModel.addIngredient.productCode = value; }, ), ], )), ], ), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, Row( children: [ Flexible( @@ -173,15 +156,11 @@ class _AddProductIngredientVCState const CustomOptionalTitle( hint: 'Category', ), - const SizedBox( - height: 4, - ), + AppSpaces.verticalSmall, getCategoryWidget(context) ], )), - const SizedBox( - width: 12, - ), + AppSpaces.horizontalMedium, Flexible( child: Column( mainAxisAlignment: MainAxisAlignment.start, @@ -190,18 +169,14 @@ class _AddProductIngredientVCState CustomOptionalTitle( hint: AppLocalizations.of(context)!.status, ), - const SizedBox( - height: 4, - ), + AppSpaces.verticalSmall, SizedBox( height: 44, child: Row( children: [ const CustomOptionalTitle( hint: 'Item In Stock'), - const SizedBox( - width: 6, - ), + AppSpaces.horizontalMedium, CustomSwitch( value: viewModel .addIngredient.isItemInStock, @@ -222,26 +197,23 @@ class _AddProductIngredientVCState ), ), ), - const SizedBox( - height: 12, - ), + AppSpaces.verticalLarge, Card( + elevation: 5, shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(4.0), + borderRadius: BorderRadius.circular(8.0), ), child: Container( - padding: const EdgeInsets.all(8), + padding: const EdgeInsets.all(15), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ const Text( 'Price, Quantity, Tax & Additional Information', - style: ThemeText.textStylePopUpHeading, - ), - const SizedBox( - height: 12, + style: ThemeText.textStyleHeadingCart, ), + AppSpaces.verticalLarge, Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -252,24 +224,26 @@ class _AddProductIngredientVCState const CustomOptionalTitle( hint: 'Sale Price (Excl. Tax)', ), - const SizedBox( - height: 4, - ), + AppSpaces.verticalSmall, CustomTextFieldForm( - key: Key(viewModel.salePriceExclTax), + key: Key(viewModel + .addIngredient.salePriceExclusiveTax + ?.toStringAsFixed(2) ?? + ''), readOnly: widget.isView, hintText: 'Enter Sale Price (Excl. Tax)', keyboardType: TextInputType.number, - initialValue: viewModel.salePriceExclTax, + initialValue: viewModel + .addIngredient.salePriceExclusiveTax + ?.toStringAsFixed(2) ?? + '', onChanged: (value) { - viewModel.salePriceExclTax = value; + viewModel.updateSalePrice(value); }, ), ], )), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -277,26 +251,27 @@ class _AddProductIngredientVCState const CustomOptionalTitle( hint: 'Purchase Price (Excl. Tax)', ), - const SizedBox( - height: 4, - ), + AppSpaces.verticalSmall, CustomTextFieldForm( - key: Key(viewModel.purchasePriceExclTax), + key: Key(viewModel.addIngredient.purchaseCost + ?.toStringAsFixed(2) ?? + ''), readOnly: widget.isView, hintText: 'Enter Purchase Price (Excl. Tax)', keyboardType: TextInputType.number, onChanged: (value) { - viewModel.purchasePriceExclTax = value; + viewModel.updatePurchasePrice(value); }, - initialValue: viewModel.purchasePriceExclTax, + initialValue: viewModel + .addIngredient.purchaseCost + ?.toStringAsFixed(2) ?? + '', ), ], )), ], ), - const SizedBox( - height: 12, - ), + AppSpaces.verticalLarge, Row( children: [ Expanded( @@ -306,24 +281,24 @@ class _AddProductIngredientVCState const CustomOptionalTitle( hint: 'Sale Price (Incl. Tax)', ), - const SizedBox( - height: 4, - ), + AppSpaces.verticalSmall, CustomTextFieldForm( - key: Key(viewModel.salePriceIncludeTax), + key: Key(viewModel.addIngredient.price + ?.toStringAsFixed(2) ?? + ''), readOnly: widget.isView, hintText: 'Enter Sale Price (Incl. Tax)', keyboardType: TextInputType.number, onChanged: (value) { - viewModel.salePriceIncludeTax = value; + viewModel.updatePriceInclTax(value); }, - initialValue: viewModel.salePriceIncludeTax, + initialValue: viewModel.addIngredient.price + ?.toStringAsFixed(2) ?? + '', ) ], )), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -331,26 +306,28 @@ class _AddProductIngredientVCState const CustomOptionalTitle( hint: 'Stock Alert Quantity', ), - const SizedBox( - height: 4, - ), + AppSpaces.verticalSmall, CustomTextFieldForm( - key: Key(viewModel.stockAlertQuantity), + key: Key(viewModel + .addIngredient.stockAlertQuantity + ?.toString() ?? + ''), readOnly: widget.isView, hintText: 'Enter Stock Alert Quantity', keyboardType: TextInputType.number, onChanged: (value) { - viewModel.stockAlertQuantity = value; + viewModel.updateStockAlertQuantity(value); }, - initialValue: viewModel.stockAlertQuantity, + initialValue: viewModel + .addIngredient.stockAlertQuantity + ?.toString() ?? + '', ), ], )), ], ), - const SizedBox( - height: 12, - ), + AppSpaces.verticalLarge, Row( children: [ Expanded( @@ -358,17 +335,13 @@ class _AddProductIngredientVCState crossAxisAlignment: CrossAxisAlignment.start, children: [ const CustomOptionalTitle( - hint: 'Measurement Category', - ), - const SizedBox( - height: 4, + hint: 'Measurement', ), + AppSpaces.verticalSmall, getMeasurementWidget(context), ], )), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, Expanded( child: Column( children: [ @@ -379,26 +352,27 @@ class _AddProductIngredientVCState ), ], ), - const SizedBox( - height: 4, - ), + AppSpaces.verticalSmall, CustomTextFieldForm( - key: Key(viewModel.quantityController), + key: Key(viewModel.addIngredient.totalQuantity + ?.toString() ?? + ''), readOnly: widget.isView, hintText: 'Enter Quantity', keyboardType: TextInputType.number, onChanged: (value) { - viewModel.quantityController = value; + viewModel.updateTotalQuantity(value); }, - initialValue: viewModel.quantityController, + initialValue: viewModel + .addIngredient.totalQuantity + ?.toString() ?? + '', ), ], )) ], ), - const SizedBox( - height: 12, - ), + AppSpaces.verticalLarge, Row( children: [ Expanded( @@ -408,9 +382,7 @@ class _AddProductIngredientVCState const CustomOptionalTitle( hint: 'Discount', ), - const SizedBox( - height: 4, - ), + AppSpaces.verticalSmall, getDiscountWidget(context), ], )), @@ -420,82 +392,31 @@ class _AddProductIngredientVCState ), ), ), - const SizedBox( - height: 12, - ), + AppSpaces.verticalLarge, Card( + elevation: 5, shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(4.0), + borderRadius: BorderRadius.circular(8.0), ), child: Padding( - padding: const EdgeInsets.all(8), + padding: const EdgeInsets.all(15), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ const Text( 'Description', - style: TextStyle( - color: MyColors.textColorBlack, - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.bold, - fontSize: 18), - ), - const SizedBox( - height: 12, + style: ThemeText.textStyleHeadingCart, ), + AppSpaces.verticalLarge, isPortrait ? Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ - const CustomOptionalTitle( - hint: 'Description', - ), - const SizedBox( - height: 4, - ), - SizedBox( - height: 100, - child: CustomTextFieldForm( - key: Key( - viewModel.descriptionController), - readOnly: widget.isView, - onChanged: (value) { - viewModel.descriptionController = - value; - }, - hintText: 'Enter Description', - initialValue: - viewModel.descriptionController, - maxLines: 5, - keyboardType: TextInputType.multiline, - ), - ), - const SizedBox( - height: 12, - ), - const CustomOptionalTitle( - hint: 'Description (Arabic)', - ), - const SizedBox( - height: 4, - ), - SizedBox( - height: 100, - child: CustomTextFieldForm( - key: Key(viewModel.descriptionArabic), - readOnly: widget.isView, - onChanged: (value) { - viewModel.descriptionArabic = value; - }, - hintText: 'Enter Description (Arabic)', - initialValue: - viewModel.descriptionArabic, - maxLines: 5, - keyboardType: TextInputType.multiline, - ), - ), + getDescription(), + AppSpaces.verticalLarge, + getDescriptionArabic() ], ) : Row( @@ -505,82 +426,21 @@ class _AddProductIngredientVCState Expanded( child: Container( padding: const EdgeInsets.all(8), - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.start, - children: [ - const CustomOptionalTitle( - hint: 'Description', - ), - const SizedBox( - height: 4, - ), - SizedBox( - height: 100, - child: CustomTextFieldForm( - key: Key(viewModel - .descriptionController), - readOnly: widget.isView, - onChanged: (value) { - viewModel - .descriptionController = - value; - }, - initialValue: viewModel - .descriptionController, - hintText: 'Enter Description', - maxLines: 5, - keyboardType: - TextInputType.multiline, - ), - ), - ], - ), + child: getDescription(), )), Expanded( child: Container( padding: const EdgeInsets.all(8), - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - const CustomOptionalTitle( - hint: 'Description (Arabic)', - ), - const SizedBox( - height: 4, - ), - SizedBox( - height: 100, - child: CustomTextFieldForm( - key: Key( - viewModel.descriptionArabic), - readOnly: widget.isView, - onChanged: (value) { - viewModel.descriptionArabic = - value; - }, - hintText: - 'Enter Description (Arabic)', - maxLines: 5, - keyboardType: - TextInputType.multiline, - ), - ), - ], - ), + child: getDescriptionArabic(), )), ], ) ], ), )), - const SizedBox( - height: 12, - ), + AppSpaces.verticalLarge, Card( + elevation: 5, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.0), ), @@ -592,11 +452,9 @@ class _AddProductIngredientVCState children: [ const Text( 'Additional Information', - style: ThemeText.textStylePopUpHeading, - ), - const SizedBox( - height: 12, + style: ThemeText.textStyleHeadingCart, ), + AppSpaces.verticalLarge, Row( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, @@ -609,77 +467,17 @@ class _AddProductIngredientVCState const CustomOptionalTitle( hint: 'Supplier', ), - const SizedBox( - height: 4, - ), + AppSpaces.verticalSmall, getSupplierWidget(context), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, const CustomOptionalTitle( hint: 'Manufacturer Date', ), - const SizedBox( - height: 4, - ), - Container( - height: 48, - padding: const EdgeInsets.only(right: 8), - decoration: BoxDecoration( - border: Border.all( - color: Colors.transparent, - width: 1, - ), - color: MyColors.backFillColor, - borderRadius: BorderRadius.circular(8.0), - ), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - crossAxisAlignment: - CrossAxisAlignment.stretch, - children: [ - Expanded( - child: TextButton( - onPressed: () { - viewModel.presentDatePicker( - context, true); - }, - child: Align( - alignment: Alignment.centerLeft, - child: Text( - viewModel.addIngredient - .manufacturerDate.isEmpty - ? 'dd/mm/yyyy' - : viewModel.addIngredient - .manufacturerDate, - textAlign: TextAlign.left, - style: TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normalButton, - color: viewModel - .addIngredient - .manufacturerDate - .isEmpty - ? Colors.black54 - : MyColors.black), - ), - ), - )), - const Icon( - // <-- Icon - Icons.calendar_month_outlined, - size: 24.0, - color: MyColors.black, - ) - ], - ), - ), + AppSpaces.verticalSmall, + getManufactureDateButton(), ], )), - const SizedBox( - width: 12, - ), + AppSpaces.horizontalMedium, Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -687,107 +485,47 @@ class _AddProductIngredientVCState const CustomOptionalTitle( hint: 'Brand', ), - const SizedBox( - height: 4, - ), + AppSpaces.verticalSmall, getBrandsWidget(context), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, const CustomOptionalTitle( hint: 'Expiry Date', ), - const SizedBox( - height: 4, - ), - Container( - height: 48, - padding: const EdgeInsets.only(right: 8), - decoration: BoxDecoration( - border: Border.all( - color: Colors.transparent, - width: 1, - ), - color: MyColors.backFillColor, - borderRadius: BorderRadius.circular(8.0), - ), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - crossAxisAlignment: - CrossAxisAlignment.stretch, - children: [ - Expanded( - child: TextButton( - onPressed: () { - viewModel.presentDatePicker( - context, false); - }, - child: Align( - alignment: Alignment.centerLeft, - child: Text( - viewModel.addIngredient.expiryDate - .isEmpty - ? 'dd/mm/yyyy' - : viewModel - .addIngredient.expiryDate, - textAlign: TextAlign.left, - style: TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normalButton, - color: viewModel.addIngredient - .expiryDate.isEmpty - ? Colors.black54 - : MyColors.black), - ), - ), - )), - const Icon( - // <-- Icon - Icons.calendar_month_outlined, - size: 24.0, - color: MyColors.black, - ) - ], - ), - ), + AppSpaces.verticalSmall, + getExpireDateButton() ], )), ], ), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, const CustomOptionalTitle( hint: 'Barcode', ), - const SizedBox( - height: 4, - ), + AppSpaces.verticalSmall, Row( children: [ Expanded( child: CustomTextFieldForm( - key: Key(viewModel.barCodeController), + key: Key( + viewModel.addIngredient.uniqueIdForStoreData), readOnly: widget.isView, onChanged: (value) { - viewModel.barCodeController = value; + viewModel.addIngredient.uniqueIdForStoreData = + value; }, hintText: 'Enter Barcode', - initialValue: viewModel.barCodeController, + initialValue: + viewModel.addIngredient.uniqueIdForStoreData, )), + AppSpaces.horizontalSmall, SizedBox( - width: 100, - child: CustomSimpleButton( - height: 48, - backGroundColor: MyColors.backColorBlue50, - textColor: MyColors.blueThemeColor, + width: 80, + child: GenerateBarCodeButton( onPressed: () { if (!widget.isView) { viewModel.generateCode(); } }, - heading: 'Generate', ), ), ], @@ -796,9 +534,7 @@ class _AddProductIngredientVCState ), ), ), - const SizedBox( - height: 12, - ), + AppSpaces.verticalLarge, Visibility( visible: !widget.isView, child: SizedBox( @@ -827,29 +563,24 @@ class _AddProductIngredientVCState builder: (c, s) { if (s.hasData) { var itemsList = s.data!; - return Material( - color: MyColors.backFillColor, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: 42, - width: double.infinity, - child: DropdownSearch( - selectedItem: viewModel.selectedBrand, - enabled: !widget.isView, - popupProps: const PopupProps.menu(), - clearButtonProps: ThemeDropDown.clearButton, - items: itemsList, - itemAsString: (Brand u) => u.name!, - onChanged: (Brand? data) { - viewModel.setIngredient(data); - }, - dropdownDecoratorProps: - MyColors.dropDownStyle(hint: 'Choose'), - ), - ), - ), + return DropdownSearch( + selectedItem: viewModel.selectedBrand, + enabled: !widget.isView, + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name ?? ''); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 200)), + items: itemsList, + itemAsString: (Brand u) => u.name!, + onChanged: (Brand? data) { + viewModel.setIngredient(data); + }, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), ); } else { return AppLoader(); @@ -859,33 +590,28 @@ class _AddProductIngredientVCState Widget getMeasurementWidget(BuildContext context) { return FutureBuilder( - future: viewModel.getMeasurementData(), + future: viewModel.getMeasurement(), builder: (c, s) { if (s.hasData) { var itemsList = s.data!; - return Material( - color: MyColors.backFillColor, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: 42, - width: double.infinity, - child: DropdownSearch( - selectedItem: viewModel.selectedMeasurement, - enabled: !widget.isView, - popupProps: const PopupProps.menu(), - clearButtonProps: ThemeDropDown.clearButton, - items: itemsList, - itemAsString: (MeasurementCategory u) => u.name!, - onChanged: (MeasurementCategory? data) { - viewModel.setMeasurement(data); - }, - dropdownDecoratorProps: - MyColors.dropDownStyle(hint: 'Choose'), - ), - ), - ), + return DropdownSearch( + selectedItem: viewModel.selectedMeasurement, + enabled: !widget.isView, + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name ?? ''); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: itemsList, + itemAsString: (Measurement u) => u.name!, + onChanged: (Measurement? data) { + viewModel.setMeasurement(data); + }, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), ); } else { return AppLoader(); @@ -899,29 +625,23 @@ class _AddProductIngredientVCState builder: (c, s) { if (s.hasData) { var itemsList = s.data!; - return Material( - color: MyColors.backFillColor, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: 42, - width: double.infinity, - child: DropdownSearch( - selectedItem: viewModel.selectedDiscount ?? - StoreDiscount(name: 'Choose'), - enabled: !widget.isView, - popupProps: const PopupProps.menu( - constraints: BoxConstraints(maxHeight: 200)), - clearButtonProps: ThemeDropDown.clearButton, - items: itemsList, - itemAsString: (StoreDiscount u) => u.name!, - onChanged: (StoreDiscount? data) {}, - dropdownDecoratorProps: - MyColors.dropDownStyle(hint: 'Choose'), - ), - ), - ), + return DropdownSearch( + selectedItem: + viewModel.selectedDiscount ?? StoreDiscount(name: 'Choose'), + enabled: !widget.isView, + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name ?? ''); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: itemsList, + itemAsString: (StoreDiscount u) => u.name!, + onChanged: (StoreDiscount? data) {}, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), ); } else { return AppLoader(); @@ -935,36 +655,24 @@ class _AddProductIngredientVCState builder: (c, s) { if (s.hasData) { var itemsList = s.data!; - return Material( - color: MyColors.backFillColor, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: 42, - width: double.infinity, - child: DropdownSearch( - selectedItem: viewModel.selectedSupplier, - enabled: !widget.isView, - popupProps: const PopupProps.menu(), - clearButtonProps: ThemeDropDown.clearButton, - items: itemsList, - itemAsString: (Supplier u) => u.name!, - onChanged: (Supplier? data) { - viewModel.setSupplier(data); + return DropdownSearch( + selectedItem: viewModel.selectedSupplier, + enabled: !widget.isView, + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name ?? ''); }, - dropdownDecoratorProps: const DropDownDecoratorProps( - baseStyle: TextStyle( - fontFamily: MyFonts.Bold, - fontSize: 12, - color: MyColors.textColorBlack), - dropdownSearchDecoration: InputDecoration( - border: InputBorder.none, hintText: 'Choose'), - ), - ), - ), - ), - ); + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: itemsList, + itemAsString: (Supplier u) => u.name!, + onChanged: (Supplier? data) { + viewModel.setSupplier(data); + }, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose')); } else { return AppLoader(); } @@ -977,29 +685,24 @@ class _AddProductIngredientVCState builder: (c, s) { if (s.hasData) { var itemsList = s.data!; - return Material( - color: MyColors.backFillColor, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: 42, - width: double.infinity, - child: DropdownSearch( - enabled: !widget.isView, - selectedItem: viewModel.selectedCategory, - popupProps: const PopupProps.menu(), - clearButtonProps: ThemeDropDown.clearButton, - items: itemsList, - itemAsString: (ItemCategory u) => u.name, - onChanged: (ItemCategory? data) { - viewModel.setSelectedCategory(data); - }, - dropdownDecoratorProps: - MyColors.dropDownStyle(hint: 'Choose'), - ), - ), - ), + return DropdownSearch( + enabled: !widget.isView, + selectedItem: viewModel.selectedCategory, + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: itemsList, + itemAsString: (ItemCategory u) => u.name, + onChanged: (ItemCategory? data) { + viewModel.setSelectedCategory(data); + }, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), ); } else { return AppLoader(); @@ -1018,4 +721,80 @@ class _AddProductIngredientVCState Navigator.pop(context, true); } } + + getDescription() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle( + hint: 'Description', + ), + AppSpaces.verticalSmall, + CustomTextFieldForm( + height: 100, + key: Key(viewModel.addIngredient.description), + readOnly: widget.isView, + onChanged: (value) { + viewModel.addIngredient.description = value; + }, + hintText: 'Enter Description', + initialValue: viewModel.addIngredient.description, + maxLines: 5, + keyboardType: TextInputType.multiline, + ), + ], + ); + } + + getDescriptionArabic() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle( + hint: 'Description (Arabic)', + ), + const SizedBox( + height: 4, + ), + CustomTextFieldForm( + height: 100, + key: Key(viewModel.addIngredient.itemDescriptionArabic), + readOnly: widget.isView, + onChanged: (value) { + viewModel.addIngredient.itemDescriptionArabic = value; + }, + hintText: 'Enter Description (Arabic)', + initialValue: viewModel.addIngredient.itemDescriptionArabic, + maxLines: 5, + keyboardType: TextInputType.multiline, + ), + ], + ); + } + + getManufactureDateButton() { + return CustomTextButtonIcon( + icon: Icons.calendar_month, + heading: viewModel.addIngredient.manufacturerDate.isEmpty + ? 'dd/mm/yyyy' + : DataTimeFormat.getFormatDateString( + viewModel.addIngredient.manufacturerDate), + onPressed: () { + viewModel.presentDatePicker(context, true); + }, + ); + } + + getExpireDateButton() { + return CustomTextButtonIcon( + icon: Icons.calendar_month, + heading: viewModel.addIngredient.expiryDate.isEmpty + ? 'dd/mm/yyyy' + : DataTimeFormat.getFormatDateString( + viewModel.addIngredient.expiryDate), + onPressed: () { + viewModel.presentDatePicker(context, false); + }, + ); + } } diff --git a/lib/application/views/inventorymodule/ingredientsViews/IngredientsVC.dart b/lib/application/views/inventorymodule/ingredientsViews/IngredientsVC.dart index 11c21b9..1a1ffb7 100644 --- a/lib/application/views/inventorymodule/ingredientsViews/IngredientsVC.dart +++ b/lib/application/views/inventorymodule/ingredientsViews/IngredientsVC.dart @@ -1,22 +1,22 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:provider/provider.dart'; +import 'package:sizer/sizer.dart'; import 'package:wosull/application/enum/DataState.dart'; -import 'package:wosull/application/model/converters/DataTimeFormat.dart'; -import 'package:wosull/application/model/inventory/AddIngredientModel.dart'; +import 'package:wosull/application/model/ingredients/AddIngredient.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/utils/AppError.dart'; import 'package:wosull/application/utils/AppLoader.dart'; import 'package:wosull/application/views/inventorymodule/ingredientsViews/AddProductIngredientVC.dart'; import 'package:wosull/application/views/inventorymodule/ingredientsViews/viewModels/IngredientViewModel.dart'; +import 'package:wosull/application/views/inventorymodule/ingredientsViews/widgets/IngredientListView.dart'; import 'package:wosull/application/views/popups/DeleteRecordPopUp.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/ThemeText.dart'; import 'package:wosull/helpers/Utils.dart'; import 'package:wosull/widgets/CustomSimpleButton.dart'; -import 'package:wosull/widgets/CustomSwitch.dart'; -import 'package:wosull/widgets/EmptyDataWidget.dart'; -import 'package:wosull/widgets/HeadingText.dart'; -import 'package:wosull/widgets/ValueText.dart'; +import 'package:wosull/widgets/PageLimitDropDown.dart'; +import 'package:wosull/widgets/SearchBox.dart'; class IngredientsVC extends StatefulWidget { const IngredientsVC({super.key}); @@ -28,252 +28,157 @@ class IngredientsVC extends StatefulWidget { class _IngredientsVCState extends State { var viewModel = IngredientViewModel(); late ScrollController _controller; + bool isPortrait = false; @override Widget build(BuildContext context) { _controller = ScrollController()..addListener(_scrollNotification); - return WillPopScope( - child: Scaffold( - backgroundColor: MyColors.fillColor, - resizeToAvoidBottomInset: true, - body: OrientationBuilder(builder: (c, orientation) { - return SingleChildScrollView( - controller: _controller, - child: Container( - padding: const EdgeInsets.all(12), - child: Column( + return Scaffold( + backgroundColor: MyColors.fillColor, + resizeToAvoidBottomInset: true, + body: OrientationBuilder(builder: (c, orientation) { + isPortrait = MediaQuery.of(c).orientation == Orientation.portrait; + + return SingleChildScrollView( + controller: _controller, + child: Container( + padding: const EdgeInsets.all(10), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Row( mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.center, children: [ - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Text( - 'Ingredient', - style: ThemeText.textStylePageHeading, - ), - const SizedBox( - width: 4, - ), - SizedBox( - width: 120, - child: CustomSimpleButton( - textColor: MyColors.blueThemeColor, - backGroundColor: MyColors.backColorBlue50, - heading: - AppLocalizations.of(context)!.add_ingredient, - onPressed: () { - addUpdateIngredient( - false, false, AddIngredient()); - }, + Text( + 'Ingredient', + style: ThemeText.textStylePageHeading, + ), + AppSpaces.horizontalSmall, + isPortrait + ? Flexible(child: newIngredientButton()) + : SizedBox( + width: 120, + child: newIngredientButton(), ), - ), + AppSpaces.horizontalMedium, + isPortrait + ? Container() + : SizedBox( + width: SizerUtil.deviceType == DeviceType.mobile + ? 200 + : 200, + height: 48, + child: SearchBox( + onEditingDone: (text) { + filterSearchResults(text); + }, + onChanged: (text) { + filterSearchResults(text); + }, + hint: AppLocalizations.of(context)!.search, + ), + ), + Flexible( + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + PageLimitDropdown(onChange: (value) { + viewModel.fetch( + isRefresh: true, limit: int.parse(value!)); + }) ], - ), - const SizedBox( - height: 8, - ), - ChangeNotifierProvider( - create: (context) => viewModel, - child: Consumer( - builder: (BuildContext context, - IngredientViewModel controller, Widget? _) { - switch (controller.dataState) { - case DataState.uninitialized: - Future(() { - controller.fetch(); - }); - return showList(controller.filteredList); - case DataState.initialFetching: - return AppLoader(); - case DataState.moreFetching: - case DataState.refreshing: - return showList(controller.filteredList); - case DataState.error: - return AppError(); - case DataState.searching: - case DataState.fetched: - case DataState.noMoreData: - return showList(controller.filteredList); - } - }, - ), - ), + )), ], ), - ), - ); - })), - onWillPop: () { - viewModel.dispose(); - return Future.value(false); - }); - } - - Widget showList(List data) { - return Column( - children: [ - data.isEmpty - ? const EmptyDataWidget() - : Column( - children: [ - Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 50, - color: MyColors.containerBackColor, - child: Row( - children: [ - Expanded( - child: HeadingText( - AppLocalizations.of(context)!.name)), - Expanded( - child: HeadingText( - AppLocalizations.of(context)!.price)), - Expanded( - child: Align( - alignment: Alignment.center, - child: HeadingText( - AppLocalizations.of(context)!.status, + isPortrait + ? SizedBox( + height: 48, + child: SearchBox( + onEditingDone: (text) { + filterSearchResults(text); + }, + onChanged: (text) { + filterSearchResults(text); + }, + hint: AppLocalizations.of(context)!.search, ), - )), - Expanded( - child: HeadingText( - AppLocalizations.of(context)!.created_on, - )), - Expanded( - child: HeadingText( - AppLocalizations.of(context)!.updated_on, - )), - Expanded( - child: Padding( - padding: const EdgeInsets.only(right: 16), - child: Align( - alignment: Alignment.centerRight, - child: HeadingText( - AppLocalizations.of(context)!.action, - ), - ), - )), - ], + ) + : Container(), + AppSpaces.verticalMedium, + ChangeNotifierProvider( + create: (context) => viewModel, + child: Consumer( + builder: (BuildContext context, + IngredientViewModel controller, Widget? _) { + switch (controller.dataState) { + case DataState.uninitialized: + Future(() { + controller.fetch(); + }); + return showList(controller.filteredList); + case DataState.initialFetching: + return AppLoader(); + case DataState.moreFetching: + case DataState.refreshing: + return showList(controller.filteredList); + case DataState.error: + return AppError( + error: 'Error', + ); + case DataState.searching: + case DataState.fetched: + case DataState.noMoreData: + return showList(controller.filteredList); + } + }, ), ), - ListView.builder( - physics: const NeverScrollableScrollPhysics(), - padding: EdgeInsets.zero, - scrollDirection: Axis.vertical, - shrinkWrap: true, - itemBuilder: (c, position) { - return Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - child: Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 56, - color: MyColors.containerBackColor, - child: Row( - children: [ - Expanded( - child: ValueText( - data[position].name, - )), - Expanded( - child: ValueText( - data[position].price.toString(), - )), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: CustomSwitch( - value: data[position].isVisibleInStore, - onToggle: (value) { - update(data[position].id, value); - }), - )), - Expanded( - child: ValueText( - DataTimeFormat.getFormatDate( - data[position].createdAt), - )), - Expanded( - child: ValueText( - DataTimeFormat.getFormatDate( - data[position].updatedAt), - )), - Expanded( - child: Padding( - padding: const EdgeInsets.all(4), - child: Align( - alignment: Alignment.centerRight, - child: Container( - width: 42, - height: 42, - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular(4)), - color: MyColors.backFillColor), - child: PopupMenuButton( - padding: EdgeInsets.zero, - icon: const Icon(Icons.more_vert), - itemBuilder: (c) { - return [ - PopupMenuItem( - value: 'edit', - child: ValueText( - AppLocalizations.of(context)! - .edit), - ), - PopupMenuItem( - value: 'view', - child: ValueText( - AppLocalizations.of(context)! - .view), - ), - PopupMenuItem( - value: 'delete', - child: ValueText( - AppLocalizations.of(context)! - .delete), - ) - ]; - }, - onSelected: (String value) => - actionPopUpItemSelected( - value, data[position]), - ), - ), - ), - )) - ], - ), - ), - ); - }, - itemCount: data.length, - ) ], ), + ), + ); + })); + } + + Widget showList(List data) { + return Column( + children: [ + IngredientListView( + data: data, + isPortrait: isPortrait, + onView: (ingredient) { + addUpdateIngredient(false, true, ingredient); + }, + onEdit: (ingredient) { + addUpdateIngredient(true, false, ingredient); + }, + onDelete: (ingredient) { + showDeletePopUp(ingredient); + }, + onUpdate: (ingredient, value) { + update(ingredient.id, value); + }), if (viewModel.dataState == DataState.moreFetching) AppLoader(), ], ); } - bool _scrollNotification() { - if (!viewModel.isLoading && _controller.position.extentAfter < 300) { - viewModel.fetch(); + Future filterSearchResults(String query) async { + if (query.isNotEmpty) { + viewModel.search(searchValue: query); + } else { + Future.delayed(const Duration(milliseconds: 700), () { + viewModel.search(searchValue: ""); + }); } - return true; } - Future actionPopUpItemSelected( - String value, AddIngredient ingredient) async { - if (value == 'edit') { - addUpdateIngredient(true, false, ingredient); - } else if (value == 'delete') { - showDeletePopUp(ingredient); - } else { - addUpdateIngredient(false, true, ingredient); + bool _scrollNotification() { + if (!viewModel.isLoading && _controller.position.extentAfter < 300) { + viewModel.fetch(limit: viewModel.limit); } + return true; } Future update(String id, bool value) async { @@ -302,8 +207,9 @@ class _IngredientsVCState extends State { checkState(); } - void addUpdateIngredient(bool isEdit, bool isView, AddIngredient ingredient) { - Navigator.push( + Future addUpdateIngredient( + bool isEdit, bool isView, AddIngredient ingredient) async { + final response = await Navigator.push( context, MaterialPageRoute( builder: (context) => AddProductIngredientVC( @@ -311,6 +217,12 @@ class _IngredientsVCState extends State { isEdit: isEdit, ingredient: ingredient, ))); + + if (!mounted) return; + + if (response != null) { + viewModel.fetch(isRefresh: true, limit: viewModel.limit); + } } void checkState({AddIngredient? ingredient}) { @@ -335,4 +247,15 @@ class _IngredientsVCState extends State { // return; // } } + + newIngredientButton() { + return CustomSimpleButton( + textColor: MyColors.blueThemeColor, + backGroundColor: MyColors.backColorBlue50, + heading: AppLocalizations.of(context)!.add_ingredient, + onPressed: () { + addUpdateIngredient(false, false, AddIngredient()); + }, + ); + } } diff --git a/lib/application/views/inventorymodule/ingredientsViews/repo/IngredientRepository.dart b/lib/application/views/inventorymodule/ingredientsViews/repo/IngredientRepository.dart new file mode 100644 index 0000000..aa2e9c4 --- /dev/null +++ b/lib/application/views/inventorymodule/ingredientsViews/repo/IngredientRepository.dart @@ -0,0 +1,71 @@ +import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/application/model/Products/ItemProductModel.dart'; +import 'package:wosull/application/model/SimpleResponsModel.dart'; +import 'package:wosull/application/model/ingredients/AddIngredient.dart'; +import 'package:wosull/application/model/ingredients/AddIngredientModel.dart'; +import 'package:wosull/application/model/ingredients/GetIngredientModel.dart'; +import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/utils/Constants.dart'; + +class IngredientRepository { + Future update(String id, bool value) async { + Map data = { + 'ingrediantId': id, + 'is_visible_in_store': value + }; + return await APIManager() + .getResponsePatch(Constants.updateIngredient, data); + } + + Future delete(String id) async { + Map data = {'ingrediantId': id}; + return await APIManager() + .getResponsePatch(Constants.deleteIngredient, data); + } + + Future> search(Map map) async { + var ingredients = []; + await APIManager() + .fetchData(Constants.searchIngredients, map) + .then((result) { + final value = GetIngredientModel.fromJson(result); + if (value.success) { + ingredients.clear(); + ingredients.addAll(ingredients); + } + }).onError((error, stackTrace) {}); + + return ingredients; + } + + Future> fetchIngredients(Map map) async { + var ingredients = []; + await APIManager() + .fetchData(Constants.getIngredientsList, map) + .then((result) { + final value = GetIngredientModel.fromJson(result); + if (value.success) { + ingredients.clear(); + ingredients.addAll(value.ingredient); + } + }).onError((error, stackTrace) {}); + return ingredients; + } + + Future getSubProducts(String categoryID) async { + Map data = { + 'store_id': sharedPrefs.storeId, + 'category_id': categoryID, + }; + final values = await APIManager() + .fetchData(Constants.ITEM_GET_PRODUCT_LIST_BY_CATEGORY, data); + return ItemProductModel.fromJson(values); + } + + Future addIngredientToServer( + Map map) async { + final response = + await APIManager().fetchData(Constants.ADD_INGREDIENTS, map); + return AddIngredientModel.fromJson(response); + } +} diff --git a/lib/application/views/inventorymodule/ingredientsViews/viewModels/AddIngredientViewModel.dart b/lib/application/views/inventorymodule/ingredientsViews/viewModels/AddIngredientViewModel.dart new file mode 100644 index 0000000..ac91b2d --- /dev/null +++ b/lib/application/views/inventorymodule/ingredientsViews/viewModels/AddIngredientViewModel.dart @@ -0,0 +1,296 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/model/Measurement/InventoryMeasurementModel.dart'; +import 'package:wosull/application/model/brands/GetBrandsModel.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/application/model/discount/StoreDiscountModel.dart'; +import 'package:wosull/application/model/ingredients/AddIngredient.dart'; +import 'package:wosull/application/model/inventory/category/ItemCategory.dart'; +import 'package:wosull/application/model/store/StoreInvoicesModel.dart'; +import 'package:wosull/application/repository/WosulRepository.dart'; +import 'package:wosull/application/utils/CRUDOperatoinState.dart'; +import 'package:wosull/application/views/inventorymodule/ingredientsViews/repo/IngredientRepository.dart'; +import 'package:wosull/helpers/DatePicker.dart'; +import 'package:wosull/helpers/Utils.dart'; + +class AddIngredientViewModel with ChangeNotifier { + var addIngredient = AddIngredient(); + + bool isLoading = false; + var isEditView = false; + + dynamic selectedCategory; + dynamic selectedDiscount; + dynamic selectedMeasurement; + dynamic selectedSupplier; + dynamic selectedBrand; + + var _crudOperationState = CRUDOperationState.uninitialized; + + CRUDOperationState get crudOperationState => _crudOperationState; + + final repository = IngredientRepository(); + + void setInStock(bool value) { + addIngredient.isItemInStock = value; + notifyListeners(); + } + + void disposeData() { + isEditView = false; + selectedCategory = null; + addIngredient = AddIngredient(); + selectedMeasurement = null; + selectedSupplier = null; + selectedDiscount = null; + selectedBrand = null; + } + + void setData(AddIngredient ingredient) { + if (!isEditView) { + isEditView = true; + addIngredient = ingredient; + } + } + + Future isValidate() async { + if (addIngredient.name.isEmpty) { + Utils.showMessage('Enter Ingredient Name'); + } else { + await addIngredientToServer(); + } + } + + Future getSubProducts(String categoryID) async { + String id = ""; + await repository.getSubProducts(categoryID).then((values) { + if (values.success) { + if (values.product.isNotEmpty) { + id = values.product.first.id; + } + } else { + Utils.showMessage('Product not found against selected category'); + } + }).onError((error, stackTrace) {}); + return id; + } + + setLoading(bool value) { + isLoading = value; + notifyListeners(); + } + + Future addIngredientToServer() async { + setLoading(true); + await repository + .addIngredientToServer(addIngredient.toJson()) + .then((response) { + if (response.success) { + _crudOperationState = CRUDOperationState.add; + setLoading(false); + Utils.showMessage(response.message); + } else { + _crudOperationState = CRUDOperationState.error; + setLoading(false); + Utils.showMessage(response.message); + } + }).onError((error, stackTrace) { + setLoading(false); + }); + } + + generateCode() { + String number = Utils.generateCode(); + addIngredient.uniqueIdForStoreData = number; + notifyListeners(); + } + + Future presentDatePicker(BuildContext context, bool isStart) async { + final pickedDate = await DatePicker.presentDatePicker(context, isStart); + + if (pickedDate == null) { + return; + } + if (isStart) { + addIngredient.manufacturerDate = + DataTimeFormat.formatDateFromPicketINVOICE(pickedDate); + } else { + addIngredient.expiryDate = + DataTimeFormat.formatDateFromPicketINVOICE(pickedDate); + } + notifyListeners(); + } + + Future> getBrandsData() async { + var items = []; + await WosulRepository().getBrandsData().then((value) { + if (value.isNotEmpty) { + items.addAll(value); + if (isEditView) { + if (addIngredient.brand.isNotEmpty) { + selectedBrand = items + .singleWhere((element) => element.name == addIngredient.brand); + } + } + } + selectedBrand ??= Brand(name: 'Choose'); + }).onError((error, stackTrace) {}); + return items; + } + + Future> getCategoriesData() async { + var items = []; + await WosulRepository().getStoreCategoriesData().then((categories) { + if (categories.isNotEmpty) { + items.addAll(categories); + if (isEditView) { + if (addIngredient.categoryId.isNotEmpty) { + selectedCategory = items.singleWhere( + (element) => element.id == addIngredient.categoryId); + addIngredient.categoryId = addIngredient.categoryId; + } else { + selectedCategory = ItemCategory(name: 'Choose'); + } + } else { + selectedCategory ??= items[0]; + addIngredient.categoryId = selectedCategory.id; + } + } + }).onError((error, stackTrace) {}); + return items; + } + + Future> getSuppliersData() async { + var items = []; + await WosulRepository().getSuppliersData().then((suppliers) { + if (suppliers.isNotEmpty) { + items.addAll(suppliers); + if (isEditView) { + if (addIngredient.supplier.isNotEmpty) { + selectedSupplier = items.singleWhere( + (element) => element.name == addIngredient.supplier); + } else { + selectedSupplier = Supplier(name: 'Choose'); + } + } + } + }).onError((error, stackTrace) {}); + + return items; + } + + Future> getDiscount() async { + var items = []; + await WosulRepository().getDiscount().then((discounts) { + if (discounts.isNotEmpty) { + items.addAll(discounts); + if (isEditView) { + if (addIngredient.discount.isNotEmpty) { + selectedDiscount = items.singleWhere( + (element) => element.name == addIngredient.discount); + } else { + selectedDiscount = StoreDiscount(name: 'Choose'); + } + } + } + }).onError((error, stackTrace) {}); + + return items; + } + + Future> getMeasurement() async { + var items = []; + await WosulRepository().getMeasurement().then((measurements) { + if (measurements.isNotEmpty) { + items.addAll(measurements); + if (isEditView) { + final name = items + .singleWhere( + (element) => element.name == addIngredient.measurement) + .name; + selectedMeasurement = Measurement(id: '', name: name ?? ''); + } + } + }).onError((error, stackTrace) {}); + + return items; + } + + void setIngredient(Brand? data) { + if (data != null) { + addIngredient.brand = data.name!; + } + notifyListeners(); + } + + void setMeasurement(Measurement? data) { + if (data != null) { + addIngredient.measurement = data.name!; + } + notifyListeners(); + } + + void setSupplier(Supplier? data) { + if (data != null) { + addIngredient.supplier = data.name!; + } + notifyListeners(); + } + + void setSelectedCategory(ItemCategory? data) { + if (data != null) { + selectedCategory = data; + addIngredient.categoryId = data.id; + } else { + addIngredient.categoryId = ''; + } + notifyListeners(); + } + + void setIsEditView(bool isEdit, bool isView) { + if (isEdit || isView) { + isEditView = true; + } else { + isEditView = false; + } + } + + void updateSalePrice(String value) { + if (value.isNotEmpty) { + addIngredient.salePriceExclusiveTax = double.parse(value); + } else { + addIngredient.salePriceExclusiveTax = 0; + } + } + + void updatePurchasePrice(String value) { + if (value.isNotEmpty) { + addIngredient.purchaseCost = double.parse(value); + } else { + addIngredient.purchaseCost = 0.0; + } + } + + void updatePriceInclTax(String value) { + if (value.isNotEmpty) { + addIngredient.price = double.parse(value); + } else { + addIngredient.price = 0.0; + } + } + + void updateStockAlertQuantity(String value) { + if (value.isNotEmpty) { + addIngredient.stockAlertQuantity = int.parse(value); + } else { + addIngredient.stockAlertQuantity = 0; + } + } + + void updateTotalQuantity(String value) { + if (value.isNotEmpty) { + addIngredient.totalQuantity = int.parse(value); + } else { + addIngredient.totalQuantity = 0; + } + } +} diff --git a/lib/application/views/inventorymodule/ingredientsViews/viewModels/IngredientViewModel.dart b/lib/application/views/inventorymodule/ingredientsViews/viewModels/IngredientViewModel.dart index 39a4460..fb7e98d 100644 --- a/lib/application/views/inventorymodule/ingredientsViews/viewModels/IngredientViewModel.dart +++ b/lib/application/views/inventorymodule/ingredientsViews/viewModels/IngredientViewModel.dart @@ -1,16 +1,21 @@ import 'package:flutter/material.dart'; import 'package:wosull/application/enum/DataState.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; -import 'package:wosull/application/model/inventory/AddIngredientModel.dart'; -import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/model/ingredients/AddIngredient.dart'; import 'package:wosull/application/utils/CRUDOperatoinState.dart'; -import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/inventorymodule/ingredientsViews/repo/IngredientRepository.dart'; class IngredientViewModel with ChangeNotifier { + final repository = IngredientRepository(); + List _filteredList = []; List get filteredList => _filteredList; + List _dataList = []; + + List get dataList => _dataList; + int limit = 10; bool _didLastLoad = false; bool _isLoading = false; @@ -26,7 +31,8 @@ class IngredientViewModel with ChangeNotifier { CRUDOperationState get crudOperationState => _crudOperationState; - fetch({bool isRefresh = false}) async { + fetch({bool isRefresh = false, int limit = 10}) async { + this.limit = limit; _isLoading = true; if (!isRefresh) { _dataState = (_dataState == DataState.uninitialized) @@ -41,22 +47,22 @@ class IngredientViewModel with ChangeNotifier { Map data = { 'store_id': sharedPrefs.storeId, 'page': _currentPageNumber, + 'limit': this.limit }; try { if (_didLastLoad) { _dataState = DataState.noMoreData; } else { - await APIManager() - .fetchData(Constants.getIngredientsList, data) - .then((result) { - final value = GetIngredientModel.fromJson(result); + await repository.fetchIngredients(data).then((ingredient) { if (_dataState == DataState.refreshing) { _filteredList.clear(); + _dataList.clear(); } - if (value.success) { - _filteredList.addAll(value.ingredient); - if (value.ingredient.length < 10) { + if (ingredient.isNotEmpty) { + _filteredList.addAll(ingredient); + _dataList.addAll(ingredient); + if (ingredient.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; @@ -79,11 +85,39 @@ class IngredientViewModel with ChangeNotifier { } } + search({String searchValue = ""}) async { + if (searchValue.isEmpty) { + _dataState = DataState.fetched; + _filteredList.clear(); + _filteredList.addAll(_dataList); + notifyListeners(); + } else { + Map data = { + 'store_id': sharedPrefs.storeId, + 'searchTerm': searchValue, + }; + _dataState = DataState.searching; + notifyListeners(); + try { + await repository.search(data).then((ingredients) { + _filteredList.clear(); + if (ingredients.isNotEmpty) { + _filteredList.addAll(ingredients); + } + _dataState = DataState.fetched; + }).onError((error, stackTrace) { + _dataState = DataState.error; + }); + notifyListeners(); + } catch (e) { + _dataState = DataState.error; + notifyListeners(); + } + } + } + Future delete(String id) async { - Map data = {'ingrediantId': id}; - await APIManager() - .getResponsePatch(Constants.deleteIngredient, data) - .then((result) { + await repository.delete(id).then((result) { if (result.success) { _filteredList.removeWhere((element) => element.id == id); _crudOperationState = CRUDOperationState.delete; @@ -98,13 +132,7 @@ class IngredientViewModel with ChangeNotifier { } Future update(String id, bool value) async { - Map data = { - 'ingrediantId': id, - 'is_visible_in_store': value - }; - await APIManager() - .getResponsePatch(Constants.updateIngredient, data) - .then((result) { + await repository.update(id, value).then((result) { if (result.success) { int index = _filteredList.indexWhere((element) => element.id == id); _filteredList[index].isVisibleInStore = value; diff --git a/lib/application/views/inventorymodule/ingredientsViews/widgets/IngredientListView.dart b/lib/application/views/inventorymodule/ingredientsViews/widgets/IngredientListView.dart new file mode 100644 index 0000000..f67914a --- /dev/null +++ b/lib/application/views/inventorymodule/ingredientsViews/widgets/IngredientListView.dart @@ -0,0 +1,248 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/application/model/ingredients/AddIngredient.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/Utils.dart'; +import 'package:wosull/widgets/ActionPopUpContainer.dart'; +import 'package:wosull/widgets/CustomPopuoMenuButton.dart'; +import 'package:wosull/widgets/CustomSwitch.dart'; +import 'package:wosull/widgets/EmptyDataWidget.dart'; +import 'package:wosull/widgets/HeadingText.dart'; +import 'package:wosull/widgets/ListHeadingContainer.dart'; +import 'package:wosull/widgets/ValueText.dart'; + +class IngredientListView extends StatelessWidget { + List data; + bool isPortrait = false; + final void Function(AddIngredient ingredient, bool status) onUpdate; + final void Function(AddIngredient ingredient) onDelete; + final void Function(AddIngredient ingredient) onView; + final void Function(AddIngredient ingredient) onEdit; + + IngredientListView( + {super.key, + required this.data, + required this.isPortrait, + required this.onView, + required this.onEdit, + required this.onDelete, + required this.onUpdate}); + + @override + Widget build(BuildContext context) { + return data.isEmpty + ? const EmptyDataWidget() + : Column( + children: [ + isPortrait + ? Container() + : ListHeadingContainer( + child: Row( + children: [ + Expanded(child: HeadingText(lang(context).name)), + Expanded(child: HeadingText(lang(context).price)), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + lang(context).status, + ), + )), + Expanded( + child: HeadingText( + lang(context).created_on, + )), + Expanded( + child: HeadingText( + lang(context).updated_on, + )), + Expanded( + child: Padding( + padding: const EdgeInsets.only(right: 16), + child: Align( + alignment: Alignment.centerRight, + child: HeadingText( + lang(context).action, + ), + ), + )), + ], + ), + ), + ListView.builder( + physics: const NeverScrollableScrollPhysics(), + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, + shrinkWrap: true, + itemBuilder: (c, position) { + if (isPortrait) { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + elevation: 2, + color: MyColors.white, + child: Container( + padding: const EdgeInsets.fromLTRB(8, 0, 0, 8), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + child: Container( + padding: const EdgeInsets.only(top: 16), + child: Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + HeadingText( + lang(context).name, + ), + AppSpaces.verticalMedium, + HeadingText(lang(context).price), + AppSpaces.verticalMedium, + HeadingText(lang(context).created_on), + AppSpaces.verticalMedium, + HeadingText(lang(context).updated_on), + AppSpaces.verticalMedium, + HeadingText(lang(context).status), + ], + )), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + ValueText(data[position].name), + AppSpaces.verticalMedium, + ValueText(data[position] + .price + ?.toStringAsFixed(2) ?? + '0'), + AppSpaces.verticalMedium, + ValueText(DataTimeFormat.getFormatDate( + data[position].createdAt)), + AppSpaces.verticalMedium, + ValueText(DataTimeFormat.getFormatDate( + data[position].updatedAt)), + AppSpaces.verticalSmall, + Row( + mainAxisAlignment: + MainAxisAlignment.end, + crossAxisAlignment: + CrossAxisAlignment.end, + children: [ + CustomSwitch( + value: + data[position].isVisibleInStore, + onToggle: (value) { + onUpdate(data[position], value); + }, + ) + ], + ), + ], + )), + ], + ), + )), + getPopUpMenuButton(context, position) + ], + ), + ), + ); + } else { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: ListHeadingContainer( + child: Row( + children: [ + Expanded( + child: ValueText( + data[position].name, + )), + Expanded( + child: ValueText( + data[position].price.toString(), + )), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: CustomSwitch( + value: data[position].isVisibleInStore, + onToggle: (value) { + onUpdate(data[position], value); + }), + )), + Expanded( + child: ValueText( + DataTimeFormat.getFormatDate( + data[position].createdAt), + )), + Expanded( + child: ValueText( + DataTimeFormat.getFormatDate( + data[position].updatedAt), + )), + Expanded( + child: Padding( + padding: const EdgeInsets.all(4), + child: Align( + alignment: Alignment.centerRight, + child: ActionPopUpContainer( + child: getPopUpMenuButton(context, position), + ), + ), + )) + ], + ), + ), + ); + } + }, + itemCount: data.length, + ) + ], + ); + } + + Future actionPopUpItemSelected( + String value, AddIngredient ingredient) async { + if (value == 'edit') { + onEdit(ingredient); + } else if (value == 'delete') { + onDelete(ingredient); + } else { + onView(ingredient); + } + } + + getPopUpMenuButton(BuildContext context, int position) { + return CustomPopupMenuButton( + onSelected: (String value) => + actionPopUpItemSelected(value, data[position]), + items: [ + PopupMenuItem( + value: 'edit', + child: ValueText(lang(context).edit), + ), + PopupMenuItem( + value: 'view', + child: ValueText(lang(context).view), + ), + PopupMenuItem( + value: 'delete', + child: ValueText(lang(context).delete), + ) + ], + ); + } +} diff --git a/lib/application/views/inventorymodule/measurementviews/AddMeasurementUnitVC.dart b/lib/application/views/inventorymodule/measurementviews/AddMeasurementUnitVC.dart index a1b739c..ee9e392 100644 --- a/lib/application/views/inventorymodule/measurementviews/AddMeasurementUnitVC.dart +++ b/lib/application/views/inventorymodule/measurementviews/AddMeasurementUnitVC.dart @@ -34,7 +34,7 @@ class _AddMeasurementUnitVCState extends State { elevation: 0, backgroundColor: const Color(0xffffffff), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(15.0), + borderRadius: BorderRadius.circular(8.0), ), child: OrientationBuilder(builder: (c, orientation) { return SingleChildScrollView( @@ -43,7 +43,6 @@ class _AddMeasurementUnitVCState extends State { MediaQuery.of(context).orientation == Orientation.landscape ? MediaQuery.of(context).size.width / 1.2 : double.infinity, - padding: const EdgeInsets.only(bottom: 8), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.end, diff --git a/lib/application/views/inventorymodule/measurementviews/InventoryAddMeasurementVC.dart b/lib/application/views/inventorymodule/measurementviews/InventoryAddMeasurementVC.dart index dd140a1..8b022f4 100644 --- a/lib/application/views/inventorymodule/measurementviews/InventoryAddMeasurementVC.dart +++ b/lib/application/views/inventorymodule/measurementviews/InventoryAddMeasurementVC.dart @@ -2,18 +2,19 @@ import 'package:dropdown_search/dropdown_search.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:provider/provider.dart'; -import 'package:wosull/application/model/inventory/InventoryMeasurementModel.dart'; -import 'package:wosull/application/model/inventory/MeasurementUnitModel.dart'; +import 'package:wosull/application/model/Measurement/InventoryMeasurementModel.dart'; +import 'package:wosull/application/model/Measurement/MeasurementUnitModel.dart'; import 'package:wosull/application/theme/MyColors.dart'; -import 'package:wosull/application/utils/AppLoader.dart'; import 'package:wosull/application/utils/CRUDOperatoinState.dart'; import 'package:wosull/application/views/inventorymodule/measurementviews/viewModels/AddMeasurementViewModel.dart'; import 'package:wosull/base/BaseStatefulState.dart'; import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeDropDown.dart'; import 'package:wosull/widgets/CustomSimpleButton.dart'; import 'package:wosull/widgets/CustomSwitch.dart'; import 'package:wosull/widgets/CustomTextFieldForm.dart'; import 'package:wosull/widgets/DialogHeader.dart'; +import 'package:wosull/widgets/DropdownItemBuilder.dart'; import 'package:wosull/widgets/HeadingText.dart'; import 'package:wosull/widgets/MandatoryTitleText.dart'; @@ -36,7 +37,9 @@ class _InventoryAddMeasurementVCState @override void initState() { - viewModel.fillValueOnEdit(widget.isEdit, widget.measurement); + context + .read() + .fillValueOnEdit(widget.isEdit, widget.measurement); super.initState(); } @@ -56,7 +59,7 @@ class _InventoryAddMeasurementVCState elevation: 0, backgroundColor: const Color(0xffffffff), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(15.0), + borderRadius: BorderRadius.circular(8.0), ), child: OrientationBuilder(builder: (c, orientation) { return SingleChildScrollView( @@ -101,9 +104,7 @@ class _InventoryAddMeasurementVCState measurementUnitWidget(), AppSpaces.verticalMedium, HeadingText(AppLocalizations.of(context)!.status), - const SizedBox( - height: 12, - ), + AppSpaces.verticalLarge, Row( children: [ CustomSwitch( @@ -114,9 +115,7 @@ class _InventoryAddMeasurementVCState ), ], ), - const SizedBox( - height: 12, - ), + AppSpaces.verticalLarge, Align( alignment: Alignment.centerRight, child: SizedBox( @@ -146,35 +145,24 @@ class _InventoryAddMeasurementVCState } Widget measurementUnitWidget() { - return FutureBuilder( - future: viewModel.getMeasurementUnits(), - builder: (c, s) { - if (s.hasData) { - final units = s.data ?? []; - return Material( - color: MyColors.backFillColor, - borderRadius: BorderRadius.circular(8), - child: SizedBox( - width: double.infinity, - child: Padding( - padding: const EdgeInsets.only(left: 8, right: 8), - child: DropdownSearch( - items: units, - itemAsString: (MeasurementUnit u) => u.name, - onChanged: (MeasurementUnit? data) { - viewModel.setMeasurementUnit(data); - }, - selectedItem: viewModel.dropdownValue, - dropdownDecoratorProps: - MyColors.dropDownStyle(hint: 'Choose'), - ), - ), - ), - ); - } else { - return AppLoader(); - } - }); + return DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: viewModel.measurementUnits, + itemAsString: (MeasurementUnit u) => u.name, + onChanged: (MeasurementUnit? data) { + viewModel.setMeasurementUnit(data); + }, + selectedItem: viewModel.dropdownValue, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), + ); } void checkState() { diff --git a/lib/application/views/inventorymodule/measurementviews/InventoryMeasurementVC.dart b/lib/application/views/inventorymodule/measurementviews/InventoryMeasurementVC.dart index 88b9fcd..7575f72 100644 --- a/lib/application/views/inventorymodule/measurementviews/InventoryMeasurementVC.dart +++ b/lib/application/views/inventorymodule/measurementviews/InventoryMeasurementVC.dart @@ -1,22 +1,24 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:provider/provider.dart'; +import 'package:sizer/sizer.dart'; import 'package:wosull/application/enum/DataState.dart'; -import 'package:wosull/application/model/converters/DataTimeFormat.dart'; -import 'package:wosull/application/model/inventory/InventoryMeasurementModel.dart'; +import 'package:wosull/application/model/Measurement/InventoryMeasurementModel.dart'; import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/AppError.dart'; +import 'package:wosull/application/utils/AppLoader.dart'; import 'package:wosull/application/views/inventorymodule/measurementviews/AddMeasurementUnitVC.dart'; import 'package:wosull/application/views/inventorymodule/measurementviews/InventoryAddMeasurementVC.dart'; import 'package:wosull/application/views/inventorymodule/measurementviews/ViewInventoryMeasurementVC.dart'; import 'package:wosull/application/views/inventorymodule/measurementviews/viewModels/MeasurementViewModel.dart'; +import 'package:wosull/application/views/inventorymodule/measurementviews/widgets/MeasurementListView.dart'; import 'package:wosull/application/views/popups/DeleteRecordPopUp.dart'; import 'package:wosull/base/BaseStatefulState.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/ThemeText.dart'; import 'package:wosull/widgets/CustomSimpleButton.dart'; -import 'package:wosull/widgets/CustomSwitch.dart'; -import 'package:wosull/widgets/EmptyDataWidget.dart'; -import 'package:wosull/widgets/HeadingText.dart'; -import 'package:wosull/widgets/ValueText.dart'; +import 'package:wosull/widgets/PageLimitDropDown.dart'; +import 'package:wosull/widgets/SearchBox.dart'; class InventoryMeasurementVC extends StatefulWidget { const InventoryMeasurementVC({Key? key}) : super(key: key); @@ -32,488 +34,237 @@ class _InventoryMeasurementVCState late ScrollController _controller; + @override + void dispose() { + viewModel.disposeData(); + super.dispose(); + } + @override Widget build(BuildContext context) { _controller = ScrollController()..addListener(_scrollNotification); - return WillPopScope( - child: Scaffold( - backgroundColor: MyColors.fillColor, - resizeToAvoidBottomInset: true, - body: OrientationBuilder(builder: (c, builder) { - isPortrait = MediaQuery.of(c).orientation == Orientation.portrait; + return Scaffold( + backgroundColor: MyColors.fillColor, + resizeToAvoidBottomInset: true, + body: OrientationBuilder(builder: (c, builder) { + isPortrait = MediaQuery.of(c).orientation == Orientation.portrait; - return SingleChildScrollView( - controller: _controller, - child: Container( - padding: const EdgeInsets.all(12), - child: Column( - children: [ - isPortrait - ? Column( - crossAxisAlignment: CrossAxisAlignment.start, + return SingleChildScrollView( + controller: _controller, + child: Container( + padding: const EdgeInsets.all(12), + child: Column( + children: [ + isPortrait + ? Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, children: [ - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Text( - AppLocalizations.of(context)!.measurement, - style: ThemeText.textStylePageHeading, - ), - const SizedBox( - width: 8, - ), - SizedBox( - width: 160, - child: CustomSimpleButton( - textColor: MyColors.blueThemeColor, - backGroundColor: - MyColors.backColorBlue50, - onPressed: () { - addUpdateMeasurement( - false, Measurement()); - }, - heading: AppLocalizations.of(context)! - .add_measurements, - ), - ), - ], + Text( + AppLocalizations.of(context)!.measurement, + style: ThemeText.textStylePageHeading, ), - SizedBox( - width: 160, + AppSpaces.horizontalMedium, + Flexible( child: CustomSimpleButton( textColor: MyColors.blueThemeColor, backGroundColor: MyColors.backColorBlue50, onPressed: () { - addMeasurementUnit(); + addUpdateMeasurement( + false, Measurement()); }, - heading: '+ Add Measurement Unit', + heading: AppLocalizations.of(context)! + .add_measurements, ), ), ], - ) - : Row( - children: [ - Expanded( - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Text( - AppLocalizations.of(context)!.measurement, - style: ThemeText.textStylePageHeading, - ), - const SizedBox( - width: 8, - ), - SizedBox( - width: 160, - child: CustomSimpleButton( - textColor: MyColors.blueThemeColor, - backGroundColor: - MyColors.backColorBlue50, - onPressed: () { - addUpdateMeasurement( - false, Measurement()); - }, - heading: AppLocalizations.of(context)! - .add_measurements, - ), - ), - const SizedBox( - width: 8, - ), - SizedBox( - width: 160, - child: CustomSimpleButton( - textColor: MyColors.blueThemeColor, - backGroundColor: - MyColors.backColorBlue50, - onPressed: () { - addMeasurementUnit(); - }, - heading: '+ Add Measurement Unit', - ), - ), - ], - )), - ], ), - const SizedBox( - height: 8, - ), - ChangeNotifierProvider( - create: (context) => viewModel, - child: Consumer( - builder: (BuildContext context, - MeasurementViewModel controller, Widget? _) { - switch (controller.dataState) { - case DataState.uninitialized: - Future(() { - controller.fetch(); - }); - return showData(controller.filteredList); - case DataState.initialFetching: - return const Center( - child: CircularProgressIndicator(), - ); - case DataState.moreFetching: - case DataState.refreshing: - return showData(controller.filteredList); - case DataState.error: - return const Center( - child: Text("Error"), - ); - case DataState.searching: - case DataState.fetched: - case DataState.noMoreData: - return showData(controller.filteredList); - } - }, - ), - ), - ], - ), - ), - ); - })), - onWillPop: () { - viewModel.dispose(); - return Future.value(false); - }); - } - - Widget showData(List data) { - return Column( - children: [ - data.isEmpty - ? const EmptyDataWidget() - : Column( - children: [ - isPortrait - ? Container() - : Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 50, - color: MyColors.containerBackColor, - child: Row( - children: [ - Expanded( - child: HeadingText( - AppLocalizations.of(context)!.measurement, - )), - Expanded( - child: HeadingText( - AppLocalizations.of(context)!.measurement_unit, - )), - Expanded( - child: Align( - alignment: Alignment.center, - child: HeadingText( - AppLocalizations.of(context)!.status, - ), - )), - Expanded( - child: HeadingText( - AppLocalizations.of(context)!.created_on, - )), - Expanded( - child: HeadingText( - AppLocalizations.of(context)!.updated_on, - )), - Expanded( - child: Padding( - padding: const EdgeInsets.only(right: 16), - child: Align( - alignment: Alignment.centerRight, - child: HeadingText( - AppLocalizations.of(context)!.action, - ), - ), - )), - ], - ), - ), - ListView.builder( - padding: EdgeInsets.zero, - scrollDirection: Axis.vertical, - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - itemBuilder: (c, position) { - final measurement = data[position]; - - if (isPortrait) { - return Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - elevation: 2, - color: MyColors.white, - child: Container( - padding: const EdgeInsets.fromLTRB(8, 0, 0, 8), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Expanded( - child: Container( - padding: const EdgeInsets.only(top: 16), - child: Row( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.start, - children: [ - HeadingText( - AppLocalizations.of(context)! - .measurement, - ), - const SizedBox( - height: 8, - ), - HeadingText( - AppLocalizations.of(context)! - .measurement_unit, - ), - const SizedBox( - height: 8, - ), - HeadingText( - AppLocalizations.of(context)! - .status, - ), - const SizedBox( - height: 8, - ), - HeadingText( - AppLocalizations.of(context)! - .created_on, - ), - const SizedBox( - height: 8, - ), - HeadingText( - AppLocalizations.of(context)! - .updated_on, - ), - ], - )), - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.end, - mainAxisAlignment: - MainAxisAlignment.start, - children: [ - ValueText( - measurement.name!, - ), - const SizedBox( - height: 8, - ), - ValueText(measurement.measurement!), - const SizedBox( - height: 4, - ), - Row( - mainAxisAlignment: - MainAxisAlignment.end, - crossAxisAlignment: - CrossAxisAlignment.end, - children: [ - CustomSwitch( - value: measurement.getStatus(), - onToggle: (value) { - _updateStatus( - measurement.id!, value); - }, - ) - ], - ), - const SizedBox( - height: 8, - ), - ValueText( - DataTimeFormat.getFormatDate( - measurement.createdAt!)), - const SizedBox( - height: 8, - ), - ValueText( - DataTimeFormat.getFormatDate( - measurement.updatedAt!)), - ], - )), - ], + Flexible( + child: CustomSimpleButton( + textColor: MyColors.blueThemeColor, + backGroundColor: MyColors.backColorBlue50, + onPressed: () { + addMeasurementUnit(); + }, + heading: '+ Add Measurement Unit', ), - )), - PopupMenuButton( - icon: const Icon(Icons.more_vert), - itemBuilder: (c) { - return [ - PopupMenuItem( - value: 'edit', - child: Text( - AppLocalizations.of(context)!.edit, - ), - ), - PopupMenuItem( - value: 'view', - child: Text( - AppLocalizations.of(context)!.view, - ), - ), - PopupMenuItem( - value: 'delete', - child: Text( - AppLocalizations.of(context)!.delete, - ), - ) - ]; + ), + AppSpaces.horizontalSmall, + PageLimitDropdown( + onChange: (value) { + viewModel.fetch( + isRefresh: true, + limit: int.parse(value!)); }, - onSelected: (String value) => - actionPopUpItemSelected( - value, measurement), ) ], ), - ), - ); - } else { - return Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - child: Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 56, - color: MyColors.containerBackColor, - child: Row( + SizedBox( + height: 48, + child: SearchBox( + onEditingDone: (text) { + filterSearchResults(text); + }, + onChanged: (text) { + filterSearchResults(text); + }, + hint: AppLocalizations.of(context)!.search, + ), + ), + ], + ) + : Row( + children: [ + Expanded( + child: Row( + mainAxisAlignment: MainAxisAlignment.start, children: [ - Expanded( - child: ValueText( - measurement.name!, - )), - Expanded( - child: ValueText( - measurement.measurement!, - )), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: CustomSwitch( - value: measurement.getStatus(), - onToggle: (value) { - _updateStatus(measurement.id!, value); + Text( + AppLocalizations.of(context)!.measurement, + style: ThemeText.textStylePageHeading, + ), + AppSpaces.horizontalMedium, + SizedBox( + width: 160, + child: CustomSimpleButton( + textColor: MyColors.blueThemeColor, + backGroundColor: MyColors.backColorBlue50, + onPressed: () { + addUpdateMeasurement( + false, Measurement()); + }, + heading: AppLocalizations.of(context)! + .add_measurements, + ), + ), + AppSpaces.horizontalMedium, + SizedBox( + width: 160, + child: CustomSimpleButton( + textColor: MyColors.blueThemeColor, + backGroundColor: MyColors.backColorBlue50, + onPressed: () { + addMeasurementUnit(); }, + heading: '+ Add Measurement Unit', ), - )), - Expanded( - child: ValueText( - DataTimeFormat.getFormatDate( - measurement.updatedAt!))), - Expanded( - child: ValueText( - DataTimeFormat.getFormatDate( - measurement.updatedAt!), - )), - Expanded( - child: Padding( - padding: const EdgeInsets.all(4), - child: Align( - alignment: Alignment.centerRight, - child: Container( - width: 42, - height: 42, - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular(4)), - color: MyColors.backFillColor), - child: PopupMenuButton( - padding: EdgeInsets.zero, - icon: const Icon(Icons.more_vert), - itemBuilder: (c) { - return [ - PopupMenuItem( - value: 'edit', - child: Text( - AppLocalizations.of(context)! - .edit, - ), - ), - PopupMenuItem( - value: 'view', - child: Text( - AppLocalizations.of(context)! - .view, - ), - ), - PopupMenuItem( - value: 'delete', - child: Text( - AppLocalizations.of(context)! - .delete, - ), - ) - ]; - }, - onSelected: (String value) => - actionPopUpItemSelected( - value, measurement), - ), - ), + ), + AppSpaces.horizontalMedium, + SizedBox( + width: + SizerUtil.deviceType == DeviceType.mobile + ? 200 + : 240, + height: 48, + child: SearchBox( + onEditingDone: (text) { + filterSearchResults(text); + }, + onChanged: (text) { + filterSearchResults(text); + }, + hint: AppLocalizations.of(context)!.search, ), - )) + ), ], - ), - ), - ); - } - }, - itemCount: data.length, - ) + )), + PageLimitDropdown( + onChange: (value) { + viewModel.fetch( + isRefresh: true, limit: int.parse(value!)); + }, + ) + ], + ), + AppSpaces.verticalMedium, + ChangeNotifierProvider( + create: (context) => viewModel, + child: Consumer( + builder: (BuildContext context, + MeasurementViewModel controller, Widget? _) { + switch (controller.dataState) { + case DataState.uninitialized: + Future(() { + controller.fetch(); + }); + return showData(controller.filteredList); + case DataState.initialFetching: + return AppLoader(); + case DataState.moreFetching: + case DataState.refreshing: + return showData(controller.filteredList); + case DataState.error: + return AppError( + error: 'Error', + ); + case DataState.searching: + case DataState.fetched: + case DataState.noMoreData: + return showData(controller.filteredList); + } + }, + ), + ), ], ), - if (viewModel.dataState == DataState.moreFetching) - const Center(child: CircularProgressIndicator()), + ), + ); + })); + } + + Widget showData(List data) { + return Column( + children: [ + MeasurementListView( + isPortrait: isPortrait, + data: data, + onUpdate: (measurement, value) { + _updateStatus(measurement.id!, value); + }, + onDelete: (measurement) { + showDeletePopup(measurement); + }, + onView: (measurement) { + showDialog( + barrierColor: Colors.black26, + context: context, + builder: (context) { + return ViewInventoryMeasurementVC(measurement: measurement); + }, + ); + }, + onEdit: (measurement) { + addUpdateMeasurement(true, measurement); + }), + if (viewModel.dataState == DataState.moreFetching) AppLoader(), ], ); } bool _scrollNotification() { if (!viewModel.isLoading && _controller.position.extentAfter < 300) { - viewModel.fetch(); + viewModel.fetch(limit: viewModel.limit); } return true; } - Future actionPopUpItemSelected( - String value, Measurement measurement) async { - if (value == 'edit') { - addUpdateMeasurement(true, measurement); - } else if (value == 'delete') { - final result = await showDialog( - barrierColor: Colors.black26, - context: context, - builder: (context) { - return const DeleteRecordPopUp(); - }, - ); + Future showDeletePopup(Measurement measurement) async { + final result = await showDialog( + barrierColor: Colors.black26, + context: context, + builder: (context) { + return const DeleteRecordPopUp(); + }, + ); - if (!mounted) return; - if (result) { - _deleteDiscount(measurement.id!); - } - } else { - showDialog( - barrierColor: Colors.black26, - context: context, - builder: (context) { - return ViewInventoryMeasurementVC(measurement: measurement); - }, - ); + if (!mounted) return; + if (result) { + _deleteDiscount(measurement.id!); } } @@ -566,7 +317,7 @@ class _InventoryMeasurementVCState if (!mounted) return; if (result) { - viewModel.fetch(isRefresh: true); + viewModel.fetch(isRefresh: true, limit: viewModel.limit); } } } diff --git a/lib/application/views/inventorymodule/measurementviews/ViewInventoryMeasurementVC.dart b/lib/application/views/inventorymodule/measurementviews/ViewInventoryMeasurementVC.dart index 356718a..b22c8af 100644 --- a/lib/application/views/inventorymodule/measurementviews/ViewInventoryMeasurementVC.dart +++ b/lib/application/views/inventorymodule/measurementviews/ViewInventoryMeasurementVC.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; +import 'package:wosull/application/model/Measurement/InventoryMeasurementModel.dart'; import 'package:wosull/application/model/converters/DataTimeFormat.dart'; -import 'package:wosull/application/model/inventory/InventoryMeasurementModel.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/theme/MySeparator.dart'; import 'package:wosull/widgets/HeadingText.dart'; @@ -18,7 +18,7 @@ class ViewInventoryMeasurementVC extends StatelessWidget { elevation: 0, backgroundColor: const Color(0xffffffff), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(15.0), + borderRadius: BorderRadius.circular(8.0), ), child: OrientationBuilder(builder: (c, orientation) { return SingleChildScrollView( diff --git a/lib/application/views/inventorymodule/measurementviews/repo/MeasurementsRepository.dart b/lib/application/views/inventorymodule/measurementviews/repo/MeasurementsRepository.dart new file mode 100644 index 0000000..afbdac8 --- /dev/null +++ b/lib/application/views/inventorymodule/measurementviews/repo/MeasurementsRepository.dart @@ -0,0 +1,43 @@ +import 'package:wosull/application/model/Measurement/GetStoreMeasurementModel.dart'; +import 'package:wosull/application/model/Measurement/InventoryMeasurementModel.dart'; +import 'package:wosull/application/model/SimpleResponsModel.dart'; +import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/utils/Constants.dart'; + +class MeasurementRepository { + Future addMeasurementName( + Map map) async { + return await APIManager().fetchData(Constants.addMeasurementUnit, map); + } + + Future addMeasurement(Map map) async { + return await APIManager().fetchData(Constants.ADD_UPDATE_MEASUREMENT, map); + } + + Future> fetch(Map map) async { + var measurements = []; + await APIManager() + .fetchData(Constants.GET_INVENTORY_MEASUREMENTS, map) + .then((result) { + final value = GetStoreMeasurementModel.fromJson(result); + if (value.success!) { + measurements.addAll(value.measurements!); + } + }).onError((error, stackTrace) {}); + return measurements; + } + + Future> search(Map map) async { + var measurements = []; + await APIManager() + .fetchData(Constants.SEARCH_MEASUREMENT, map) + .then((result) { + final value = GetStoreMeasurementModel.fromJson(result); + if (value.success!) { + measurements.clear(); + measurements.addAll(value.measurements!); + } + }).onError((error, stackTrace) {}); + return measurements; + } +} diff --git a/lib/application/views/inventorymodule/measurementviews/viewModels/AddMeasurementUnitVM.dart b/lib/application/views/inventorymodule/measurementviews/viewModels/AddMeasurementUnitVM.dart index 63a7ecf..dcc08d3 100644 --- a/lib/application/views/inventorymodule/measurementviews/viewModels/AddMeasurementUnitVM.dart +++ b/lib/application/views/inventorymodule/measurementviews/viewModels/AddMeasurementUnitVM.dart @@ -1,22 +1,21 @@ import 'package:flutter/material.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; -import 'package:wosull/application/model/SimpleResponsModel.dart'; -import 'package:wosull/application/network/APIManager.dart'; import 'package:wosull/application/utils/CRUDOperatoinState.dart'; -import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/inventorymodule/measurementviews/repo/MeasurementsRepository.dart'; import 'package:wosull/helpers/Utils.dart'; class AddMeasurementUnitVM with ChangeNotifier { bool _isLoading = false; bool get isLoading => _isLoading; - - String unitName = ''; - var _crudOperation = CRUDOperationState.uninitialized; CRUDOperationState get crudOperation => _crudOperation; + String unitName = ''; + + final repository = MeasurementRepository(); + void disposeData() { unitName = ''; } @@ -36,16 +35,11 @@ class AddMeasurementUnitVM with ChangeNotifier { Future addMeasurementName() async { setLoading(true); - Map data = { + Map map = { 'store_id': sharedPrefs.storeId, 'name': unitName, }; - - await APIManager() - .fetchData(Constants.addMeasurementUnit, data) - .then((value) { - final response = SimpleResponseModel.fromJson(value); - + await repository.addMeasurementName(map).then((response) { if (response.success) { Utils.showMessage(response.message); _crudOperation = CRUDOperationState.add; diff --git a/lib/application/views/inventorymodule/measurementviews/viewModels/AddMeasurementViewModel.dart b/lib/application/views/inventorymodule/measurementviews/viewModels/AddMeasurementViewModel.dart index e6a6175..a0bc267 100644 --- a/lib/application/views/inventorymodule/measurementviews/viewModels/AddMeasurementViewModel.dart +++ b/lib/application/views/inventorymodule/measurementviews/viewModels/AddMeasurementViewModel.dart @@ -1,23 +1,19 @@ import 'package:flutter/material.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; -import 'package:wosull/application/model/SimpleResponsModel.dart'; -import 'package:wosull/application/model/inventory/InventoryMeasurementModel.dart'; -import 'package:wosull/application/model/inventory/MeasurementUnitModel.dart'; -import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/model/Measurement/InventoryMeasurementModel.dart'; +import 'package:wosull/application/model/Measurement/MeasurementUnitModel.dart'; +import 'package:wosull/application/repository/WosulRepository.dart'; import 'package:wosull/application/utils/CRUDOperatoinState.dart'; -import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/inventorymodule/measurementviews/repo/MeasurementsRepository.dart'; import 'package:wosull/helpers/Utils.dart'; class AddMeasurementViewModel with ChangeNotifier { - void disposeData() { - _isLoading = false; - measurement = Measurement(); - } - bool _isLoading = false; bool get isLoading => _isLoading; + List measurementUnits = []; + bool isEdit = false; var dropdownValue; var _crudOperation = CRUDOperationState.uninitialized; @@ -25,14 +21,31 @@ class AddMeasurementViewModel with ChangeNotifier { CRUDOperationState get crudOperation => _crudOperation; var measurement = Measurement(); + final repository = MeasurementRepository(); + void setLoading(bool value) { _isLoading = value; notifyListeners(); } - void fillValueOnEdit(bool isEdit, Measurement measurement) { + void disposeData() { + _isLoading = false; + measurementUnits.clear(); + dropdownValue = null; + measurement = Measurement(); + } + + Future fillValueOnEdit(bool isEdit, Measurement measurement) async { this.isEdit = isEdit; this.measurement = measurement; + final response = await WosulRepository().getMeasurementUnits(); + measurementUnits.addAll(response); + if (isEdit) { + dropdownValue ??= measurementUnits + .singleWhere((element) => element.name == measurement.measurement); + } + dropdownValue ??= MeasurementUnit(id: '', name: 'Choose'); + notifyListeners(); } Future isValidate() async { @@ -41,26 +54,22 @@ class AddMeasurementViewModel with ChangeNotifier { } else if (dropdownValue == null) { Utils.showMessage('Select Measurement Unit'); } else { - await _addMeasurement(); + await addMeasurement(); } } - Future _addMeasurement() async { + Future addMeasurement() async { setLoading(true); MeasurementUnit unit = dropdownValue as MeasurementUnit; - // widget.measurement.measurement = dropdownValue as String?; - Map data = { + Map map = { 'store_id': sharedPrefs.storeId, 'name': measurement.name ?? '', 'measurement_unit': unit.name, - 'status': measurement.getStatus(), + 'status': measurement.getStatus() ? 'Active' : 'Inactive', 'measurement_id': measurement.id ?? '', }; - await APIManager() - .fetchData(Constants.ADD_UPDATE_MEASUREMENT, data) - .then((value) { - final response = SimpleResponseModel.fromJson(value); + await repository.addMeasurement(map).then((response) { if (response.success) { Utils.showMessage(response.message); _crudOperation = CRUDOperationState.add; @@ -71,28 +80,6 @@ class AddMeasurementViewModel with ChangeNotifier { }).onError((error, stackTrace) {}); } - Future> getMeasurementUnits() async { - var items = []; - Map data = {}; - await APIManager() - .fetchData(Constants.GET_INVENTORY_MEASUREMENTS_UNITS, data) - .then((value) { - final response = MeasurementUnitModel.fromJson(value); - if (response.success) { - print(value); - items.addAll(response.measurementUnits); - if (isEdit) { - dropdownValue ??= - items.where((element) => element.name == measurement.measurement); - } - } - }).onError((error, stackTrace) { - print(error.toString()); - }); - dropdownValue ??= MeasurementUnit(name: 'Choose'); - return items; - } - void setMeasurementUnit(MeasurementUnit? value) { if (value != null) { dropdownValue = value; @@ -105,7 +92,6 @@ class AddMeasurementViewModel with ChangeNotifier { } else { measurement.status = "Inactive"; } - notifyListeners(); } } diff --git a/lib/application/views/inventorymodule/measurementviews/viewModels/MeasurementViewModel.dart b/lib/application/views/inventorymodule/measurementviews/viewModels/MeasurementViewModel.dart index c889a63..bc4029b 100644 --- a/lib/application/views/inventorymodule/measurementviews/viewModels/MeasurementViewModel.dart +++ b/lib/application/views/inventorymodule/measurementviews/viewModels/MeasurementViewModel.dart @@ -1,15 +1,16 @@ import 'package:flutter/cupertino.dart'; import 'package:wosull/application/enum/DataState.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; -import 'package:wosull/application/model/inventory/InventoryMeasurementModel.dart'; +import 'package:wosull/application/model/Measurement/InventoryMeasurementModel.dart'; import 'package:wosull/application/network/APIManager.dart'; import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/inventorymodule/measurementviews/repo/MeasurementsRepository.dart'; class MeasurementViewModel extends ChangeNotifier { bool _isLoading = false; bool get isLoading => _isLoading; - + int limit = 10; int _currentPageNumber = 1; DataState _dataState = DataState.uninitialized; @@ -21,7 +22,15 @@ class MeasurementViewModel extends ChangeNotifier { List get filteredList => _filteredList; - fetch({bool isRefresh = false}) async { + final repository = MeasurementRepository(); + + void disposeData() { + _filteredList.clear(); + _dataState = DataState.uninitialized; + } + + fetch({bool isRefresh = false, int limit = 10}) async { + this.limit = limit; _isLoading = true; if (!isRefresh) { _dataState = (_dataState == DataState.uninitialized) @@ -36,22 +45,20 @@ class MeasurementViewModel extends ChangeNotifier { Map data = { 'store_id': sharedPrefs.storeId, 'page': _currentPageNumber, + 'limit': this.limit }; try { if (_didLastLoad) { _dataState = DataState.noMoreData; } else { - await APIManager() - .fetchData(Constants.GET_INVENTORY_MEASUREMENTS, data) - .then((result) { - final value = InvoiceMeasurementModel.fromJson(result); + await repository.fetch(data).then((measurements) { if (_dataState == DataState.refreshing) { _filteredList.clear(); } - if (value.success!) { - _filteredList.addAll(value.measurements!); - if (value.measurements!.length < 10) { + if (measurements.isNotEmpty) { + _filteredList.addAll(measurements); + if (measurements.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; @@ -79,20 +86,17 @@ class MeasurementViewModel extends ChangeNotifier { _filteredList.clear(); notifyListeners(); } else { - Map data = { + Map map = { 'store_id': sharedPrefs.storeId, 'searchTerm': searchValue }; _dataState = DataState.searching; notifyListeners(); try { - await APIManager() - .fetchData(Constants.SEARCH_MEASUREMENT, data) - .then((result) { - final value = InvoiceMeasurementModel.fromJson(result); + await repository.search(map).then((measurements) { filteredList.clear(); - if (value.success!) { - filteredList.addAll(value.measurements!); + if (measurements.isNotEmpty) { + filteredList.addAll(measurements); } _dataState = DataState.fetched; }).onError((error, stackTrace) { diff --git a/lib/application/views/inventorymodule/measurementviews/widgets/MeasurementListView.dart b/lib/application/views/inventorymodule/measurementviews/widgets/MeasurementListView.dart new file mode 100644 index 0000000..00b0faa --- /dev/null +++ b/lib/application/views/inventorymodule/measurementviews/widgets/MeasurementListView.dart @@ -0,0 +1,275 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/model/Measurement/InventoryMeasurementModel.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/Utils.dart'; +import 'package:wosull/widgets/ActionPopUpContainer.dart'; +import 'package:wosull/widgets/CustomPopuoMenuButton.dart'; +import 'package:wosull/widgets/CustomSwitch.dart'; +import 'package:wosull/widgets/EmptyDataWidget.dart'; +import 'package:wosull/widgets/HeadingText.dart'; +import 'package:wosull/widgets/ListHeadingContainer.dart'; +import 'package:wosull/widgets/ValueText.dart'; + +class MeasurementListView extends StatelessWidget { + List data; + bool isPortrait; + final void Function(Measurement measurement, bool status) onUpdate; + final void Function(Measurement measurement) onDelete; + final void Function(Measurement measurement) onView; + final void Function(Measurement measurement) onEdit; + + MeasurementListView( + {super.key, + required this.isPortrait, + required this.data, + required this.onUpdate, + required this.onDelete, + required this.onView, + required this.onEdit}); + + @override + Widget build(BuildContext context) { + return data.isEmpty + ? const EmptyDataWidget() + : Column( + children: [ + isPortrait + ? Container() + : ListHeadingContainer( + child: Row( + children: [ + Expanded( + child: HeadingText( + lang(context).measurement, + )), + Expanded( + child: HeadingText( + lang(context).measurement_unit, + )), + Expanded( + child: Align( + alignment: Alignment.center, + child: HeadingText( + lang(context).status, + ), + )), + Expanded( + child: HeadingText( + lang(context).created_on, + )), + Expanded( + child: HeadingText( + lang(context).updated_on, + )), + Expanded( + child: Padding( + padding: const EdgeInsets.only(right: 16), + child: Align( + alignment: Alignment.centerRight, + child: HeadingText( + lang(context).action, + ), + ), + )), + ], + ), + ), + ListView.builder( + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (c, position) { + final measurement = data[position]; + + if (isPortrait) { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + elevation: 2, + color: MyColors.white, + child: Container( + padding: const EdgeInsets.fromLTRB(8, 0, 0, 8), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + child: Container( + padding: const EdgeInsets.only(top: 16), + child: Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + HeadingText( + lang(context).measurement, + ), + const SizedBox( + height: 8, + ), + HeadingText( + lang(context).measurement_unit, + ), + const SizedBox( + height: 8, + ), + HeadingText( + lang(context).status, + ), + const SizedBox( + height: 8, + ), + HeadingText( + lang(context).created_on, + ), + const SizedBox( + height: 8, + ), + HeadingText( + lang(context).updated_on, + ), + ], + )), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + ValueText( + measurement.name!, + ), + AppSpaces.verticalMedium, + ValueText(measurement.measurement!), + AppSpaces.verticalSmall, + Row( + mainAxisAlignment: + MainAxisAlignment.end, + crossAxisAlignment: + CrossAxisAlignment.end, + children: [ + CustomSwitch( + value: measurement.getStatus(), + onToggle: (value) { + onUpdate(measurement, value); + }, + ) + ], + ), + AppSpaces.verticalMedium, + ValueText(DataTimeFormat.getFormatDate( + measurement.createdAt!)), + AppSpaces.verticalMedium, + ValueText(DataTimeFormat.getFormatDate( + measurement.updatedAt!)), + ], + )), + ], + ), + )), + getPopupMenuButton(context, position) + ], + ), + ), + ); + } else { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: ListHeadingContainer( + child: Row( + children: [ + Expanded( + child: ValueText( + measurement.name!, + )), + Expanded( + child: ValueText( + measurement.measurement!, + )), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: CustomSwitch( + value: measurement.getStatus(), + onToggle: (value) { + onUpdate(measurement, value); + }, + ), + )), + Expanded( + child: ValueText(DataTimeFormat.getFormatDate( + measurement.updatedAt!))), + Expanded( + child: ValueText( + DataTimeFormat.getFormatDate( + measurement.updatedAt!), + )), + Expanded( + child: Padding( + padding: const EdgeInsets.all(4), + child: Align( + alignment: Alignment.centerRight, + child: ActionPopUpContainer( + child: getPopupMenuButton(context, position), + ), + ), + )) + ], + ), + ), + ); + } + }, + itemCount: data.length, + ) + ], + ); + } + + Future actionPopUpItemSelected( + String value, Measurement measurement) async { + if (value == 'edit') { + onEdit(measurement); + } else if (value == 'delete') { + onDelete(measurement); + } else { + onView(measurement); + } + } + + getPopupMenuButton(BuildContext context, int position) { + return CustomPopupMenuButton( + onSelected: (String value) => + actionPopUpItemSelected(value, data[position]), + items: [ + PopupMenuItem( + value: 'edit', + child: ValueText( + lang(context).edit, + ), + ), + PopupMenuItem( + value: 'view', + child: ValueText( + lang(context).view, + ), + ), + PopupMenuItem( + value: 'delete', + child: ValueText( + lang(context).delete, + ), + ) + ], + ); + } +} diff --git a/lib/application/views/inventorymodule/modiferOption/repo/ModifierOptionRepository.dart b/lib/application/views/inventorymodule/modiferOption/repo/ModifierOptionRepository.dart new file mode 100644 index 0000000..2cdd291 --- /dev/null +++ b/lib/application/views/inventorymodule/modiferOption/repo/ModifierOptionRepository.dart @@ -0,0 +1,39 @@ +import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/application/model/SimpleResponsModel.dart'; +import 'package:wosull/application/model/modifierOptions/ModifierOption.dart'; +import 'package:wosull/application/model/modifierOptions/ModifierOptionsResponse.dart'; +import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/utils/Constants.dart'; + +class ModifierOptionRepository { + Future delete(String id) async { + Map data = {'modifier_option_id': id}; + return await APIManager() + .getResponsePatch(Constants.deleteModifierOption, data); + } + + Future update(String id, bool value) async { + Map data = {'modifier_option_id': id, 'status': value}; + return await APIManager() + .getResponsePatch(Constants.updateModifierOption, data); + } + + Future> fetch(Map map) async { + var options = []; + await APIManager() + .getResponseAuth( + Constants.getModifierOptions + sharedPrefs.storeId, map) + .then((result) { + final value = ModifierOptionsResponse.fromJson(result); + if (value.status!) { + options.addAll(value.modifierOptions ?? []); + } + }).onError((error, stackTrace) {}); + return options; + } + + Future addUpdateModifierOption( + Map map) async { + return await APIManager().fetchData(Constants.addModifierOptions, map); + } +} diff --git a/lib/application/views/inventorymodule/modiferOption/viewModels/ModifierOptionsViewModel.dart b/lib/application/views/inventorymodule/modiferOption/viewModels/ModifierOptionsViewModel.dart new file mode 100644 index 0000000..c2b32b6 --- /dev/null +++ b/lib/application/views/inventorymodule/modiferOption/viewModels/ModifierOptionsViewModel.dart @@ -0,0 +1,95 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/enum/DataState.dart'; +import 'package:wosull/application/model/modifierOptions/ModifierOption.dart'; +import 'package:wosull/application/views/inventorymodule/modiferOption/repo/ModifierOptionRepository.dart'; + +class ModifierOptionsViewModel with ChangeNotifier { + bool _isLoading = false; + + bool get isLoading => _isLoading; + int limit = 10; + int _currentPageNumber = 1; + + DataState _dataState = DataState.uninitialized; + + bool _didLastLoad = false; + + DataState get dataState => _dataState; + List _filteredList = []; + + List get filteredList => _filteredList; + + final repository = ModifierOptionRepository(); + + void setLoading(bool value) { + _isLoading = value; + notifyListeners(); + } + + fetch({bool isRefresh = false, int limit = 10}) async { + this.limit = limit; + _isLoading = true; + if (!isRefresh) { + _dataState = (_dataState == DataState.uninitialized) + ? DataState.initialFetching + : DataState.moreFetching; + } else { + _didLastLoad = false; + _currentPageNumber = 1; + _dataState = DataState.refreshing; + } + notifyListeners(); + Map data = { + 'page': _currentPageNumber, + 'limit': this.limit + }; + + try { + if (_didLastLoad) { + _dataState = DataState.noMoreData; + } else { + await repository.fetch(data).then((value) { + if (_dataState == DataState.refreshing) { + _filteredList.clear(); + } + if (value.isNotEmpty) { + _filteredList.addAll(value); + if (value.length < this.limit) { + _didLastLoad = true; + } else { + _didLastLoad = false; + } + } + _isLoading = false; + _dataState = DataState.fetched; + _currentPageNumber += 1; + }).onError((error, stackTrace) { + _dataState = DataState.error; + }); + } + notifyListeners(); + } catch (e) { + _isLoading = false; + _dataState = DataState.error; + notifyListeners(); + } + } + + Future delete(String id) async { + await repository.delete(id).then((result) { + filteredList.removeWhere((element) => element.id! == id); + notifyListeners(); + }).onError((error, stackTrace) { + notifyListeners(); + }); + } + + Future update(String id, bool value) async { + await repository.update(id, value).then((result) { + _filteredList.singleWhere((element) => element.id == id).status = value; + notifyListeners(); + }).onError((error, stackTrace) { + notifyListeners(); + }); + } +} diff --git a/lib/application/views/inventorymodule/modiferOption/viewModels/NewModifierOptionViewModel.dart b/lib/application/views/inventorymodule/modiferOption/viewModels/NewModifierOptionViewModel.dart new file mode 100644 index 0000000..88bf935 --- /dev/null +++ b/lib/application/views/inventorymodule/modiferOption/viewModels/NewModifierOptionViewModel.dart @@ -0,0 +1,184 @@ +import 'package:flutter/material.dart'; +import 'package:objectbox/objectbox.dart'; +import 'package:wosull/application/model/Measurement/MeasurementUnitModel.dart'; +import 'package:wosull/application/model/Modifiers/Modifier.dart'; +import 'package:wosull/application/model/ingredients/AddIngredient.dart'; +import 'package:wosull/application/model/modifierOptions/ModifierId.dart'; +import 'package:wosull/application/model/modifierOptions/ModifierOption.dart'; +import 'package:wosull/application/repository/WosulRepository.dart'; +import 'package:wosull/application/utils/CRUDOperatoinState.dart'; +import 'package:wosull/application/views/inventorymodule/modiferOption/repo/ModifierOptionRepository.dart'; +import 'package:wosull/helpers/Utils.dart'; + +class NewModifierOptionViewModel with ChangeNotifier { + final repository = ModifierOptionRepository(); + + bool _isLoading = false; + + bool get isLoading => _isLoading; + var modifierOption = ModifierOption(); + var selectedMeasurementUnits = []; + var modifiers = []; + bool isEdit = false; + dynamic selectedModifier; + + var _crudOperation = CRUDOperationState.uninitialized; + + CRUDOperationState get crudOperation => _crudOperation; + + void disposeData() { + setState(CRUDOperationState.uninitialized); + setLoading(false); + modifiers.clear(); + selectedMeasurementUnits.clear(); + modifierOption = ModifierOption(); + selectedModifier = null; + } + + void setState(CRUDOperationState state) { + _crudOperation = state; + } + + Future init(bool isEdit, ModifierOption modifierOption) async { + this.modifierOption = modifierOption; + this.isEdit = isEdit; + + if (isEdit) { + selectedModifier = Modifier( + options: ToMany(items: []), + selected: ToMany(items: []), + id: modifierOption.modifier!.id!, + name: modifierOption.modifier!.name!); + for (var ingredient in this.modifierOption.ingredients!) { + selectedMeasurementUnits + .add(MeasurementUnit(id: '', name: ingredient.measuringUnit)); + } + } else { + this.modifierOption.ingredients = []; + } + + final response = await WosulRepository().getModifiers(); + modifiers.addAll(response); + } + + Future> getModifiers() async { + var modifiers = []; + await WosulRepository().getModifiers().then((data) { + if (data.isNotEmpty) { + modifiers.clear(); + modifiers.addAll(data); + } + }).onError((error, stackTrace) {}); + return modifiers; + } + + Future isValidate() async { + if (selectedModifier == null) { + Utils.showMessage('Please select modifier.'); + } else if (modifierOption.name!.isEmpty) { + Utils.showMessage('Please fill name.'); + } else if (modifierOption.price == null) { + Utils.showMessage('Please fill price.'); + } else if (modifierOption.ingredients!.isEmpty) { + Utils.showMessage('Please choose ingredient.'); + } else { + await addUpdateModifierOption(); + } + } + + Future addUpdateModifierOption() async { + setLoading(true); + await repository + .addUpdateModifierOption(modifierOption.toJson()) + .then((response) { + Utils.showMessage(response.message); + if (response.success) { + setState(CRUDOperationState.add); + } else { + setState(CRUDOperationState.error); + } + setLoading(false); + }).onError((error, stackTrace) { + setState(CRUDOperationState.error); + setLoading(false); + }); + } + + void setLoading(bool value) { + _isLoading = value; + notifyListeners(); + } + + void setStatus(bool value) { + modifierOption.status = value; + notifyListeners(); + } + + Future> getMeasurements() async { + var items = []; + await WosulRepository().getMeasurements().then((data) { + if (data.isNotEmpty) { + items.addAll(data); + } + }).onError((error, stackTrace) {}); + return items; + } + + Future> getIngredients() async { + var ingredients = []; + await WosulRepository().getIngredients().then((data) { + if (data.isNotEmpty) { + ingredients.addAll(data); + } + }).onError((error, stackTrace) {}); + return ingredients; + } + + void setMeasurementUnit(int position, MeasurementUnit? data) { + if (data != null) { + selectedMeasurementUnits[position] = data; + modifierOption.ingredients![position].measuringUnit = data.name; + } else { + modifierOption.ingredients![position].measuringUnit = ''; + } + notifyListeners(); + } + + void addIngredient(AddIngredient? options) { + if (options != null) { + selectedMeasurementUnits.add(MeasurementUnit(id: '', name: 'Choose')); + modifierOption.ingredients!.add(options); + } + notifyListeners(); + } + + void updatePrice(String value) { + if (value.isNotEmpty) { + modifierOption.price = double.parse(value); + } else { + modifierOption.price = 0.0; + } + } + + void removeIngredient(int position) { + selectedMeasurementUnits.removeAt(position); + modifierOption.ingredients!.removeAt(position); + notifyListeners(); + } + + void updateQuantity(int position, String value) { + modifierOption.ingredients![position].quantity = value; + } + + void updateName(String value) { + modifierOption.name = value; + } + + void onSelectModifier(Modifier? options) { + if (options != null) { + selectedModifier = options; + modifierOption.modifier = ModifierId(id: options.id); + } + notifyListeners(); + } +} diff --git a/lib/application/views/inventorymodule/modiferOption/views/ModiferOptionVC.dart b/lib/application/views/inventorymodule/modiferOption/views/ModiferOptionVC.dart new file mode 100644 index 0000000..a95f74d --- /dev/null +++ b/lib/application/views/inventorymodule/modiferOption/views/ModiferOptionVC.dart @@ -0,0 +1,225 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:wosull/application/enum/DataState.dart'; +import 'package:wosull/application/model/modifierOptions/ModifierOption.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/AppLoader.dart'; +import 'package:wosull/application/views/inventorymodule/modiferOption/viewModels/ModifierOptionsViewModel.dart'; +import 'package:wosull/application/views/inventorymodule/modiferOption/views/NewModifierOptionVC.dart'; +import 'package:wosull/application/views/inventorymodule/modiferOption/widgets/ModifierOptionsListView.dart'; +import 'package:wosull/application/views/popups/DeleteRecordPopUp.dart'; +import 'package:wosull/base/BaseStatefulState.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/widgets/CustomSimpleButton.dart'; +import 'package:wosull/widgets/PageLimitDropDown.dart'; + +class ModifierOptionVC extends StatefulWidget { + const ModifierOptionVC({super.key}); + + @override + State createState() => _ModifierOptionVCState(); +} + +class _ModifierOptionVCState extends BaseStatefulState { + bool isPortrait = true; + + final viewModel = ModifierOptionsViewModel(); + late ScrollController _controller; + + @override + Widget build(BuildContext context) { + _controller = ScrollController()..addListener(_scrollNotification); + return Scaffold( + backgroundColor: MyColors.fillColor, + resizeToAvoidBottomInset: true, + body: OrientationBuilder(builder: (c, orientation) { + isPortrait = MediaQuery.of(c).orientation == Orientation.portrait; + return SingleChildScrollView( + controller: _controller, + child: Container( + padding: const EdgeInsets.all(12), + child: Column( + children: [ + isPortrait + ? Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + 'Modifier Options', + style: ThemeText.textStylePageHeading, + ), + AppSpaces.horizontalSmall, + Flexible(child: newModifier()), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + PageLimitDropdown(onChange: (value) { + viewModel.fetch( + isRefresh: true, + limit: int.parse(value!)); + }) + ], + ) + ], + ) + : Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + 'Modifier Options', + style: ThemeText.textStylePageHeading, + ), + AppSpaces.horizontalSmall, + SizedBox( + width: 170, + child: newModifier(), + ), + Flexible( + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + PageLimitDropdown(onChange: (value) { + viewModel.fetch( + isRefresh: true, + limit: int.parse(value!)); + }) + ], + )) + ], + ), + AppSpaces.verticalMedium, + ChangeNotifierProvider( + create: (context) => viewModel, + child: Consumer( + builder: (BuildContext context, + ModifierOptionsViewModel controller, Widget? _) { + switch (controller.dataState) { + case DataState.uninitialized: + Future(() { + controller.fetch(); + }); + return showData(controller.filteredList); + case DataState.initialFetching: + return AppLoader(); + case DataState.moreFetching: + case DataState.refreshing: + return showData(controller.filteredList); + case DataState.error: + return const Center( + child: Text("Error"), + ); + case DataState.searching: + case DataState.fetched: + case DataState.noMoreData: + return showData(controller.filteredList); + } + }, + ), + ), + ], + ), + ), + ); + })); + } + + Widget showData(List data) { + return Column( + children: [ + ModifierOptionsListView( + data: data, + isPortrait: isPortrait, + onUpdate: (options, value) { + _update(options.id!, value); + }, + onDelete: (option) { + showDeletePopUp(option); + }, + onView: (option) { + addEditModifierOption(true, option, true); + }, + onEdit: (option) { + addEditModifierOption(true, option, false); + }), + if (viewModel.dataState == DataState.moreFetching) AppLoader(), + ], + ); + } + + bool _scrollNotification() { + if (!viewModel.isLoading && _controller.position.extentAfter < 300) { + viewModel.fetch(limit: viewModel.limit); + } + return true; + } + + Future _update(String id, bool status) async { + progressDialogue(context); + await viewModel.update(id, status); + hideProgressBar(); + } + + Future showDeletePopUp(ModifierOption modifier) async { + final result = await showDialog( + barrierColor: Colors.black26, + context: context, + builder: (context) { + return const DeleteRecordPopUp(); + }, + ); + + if (!mounted) return; + bool isDelete = result; + if (isDelete) { + _delete(modifier.id!); + } + } + + Future _delete(String id) async { + progressDialogue(context); + await viewModel.delete(id); + hideProgressBar(); + } + + Widget newModifier() { + return CustomSimpleButton( + heading: '+ New Modifiers Options', + textColor: MyColors.blueThemeColor, + backGroundColor: MyColors.backColorBlue50, + height: 38, + onPressed: () { + addEditModifierOption(false, ModifierOption()); + }, + ); + } + + Future addEditModifierOption( + bool isEdit, + ModifierOption option, [ + bool? isView, + ]) async { + final result = await showDialog( + barrierColor: Colors.black26, + context: context, + builder: (context) { + return NewModifierOptionVC( + isView: isView ?? false, + isEdit: isEdit, + modifierOption: option, + ); + }, + ); + + if (!mounted) return; + if (result != null) { + viewModel.fetch(isRefresh: true, limit: viewModel.limit); + } + } +} diff --git a/lib/application/views/inventorymodule/modiferOption/views/NewModifierOptionVC.dart b/lib/application/views/inventorymodule/modiferOption/views/NewModifierOptionVC.dart new file mode 100644 index 0000000..8ee0cac --- /dev/null +++ b/lib/application/views/inventorymodule/modiferOption/views/NewModifierOptionVC.dart @@ -0,0 +1,434 @@ +import 'package:dropdown_search/dropdown_search.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:provider/provider.dart'; +import 'package:wosull/application/model/Measurement/MeasurementUnitModel.dart'; +import 'package:wosull/application/model/Modifiers/Modifier.dart'; +import 'package:wosull/application/model/ingredients/AddIngredient.dart'; +import 'package:wosull/application/model/modifierOptions/ModifierOption.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/AppLoader.dart'; +import 'package:wosull/application/utils/CRUDOperatoinState.dart'; +import 'package:wosull/application/views/inventorymodule/modiferOption/viewModels/NewModifierOptionViewModel.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeDropDown.dart'; +import 'package:wosull/widgets/BorderContainer.dart'; +import 'package:wosull/widgets/ChildContainer.dart'; +import 'package:wosull/widgets/CustomRemoveItemButton.dart'; +import 'package:wosull/widgets/CustomSimpleButton.dart'; +import 'package:wosull/widgets/CustomSwitch.dart'; +import 'package:wosull/widgets/CustomTextFieldForm.dart'; +import 'package:wosull/widgets/DialogHeader.dart'; +import 'package:wosull/widgets/DropdownItemBuilder.dart'; +import 'package:wosull/widgets/HeadingContainer.dart'; +import 'package:wosull/widgets/HeadingText.dart'; +import 'package:wosull/widgets/MandatoryTitleText.dart'; +import 'package:wosull/widgets/PortraitContainer.dart'; +import 'package:wosull/widgets/ValueText.dart'; +import 'package:wosull/widgets/WrapHeightContainer.dart'; + +class NewModifierOptionVC extends StatefulWidget { + bool isEdit = false; + bool isView; + late ModifierOption modifierOption; + + NewModifierOptionVC( + {super.key, + required this.isEdit, + required this.modifierOption, + this.isView = false}); + + @override + State createState() => _NewModifierOptionVCState(); +} + +class _NewModifierOptionVCState extends State { + bool isPortrait = true; + + var viewModel = NewModifierOptionViewModel(); + + @override + void initState() { + context + .read() + .init(widget.isEdit, widget.modifierOption); + super.initState(); + } + + @override + void dispose() { + viewModel.disposeData(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + viewModel = context.watch(); + return Directionality( + textDirection: TextDirection.ltr, + child: Dialog( + elevation: 0, + backgroundColor: const Color(0xffffffff), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: OrientationBuilder(builder: (c, orientation) { + isPortrait = + MediaQuery.of(context).orientation == Orientation.portrait; + return SingleChildScrollView( + child: Container( + width: !isPortrait + ? MediaQuery.of(context).size.width / 1.2 + : double.infinity, + padding: const EdgeInsets.only(bottom: 8), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + DialogHeader( + title: viewModel.isEdit + ? 'Edit Modifier Options' + : 'New Modifier Options'), + Padding( + padding: const EdgeInsets.all(12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + MandatoryTitleText( + hint: AppLocalizations.of(context)!.modifier), + AppSpaces.verticalSmall, + getModifierWidget(), + AppSpaces.verticalMedium, + const MandatoryTitleText(hint: 'Label'), + AppSpaces.verticalSmall, + CustomTextFieldForm( + readOnly: widget.isView, + initialValue: viewModel.modifierOption.name ?? '', + onChanged: (value) { + viewModel.updateName(value); + }, + hintText: 'Enter Name'), + AppSpaces.verticalMedium, + MandatoryTitleText( + hint: AppLocalizations.of(context)!.price), + AppSpaces.verticalSmall, + CustomTextFieldForm( + readOnly: widget.isView, + keyboardType: TextInputType.number, + initialValue: viewModel.modifierOption.price + ?.toStringAsFixed(2) ?? + '', + onChanged: (value) { + viewModel.updatePrice(value); + }, + hintText: AppLocalizations.of(context)!.price), + AppSpaces.verticalLarge, + Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + MandatoryTitleText( + hint: AppLocalizations.of(context)!.status), + AppSpaces.horizontalSmall, + CustomSwitch( + value: viewModel.modifierOption.status ?? false, + onToggle: (value) { + if (!widget.isView) { + viewModel.setStatus(value); + } + }, + ), + ], + ), + AppSpaces.verticalLarge, + const MandatoryTitleText(hint: 'Select Ingredient'), + AppSpaces.verticalSmall, + getIngredientWidget(), + AppSpaces.verticalLarge, + getIngredientsTitlesWidget(), + AppSpaces.verticalSmall, + ingredientsListWidget() + ], + ), + ), + Visibility( + visible: !widget.isView, + child: Padding( + padding: const EdgeInsets.only(right: 16), + child: SizedBox( + width: 120, + child: CustomSimpleButton( + textColor: MyColors.white, + isLoading: viewModel.isLoading, + backGroundColor: MyColors.blueThemeColor, + heading: AppLocalizations.of(context)!.save, + onPressed: () async { + await viewModel.isValidate(); + checkState(); + }, + ), + ), + )), + ], + ), + ), + ); + }), + )); + } + + Widget getModifierWidget() { + return DropdownSearch( + enabled: !widget.isView, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 300), + ), + clearButtonProps: ThemeDropDown.clearButton, + selectedItem: viewModel.selectedModifier, + items: viewModel.modifiers, + itemAsString: (Modifier u) => u.name, + onChanged: (options) { + viewModel.onSelectModifier(options); + }, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose Modifier'), + ); + } + + Widget getIngredientWidget() { + return FutureBuilder( + future: viewModel.getIngredients(), + builder: (c, s) { + if (s.hasData) { + var itemsList = s.data ?? []; + return DropdownSearch( + enabled: !widget.isView, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 300), + ), + clearButtonProps: ThemeDropDown.clearButton, + //selectedItem: selectedCategoryDropDown, + items: itemsList, + itemAsString: (AddIngredient u) => u.name, + onChanged: (options) { + viewModel.addIngredient(options); + }, + dropdownDecoratorProps: + MyColors.dropDownStyle(hint: 'Choose Ingredient'), + ); + } else { + return AppLoader(); + } + }); + } + + getIngredientsTitlesWidget() { + return isPortrait + ? Container() + : BorderContainer( + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + child: HeadingContainer( + heading: + AppLocalizations.of(context)!.name_description)), + Expanded( + child: HeadingContainer( + heading: AppLocalizations.of(context)!.quantity)), + Expanded( + child: HeadingContainer( + heading: 'Measuring Unit', + )), + HeadingContainer( + width: 48, + height: 48, + heading: '', + ) + ], + ), + ); + } + + ingredientsListWidget() { + return ListView.builder( + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (c, position) { + if (isPortrait) { + return WrapHeightContainer( + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Column( + children: [ + Row( + children: [ + Expanded( + child: PortraitContainer( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + AppLocalizations.of(context)!.name_description), + ), + )), + Expanded( + child: PortraitContainer( + child: getIngredientNameWidget(position), + ), + ) + ], + ), + Row( + children: [ + Expanded( + child: PortraitContainer( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + AppLocalizations.of(context)!.quantity)), + )), + Expanded( + child: PortraitContainer( + child: getIngredientQuantity(position), + ), + ) + ], + ), + Row( + children: [ + Expanded( + child: PortraitContainer( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + 'Measuring Unit', + ), + ), + )), + Expanded( + child: PortraitContainer( + child: Center( + child: getMeasurementUnit(position), + ), + )) + ], + ), + ], + )), + getRemoveButton(position) + ], + ), + ); + } else { + return WrapHeightContainer( + child: Row( + children: [ + Expanded( + child: ChildContainer( + child: getIngredientNameWidget(position), + ), + ), + Expanded( + child: ChildContainer( + child: getIngredientQuantity(position), + ), + ), + Expanded( + child: ChildContainer( + child: getMeasurementUnit(position), + )), + getRemoveButton(position) + ], + ), + ); + } + }, + itemCount: viewModel.modifierOption.ingredients!.length ?? 0, + ); + } + + Widget getMeasurementUnit(int position) { + return FutureBuilder( + future: viewModel.getMeasurements(), + builder: (c, s) { + if (s.hasData) { + var itemsList = s.data!; + return DropdownSearch( + enabled: !widget.isView, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + selectedItem: viewModel.selectedMeasurementUnits[position], + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 300), + ), + clearButtonProps: ThemeDropDown.clearButton, + items: itemsList, + itemAsString: (MeasurementUnit u) => u.name, + onChanged: (MeasurementUnit? data) { + viewModel.setMeasurementUnit(position, data); + }, + dropdownDecoratorProps: + MyColors.dropDownStyleAddProduct(hint: 'Choose Unit')); + } else { + return AppLoader(); + } + }); + } + + getRemoveButton(int position) { + return CustomRemoveItemButton(onPressed: () { + viewModel.removeIngredient(position); + }); + } + + getIngredientNameWidget(int position) { + return Align( + alignment: Alignment.centerLeft, + child: ValueText( + viewModel.modifierOption.ingredients![position].name, + ), + ); + } + + getIngredientQuantity(int position) { + return Center( + child: CustomTextFieldForm( + readOnly: widget.isView, + initialValue: viewModel.modifierOption.ingredients![position].quantity, + keyboardType: TextInputType.number, + onChanged: (value) { + viewModel.updateQuantity(position, value); + }, + hintText: '0.0', + ), + ); + } + + void checkState() { + if (viewModel.crudOperation == CRUDOperationState.add) { + Navigator.pop(context, true); + } + } +} diff --git a/lib/application/views/inventorymodule/modiferOption/widgets/ModifierOptionsListView.dart b/lib/application/views/inventorymodule/modiferOption/widgets/ModifierOptionsListView.dart new file mode 100644 index 0000000..9537526 --- /dev/null +++ b/lib/application/views/inventorymodule/modiferOption/widgets/ModifierOptionsListView.dart @@ -0,0 +1,231 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/application/model/modifierOptions/ModifierOption.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/Utils.dart'; +import 'package:wosull/widgets/ActionPopUpContainer.dart'; +import 'package:wosull/widgets/CustomPopuoMenuButton.dart'; +import 'package:wosull/widgets/CustomSwitch.dart'; +import 'package:wosull/widgets/EmptyDataWidget.dart'; +import 'package:wosull/widgets/HeadingText.dart'; +import 'package:wosull/widgets/ListHeadingContainer.dart'; +import 'package:wosull/widgets/ValueText.dart'; + +class ModifierOptionsListView extends StatelessWidget { + List data; + bool isPortrait = false; + final void Function(ModifierOption item, bool status) onUpdate; + final void Function(ModifierOption item) onDelete; + final void Function(ModifierOption item) onView; + final void Function(ModifierOption item) onEdit; + + ModifierOptionsListView( + {super.key, + required this.data, + required this.isPortrait, + required this.onUpdate, + required this.onDelete, + required this.onView, + required this.onEdit}); + + @override + Widget build(BuildContext context) { + return data.isEmpty + ? const EmptyDataWidget() + : Column( + children: [ + isPortrait + ? Container() + : ListHeadingContainer( + child: Row( + children: [ + Expanded( + child: HeadingText( + lang(context).modifier, + )), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText(lang(context).status), + )), + Expanded( + child: HeadingText(lang(context).created_on)), + Expanded( + child: HeadingText(lang(context).updated_on)), + Expanded( + child: Padding( + padding: const EdgeInsets.only(right: 16), + child: Align( + alignment: Alignment.centerRight, + child: HeadingText(lang(context).action), + ), + )), + ], + ), + ), + ListView.builder( + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (c, position) { + final modifier = data[position]; + if (isPortrait) { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + elevation: 2, + color: MyColors.white, + child: Container( + padding: const EdgeInsets.fromLTRB(8, 0, 0, 8), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + child: Container( + padding: const EdgeInsets.only(top: 16), + child: Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + HeadingText( + lang(context).modifier, + ), + AppSpaces.verticalMedium, + HeadingText(lang(context).status), + AppSpaces.verticalMedium, + HeadingText(lang(context).created_on), + AppSpaces.verticalMedium, + HeadingText(lang(context).updated_on), + ], + )), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + ValueText(modifier.name!), + AppSpaces.verticalMedium, + Row( + mainAxisAlignment: + MainAxisAlignment.end, + crossAxisAlignment: + CrossAxisAlignment.end, + children: [ + CustomSwitch( + value: modifier.status!, + onToggle: (value) { + onUpdate(modifier, value); + }, + ) + ], + ), + AppSpaces.verticalMedium, + ValueText(DataTimeFormat.getFormatDate( + modifier.createdAt!)), + AppSpaces.verticalMedium, + ValueText(DataTimeFormat.getFormatDate( + modifier.updatedAt!)), + ], + )), + ], + ), + )), + getPopupMenuButton(context, position) + ], + ), + ), + ); + } else { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: ListHeadingContainer( + child: Row( + children: [ + Expanded(child: ValueText(modifier.name!)), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: CustomSwitch( + value: modifier.status!, + onToggle: (value) { + onUpdate(modifier, value); + }, + ), + )), + Expanded( + child: ValueText(DataTimeFormat.getFormatDate( + modifier.createdAt!))), + Expanded( + child: ValueText(DataTimeFormat.getFormatDate( + modifier.updatedAt!))), + Expanded( + child: Padding( + padding: const EdgeInsets.all(4), + child: Align( + alignment: Alignment.centerRight, + child: ActionPopUpContainer( + child: getPopupMenuButton(context, position), + ), + ), + )) + ], + ), + ), + ); + } + }, + itemCount: data.length, + ) + ], + ); + } + + Future actionPopUpItemSelected( + String value, ModifierOption item) async { + if (value == 'edit') { + onEdit(item); + } else if (value == 'delete') { + onDelete(item); + } else { + onView(item); + } + } + + getPopupMenuButton(BuildContext context, int position) { + return CustomPopupMenuButton( + onSelected: (String value) => + actionPopUpItemSelected(value, data[position]), + items: [ + PopupMenuItem( + value: 'edit', + child: ValueText( + lang(context).edit, + ), + ), + PopupMenuItem( + value: 'view', + child: ValueText( + lang(context).view, + ), + ), + PopupMenuItem( + value: 'delete', + child: ValueText( + lang(context).delete, + ), + ) + ], + ); + } +} diff --git a/lib/application/views/inventorymodule/modifierviews/InventoryModifierVC.dart b/lib/application/views/inventorymodule/modifierviews/InventoryModifierVC.dart index a3edd4f..6fda598 100644 --- a/lib/application/views/inventorymodule/modifierviews/InventoryModifierVC.dart +++ b/lib/application/views/inventorymodule/modifierviews/InventoryModifierVC.dart @@ -3,7 +3,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:objectbox/objectbox.dart'; import 'package:provider/provider.dart'; import 'package:wosull/application/enum/DataState.dart'; -import 'package:wosull/application/model/Modifiers/GetModifiersModel.dart'; +import 'package:wosull/application/model/Modifiers/Modifier.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/utils/AppLoader.dart'; import 'package:wosull/application/views/inventorymodule/modifierviews/InventoryNewModifierVC.dart'; @@ -15,6 +15,7 @@ import 'package:wosull/base/BaseStatefulState.dart'; import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/ThemeText.dart'; import 'package:wosull/widgets/CustomSimpleButton.dart'; +import 'package:wosull/widgets/PageLimitDropDown.dart'; class InventoryModifierVC extends StatefulWidget { const InventoryModifierVC({Key? key}) : super(key: key); @@ -29,16 +30,6 @@ class _InventoryModifierVCState extends BaseStatefulState { final viewModel = ModifierViewModel(); late ScrollController _controller; - @override - void initState() { - super.initState(); - } - - @override - void dispose() { - super.dispose(); - } - @override Widget build(BuildContext context) { _controller = ScrollController()..addListener(_scrollNotification); @@ -61,7 +52,23 @@ class _InventoryModifierVCState extends BaseStatefulState { style: ThemeText.textStylePageHeading, ), AppSpaces.horizontalSmall, - newModifier(), + isPortrait + ? Flexible(child: newModifier()) + : SizedBox( + width: 110, + child: newModifier(), + ), + AppSpaces.horizontalSmall, + Flexible( + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + PageLimitDropdown(onChange: (value) { + viewModel.fetch( + isRefresh: true, limit: int.parse(value!)); + }) + ], + )) ], ), AppSpaces.verticalMedium, @@ -125,7 +132,7 @@ class _InventoryModifierVCState extends BaseStatefulState { bool _scrollNotification() { if (!viewModel.isLoading && _controller.position.extentAfter < 300) { - viewModel.fetch(); + viewModel.fetch(limit: viewModel.limit); } return true; } @@ -175,17 +182,14 @@ class _InventoryModifierVCState extends BaseStatefulState { } Widget newModifier() { - return SizedBox( - width: 130, - child: CustomSimpleButton( - heading: AppLocalizations.of(context)!.new_modifiers, - textColor: MyColors.blueThemeColor, - backGroundColor: MyColors.backColorBlue50, - height: 38, - onPressed: () { - addModifier(); - }, - ), + return CustomSimpleButton( + heading: AppLocalizations.of(context)!.new_modifiers, + textColor: MyColors.blueThemeColor, + backGroundColor: MyColors.backColorBlue50, + height: 38, + onPressed: () { + addModifier(); + }, ); } diff --git a/lib/application/views/inventorymodule/modifierviews/InventoryNewModifierVC.dart b/lib/application/views/inventorymodule/modifierviews/InventoryNewModifierVC.dart index 4b1f26c..0b7073a 100644 --- a/lib/application/views/inventorymodule/modifierviews/InventoryNewModifierVC.dart +++ b/lib/application/views/inventorymodule/modifierviews/InventoryNewModifierVC.dart @@ -1,9 +1,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:provider/provider.dart'; -import 'package:wosull/application/model/Modifiers/GetModifiersModel.dart'; +import 'package:wosull/application/model/Modifiers/Modifier.dart'; import 'package:wosull/application/theme/MyColors.dart'; -import 'package:wosull/application/theme/MyFonts.dart'; import 'package:wosull/application/utils/CRUDOperatoinState.dart'; import 'package:wosull/application/views/inventorymodule/modifierviews/viewModels/NewModifierVM.dart'; import 'package:wosull/base/BaseStatefulState.dart'; @@ -36,6 +35,7 @@ class _InventoryNewModifierVCState @override void initState() { + context.read().initModifier(widget.isEdit, widget.modifier); super.initState(); } @@ -48,14 +48,13 @@ class _InventoryNewModifierVCState @override Widget build(BuildContext context) { viewModel = context.watch(); - viewModel.initModifier(widget.isEdit, widget.modifier); return Directionality( textDirection: TextDirection.ltr, child: Dialog( elevation: 0, backgroundColor: const Color(0xffffffff), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(15.0), + borderRadius: BorderRadius.circular(8.0), ), child: OrientationBuilder(builder: (c, orientation) { isPortrait = @@ -82,7 +81,7 @@ class _InventoryNewModifierVCState hint: AppLocalizations.of(context)!.name), AppSpaces.verticalSmall, CustomTextFieldForm( - initialValue: viewModel.modifier.name ?? '', + initialValue: viewModel.modifier.name, onChanged: (value) { viewModel.modifier.name = value; }, @@ -132,309 +131,6 @@ class _InventoryNewModifierVCState ], ), AppSpaces.verticalLarge, - MandatoryTitleText( - hint: AppLocalizations.of(context)! - .add_modifier_options), - AppSpaces.verticalMedium, - Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all( - width: 1, color: MyColors.fillColorGray2), - color: MyColors.fillColor2, - ), - height: 48, - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Expanded( - child: Container( - padding: - const EdgeInsets.only(left: 4, right: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .modifier_option, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 11, - fontWeight: FontWeight.w500, - color: MyColors.black), - ), - ), - )), - Expanded( - child: Container( - padding: - const EdgeInsets.only(left: 4, right: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .modifier_option_ar, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 11, - fontWeight: FontWeight.w500, - color: MyColors.black), - ), - ), - )), - Expanded( - child: Container( - padding: - const EdgeInsets.only(left: 4, right: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Align( - alignment: Alignment.centerLeft, - child: Row( - children: [ - Text( - AppLocalizations.of(context)!.price, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 11, - fontWeight: FontWeight.w500, - color: MyColors.black), - ), - const Text( - '*', - style: TextStyle( - fontSize: 11, - fontFamily: MyFonts.Medium, - color: MyColors.fillRed), - ) - ], - ), - ), - )), - Container( - width: 48, - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: const Center( - child: Text( - '', - style: TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.bold, - fontSize: MyFonts.normal, - color: MyColors.textColorBlack20), - ), - ), - ) - ], - ), - ), - ListView.builder( - padding: EdgeInsets.zero, - scrollDirection: Axis.vertical, - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - itemBuilder: (context, position) { - return Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all( - width: 1, color: MyColors.fillColorGray2), - color: MyColors.white, - ), - height: 48, - child: Row( - children: [ - Expanded( - child: Container( - padding: const EdgeInsets.all(4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: CustomTextFieldForm( - hintText: - AppLocalizations.of(context)! - .name, - initialValue: viewModel - .modifier.options![position].name, - onChanged: (value) { - viewModel.onChangeModifierOption( - value, position); - }, - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.all(4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: CustomTextFieldForm( - hintText: - AppLocalizations.of(context)! - .arabic_name, - onChanged: (value) { - viewModel - .onChangeModifierOptionArabic( - value, position); - }, - initialValue: viewModel.modifier - .options![position].arabicName, - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.all(4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: CustomTextFieldForm( - onChanged: (value) { - viewModel - .onChangeModifierOptionPrice( - value, position); - }, - initialValue: viewModel - .modifier.options![position].price - .toString(), - hintText: - AppLocalizations.of(context)! - .price, - ), - ), - )), - SizedBox( - width: 48, - height: 48, - child: Center( - child: Container( - width: 32, - height: 32, - decoration: const BoxDecoration( - borderRadius: BorderRadius.all( - Radius.circular(4)), - color: MyColors.fillColor2), - child: IconButton( - icon: const Icon( - size: 18, - Icons.close, - color: - MyColors.textColorBlack, - ), - onPressed: () { - viewModel - .removeModifierOption( - position); - }), - ), - )), - ], - ), - ); - }, - itemCount: viewModel.modifier.options.length ?? 1, - ), - Container( - padding: const EdgeInsets.all(8), - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all( - width: 1, color: MyColors.fillColorGray2), - color: Colors.white, - ), - height: 48, - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - SizedBox( - width: 120, - child: ElevatedButton( - style: ElevatedButton.styleFrom( - elevation: 0, - shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.circular(8.0), - ), - backgroundColor: MyColors.fillColor2, - minimumSize: - const Size.fromHeight(38), // NEW - ), - onPressed: () { - viewModel.addNewModifierOption(); - }, - child: Text( - AppLocalizations.of(context)! - .add_option, - style: const TextStyle( - fontSize: MyFonts.normal, - fontWeight: FontWeight.w500, - color: MyColors.textColorBlack, - fontFamily: MyFonts.Bold), - ), - )) - ], - ), - ), ], ), ), diff --git a/lib/application/views/inventorymodule/modifierviews/ViewInventoryModifiersVC.dart b/lib/application/views/inventorymodule/modifierviews/ViewInventoryModifiersVC.dart index 343b77c..66bed18 100644 --- a/lib/application/views/inventorymodule/modifierviews/ViewInventoryModifiersVC.dart +++ b/lib/application/views/inventorymodule/modifierviews/ViewInventoryModifiersVC.dart @@ -1,11 +1,12 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:wosull/application/model/Modifiers/GetModifiersModel.dart'; +import 'package:wosull/application/model/Modifiers/Modifier.dart'; import 'package:wosull/application/model/converters/DataTimeFormat.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/theme/MyFonts.dart'; import 'package:wosull/application/theme/MySeparator.dart'; import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/widgets/DialogHeader.dart'; import 'package:wosull/widgets/HeadingText.dart'; import 'package:wosull/widgets/ValueText.dart'; @@ -21,7 +22,7 @@ class ViewInventoryModifiersVC extends StatelessWidget { elevation: 0, backgroundColor: const Color(0xffffffff), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(15.0), + borderRadius: BorderRadius.circular(8.0), ), child: OrientationBuilder(builder: (c, orientation) { return SingleChildScrollView( @@ -35,32 +36,7 @@ class ViewInventoryModifiersVC extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end, children: [ - Row( - mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.max, - children: [ - Expanded( - child: Padding( - padding: const EdgeInsets.only(left: 16), - child: Text( - 'Basic Information', - style: MyColors.textStylePopUpHeading(), - ), - )), - Align( - alignment: Alignment.topRight, - child: IconButton( - onPressed: () { - Navigator.of(context).pop(); - }, - icon: const Icon(Icons.close)), - ), - ], - ), - Container( - height: 2, - color: MyColors.fillColorGray, - ), + DialogHeader(title: 'Basic Information'), AppSpaces.verticalLarge, Row( crossAxisAlignment: CrossAxisAlignment.center, @@ -69,9 +45,7 @@ class ViewInventoryModifiersVC extends StatelessWidget { HeadingText( 'Status', ), - const SizedBox( - width: 6, - ), + AppSpaces.horizontalSmall, Container( height: 32, padding: const EdgeInsets.all(10.0), @@ -84,7 +58,7 @@ class ViewInventoryModifiersVC extends StatelessWidget { BorderRadius.all(Radius.circular(6.0))), child: Text( modifier.status, - style: const TextStyle( + style: TextStyle( fontFamily: MyFonts.Bold, fontWeight: FontWeight.w500, fontSize: MyFonts.normal, diff --git a/lib/application/views/inventorymodule/modifierviews/repo/ModifierRepository.dart b/lib/application/views/inventorymodule/modifierviews/repo/ModifierRepository.dart new file mode 100644 index 0000000..2cdc5e5 --- /dev/null +++ b/lib/application/views/inventorymodule/modifierviews/repo/ModifierRepository.dart @@ -0,0 +1,55 @@ +import 'package:wosull/application/model/Modifiers/GetModifiersModel.dart'; +import 'package:wosull/application/model/Modifiers/Modifier.dart'; +import 'package:wosull/application/model/SimpleResponsModel.dart'; +import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/utils/Constants.dart'; + +class ModifierRepository { + Future> fetch(Map data) async { + var modifiers = []; + await APIManager().fetchData(Constants.GET_MODIFIERS, data).then((result) { + final value = GetModifiersModel.fromJson(result); + if (value.success!) { + modifiers.addAll(value.modifiers ?? []); + } + }).onError((error, stackTrace) {}); + return modifiers; + } + + Future addUpdateModifier( + Map data) async { + return await APIManager().fetchData(Constants.ADD_UPDATE_MODIFIER, data); + } + + Future delete(String id) async { + Map data = {'modifier_id': id}; + return await APIManager().getResponsePatch(Constants.DELETE_MODIFIER, data); + } + + Future update(String id, bool value) async { + String status; + if (value) { + status = "Active"; + } else { + status = "Inactive"; + } + Map data = {'modifierId': id, 'status': status}; + return await APIManager() + .getResponsePatch(Constants.UPDATE_MODIFIER_STATUS, data); + } + + Future> search(Map data) async { + var modifiers = []; + await APIManager() + .fetchData(Constants.SEARCH_MODIFIERS, data) + .then((result) { + final value = GetModifiersModel.fromJson(result); + modifiers.clear(); + if (value.success!) { + modifiers.addAll(value.modifiers!); + } + }).onError((error, stackTrace) {}); + + return modifiers; + } +} diff --git a/lib/application/views/inventorymodule/modifierviews/viewModels/ModiferViewModel.dart b/lib/application/views/inventorymodule/modifierviews/viewModels/ModiferViewModel.dart index fa5259b..3a2baa5 100644 --- a/lib/application/views/inventorymodule/modifierviews/viewModels/ModiferViewModel.dart +++ b/lib/application/views/inventorymodule/modifierviews/viewModels/ModiferViewModel.dart @@ -1,15 +1,14 @@ -import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; import 'package:wosull/application/enum/DataState.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; -import 'package:wosull/application/model/Modifiers/GetModifiersModel.dart'; -import 'package:wosull/application/network/APIManager.dart'; -import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/model/Modifiers/Modifier.dart'; +import 'package:wosull/application/views/inventorymodule/modifierviews/repo/ModifierRepository.dart'; class ModifierViewModel extends ChangeNotifier { bool _isLoading = false; bool get isLoading => _isLoading; - + int limit = 10; int _currentPageNumber = 1; DataState _dataState = DataState.uninitialized; @@ -24,12 +23,15 @@ class ModifierViewModel extends ChangeNotifier { List get filteredList => _filteredList; + final repository = ModifierRepository(); + void setLoading(bool value) { _isLoading = value; notifyListeners(); } - fetch({bool isRefresh = false}) async { + fetch({bool isRefresh = false, int limit = 10}) async { + this.limit = limit; _isLoading = true; if (!isRefresh) { _dataState = (_dataState == DataState.uninitialized) @@ -44,24 +46,22 @@ class ModifierViewModel extends ChangeNotifier { Map data = { 'store_id': sharedPrefs.storeId, 'page': _currentPageNumber, + 'limit': this.limit }; try { if (_didLastLoad) { _dataState = DataState.noMoreData; } else { - await APIManager() - .fetchData(Constants.GET_MODIFIERS, data) - .then((result) { - final value = GetModifiersModel.fromJson(result); + await repository.fetch(data).then((value) { if (_dataState == DataState.refreshing) { _filteredList.clear(); _dataList.clear(); } - if (value.success!) { - _filteredList.addAll(value.modifiers!); - _dataList.addAll(value.modifiers!); - if (value.modifiers!.length < 10) { + if (value.isNotEmpty) { + _filteredList.addAll(value); + _dataList.addAll(value); + if (value.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; @@ -96,13 +96,10 @@ class ModifierViewModel extends ChangeNotifier { _dataState = DataState.searching; notifyListeners(); try { - await APIManager() - .fetchData(Constants.SEARCH_MODIFIERS, data) - .then((result) { - final value = GetModifiersModel.fromJson(result); + await repository.search(data).then((value) { filteredList.clear(); - if (value.success!) { - filteredList.addAll(value.modifiers!); + if (value.isNotEmpty) { + filteredList.addAll(value); } _dataState = DataState.fetched; }).onError((error, stackTrace) { @@ -117,12 +114,9 @@ class ModifierViewModel extends ChangeNotifier { } Future delete(String id) async { - Map data = {'modifier_id': id}; - await APIManager() - .getResponsePatch(Constants.DELETE_MODIFIER, data) - .then((result) { - filteredList.removeWhere((element) => element.id! == id); - dataList.removeWhere((element) => element.id! == id); + await repository.delete(id).then((result) { + filteredList.removeWhere((element) => element.id == id); + dataList.removeWhere((element) => element.id == id); notifyListeners(); }).onError((error, stackTrace) { notifyListeners(); @@ -136,10 +130,7 @@ class ModifierViewModel extends ChangeNotifier { } else { status = "Inactive"; } - Map data = {'modifierId': id, 'status': status}; - await APIManager() - .getResponsePatch(Constants.UPDATE_MODIFIER_STATUS, data) - .then((result) { + await repository.update(id, value).then((result) { _filteredList.singleWhere((element) => element.id == id).status = status; _dataList.singleWhere((element) => element.id == id).status = status; notifyListeners(); diff --git a/lib/application/views/inventorymodule/modifierviews/viewModels/NewModifierVM.dart b/lib/application/views/inventorymodule/modifierviews/viewModels/NewModifierVM.dart index 7c272a0..c01e02c 100644 --- a/lib/application/views/inventorymodule/modifierviews/viewModels/NewModifierVM.dart +++ b/lib/application/views/inventorymodule/modifierviews/viewModels/NewModifierVM.dart @@ -1,12 +1,9 @@ -import 'dart:convert'; - import 'package:flutter/material.dart'; import 'package:objectbox/objectbox.dart'; -import 'package:wosull/application/model/Modifiers/GetModifiersModel.dart'; -import 'package:wosull/application/model/SimpleResponsModel.dart'; -import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/model/Modifiers/Modifier.dart'; +import 'package:wosull/application/model/Modifiers/ModifierOption.dart'; import 'package:wosull/application/utils/CRUDOperatoinState.dart'; -import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/inventorymodule/modifierviews/repo/ModifierRepository.dart'; import 'package:wosull/helpers/Utils.dart'; class NewModifierVM with ChangeNotifier { @@ -14,10 +11,6 @@ class NewModifierVM with ChangeNotifier { bool get isLoading => _isLoading; - // - // List controllersName = []; - // List controllersArabic = []; - // List controllersPrice = []; bool isEdit = false; Modifier modifier = Modifier(options: ToMany(items: []), selected: ToMany(items: [])); @@ -26,6 +19,8 @@ class NewModifierVM with ChangeNotifier { CRUDOperationState get crudOperationState => _crudOperationState; + final repository = ModifierRepository(); + void disposeData() { _isLoading = false; modifier = @@ -37,24 +32,6 @@ class NewModifierVM with ChangeNotifier { if (isEdit) { this.modifier = modifier; this.isEdit = isEdit; - - // for (var item in modifier.options!) { - // controllersName.add(item.name); - // controllersArabic.add(item.arabicName); - // controllersPrice.add(item.price.toString()); - // } - } else { - // modifier.options = []; - if (modifier.options!.isEmpty) { - print('here'); - modifier.options!.add( - ModifierOption(name: '', arabicName: '', price: 0), - ); - } - - // controllersName.add(''); - // controllersArabic.add(''); - // controllersPrice.add(''); } } @@ -69,36 +46,14 @@ class NewModifierVM with ChangeNotifier { Utils.showMessage('Please enter modifier name'); } else if (modifier.arabicName.isEmpty) { Utils.showMessage('Please enter modifier arabic name'); - } else if (modifier.options!.isEmpty) { - Utils.showMessage('Please fill at least one modifier option'); - } else if (modifier.options!.first.name.isEmpty || - modifier.options!.first.price == 0) { - Utils.showMessage('Please fill all required data'); } else { - bool isValidate = false; - for (int i = 0; i < modifier.options!.length; i++) { - if (modifier.options![i].price == 0) { - isValidate = false; - Utils.showMessage('Please fill all required data'); - break; - } else { - isValidate = true; - } - } - if (isValidate) { - await addUpdateModifier(); - } + await addUpdateModifier(); } } Future addUpdateModifier() async { setLoading(true); - Map data = modifier.toJson(); - print(jsonEncode(data)); - await APIManager() - .fetchData(Constants.ADD_UPDATE_MODIFIER, data) - .then((response) { - final value = SimpleResponseModel.fromJson(response); + await repository.addUpdateModifier(modifier.toJson()).then((value) { if (value.success) { _crudOperationState = CRUDOperationState.add; } else { @@ -111,31 +66,25 @@ class NewModifierVM with ChangeNotifier { } void onChangeModifierOption(String value, int position) { - modifier.options![position].name = value; + modifier.options[position].name = value; } void onChangeModifierOptionArabic(String value, int position) { - modifier.options![position].arabicName = value; + modifier.options[position].arabicName = value; } void onChangeModifierOptionPrice(String value, int position) { - modifier.options![position].price = double.parse(value); + modifier.options[position].price = double.parse(value); } void removeModifierOption(int position) { - // controllersName.removeAt(position); - // controllersArabic.removeAt(position); - // controllersPrice.removeAt(position); - modifier.options!.removeAt(position); + modifier.options.removeAt(position); notifyListeners(); } void addNewModifierOption() { - // controllersName.add(''); - // controllersArabic.add(''); - // controllersPrice.add(''); - - modifier.options!.add(ModifierOption(name: '', arabicName: '')); + modifier.options.add(ModifierOption( + name: '', arabicName: '', ingredients: ToMany(items: []))); notifyListeners(); } diff --git a/lib/application/views/inventorymodule/modifierviews/widgets/ModifierListView.dart b/lib/application/views/inventorymodule/modifierviews/widgets/ModifierListView.dart index 29ae03d..c42f5bb 100644 --- a/lib/application/views/inventorymodule/modifierviews/widgets/ModifierListView.dart +++ b/lib/application/views/inventorymodule/modifierviews/widgets/ModifierListView.dart @@ -1,12 +1,15 @@ import 'package:flutter/material.dart'; -import 'package:wosull/application/model/Modifiers/GetModifiersModel.dart'; +import 'package:wosull/application/model/Modifiers/Modifier.dart'; import 'package:wosull/application/model/converters/DataTimeFormat.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/Utils.dart'; +import 'package:wosull/widgets/ActionPopUpContainer.dart'; +import 'package:wosull/widgets/CustomPopuoMenuButton.dart'; import 'package:wosull/widgets/CustomSwitch.dart'; import 'package:wosull/widgets/EmptyDataWidget.dart'; import 'package:wosull/widgets/HeadingText.dart'; +import 'package:wosull/widgets/ListHeadingContainer.dart'; import 'package:wosull/widgets/ValueText.dart'; class ModifierListView extends StatelessWidget { @@ -34,10 +37,7 @@ class ModifierListView extends StatelessWidget { children: [ isPortrait ? Container() - : Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 50, - color: MyColors.containerBackColor, + : ListHeadingContainer( child: Row( children: [ Expanded( @@ -158,33 +158,7 @@ class ModifierListView extends StatelessWidget { ], ), )), - PopupMenuButton( - icon: const Icon(Icons.more_vert), - itemBuilder: (c) { - return [ - PopupMenuItem( - value: 'edit', - child: Text( - lang(context).edit, - ), - ), - PopupMenuItem( - value: 'view', - child: Text( - lang(context).view, - ), - ), - PopupMenuItem( - value: 'delete', - child: Text( - lang(context).delete, - ), - ) - ]; - }, - onSelected: (String value) => - actionPopUpItemSelected(value, modifier), - ) + getPopupMenuButton(context, position) ], ), ), @@ -194,10 +168,7 @@ class ModifierListView extends StatelessWidget { shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.0), ), - child: Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 56, - color: MyColors.containerBackColor, + child: ListHeadingContainer( child: Row( children: [ Expanded(child: ValueText(modifier.name)), @@ -226,39 +197,8 @@ class ModifierListView extends StatelessWidget { padding: const EdgeInsets.all(4), child: Align( alignment: Alignment.centerRight, - child: Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular(4)), - color: MyColors.backFillColor), - child: PopupMenuButton( - icon: const Icon(Icons.more_vert), - itemBuilder: (c) { - return [ - PopupMenuItem( - value: 'edit', - child: ValueText( - lang(context).edit, - ), - ), - PopupMenuItem( - value: 'view', - child: ValueText( - lang(context).view, - ), - ), - PopupMenuItem( - value: 'delete', - child: ValueText( - lang(context).delete, - ), - ) - ]; - }, - onSelected: (String value) => - actionPopUpItemSelected( - value, modifier), - ), + child: ActionPopUpContainer( + child: getPopupMenuButton(context, position), ), ), )) @@ -284,4 +224,31 @@ class ModifierListView extends StatelessWidget { onView(itemCategory); } } + + getPopupMenuButton(BuildContext context, int position) { + return CustomPopupMenuButton( + onSelected: (String value) => + actionPopUpItemSelected(value, data[position]), + items: [ + PopupMenuItem( + value: 'edit', + child: ValueText( + lang(context).edit, + ), + ), + PopupMenuItem( + value: 'view', + child: ValueText( + lang(context).view, + ), + ), + PopupMenuItem( + value: 'delete', + child: ValueText( + lang(context).delete, + ), + ) + ], + ); + } } diff --git a/lib/application/views/inventorymodule/productviews/AddNewInventoryProductVC.dart b/lib/application/views/inventorymodule/productviews/AddNewInventoryProductVC.dart index a99474a..8106292 100644 --- a/lib/application/views/inventorymodule/productviews/AddNewInventoryProductVC.dart +++ b/lib/application/views/inventorymodule/productviews/AddNewInventoryProductVC.dart @@ -3,42 +3,54 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:provider/provider.dart'; import 'package:wosull/application/model/DeliveryPartner/GetDeliveryPartner.dart'; +import 'package:wosull/application/model/Measurement/InventoryMeasurementModel.dart'; +import 'package:wosull/application/model/Measurement/MeasurementUnitModel.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; import 'package:wosull/application/model/discount/StoreDiscountModel.dart'; -import 'package:wosull/application/model/inventory/AddIngredientModel.dart'; -import 'package:wosull/application/model/inventory/InventoryMeasurementModel.dart'; -import 'package:wosull/application/model/inventory/MeasurementUnitModel.dart'; +import 'package:wosull/application/model/ingredients/AddIngredient.dart'; import 'package:wosull/application/model/inventory/category/ItemCategory.dart'; import 'package:wosull/application/model/store/StoreInvoicesModel.dart'; -import 'package:wosull/application/model/store/StoreItemsResponse.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/theme/MyFonts.dart'; import 'package:wosull/application/utils/AppLoader.dart'; +import 'package:wosull/application/utils/CRUDOperatoinState.dart'; +import 'package:wosull/application/views/inventorymodule/categoryviews/InventoryAddCategoryVC.dart'; import 'package:wosull/application/views/inventorymodule/productviews/viewModels/AddProductViewModel.dart'; +import 'package:wosull/application/views/inventorymodule/productviews/widgets/GenerateBarCodeButton.dart'; import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/ThemeDropDown.dart'; import 'package:wosull/helpers/ThemeText.dart'; import 'package:wosull/widgets/AlertDialogForPicture.dart'; +import 'package:wosull/widgets/BorderContainer.dart'; +import 'package:wosull/widgets/ChildContainer.dart'; +import 'package:wosull/widgets/CustomAddButton.dart'; +import 'package:wosull/widgets/CustomAppBar.dart'; import 'package:wosull/widgets/CustomCheckBox.dart'; import 'package:wosull/widgets/CustomOptionalTitle.dart'; +import 'package:wosull/widgets/CustomRemoveItemButton.dart'; import 'package:wosull/widgets/CustomSimpleButton.dart'; import 'package:wosull/widgets/CustomSwitch.dart'; +import 'package:wosull/widgets/CustomTextAddProduct.dart'; +import 'package:wosull/widgets/CustomTextButtonIcon.dart'; import 'package:wosull/widgets/CustomTextFieldForm.dart'; +import 'package:wosull/widgets/DropdownItemBuilder.dart'; +import 'package:wosull/widgets/HeadingContainer.dart'; import 'package:wosull/widgets/HeadingText.dart'; import 'package:wosull/widgets/MandatoryTitleText.dart'; +import 'package:wosull/widgets/PortraitContainer.dart'; import 'package:wosull/widgets/ValueText.dart'; +import 'package:wosull/widgets/WrapHeightContainer.dart'; class AddNewInventoryProductVC extends StatefulWidget { bool isEdit = false; bool isView = false; - late StoreItems storeItems; - String categoryId; + String productId; AddNewInventoryProductVC( {Key? key, required this.isEdit, required this.isView, - required this.storeItems, - required this.categoryId}) + required this.productId}) : super(key: key); @override @@ -59,47 +71,38 @@ class _AddNewInventoryProductVCState extends State @override void initState() { + context + .read() + .setDataOnEdit(widget.isEdit, widget.productId); super.initState(); } @override Widget build(BuildContext context) { viewModel = context.watch(); - if (widget.isEdit || widget.isView) { - viewModel.setDataOnEdit(widget.storeItems); - } - return WillPopScope( - child: MaterialApp( - debugShowCheckedModeBanner: false, - home: Scaffold( - resizeToAvoidBottomInset: true, - appBar: AppBar( - leading: BackButton( - color: Colors.black, - onPressed: () { - Navigator.pop(context); - }, // <-- SEE HERE - ), - centerTitle: true, - title: Text( - widget.isEdit ? "Edit Product" : 'Add Product', - style: ThemeText.mediumHeader, - ), - backgroundColor: MyColors.white, - elevation: 5, - ), - body: OrientationBuilder(builder: (c, orientation) { - isPortrait = - MediaQuery.of(context).orientation == Orientation.portrait; + return Scaffold( + backgroundColor: MyColors.fillColor, + resizeToAvoidBottomInset: true, + appBar: CustomAppBar( + heading: widget.isEdit + ? widget.isView + ? "View Product" + : "Edit Product" + : 'Add Product', + ), + body: OrientationBuilder(builder: (c, orientation) { + isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; - return SingleChildScrollView( - child: Container( - color: MyColors.white, - padding: const EdgeInsets.all(8), - child: Column( + return SingleChildScrollView( + child: Container( + padding: const EdgeInsets.all(8), + child: (widget.isEdit || widget.isView) && viewModel.isLoadingFirst + ? AppLoader() + : Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ Card( + elevation: 5, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.0), ), @@ -109,215 +112,23 @@ class _AddNewInventoryProductVCState extends State ? Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - MandatoryTitleText( - hint: AppLocalizations.of(context)! - .item_name, - ), - const SizedBox( - height: 4, - ), - CustomTextFieldForm( - initialValue: viewModel.nameController, - readOnly: widget.isView, - hintText: 'Enter Item name', - onChanged: (String value) { - viewModel.nameController = value; - }, - ), - const SizedBox( - height: 8, - ), - MandatoryTitleText( - hint: AppLocalizations.of(context)! - .category, - ), - const SizedBox( - height: 8, - ), - getCategoryWidget(context), - const SizedBox( - height: 8, - ), - Row( - children: [ - Expanded( - child: MandatoryTitleText( - hint: AppLocalizations.of(context)! - .quantity, - ), - ), - CustomCheckBox( - heading: 'Unlimited Quantity', - value: viewModel - .storeItem.isUnlimitedQuantity, - onChange: (value) { - viewModel.setIsUnlimitedQuantity( - value); - }) - ], - ), - const SizedBox( - height: 4, - ), - CustomTextFieldForm( - hintText: 'Enter Quantity', - readOnly: widget.isView || - viewModel - .storeItem.isUnlimitedQuantity, - keyboardType: TextInputType.number, - onChanged: (value) { - viewModel.setQuantity(value); - }, - ), - const SizedBox( - height: 8, - ), - MandatoryTitleText( - hint: AppLocalizations.of(context)! - .description, - ), - const SizedBox( - height: 4, - ), - SizedBox( - height: 100, - child: CustomTextFieldForm( - hintText: AppLocalizations.of(context)! - .description, - readOnly: widget.isView, - maxLines: 5, - keyboardType: TextInputType.multiline, - onChanged: (String value) { - viewModel.descriptionController = - value; - }, - ), - ), - const SizedBox( - height: 8, - ), - CustomOptionalTitle( - hint: AppLocalizations.of(context)! - .item_name_ar_optional, - ), - const SizedBox( - height: 4, - ), - CustomTextFieldForm( - readOnly: widget.isView, - onChanged: (value) { - viewModel.productCode = value; - }, - hintText: 'Enter Item Name in Arabic', - ), - const SizedBox( - height: 8, - ), - const MandatoryTitleText( - hint: 'Default Price (Incl. Tax)'), - const SizedBox( - height: 4, - ), - CustomTextFieldForm( - hintText: 'Enter Price (Incl. Tax)', - readOnly: widget.isView, - keyboardType: TextInputType.number, - onChanged: (value) { - viewModel.setPrice(value); - }), - const SizedBox( - height: 8, - ), - CustomOptionalTitle( - hint: AppLocalizations.of(context)! - .description_ar), - const SizedBox( - height: 4, - ), - SizedBox( - height: 100, - child: CustomTextFieldForm( - hintText: 'Enter Description in Arabic', - readOnly: widget.isView, - onChanged: (value) { - viewModel.descriptionArabic = value; - }, - maxLines: 5, - keyboardType: TextInputType.multiline, - ), - ), - const SizedBox( - height: 8, - ), - MandatoryTitleText( - hint: - AppLocalizations.of(context)!.barcode, - ), - const SizedBox( - height: 4, - ), - Row( - children: [ - Expanded( - child: CustomTextFieldForm( - hintText: 'Enter Barcode', - readOnly: widget.isView, - key: Key(viewModel.barCodeController), - initialValue: - viewModel.barCodeController, - onChanged: (value) { - viewModel.barCodeController = value; - }, - )), - SizedBox( - width: 100, - child: CustomSimpleButton( - height: 48, - key: Key( - viewModel.barCodeController), - backGroundColor: - MyColors.backColorBlue50, - textColor: MyColors.blueThemeColor, - onPressed: () { - if (!widget.isView) { - viewModel.generateCode(); - } - }, - heading: 'Generate', - ), - ), - ], - ), - const SizedBox( - height: 8, - ), - MandatoryTitleText( - hint: AppLocalizations.of(context)! - .status), - const SizedBox( - height: 4, - ), - SizedBox( - height: 44, - child: Row( - children: [ - const CustomOptionalTitle( - hint: 'Item In Stock', - ), - const SizedBox( - width: 6, - ), - CustomSwitch( - value: viewModel - .storeItem.isItemInStock, - onToggle: (value) { - viewModel - .setItemInStockStatus(value); - }, - ) - ], - ), - ) + getItemName(), + AppSpaces.verticalMedium, + getCategory(), + AppSpaces.verticalMedium, + getQuantityWidget(), + AppSpaces.verticalMedium, + getDescriptionWidget(), + AppSpaces.verticalMedium, + getArabicNameWidget(), + AppSpaces.verticalMedium, + getDefaultPriceWidget(), + AppSpaces.verticalMedium, + getArabicDescriptionWidget(), + AppSpaces.verticalMedium, + getBarCodeWidget(), + AppSpaces.verticalMedium, + getItemInStockWidget() ], ) : Row( @@ -331,259 +142,52 @@ class _AddNewInventoryProductVCState extends State crossAxisAlignment: CrossAxisAlignment.start, children: [ - MandatoryTitleText( - hint: - AppLocalizations.of(context)! - .item_name), - const SizedBox( - height: 4, - ), - CustomTextFieldForm( - initialValue: - viewModel.nameController, - onChanged: (value) { - viewModel.nameController = value; - }, - readOnly: widget.isView, - hintText: 'Enter Item name', - ), - const SizedBox( - height: 8, - ), - MandatoryTitleText( - hint: - AppLocalizations.of(context)! - .category), - const SizedBox( - height: 4, - ), - getCategoryWidget(context), - const SizedBox( - height: 8, - ), - MandatoryTitleText( - hint: - AppLocalizations.of(context)! - .description), - const SizedBox( - height: 4, - ), - SizedBox( - height: 100, - child: CustomTextFieldForm( - initialValue: viewModel - .descriptionController, - hintText: 'Description', - onChanged: (value) { - viewModel - .descriptionController = - value; - }, - readOnly: widget.isView, - maxLines: 5, - keyboardType: - TextInputType.multiline, - ), - ), + getItemName(), + AppSpaces.verticalMedium, + getCategory(), + AppSpaces.verticalMedium, + getDescriptionWidget() ], ), ), - const SizedBox( - width: 12, - ), + AppSpaces.horizontalMedium, Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - CustomOptionalTitle( - hint: AppLocalizations.of(context)! - .item_name_ar_optional), - const SizedBox( - height: 4, - ), - CustomTextFieldForm( - initialValue: viewModel.productCode, - hintText: - 'Enter Item Name in Arabic', - readOnly: widget.isView, - onChanged: (value) { - viewModel.productCode = value; - }), - const SizedBox( - height: 8, - ), - const MandatoryTitleText( - hint: 'Default Price (Incl. Tax)'), - const SizedBox( - height: 4, - ), - CustomTextFieldForm( - initialValue: - viewModel.salePriceIncludeTax, - hintText: 'Enter Price (Incl. Tax)', - readOnly: widget.isView, - keyboardType: TextInputType.number, - onChanged: (value) { - viewModel.setPrice(value); - }), - const SizedBox( - height: 8, - ), - CustomOptionalTitle( - hint: AppLocalizations.of(context)! - .description_ar), - const SizedBox( - height: 4, - ), - SizedBox( - height: 100, - child: CustomTextFieldForm( - initialValue: - viewModel.descriptionArabic, - hintText: - 'Enter Description in Arabic', - readOnly: widget.isView, - onChanged: (value) { - viewModel.descriptionArabic = - value; - }, - maxLines: 5, - keyboardType: - TextInputType.multiline, - ), - ), + getArabicNameWidget(), + AppSpaces.verticalMedium, + getDefaultPriceWidget(), + AppSpaces.verticalMedium, + getArabicDescriptionWidget() ], )), - const SizedBox( - width: 12, - ), + AppSpaces.horizontalMedium, Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - MandatoryTitleText( - hint: AppLocalizations.of(context)! - .barcode), - const SizedBox( - height: 4, - ), - Row( - children: [ - Expanded( - child: CustomTextFieldForm( - hintText: 'Enter Barcode', - readOnly: widget.isView, - key: Key( - viewModel.barCodeController), - initialValue: - viewModel.barCodeController, - onChanged: (String value) { - viewModel.barCodeController = - value; - }, - )), - SizedBox( - width: 100, - child: CustomSimpleButton( - height: 48, - backGroundColor: - MyColors.backColorBlue50, - textColor: - MyColors.blueThemeColor, - onPressed: () { - if (!widget.isView) { - viewModel.generateCode(); - } - }, - heading: 'Generate', - ), - ), - ], - ), - const SizedBox( - height: 8, - ), - Row( - children: [ - Expanded( - child: MandatoryTitleText( - hint: AppLocalizations.of( - context)! - .quantity, - ), - ), - CustomCheckBox( - heading: 'Unlimited Quantity', - value: viewModel.storeItem - .isUnlimitedQuantity, - onChange: (value) { - viewModel - .setIsUnlimitedQuantity( - value); - }) - ], - ), - CustomTextFieldForm( - initialValue: - viewModel.quantityController, - hintText: 'Enter Quantity', - readOnly: widget.isView || - viewModel.storeItem - .isUnlimitedQuantity, - keyboardType: TextInputType.number, - onChanged: (value) { - viewModel.quantityController = - value; - }, - ), - const SizedBox( - height: 8, - ), - MandatoryTitleText( - hint: AppLocalizations.of(context)! - .status), - const SizedBox( - height: 4, - ), - SizedBox( - height: 44, - child: Row( - children: [ - const CustomOptionalTitle( - hint: 'Item In Stock', - ), - const SizedBox( - width: 6, - ), - CustomSwitch( - value: viewModel - .storeItem.isItemInStock, - onToggle: (value) { - viewModel - .setItemInStockStatus( - value); - }, - ) - ], - ), - ) + getBarCodeWidget(), + AppSpaces.verticalMedium, + getQuantityWidget(), + AppSpaces.verticalMedium, + getItemInStockWidget() ], )), ], ), ), ), - const SizedBox( - height: 12, - ), + AppSpaces.verticalLarge, Card( + elevation: 5, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(4.0), ), child: Container( - padding: const EdgeInsets.all(8), + padding: const EdgeInsets.all(15), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, @@ -593,279 +197,59 @@ class _AddNewInventoryProductVCState extends State .price_quantity_tax_additional_information, style: ThemeText.textStyleHeadingCart, ), - const SizedBox( - height: 12, - ), + AppSpaces.verticalLarge, Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - CustomOptionalTitle( - hint: AppLocalizations.of(context)! - .sale_price_excl_tax), - AppSpaces.verticalSmall, - CustomTextFieldForm( - readOnly: true, - initialValue: - viewModel.salePriceExclTax, - key: Key(viewModel.salePriceExclTax), - keyboardType: TextInputType.number, - onChanged: (value) {}, - hintText: - 'Enter Sale Price (Excl. Tax)', - ), - ], - )), - AppSpaces.horizontalMedium, - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - const CustomOptionalTitle( - hint: 'Price (Incl. Tax)', - ), - AppSpaces.verticalSmall, - CustomTextFieldForm( - initialValue: - viewModel.purchasePriceExclTax, - hintText: 'Enter Price (Incl. Tax)', - readOnly: widget.isView, - keyboardType: TextInputType.number, - onChanged: (value) { - viewModel.purchasePriceExclTax = - value; - }, - ), - ], - )), + Expanded(child: getSalePriceExclTax()), AppSpaces.horizontalMedium, - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - CustomOptionalTitle( - hint: AppLocalizations.of(context)! - .stock_alert_quantity, - ), - AppSpaces.verticalSmall, - CustomTextFieldForm( - initialValue: - viewModel.stockAlertQuantity, - hintText: 'Enter Stock Alert Quantity', - readOnly: widget.isView, - keyboardType: TextInputType.number, - onChanged: (value) { - viewModel.stockAlertQuantity = value; - }, - ), - ], - )), + Expanded(child: getPriceIncludeTax()), + isPortrait + ? Container() + : AppSpaces.horizontalMedium, + isPortrait + ? Container() + : Expanded( + child: getStockAlertQuantityWidget()), ], ), - const SizedBox( - height: 12, - ), + isPortrait + ? AppSpaces.verticalMedium + : Container(), + isPortrait + ? getStockAlertQuantityWidget() + : Container(), + AppSpaces.verticalLarge, Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - CustomOptionalTitle( - hint: AppLocalizations.of(context)! - .discount, - ), - AppSpaces.verticalSmall, - getDiscounts(context), - ], - )), + Expanded(child: getDiscountWidget()), AppSpaces.horizontalMedium, - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - CustomOptionalTitle( - hint: AppLocalizations.of(context)! - .supplier, - ), - AppSpaces.verticalSmall, - getSupplierWidget(context), - ], - )), + Expanded(child: getSupplier()), ], ), - const SizedBox( - height: 12, - ), + AppSpaces.verticalLarge, Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - CustomOptionalTitle( - hint: AppLocalizations.of(context)! - .manufacturer_date, - ), - AppSpaces.verticalSmall, - Container( - height: 48, - padding: - const EdgeInsets.only(right: 8), - decoration: BoxDecoration( - border: Border.all( - color: Colors.transparent, - width: 1, - ), - color: MyColors.backFillColor, - borderRadius: - BorderRadius.circular(8.0), - ), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - crossAxisAlignment: - CrossAxisAlignment.stretch, - children: [ - Expanded( - child: TextButton( - onPressed: () { - viewModel.presentDatePicker( - context, true); - }, - child: Align( - alignment: Alignment.centerLeft, - child: Text( - viewModel - .storeItem - .manufactureDate - .isEmpty - ? 'dd/mm/yyyy' - : viewModel.storeItem - .manufactureDate, - textAlign: TextAlign.left, - style: TextStyle( - fontFamily: - MyFonts.DMREGULAR, - fontSize: - MyFonts.normalButton, - color: viewModel - .storeItem - .manufactureDate - .isEmpty - ? Colors.black54 - : MyColors.black), - ), - ), - )), - const Icon( - // <-- Icon - Icons.calendar_month_outlined, - size: 24.0, - color: MyColors.black, - ) - ], - ), - ), - ], - )), + Expanded(child: getManufactureDate()), AppSpaces.horizontalMedium, - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - CustomOptionalTitle( - hint: AppLocalizations.of(context)! - .expiry_date, - ), - AppSpaces.verticalSmall, - Container( - height: 48, - padding: - const EdgeInsets.only(right: 8), - decoration: BoxDecoration( - border: Border.all( - color: Colors.transparent, - width: 1, - ), - color: MyColors.backFillColor, - borderRadius: - BorderRadius.circular(8.0), - ), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - crossAxisAlignment: - CrossAxisAlignment.stretch, - children: [ - Expanded( - child: TextButton( - onPressed: () { - viewModel.presentDatePicker( - context, false); - }, - child: Align( - alignment: Alignment.centerLeft, - child: Text( - viewModel.storeItem.expireDate - .isEmpty - ? 'dd/mm/yyyy' - : viewModel - .storeItem.expireDate, - textAlign: TextAlign.left, - style: TextStyle( - fontFamily: - MyFonts.DMREGULAR, - fontSize: - MyFonts.normalButton, - color: viewModel - .storeItem - .expireDate - .isEmpty - ? Colors.black54 - : MyColors.black), - ), - ), - )), - const Icon( - // <-- Icon - Icons.calendar_month_outlined, - size: 24.0, - color: MyColors.black, - ) - ], - ), - ), - ], - )), + Expanded(child: getExpireDate()), ], ), ], ), ), ), - const SizedBox( - height: 12, - ), + AppSpaces.verticalLarge, Card( + elevation: 5, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(4.0), ), child: Container( width: double.infinity, - padding: const EdgeInsets.all(8), + padding: const EdgeInsets.all(15), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -874,76 +258,25 @@ class _AddNewInventoryProductVCState extends State .delivery_partner_price, style: ThemeText.textStyleHeadingCart, ), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, isPortrait ? Container() - : Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all( - width: 1, - color: MyColors.fillColorGray2), - color: MyColors.containerBackColor, - ), - height: 48, + : BorderContainer( child: Row( children: [ - Container( - padding: - const EdgeInsets.only(left: 8), - height: 48, - width: 250, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: Alignment.centerLeft, - child: HeadingText( + HeadingContainer( + height: 48, + width: 250, + heading: AppLocalizations.of(context)! .name), - ), - ), Expanded( - child: Container( - padding: const EdgeInsets.only( - left: 4, right: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: Alignment.centerLeft, - child: HeadingText( + child: HeadingContainer( + heading: 'Delivery Partner Price(Exclusive of vat & Including vat)', - ), - ), )), - Container( + ChildContainer( width: 44, - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), child: Container(), ) ], @@ -951,127 +284,28 @@ class _AddNewInventoryProductVCState extends State ), getListViewDeliveryPartner(), isPortrait - ? Container( - margin: - const EdgeInsets.fromLTRB(8, 0, 0, 8), - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all( - width: 1, - color: MyColors.fillColorGray2), - color: Colors.white, - ), - height: 48, + ? BorderContainer( + backgroundColor: Colors.transparent, child: Row( children: [ Expanded( - child: Container( + child: HeadingContainer( height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: Text( - '', - style: - MyColors.textStyleValue(), - ), - ), + heading: '', )), - Center( - child: Container( - margin: const EdgeInsets.all(5), - width: 32, - height: 32, - decoration: const BoxDecoration( - borderRadius: - BorderRadius.all( - Radius.circular(4)), - color: - MyColors.fillColorGray2), - child: IconButton( - icon: const Icon( - size: 14, - Icons.add, - color: - MyColors.textColorBlack, - ), - onPressed: () { - viewModel - .addNewDeliveryPartner(); - }), - ), - ), + getAddDeliveryPartnerButton() ], ), ) - : Container( - margin: - const EdgeInsets.fromLTRB(0, 0, 0, 8), - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all( - width: 1, - color: MyColors.fillColorGray2), - color: Colors.white, - ), - height: 48, + : BorderContainer( + backgroundColor: Colors.transparent, child: Row( children: [ Expanded( - child: Container( - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: Text( - '', - style: - MyColors.textStyleValue(), - ), - ), + child: HeadingContainer( + heading: '', )), - Center( - child: Container( - margin: const EdgeInsets.all(5), - width: 34, - height: 32, - decoration: const BoxDecoration( - borderRadius: - BorderRadius.all( - Radius.circular(4)), - color: - MyColors.fillColorGray2), - child: IconButton( - icon: const Icon( - size: 14, - Icons.add, - color: - MyColors.textColorBlack, - ), - onPressed: () { - viewModel - .addNewDeliveryPartner(); - }), - ), - ), + getAddDeliveryPartnerButton() ], ), ), @@ -1079,15 +313,14 @@ class _AddNewInventoryProductVCState extends State ), ), ), - const SizedBox( - height: 12, - ), + AppSpaces.verticalLarge, Card( + elevation: 5, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(4.0), ), child: Container( - padding: const EdgeInsets.all(8), + padding: const EdgeInsets.all(15), child: Column( children: [ Row( @@ -1108,170 +341,38 @@ class _AddNewInventoryProductVCState extends State .search_and_add_products, style: ThemeText.textStyleHeadingCart, ), - const SizedBox( - height: 12, - ), + AppSpaces.verticalLarge, CustomOptionalTitle( hint: AppLocalizations.of(context)! .search, ), - const SizedBox( - height: 4, - ), + AppSpaces.verticalSmall, getIngredientsWidget(context), - const SizedBox( - height: 4, - ), + AppSpaces.verticalSmall, CustomOptionalTitle( hint: AppLocalizations.of(context)! .choose_ingredients), - const SizedBox( - height: 12, - ), + AppSpaces.verticalLarge, ], ), )), isPortrait ? Container() : Expanded( - child: Container( - padding: const EdgeInsets.all(8), - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.start, - children: [ - Row(children: [ - SizedBox( - height: 20, - width: 20, - child: Transform.scale( - scale: 1, - child: Checkbox( - value: false, - side: const BorderSide( - color: MyColors - .fillColorGray2), - onChanged: - (bool? value) {}, - shape: - RoundedRectangleBorder( - // Making around shape - borderRadius: - BorderRadius - .circular( - 4)), - activeColor: - MyColors.primary, - checkColor: Colors.white, - fillColor: - MaterialStateProperty - .all(MyColors - .fillColorGray2), - tristate: true, - ), - ), - ), - Text( - AppLocalizations.of(context)! - .set_product_price_as_ingredient_cost, - style: ThemeText - .textStylePopUpHeading, - textAlign: TextAlign.center, - ) - ]), - const SizedBox( - height: 4, - ), - Text( - AppLocalizations.of(context)! - .option_enable_product_invoice, - style: - ThemeText.textStyleHeading, - ), - ], - ), - )), + child: getProductAsIngredientCost()), ], ), isPortrait - ? Container( - padding: const EdgeInsets.all(8), - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.start, - children: [ - Row(children: [ - SizedBox( - height: 20, - width: 20, - child: Transform.scale( - scale: 1, - child: Checkbox( - value: false, - side: const BorderSide( - color: MyColors - .fillColorGray2), - onChanged: (bool? value) {}, - shape: RoundedRectangleBorder( - // Making around shape - borderRadius: - BorderRadius.circular( - 4)), - activeColor: MyColors.primary, - checkColor: Colors.white, - fillColor: - MaterialStateProperty.all( - MyColors - .fillColorGray2), - tristate: true, - ), - ), - ), - Text( - AppLocalizations.of(context)! - .set_product_price_as_ingredient_cost, - style: - ThemeText.labelStyleTextField, - textAlign: TextAlign.center, - ) - ]), - const SizedBox( - height: 4, - ), - Text( - AppLocalizations.of(context)! - .option_enable_product_invoice, - style: ThemeText.textStyleHeading, - ), - ], - ), - ) + ? getProductAsIngredientCost() : Container(), Visibility( visible: viewModel - .storeItem.ingredients!.isNotEmpty, + .storeItem.ingredients.isNotEmpty, child: Column( children: [ isPortrait ? Container() - : Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius - .all( - Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all( - width: 1, - color: MyColors - .fillColorGray2), - color: MyColors.backFillColor, - ), - height: 48, + : BorderContainer( child: Row( crossAxisAlignment: CrossAxisAlignment.start, @@ -1279,888 +380,84 @@ class _AddNewInventoryProductVCState extends State MainAxisAlignment.start, children: [ Expanded( - child: Container( - padding: - const EdgeInsets.only( - left: 4, right: 4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: - Alignment.centerLeft, - child: HeadingText( + child: HeadingContainer( + heading: AppLocalizations.of( context)! .name_description, - ), - ), - )), - Expanded( - child: Container( - padding: - const EdgeInsets.only( - left: 4, right: 4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: - Alignment.centerLeft, - child: HeadingText( - 'Purchase Price of 1 Unit'), - ), )), Expanded( - child: Container( - padding: - const EdgeInsets.only( - left: 4, right: 4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: - Alignment.centerLeft, - child: HeadingText( - 'Sale Price of 1 Unit'), - ), + child: HeadingContainer( + heading: + 'Purchase Price of 1 Unit', )), Expanded( - child: Container( - padding: - const EdgeInsets.only( - left: 4, right: 4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: - Alignment.centerLeft, - child: HeadingText( - 'Sale Price of 1 Unit'), - ), + child: HeadingContainer( + heading: + 'Sale Price of 1 Unit', )), Expanded( - child: Container( - padding: - const EdgeInsets.only( - left: 4, right: 4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: - Alignment.centerLeft, - child: HeadingText( - 'Measuring Unit'), - ), + child: HeadingContainer( + heading: 'Measuring Unit', )), - Container( + HeadingContainer( width: 48, - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: HeadingText( - '', - ), - ), + heading: '', ) ], ), ), - ListView.builder( - padding: EdgeInsets.zero, - scrollDirection: Axis.vertical, - physics: - const NeverScrollableScrollPhysics(), - shrinkWrap: true, - itemBuilder: (c, position) { - if (isPortrait) { - return Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius - .all( - Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all( - width: 1, - color: MyColors - .fillColorGray2), - color: MyColors.white, - ), - child: Row( - mainAxisAlignment: - MainAxisAlignment.start, - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Expanded( - child: Column( - children: [ - Row( - children: [ - Expanded( - child: Container( - padding: - const EdgeInsets - .only( - left: 4, - right: 4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: Alignment - .centerLeft, - child: HeadingText( - AppLocalizations.of( - context)! - .name_description), - ), - )), - Expanded( - child: Container( - padding: - const EdgeInsets - .all(4), - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: - 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: Alignment - .centerLeft, - child: ValueText(viewModel - .storeItem - .ingredients![ - position] - .name), - ), - ), - ) - ], - ), - Row( - children: [ - Expanded( - child: Container( - padding: - const EdgeInsets - .only( - left: 4, - right: 4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: Alignment - .centerLeft, - child: HeadingText( - 'Purchase Price of 1 Unit'), - ), - )), - Expanded( - child: Container( - padding: - const EdgeInsets - .all(4), - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: - 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: Alignment - .centerLeft, - child: - ValueText( - viewModel - .storeItem - .ingredients![ - position] - .purchasePrice! - .toString(), - ), - ), - ), - ) - ], - ), - Row( - children: [ - Expanded( - child: Container( - padding: - const EdgeInsets - .only( - left: 4, - right: 4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: Alignment - .centerLeft, - child: HeadingText( - 'Sale Price of 1 Unit'), - ), - )), - Expanded( - child: Container( - padding: - const EdgeInsets - .all(4), - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: - 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: Alignment - .centerLeft, - child: ValueText(viewModel - .storeItem - .ingredients![ - position] - .salePrice! - .toString()), - ), - ), - ) - ], - ), - Row( - children: [ - Expanded( - child: Container( - padding: - const EdgeInsets - .only( - left: 4, - right: 4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: Alignment - .centerLeft, - child: HeadingText( - 'Sale Price of 1 Unit'), - ), - )), - Expanded( - child: Container( - padding: - const EdgeInsets - .all(4), - width: 100, - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: - 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: - CustomTextFieldForm( - readOnly: widget - .isView, - onChanged: - (value) { - viewModel.unitsController[ - position] = - value; - if (value - .isNotEmpty) { - viewModel - .storeItem - .ingredients![ - position] - .defaultSalePrice = int.parse(value); - } - }, - hintText: - '0.0', - ), - ), - ), - ) - ], - ), - Row( - children: [ - Expanded( - child: Container( - padding: - const EdgeInsets - .only( - left: 4, - right: 4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: Alignment - .centerLeft, - child: - HeadingText( - 'Measuring Unit', - ), - ), - )), - Expanded( - child: Container( - padding: - const EdgeInsets - .all(4), - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: - getMeasurementUnit( - context, - position), - )) - ], - ), - ], - )), - SizedBox( - width: 48, - height: 48, - child: Center( - child: Container( - width: 32, - height: 32, - decoration: BoxDecoration( - borderRadius: - const BorderRadius - .all( - Radius.circular( - 4)), - color: MyColors - .backFillColor), - child: IconButton( - icon: const Icon( - size: 18, - Icons.close, - color: MyColors - .textColorBlack, - ), - onPressed: () { - viewModel - .removeUnit( - position); - }), - ), - )), - ], - ), - ); - } else { - return Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius - .all( - Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all( - width: 1, - color: MyColors - .fillColorGray2), - color: MyColors.white, - ), - child: Row( - children: [ - Expanded( - child: Container( - padding: - const EdgeInsets.all( - 4), - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: Alignment - .centerLeft, - child: Text( - viewModel - .storeItem - .ingredients![ - position] - .name, - style: const TextStyle( - fontSize: 11, - fontFamily: MyFonts - .DMREGULAR, - color: MyColors - .textColorBlack), - ), - ), - ), - ), - Expanded( - child: Container( - padding: - const EdgeInsets.all( - 4), - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: Alignment - .centerLeft, - child: Text( - viewModel - .storeItem - .ingredients![ - position] - .purchasePrice! - .toString(), - style: const TextStyle( - fontSize: 11, - fontFamily: MyFonts - .DMREGULAR, - color: MyColors - .textColorBlack), - ), - ), - ), - ), - Expanded( - child: Container( - padding: - const EdgeInsets.all( - 4), - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: Alignment - .centerLeft, - child: Text( - viewModel - .storeItem - .ingredients![ - position] - .salePrice! - .toString(), - style: const TextStyle( - fontSize: 11, - fontFamily: MyFonts - .DMREGULAR, - color: MyColors - .textColorBlack), - ), - ), - ), - ), - Expanded( - child: Container( - padding: - const EdgeInsets.all( - 4), - width: 100, - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: - CustomTextFieldForm( - readOnly: - widget.isView, - onChanged: (value) { - viewModel.unitsController[ - position] = - value; - if (value - .isNotEmpty) { - viewModel - .storeItem - .ingredients![ - position] - .defaultSalePrice = - int.parse( - value); - } - }, - hintText: '0.0', - ), - ), - ), - ), - Expanded( - child: Container( - padding: - const EdgeInsets.all(4), - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: getMeasurementUnit( - context, position), - )), - SizedBox( - width: 48, - height: 48, - child: Center( - child: Container( - width: 32, - height: 32, - decoration: BoxDecoration( - borderRadius: - const BorderRadius - .all( - Radius.circular( - 4)), - color: MyColors - .backFillColor), - child: IconButton( - icon: const Icon( - size: 18, - Icons.close, - color: MyColors - .textColorBlack, - ), - onPressed: () { - setState(() { - viewModel - .unitsController - .removeAt( - position); - viewModel - .storeItem - .ingredients! - .removeAt( - position); - }); - }), - ), - )), - ], - ), - ); - } - }, - itemCount: viewModel - .storeItem.ingredients!.length, - ), + getIngredientsList() ], )) ], ), ), ), + AppSpaces.verticalLarge, isPortrait ? Column( children: [ - Card( - child: Container( - padding: const EdgeInsets.all(8), - child: Column( - crossAxisAlignment: - CrossAxisAlignment.center, - children: [ - Text( - AppLocalizations.of(context)! - .item_image, - style: const TextStyle( - fontSize: MyFonts.bold, - fontFamily: MyFonts.Bold, - color: MyColors.black), - ), - const SizedBox( - height: 12, - ), - AlertDialogForPicture( - viewModel.storeItem.imageUrl, - viewModel.imageFile, - this), - const SizedBox( - height: 8, - ), - Center( - child: Text( - AppLocalizations.of(context)! - .image_information_txt, - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normal, - color: MyColors.textColorGray), - textAlign: TextAlign.center, - ), - ), - ], - ), - ), + getItemImageCard(), + AppSpaces.verticalLarge, + getMeasurementCard() + ], + ) + : Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: getItemImageCard(), ), - const SizedBox( - height: 12, - ), - Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(4.0), - ), - child: Container( - width: double.infinity, - padding: const EdgeInsets.all(8), - child: Column( - mainAxisAlignment: - MainAxisAlignment.start, - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - CustomOptionalTitle( - hint: AppLocalizations.of(context)! - .measurements), - const SizedBox( - height: 12, - ), - getChooseMeasurement(), - ], - ), - ), - ) - ], - ) - : Row( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: Card( - child: Container( - padding: const EdgeInsets.all(8), - child: Column( - crossAxisAlignment: - CrossAxisAlignment.center, - children: [ - Text( - AppLocalizations.of(context)! - .item_image, - style: const TextStyle( - fontSize: MyFonts.bold, - fontFamily: MyFonts.Bold, - color: MyColors.black), - ), - const SizedBox( - height: 12, - ), - AlertDialogForPicture( - viewModel.storeItem.imageUrl, - viewModel.imageFile, - this), - const SizedBox( - height: 8, - ), - Center( - child: Text( - AppLocalizations.of(context)! - .image_information_txt, - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normal, - color: - MyColors.textColorGray), - textAlign: TextAlign.center, - ), - ), - ], - ), - ), - ), - ), - Expanded( - child: Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(4.0), - ), - child: Container( - width: double.infinity, - padding: const EdgeInsets.all(8), - child: Column( - mainAxisAlignment: - MainAxisAlignment.start, - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - CustomOptionalTitle( - hint: - AppLocalizations.of(context)! - .measurements), - const SizedBox( - height: 12, - ), - getChooseMeasurement(), - ], - ), - ), - ), + Expanded( + child: getMeasurementCard(), ), ], ), - const SizedBox( - height: 12, - ), + AppSpaces.verticalLarge, Card( + elevation: 5, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(4.0), ), child: Container( width: double.infinity, - padding: const EdgeInsets.all(8), + padding: const EdgeInsets.all(15), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ - CustomOptionalTitle( - hint: AppLocalizations.of(context)!.modifiers, - ), - const SizedBox( - height: 12, + Text( + style: ThemeText.textStyleHeadingCart, + AppLocalizations.of(context)!.modifiers, ), + AppSpaces.verticalLarge, getModifierWidget(), ], )), ), + AppSpaces.verticalLarge, Visibility( visible: !widget.isView, child: SizedBox( @@ -2169,8 +466,10 @@ class _AddNewInventoryProductVCState extends State textColor: MyColors.white, isLoading: viewModel.isLoadingData, backGroundColor: MyColors.blueThemeColor, - onPressed: () { - viewModel.isValidate(context, widget.isEdit); + onPressed: () async { + await viewModel.isValidate( + context, widget.isEdit); + checkState(); }, heading: widget.isEdit ? "Update" @@ -2179,134 +478,106 @@ class _AddNewInventoryProductVCState extends State )), ], ), - ), - ); - }), ), - ), - onWillPop: () { - viewModel.dispose(); - return Future.value(false); - }); + ); + }), + ); + } + + void checkState() { + if (viewModel.crudOperation == CRUDOperationState.add || + viewModel.crudOperation == CRUDOperationState.update) { + Navigator.pop(context, true); + } } - Widget getDeliveryPartner(BuildContext context, int position) { + Widget getDeliveryPartner(int position) { return FutureBuilder( future: viewModel.getAllPartners(), builder: (c, s) { if (s.hasData) { var itemsList = s.data!; - return Material( - color: MyColors.backFillColor, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: 48, - width: double.infinity, - child: DropdownSearch( - selectedItem: viewModel.selectedPartners[position], - enabled: !widget.isView, - popupProps: const PopupProps.menu( - constraints: BoxConstraints(maxHeight: 150)), - clearButtonProps: const ClearButtonProps( - alignment: Alignment.centerRight, - padding: EdgeInsets.zero, - icon: Icon(Icons.clear, size: 12), - color: MyColors.black, - isVisible: true, - ), - items: itemsList, - itemAsString: (DeliveryPartner u) => u.name!, - onChanged: (DeliveryPartner? partner) { - viewModel.editDeliveryPartner(position, partner); - }, - dropdownDecoratorProps: - MyColors.dropDownStyle(hint: 'Choose Partner')), - ), - ), - ); + return DropdownSearch( + selectedItem: viewModel.selectedPartners[position], + enabled: !widget.isView, + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: itemsList, + itemAsString: (DeliveryPartner u) => u.name, + onChanged: (DeliveryPartner? partner) { + viewModel.editDeliveryPartner(position, partner); + }, + dropdownDecoratorProps: + MyColors.dropDownStyleAddProduct(hint: 'Choose Partner')); } else { return AppLoader(); } }); } - Widget getMeasurementUnit(BuildContext context, int position) { + Widget getMeasurementUnit(int position) { return FutureBuilder( - future: viewModel.getMeasurements(), + future: viewModel.getMeasurements(true), builder: (c, s) { if (s.hasData) { var itemsList = s.data!; - return Material( - color: MyColors.backFillColor, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: 48, - width: double.infinity, - child: DropdownSearch( - enabled: !widget.isView, - popupProps: const PopupProps.menu(), - clearButtonProps: const ClearButtonProps( - alignment: Alignment.centerRight, - padding: EdgeInsets.zero, - icon: Icon(Icons.clear, size: 12), - color: MyColors.black, - isVisible: true, - ), - items: itemsList, - itemAsString: (MeasurementUnit u) => u.name!, - onChanged: (MeasurementUnit? data) { - viewModel.setMeasurementUnit(position, data); - }, - dropdownDecoratorProps: - MyColors.dropDownStyle(hint: 'Choose')), - ), - ), - ); + return DropdownSearch( + enabled: !widget.isView, + selectedItem: + viewModel.selectedIngredientsMeasurement[position], + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: itemsList, + itemAsString: (MeasurementUnit u) => u.name, + onChanged: (MeasurementUnit? data) { + viewModel.setMeasurementUnit(position, data); + }, + dropdownDecoratorProps: + MyColors.dropDownStyleAddProduct(hint: 'Choose')); } else { return AppLoader(); } }); } - Widget getSupplierWidget(BuildContext context) { + Widget getSupplierWidget() { return FutureBuilder( future: viewModel.getSuppliersData(), builder: (c, s) { if (s.hasData) { var itemsList = s.data!; - return Material( - color: MyColors.backFillColor, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: 48, - width: double.infinity, - child: DropdownSearch( - selectedItem: viewModel.selectedSupplier, - enabled: !widget.isView, - popupProps: const PopupProps.menu(), - clearButtonProps: ThemeDropDown.clearButton, - items: itemsList, - itemAsString: (Supplier u) => u.name!, - onChanged: (Supplier? data) { - viewModel.setSupplier(data); - }, - dropdownDecoratorProps: const DropDownDecoratorProps( - baseStyle: TextStyle( - fontFamily: MyFonts.Bold, - fontSize: 12, - color: MyColors.textColorBlack), - dropdownSearchDecoration: InputDecoration( - border: InputBorder.none, hintText: 'Choose'), - ), - ), - ), - ), + return DropdownSearch( + selectedItem: viewModel.selectedSupplier, + enabled: !widget.isView, + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name ?? ''); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: itemsList, + itemAsString: (Supplier u) => u.name!, + onChanged: (Supplier? data) { + viewModel.setSupplier(data); + }, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), ); } else { return AppLoader(); @@ -2314,35 +585,30 @@ class _AddNewInventoryProductVCState extends State }); } - Widget getCategoryWidget(BuildContext context) { + Widget getCategoryWidget() { return FutureBuilder( - future: viewModel.getCategoriesData(widget.categoryId), + future: viewModel.getCategoriesData(), builder: (c, s) { if (s.hasData) { var itemsList = s.data!; - return Material( - color: MyColors.backFillColor, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: 48, - width: double.infinity, - child: DropdownSearch( - enabled: !widget.isView, - selectedItem: viewModel.selectedCategory, - popupProps: const PopupProps.menu(), - clearButtonProps: ThemeDropDown.clearButton, - items: itemsList, - itemAsString: (ItemCategory u) => u.name, - onChanged: (ItemCategory? data) { - viewModel.setSelectedCategory(data); - }, - dropdownDecoratorProps: - MyColors.dropDownStyle(hint: 'Choose'), - ), - ), - ), + return DropdownSearch( + enabled: !widget.isView, + selectedItem: viewModel.selectedCategory, + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name ?? ''); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: itemsList, + itemAsString: (ItemCategory u) => u.name, + onChanged: (ItemCategory? data) { + viewModel.setSelectedCategory(data); + }, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), ); } else { return AppLoader(); @@ -2350,44 +616,30 @@ class _AddNewInventoryProductVCState extends State }); } - Widget getDiscounts(BuildContext context) { + Widget getDiscounts() { return FutureBuilder( future: viewModel.getDiscount(), builder: (c, s) { if (s.hasData) { var itemsList = s.data!; - return Container( - padding: const EdgeInsets.all(4), - child: Material( - color: MyColors.backFillColor, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: 48, - width: double.infinity, - child: DropdownSearch( - selectedItem: viewModel.selectedDiscount, - enabled: !widget.isView, - popupProps: const PopupProps.menu(), - clearButtonProps: const ClearButtonProps( - alignment: Alignment.centerRight, - padding: EdgeInsets.zero, - icon: Icon(Icons.clear, size: 12), - color: MyColors.black, - isVisible: true, - ), - items: itemsList, - itemAsString: (StoreDiscount u) => u.name!, - onChanged: (StoreDiscount? data) { - viewModel.setSelectedDiscount(data); - }, - dropdownDecoratorProps: - MyColors.dropDownStyle(hint: 'Choose'), - ), - ), - ), - ), + return DropdownSearch( + selectedItem: viewModel.selectedDiscount, + enabled: !widget.isView, + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name ?? ''); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: itemsList, + itemAsString: (StoreDiscount u) => u.name!, + onChanged: (StoreDiscount? data) { + viewModel.setSelectedDiscount(data); + }, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), ); } else { return AppLoader(); @@ -2401,37 +653,23 @@ class _AddNewInventoryProductVCState extends State builder: (c, s) { if (s.hasData) { var itemsList = s.data!; - return Container( - padding: const EdgeInsets.all(4), - child: Material( - color: MyColors.backFillColor, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: 48, - width: double.infinity, - child: DropdownSearch( - enabled: !widget.isView, - popupProps: const PopupProps.menu(), - clearButtonProps: const ClearButtonProps( - alignment: Alignment.centerRight, - padding: EdgeInsets.zero, - icon: Icon(Icons.clear, size: 12), - color: MyColors.black, - isVisible: true, - ), - items: itemsList, - itemAsString: (AddIngredient u) => u.name, - onChanged: (AddIngredient? data) { - viewModel.setIngredient(data); - }, - dropdownDecoratorProps: - MyColors.dropDownStyle(hint: 'Choose'), - ), - ), - ), - ), + return DropdownSearch( + enabled: !widget.isView, + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: itemsList, + itemAsString: (AddIngredient u) => u.name, + onChanged: (AddIngredient? data) { + viewModel.setIngredient(data); + }, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), ); } else { return AppLoader(); @@ -2445,94 +683,90 @@ class _AddNewInventoryProductVCState extends State builder: (c, s) { if (s.hasData) { var itemsList = s.data!; - return SizedBox( - height: 198, - child: GridView.builder( - physics: const AlwaysScrollableScrollPhysics(), - shrinkWrap: true, - itemCount: itemsList.length, - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: isPortrait ? 3 : 6, - crossAxisSpacing: 0, - mainAxisSpacing: 0, - ), - itemBuilder: (c, i) { - return GestureDetector( - onTap: () { - if (widget.isView) { - return; - } - viewModel.setModifier(itemsList[i]); - }, - child: Container( - margin: const EdgeInsets.all(4), - padding: const EdgeInsets.all(4), - decoration: BoxDecoration( - color: viewModel.selectedMod - .contains(itemsList[i].id) - ? MyColors.blueThemeColor - : MyColors.backFillColor, - border: Border.all( - width: 1, color: MyColors.fillColor3), - borderRadius: - const BorderRadius.all(Radius.circular(12))), - child: Row( - children: [ - Expanded( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Center( - child: Text( - textAlign: TextAlign.center, - itemsList[i].name, - style: TextStyle( - fontSize: 12, - fontFamily: MyFonts.Bold, - color: viewModel.selectedMod - .contains(itemsList[i].id) - ? MyColors.white - : MyColors.textColorBlack, - ), + return GridView.builder( + physics: const AlwaysScrollableScrollPhysics(), + shrinkWrap: true, + itemCount: itemsList.length, + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: isPortrait ? 3 : 6, + crossAxisSpacing: 0, + mainAxisExtent: 60, + mainAxisSpacing: 0, + ), + itemBuilder: (c, i) { + return GestureDetector( + onTap: () { + if (widget.isView) { + return; + } + viewModel.setModifier(itemsList[i]); + }, + child: Container( + margin: const EdgeInsets.all(4), + padding: const EdgeInsets.all(4), + decoration: BoxDecoration( + color: + viewModel.selectedMod.contains(itemsList[i].id) + ? MyColors.blueThemeColor + : MyColors.backFillColor, + border: Border.all( + width: 1, color: MyColors.fillColor3), + borderRadius: + const BorderRadius.all(Radius.circular(12))), + child: Row( + children: [ + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Center( + child: Text( + textAlign: TextAlign.center, + itemsList[i].name, + style: TextStyle( + fontSize: 12, + fontFamily: MyFonts.Bold, + color: viewModel.selectedMod + .contains(itemsList[i].id) + ? MyColors.white + : MyColors.textColorBlack, ), ), - const SizedBox( - height: 8, - ), - Wrap( - alignment: WrapAlignment.spaceAround, - direction: Axis.horizontal, - spacing: 4, // space between items - children: itemsList[i] - .options! - .map((e) => Container( - padding: const EdgeInsets.all(3), - decoration: BoxDecoration( - color: viewModel.selectedMod - .contains( - itemsList[i].id) - ? MyColors.backColorBlue50 - : const Color(0x1004aed0), - borderRadius: - BorderRadius.circular(4), - ), - child: Text(e.name, - style: const TextStyle( - fontSize: 9, - fontFamily: - MyFonts.DMREGULAR, - color: - Color(0xFF04aed0))), - )) - .toList(), - ), - ], - )) - ], - ), - )); - }), - ); + ), + // AppSpaces.verticalMedium, + // Wrap( + // alignment: WrapAlignment.spaceAround, + // direction: Axis.horizontal, + // spacing: 4, // space between items + // children: itemsList[i] + // .options + // .map((e) => Container( + // padding: const EdgeInsets.all(3), + // decoration: BoxDecoration( + // color: viewModel.selectedMod + // .contains( + // itemsList[i].id) + // ? MyColors.backColorBlue50 + // : const Color(0x1004aed0), + // borderRadius: + // BorderRadius.circular(4), + // ), + // child: Text(e.name, + // style: const TextStyle( + // fontSize: 9, + // fontFamily: + // MyFonts.DMREGULAR, + // color: + // Color(0xFF04aed0))), + // )) + // .toList(), + // ), + ], + )) + ], + ), + )); + }); } else { return AppLoader(); } @@ -2547,56 +781,71 @@ class _AddNewInventoryProductVCState extends State AppLocalizations.of(context)!.measurements, style: ThemeText.textStylePopUpHeading, ), - const SizedBox( - height: 4, - ), + AppSpaces.verticalSmall, getMeasurementWidget(), + AppSpaces.verticalLarge, + getMeasurementUnitWidget(), ], ); } + Widget getMeasurementUnitWidget() { + return FutureBuilder( + future: viewModel.getMeasurements(false), + builder: (c, s) { + if (s.hasData) { + var itemsList = s.data!; + return DropdownSearch( + enabled: !widget.isView, + selectedItem: viewModel.selectedMeasurementUnit, + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: itemsList, + itemAsString: (MeasurementUnit u) => u.name, + onChanged: (MeasurementUnit? data) { + viewModel.setMeasurementUnitProduct(data); + }, + dropdownDecoratorProps: + MyColors.dropDownStyle(hint: 'Choose Measurement Unit'), + ); + } else { + return AppLoader(); + } + }); + } + Widget getMeasurementWidget() { return FutureBuilder( future: viewModel.getMeasurement(), builder: (c, s) { if (s.hasData) { var itemsList = s.data!; - return Container( - padding: const EdgeInsets.all(4), - decoration: const BoxDecoration( - border: Border( - right: BorderSide(width: 1.0, color: MyColors.fillColorGray2), - ), - ), - child: Material( - color: MyColors.backFillColor, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: 48, - width: double.infinity, - child: DropdownSearch( - enabled: !widget.isView, - popupProps: const PopupProps.menu(), - clearButtonProps: const ClearButtonProps( - alignment: Alignment.centerRight, - padding: EdgeInsets.zero, - icon: Icon(Icons.clear, size: 12), - color: MyColors.black, - isVisible: true, - ), - items: itemsList, - itemAsString: (Measurement u) => u.name!, - onChanged: (Measurement? data) { - viewModel.setMeasurement(data); - }, - dropdownDecoratorProps: - MyColors.dropDownStyle(hint: 'Choose Measurement'), - ), - ), - ), - ), + return DropdownSearch( + enabled: !widget.isView, + selectedItem: viewModel.selectedMeasurement, + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name ?? ''); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: itemsList, + itemAsString: (Measurement u) => u.name ?? '', + onChanged: (Measurement? data) { + viewModel.setMeasurement(data); + }, + dropdownDecoratorProps: + MyColors.dropDownStyle(hint: 'Choose Measurement'), ); } else { return AppLoader(); @@ -2622,123 +871,77 @@ class _AddNewInventoryProductVCState extends State shrinkWrap: true, itemBuilder: (c, position) { if (isPortrait) { - return Container( - padding: const EdgeInsets.fromLTRB(8, 0, 0, 8), - color: MyColors.containerBackColor, + return WrapHeightContainer( child: Row( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ Expanded( - flex: 2, - child: Container( - padding: const EdgeInsets.only(top: 8), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Expanded( - child: Column( - children: [ - Container( - padding: const EdgeInsets.all(4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - left: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - bottom: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)!.name, - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.bold, - fontSize: 11, - color: MyColors.textColorBlack20), - ), - ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Row( + children: [ + Expanded( + child: PortraitContainer( + width: double.infinity, + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + AppLocalizations.of(context)!.name, ), - Container( - padding: const EdgeInsets.all(4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - left: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - bottom: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: const Align( - alignment: Alignment.centerLeft, - child: Text( - 'Delivery Partner Price', - style: TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.bold, - fontSize: 11, - color: MyColors.textColorBlack20), - ), - ), - ) - ], - )), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - getDeliveryPartner(context, position), - deliveryPartnerPrice(position) - ], - )), - ], - ), - )), + ), + ), + ), + Expanded( + child: PortraitContainer( + width: double.infinity, + child: getDeliveryPartner(position)), + ), + ], + ), + Row( + children: [ + Expanded( + child: PortraitContainer( + width: double.infinity, + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + 'Delivery Partner Price', + ), + ), + ), + ), + Expanded( + child: PortraitContainer( + width: double.infinity, + child: Center( + child: deliveryPartnerPrice(position), + )), + ), + ], + ) + ], + )), removeDeliveryPartnerButton(position) ], ), ); } else { - return Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius.all(Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all(width: 1, color: MyColors.fillColorGray2), - color: MyColors.white, - ), + return BorderContainer( + backgroundColor: MyColors.white, child: Row( children: [ - Container( - padding: const EdgeInsets.all(4), - height: 48, + ChildContainer( width: 250, - child: getDeliveryPartner(context, position), + child: getDeliveryPartner(position), ), Expanded( - child: deliveryPartnerPrice(position), + child: ChildContainer( + child: deliveryPartnerPrice(position), + ), ), removeDeliveryPartnerButton(position), ], @@ -2746,65 +949,666 @@ class _AddNewInventoryProductVCState extends State ); } }, - itemCount: viewModel.storeItem.deliveryPartners != null - ? viewModel.storeItem.deliveryPartners!.length - : 0, + itemCount: viewModel.storeItem.deliveryPartners.length, ); } Widget removeDeliveryPartnerButton(int position) { - return SizedBox( - width: 44, - height: 48, - child: Center( - child: Container( - width: 32, - height: 32, - decoration: const BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(4)), - color: MyColors.fillColorGray2), - child: IconButton( - icon: const Icon( - size: 14, - Icons.close, - color: MyColors.textColorBlack, - ), - onPressed: () { - viewModel.removeDeliveryPartner(position); - }), - ), - )); + return CustomRemoveItemButton( + onPressed: () { + viewModel.removeDeliveryPartner(position); + }, + ); } Widget deliveryPartnerPrice(int position) { - return Container( - decoration: const BoxDecoration( - border: Border( - right: BorderSide(width: 1.0, color: MyColors.fillColorGray2), + return CustomTextFieldForm( + key: Key(viewModel.storeItem.deliveryPartners[position].price + .toStringAsFixed(2)), + initialValue: viewModel.storeItem.deliveryPartners[position].price + .toStringAsFixed(2), + hintText: '', + onChanged: (String value) { + viewModel.editDeliveryPartnerPrice(position, value); + }, + ); + } + + getItemName() { + return Column( + children: [ + MandatoryTitleText( + hint: AppLocalizations.of(context)!.item_name, ), - ), - height: 48, - padding: const EdgeInsets.all(4), - child: Container( - decoration: BoxDecoration( - border: Border.all( - color: Colors.transparent, - width: 1, + AppSpaces.verticalSmall, + CustomTextFieldForm( + initialValue: viewModel.storeItem.name, + readOnly: widget.isView, + hintText: 'Enter Item name', + onChanged: (String value) { + viewModel.storeItem.name = value; + }, + ), + ], + ); + } + + getCategory() { + return Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + MandatoryTitleText(hint: AppLocalizations.of(context)!.category), + GestureDetector( + onTap: () { + showPopUP(); + }, + child: Text( + '+ Add Category', + style: ThemeText.textStyleBlueColorSmall, + ), + ) + ], + ), + AppSpaces.verticalSmall, + getCategoryWidget(), + ], + ); + } + + Future showPopUP() async { + final result = await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => InventoryAddCategoryVC( + item: ItemCategory(), + isEdit: false, + )), + ); + + if (result != null) { + setState(() {}); + } + } + + getQuantityWidget() { + return Column( + children: [ + Row( + children: [ + Expanded( + child: MandatoryTitleText( + hint: AppLocalizations.of(context)!.quantity, + ), + ), + CustomCheckBox( + heading: 'Unlimited Quantity', + value: viewModel.storeItem.isUnlimitedQuantity, + onChange: (value) { + viewModel.setIsUnlimitedQuantity(value); + }) + ], + ), + AppSpaces.verticalSmall, + CustomTextFieldForm( + hintText: 'Enter Quantity', + initialValue: + viewModel.storeItem.totalAddedQuantity?.toString() ?? '', + readOnly: widget.isView || viewModel.storeItem.isUnlimitedQuantity, + keyboardType: TextInputType.number, + onChanged: (value) { + viewModel.setQuantity(value); + }, + ), + ], + ); + } + + getBarCodeWidget() { + return Column( + children: [ + MandatoryTitleText( + hint: AppLocalizations.of(context)!.barcode, + ), + AppSpaces.verticalSmall, + Container( + decoration: const BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(8)), + ), + child: Row( + children: [ + Expanded( + child: CustomTextFieldForm( + readOnly: widget.isView, + key: Key(viewModel.storeItem.uniqueIdForStoreData.toString()), + initialValue: + viewModel.storeItem.uniqueIdForStoreData.toString(), + onChanged: (value) { + viewModel.storeItem.uniqueIdForStoreData = value; + }, + hintText: 'Enter bar code', + )), + AppSpaces.horizontalSmall, + SizedBox( + width: 80, + child: GenerateBarCodeButton( + onPressed: () { + if (!widget.isView) { + viewModel.generateCode(); + } + }, + ), + ), + ], ), - color: MyColors.backFillColor, - borderRadius: BorderRadius.circular(8.0), + ) + ], + ); + } + + getItemInStockWidget() { + return Column( + children: [ + MandatoryTitleText(hint: AppLocalizations.of(context)!.status), + AppSpaces.verticalSmall, + SizedBox( + height: 44, + child: Row( + children: [ + const CustomOptionalTitle( + hint: 'Item In Stock', + ), + AppSpaces.horizontalMedium, + CustomSwitch( + value: viewModel.storeItem.isItemInStock, + onToggle: (value) { + viewModel.setItemInStockStatus(value); + }, + ) + ], + ), + ) + ], + ); + } + + getArabicDescriptionWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle(hint: AppLocalizations.of(context)!.description_ar), + AppSpaces.verticalSmall, + CustomTextFieldForm( + height: 100, + initialValue: viewModel.storeItem.descriptionArabic, + hintText: 'Enter Description in Arabic', + readOnly: widget.isView, + onChanged: (value) { + viewModel.storeItem.descriptionArabic = value; + }, + maxLines: 5, + keyboardType: TextInputType.multiline, ), - child: CustomTextFieldForm( - key: Key(viewModel.storeItem.deliveryPartners![position].price - .toStringAsFixed(2)), - initialValue: viewModel.storeItem.deliveryPartners![position].price - .toStringAsFixed(2), - hintText: '', + ], + ); + } + + getDefaultPriceWidget() { + return Column( + children: [ + const MandatoryTitleText(hint: 'Default Price (Incl. Tax)'), + AppSpaces.verticalSmall, + CustomTextFieldForm( + hintText: 'Enter Price (Incl. Tax)', + readOnly: widget.isView, + initialValue: viewModel.storeItem.price?.toStringAsFixed(2) ?? '', + keyboardType: TextInputType.number, + onChanged: (value) { + viewModel.setPrice(value); + }), + ], + ); + } + + getArabicNameWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.item_name_ar_optional, + ), + AppSpaces.verticalSmall, + CustomTextFieldForm( + readOnly: widget.isView, + initialValue: viewModel.storeItem.itemNameArabic, + onChanged: (value) { + viewModel.storeItem.itemNameArabic = value; + }, + hintText: 'Enter Item Name in Arabic', + ), + ], + ); + } + + getDescriptionWidget() { + return Column( + children: [ + MandatoryTitleText( + hint: AppLocalizations.of(context)!.description, + ), + AppSpaces.verticalSmall, + CustomTextFieldForm( + height: 100, + hintText: AppLocalizations.of(context)!.description, + readOnly: widget.isView, + maxLines: 5, + initialValue: viewModel.storeItem.description, + keyboardType: TextInputType.multiline, onChanged: (String value) { - viewModel.editDeliveryPartnerPrice(position, value); + viewModel.storeItem.description = value; }, ), + ], + ); + } + + getSalePriceExclTax() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.sale_price_excl_tax), + AppSpaces.verticalSmall, + CustomTextFieldForm( + readOnly: true, + initialValue: + viewModel.storeItem.salePriceExclusiveTax?.toString() ?? '', + key: Key(viewModel.storeItem.salePriceExclusiveTax?.toString() ?? ''), + keyboardType: TextInputType.number, + onChanged: (value) {}, + hintText: 'Enter Sale Price (Excl. Tax)', + ), + ], + ); + } + + getPriceIncludeTax() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle( + hint: 'Price (Incl. Tax)', + ), + AppSpaces.verticalSmall, + CustomTextFieldForm( + initialValue: viewModel.storeItem.purchasePrice?.toString() ?? '', + hintText: 'Enter Price (Incl. Tax)', + readOnly: widget.isView, + keyboardType: TextInputType.number, + onChanged: (value) { + viewModel.updatePurchasePrice(value); + }, + ), + ], + ); + } + + getStockAlertQuantityWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.stock_alert_quantity, + ), + AppSpaces.verticalSmall, + CustomTextFieldForm( + initialValue: + viewModel.storeItem.stockAlertQuantity?.toString() ?? '', + hintText: 'Enter Stock Alert Quantity', + readOnly: widget.isView, + keyboardType: TextInputType.number, + onChanged: (value) { + viewModel.updateStockAlert(value); + }, + ), + ], + ); + } + + getDiscountWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.discount, + ), + AppSpaces.verticalSmall, + getDiscounts(), + ], + ); + } + + getSupplier() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.supplier, + ), + AppSpaces.verticalSmall, + getSupplierWidget(), + ], + ); + } + + getManufactureDate() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.manufacturer_date, + ), + AppSpaces.verticalSmall, + getManufactureDateButton() + ], + ); + } + + Widget getManufactureDateButton() { + return CustomTextButtonIcon( + backgroundColor: MyColors.backFillColor, + icon: Icons.calendar_month, + heading: viewModel.storeItem.manufactureDate.isEmpty + ? 'dd/mm/yyyy' + : DataTimeFormat.getFormatDateString( + viewModel.storeItem.manufactureDate), + onPressed: () { + viewModel.presentDatePicker(context, true); + }, + ); + } + + getExpireDate() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.expiry_date, + ), + AppSpaces.verticalSmall, + getExpireDateButton(), + ], + ); + } + + Widget getExpireDateButton() { + return CustomTextButtonIcon( + backgroundColor: MyColors.backFillColor, + icon: Icons.calendar_month, + heading: viewModel.storeItem.expireDate.isEmpty + ? 'dd/mm/yyyy' + : DataTimeFormat.getFormatDateString(viewModel.storeItem.expireDate), + onPressed: () { + viewModel.presentDatePicker(context, false); + }, + ); + } + + getAddDeliveryPartnerButton() { + return CustomAddButton(onPressed: () { + viewModel.addNewDeliveryPartner(); + }); + } + + getProductAsIngredientCost() { + return Container( + padding: const EdgeInsets.all(8), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Row(children: [ + CustomCheckBox(value: false, onChange: (value) {}), + AppSpaces.horizontalSmall, + Text( + AppLocalizations.of(context)! + .set_product_price_as_ingredient_cost, + style: ThemeText.textStylePopUpHeading, + textAlign: TextAlign.center, + ) + ]), + AppSpaces.horizontalSmall, + Text( + AppLocalizations.of(context)!.option_enable_product_invoice, + style: ThemeText.textStyleHeading, + ), + ], + ), + ); + } + + getItemImageCard() { + return Card( + elevation: 5, + child: Container( + padding: const EdgeInsets.all(15), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text( + AppLocalizations.of(context)!.item_image, + style: ThemeText.textStyleHeadingCart, + ), + AppSpaces.verticalLarge, + AlertDialogForPicture( + viewModel.storeItem.imageUrl, viewModel.imageFile, this), + AppSpaces.verticalMedium, + Center( + child: Text( + AppLocalizations.of(context)!.image_information_txt, + style: TextStyle( + fontFamily: MyFonts.DMREGULAR, + fontSize: MyFonts.normal, + color: MyColors.textColorGray), + textAlign: TextAlign.center, + ), + ), + ], + ), + ), + ); + } + + getMeasurementCard() { + return Card( + elevation: 5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(4.0), ), + child: Container( + width: double.infinity, + padding: const EdgeInsets.all(15), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)!.measurements, + style: ThemeText.textStyleHeadingCart, + ), + AppSpaces.verticalLarge, + getChooseMeasurement(), + ], + ), + ), + ); + } + + getSalePriceOneUnitIngredient(int position) { + return CustomTextFieldForm( + readOnly: widget.isView, + initialValue: viewModel.storeItem.ingredients[position].price.toString(), + onChanged: (value) { + viewModel.updateIngredientUnitPrice(position, value); + }, + hintText: '0.0', + ); + } + + getRemoveIngredientButton(int position) { + return CustomRemoveItemButton(onPressed: () { + viewModel.removeIngredient(position); + }); + } + + getIngredientsList() { + return ListView.builder( + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (c, position) { + if (isPortrait) { + return WrapHeightContainer( + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Column( + children: [ + Row( + children: [ + Expanded( + child: PortraitContainer( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + AppLocalizations.of(context)!.name_description), + ), + )), + Expanded( + child: PortraitContainer( + child: Align( + alignment: Alignment.centerLeft, + child: CustomTextAddProduct(viewModel + .storeItem.ingredients[position].name), + ), + ), + ) + ], + ), + Row( + children: [ + Expanded( + child: PortraitContainer( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText('Purchase Price of 1 Unit'), + ), + )), + Expanded( + child: PortraitContainer( + child: Align( + alignment: Alignment.centerLeft, + child: CustomTextAddProduct( + viewModel.storeItem.ingredients[position] + .purchaseCost! + .toString(), + ), + ), + ), + ) + ], + ), + Row( + children: [ + Expanded( + child: PortraitContainer( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText('Sale Price of 1 Unit'), + ), + )), + Expanded( + child: PortraitContainer( + width: 100, + child: Center( + child: getSalePriceOneUnitIngredient(position), + ), + ), + ) + ], + ), + Row( + children: [ + Expanded( + child: PortraitContainer( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + 'Measuring Unit', + ), + ), + )), + Expanded( + child: PortraitContainer( + width: double.infinity, + child: getMeasurementUnit(position), + )) + ], + ), + ], + )), + getRemoveIngredientButton(position) + ], + ), + ); + } else { + return BorderContainer( + backgroundColor: MyColors.white, + child: Row( + children: [ + Expanded( + child: ChildContainer( + child: Align( + alignment: Alignment.centerLeft, + child: ValueText( + viewModel.storeItem.ingredients[position].name, + ), + ), + ), + ), + Expanded( + child: ChildContainer( + child: Align( + alignment: Alignment.centerLeft, + child: ValueText( + viewModel.storeItem.ingredients[position].purchaseCost! + .toString(), + ), + ), + ), + ), + Expanded( + child: ChildContainer( + child: Center( + child: getSalePriceOneUnitIngredient(position), + ), + ), + ), + Expanded( + child: ChildContainer( + child: getMeasurementUnit(position), + )), + getRemoveIngredientButton(position) + ], + ), + ); + } + }, + itemCount: viewModel.storeItem.ingredients.length, ); } } diff --git a/lib/application/views/inventorymodule/productviews/InventoryProductVC.dart b/lib/application/views/inventorymodule/productviews/InventoryProductVC.dart index c5be937..8d22a12 100644 --- a/lib/application/views/inventorymodule/productviews/InventoryProductVC.dart +++ b/lib/application/views/inventorymodule/productviews/InventoryProductVC.dart @@ -1,28 +1,24 @@ -import 'package:dropdown_search/dropdown_search.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:objectbox/objectbox.dart'; import 'package:provider/provider.dart'; +import 'package:sizer/sizer.dart'; import 'package:wosull/application/enum/DataState.dart'; -import 'package:wosull/application/model/converters/DataTimeFormat.dart'; -import 'package:wosull/application/model/inventory/category/ItemCategory.dart'; import 'package:wosull/application/model/store/StoreItemsResponse.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/utils/AppError.dart'; import 'package:wosull/application/utils/AppLoader.dart'; import 'package:wosull/application/views/inventorymodule/productviews/AddNewInventoryProductVC.dart'; import 'package:wosull/application/views/inventorymodule/productviews/viewModels/ProductViewModel.dart'; +import 'package:wosull/application/views/inventorymodule/productviews/views/ProductListView.dart'; import 'package:wosull/application/views/popups/DeleteRecordPopUp.dart'; import 'package:wosull/base/BaseStatefulState.dart'; -import 'package:wosull/helpers/ThemeImage.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/ThemeText.dart'; import 'package:wosull/helpers/Utils.dart'; import 'package:wosull/widgets/CustomSimpleButton.dart'; -import 'package:wosull/widgets/CustomSwitch.dart'; -import 'package:wosull/widgets/EmptyDataWidget.dart'; -import 'package:wosull/widgets/HeadingText.dart'; +import 'package:wosull/widgets/ItemCategoryDropdown.dart'; +import 'package:wosull/widgets/PageLimitDropDown.dart'; import 'package:wosull/widgets/SearchBox.dart'; -import 'package:wosull/widgets/ValueText.dart'; class InventoryProductVC extends StatefulWidget { const InventoryProductVC({Key? key}) : super(key: key); @@ -37,453 +33,178 @@ class _InventoryProductVCState extends BaseStatefulState { late ScrollController _controller; final viewModel = ProductViewModel(); - @override - void initState() { - super.initState(); - } - @override Widget build(BuildContext context) { _controller = ScrollController()..addListener(_scrollNotification); - return WillPopScope( - onWillPop: () { - viewModel.dispose(); - return Future.value(false); - }, - child: MaterialApp( - debugShowCheckedModeBanner: false, - home: Scaffold( - backgroundColor: MyColors.fillColor, - resizeToAvoidBottomInset: true, - body: OrientationBuilder(builder: (c, orientation) { - isPortrait = - MediaQuery.of(context).orientation == Orientation.portrait; - return SingleChildScrollView( - controller: _controller, - child: Container( - padding: const EdgeInsets.all(8), - child: ChangeNotifierProvider( - create: (context) => viewModel, - child: Consumer( - builder: (BuildContext context, - ProductViewModel controller, Widget? _) { - switch (controller.dataState) { - case DataState.uninitialized: - if (viewModel.isFirstLoadRunning) { - Future(() { - controller.getCategory(); - }); - } - return Container(); - case DataState.initialFetching: - return AppLoader(); - case DataState.moreFetching: - case DataState.refreshing: - return showData(controller.filteredList); - case DataState.error: - return AppError(); - case DataState.searching: - case DataState.fetched: - case DataState.noMoreData: - return showData(controller.filteredList); - } - }, - ), - ), - ), - ); - }))), - ); - } - - Widget showData(List data) { - return viewModel.isFirstLoadRunning - ? AppLoader() - : Column( - children: [ - isPortrait - ? Column( - children: [ - Row( + return Scaffold( + backgroundColor: MyColors.fillColor, + resizeToAvoidBottomInset: true, + body: OrientationBuilder(builder: (c, orientation) { + isPortrait = + MediaQuery.of(context).orientation == Orientation.portrait; + return SingleChildScrollView( + controller: _controller, + child: Container( + padding: const EdgeInsets.all(8), + child: Column( + children: [ + isPortrait + ? Column( children: [ Row( - mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, children: [ Text( AppLocalizations.of(context)!.our_products, style: ThemeText.textStylePageHeading, ), - const SizedBox( - width: 4, - ), - SizedBox( - width: 150, child: getCategoriesDropdown()), - const SizedBox( - width: 4, - ), - SizedBox( - width: 120, - child: addProductButton(), + AppSpaces.horizontalMedium, + Flexible( + child: SizedBox( + height: 38, + child: getCategoriesDropdown())), + AppSpaces.horizontalMedium, + Flexible( + child: SizedBox( + child: addProductButton(), + ), ), ], ), + Row( + children: [ + Flexible( + child: SizedBox( + height: 48, + child: SearchBox( + onEditingDone: (text) { + // filterSearchResults(text); + }, + onChanged: (text) { + // filterSearchResults(text); + }, + hint: + AppLocalizations.of(context)!.search, + ), + ), + ), + PageLimitDropdown(onChange: (value) { + viewModel.fetch( + isRefresh: true, + limit: int.parse(value!)); + }) + ], + ) ], ) - ], - ) - : Row( - children: [ - Row( + : Row( mainAxisAlignment: MainAxisAlignment.start, children: [ Text( AppLocalizations.of(context)!.our_products, style: ThemeText.textStylePageHeading, ), - const SizedBox( - width: 4, - ), + AppSpaces.horizontalSmall, SizedBox( - width: 150, child: getCategoriesDropdown()), - const SizedBox( - width: 4, - ), + height: 38, + width: 150, + child: getCategoriesDropdown()), + AppSpaces.horizontalSmall, SizedBox( width: 120, child: addProductButton(), ), + AppSpaces.horizontalMedium, + SizedBox( + width: SizerUtil.deviceType == DeviceType.mobile + ? 200 + : 240, + height: 48, + child: SearchBox( + onEditingDone: (text) { + // filterSearchResults(text); + }, + onChanged: (text) { + // filterSearchResults(text); + }, + hint: AppLocalizations.of(context)!.search, + ), + ), + Flexible( + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + PageLimitDropdown(onChange: (value) { + viewModel.fetch( + isRefresh: true, + limit: int.parse(value!)); + }) + ], + )) ], ), - ], + ChangeNotifierProvider( + create: (context) => viewModel, + child: Consumer( + builder: (BuildContext context, + ProductViewModel controller, Widget? _) { + switch (controller.dataState) { + case DataState.uninitialized: + Future(() { + controller.getSubProducts('All'); + }); + return Container(); + case DataState.initialFetching: + return AppLoader(); + case DataState.moreFetching: + case DataState.refreshing: + return showData(controller.filteredList); + case DataState.error: + return AppError(); + case DataState.searching: + case DataState.fetched: + case DataState.noMoreData: + return showData(controller.filteredList); + } + }, ), - const SizedBox( - height: 8, + ) + ], ), - viewModel.isLoading - ? AppLoader() - : data.isEmpty - ? const EmptyDataWidget() - : Column( - children: [ - isPortrait - ? Container() - : Container( - padding: const EdgeInsets.only( - left: 8, right: 8), - height: 50, - color: MyColors.containerBackColor, - child: Row( - children: [ - Expanded( - child: HeadingText( - AppLocalizations.of(context)! - .thumbnail, - )), - Expanded( - child: HeadingText( - AppLocalizations.of(context)! - .name)), - Expanded( - child: HeadingText( - AppLocalizations.of(context)! - .category)), - Expanded( - child: HeadingText( - AppLocalizations.of(context)! - .price)), - Expanded( - child: Align( - alignment: Alignment.center, - child: HeadingText( - AppLocalizations.of(context)! - .status), - )), - Expanded( - child: HeadingText( - AppLocalizations.of(context)! - .updated_on)), - Expanded( - child: Padding( - padding: - const EdgeInsets.only(right: 16), - child: Align( - alignment: Alignment.centerRight, - child: HeadingText( - AppLocalizations.of(context)! - .action), - ), - )), - ], - ), - ), - ListView.builder( - padding: EdgeInsets.zero, - scrollDirection: Axis.vertical, - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - itemBuilder: (c, position) { - final item = data[position]; - if (isPortrait) { - return Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - elevation: 2, - color: MyColors.white, - child: Container( - padding: const EdgeInsets.fromLTRB( - 16, 0, 0, 16), - child: Row( - crossAxisAlignment: - CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.start, - children: [ - Expanded( - child: Container( - padding: - const EdgeInsets.only(top: 16), - child: Column( - children: [ - Align( - alignment: - Alignment.topCenter, - child: SizedBox( - height: 48, - width: 48, - child: CircleAvatar( - radius: 16, - backgroundColor: - MyColors.fillColor, - child: Padding( - padding: - const EdgeInsets - .fromLTRB( - 2, 2, 2, 2), - // Border radius - child: ClipOval( - child: item - .imageUrl! - .isEmpty - ? Image.asset( - ThemeImage - .wosulLogo) - : Image.network( - item.imageUrl!)), - ), - ), - ), - ), - Row( - crossAxisAlignment: - CrossAxisAlignment.end, - children: [ - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment - .start, - mainAxisAlignment: - MainAxisAlignment - .start, - children: [ - HeadingText( - AppLocalizations.of( - context)! - .name), - const SizedBox( - height: 8, - ), - HeadingText( - AppLocalizations.of( - context)! - .category), - const SizedBox( - height: 8, - ), - HeadingText( - AppLocalizations.of( - context)! - .price), - const SizedBox( - height: 8, - ), - HeadingText( - AppLocalizations.of( - context)! - .status), - const SizedBox( - height: 8, - ), - HeadingText( - AppLocalizations.of( - context)! - .updated_on), - ], - )), - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment - .end, - mainAxisAlignment: - MainAxisAlignment - .start, - children: [ - ValueText(item.name!), - const SizedBox( - height: 8, - ), - ValueText(viewModel - .selectedCategoryDropDown - .name), - const SizedBox( - height: 8, - ), - ValueText(item.price! - .toString()), - const SizedBox( - height: 4, - ), - Row( - mainAxisAlignment: - MainAxisAlignment - .end, - crossAxisAlignment: - CrossAxisAlignment - .end, - children: [ - CustomSwitch( - value: item - .isItemInStock!, - onToggle: - (value) { - _update( - item.id!, - value); - }, - ) - ], - ), - const SizedBox( - height: 8, - ), - ValueText(DataTimeFormat - .getFormatDate(item - .updatedAt!)), - ], - )), - ], - ) - ], - ), - )), - getPopUpBuilder(item) - ], - ), - ), - ); - } else { - return Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - child: Container( - padding: const EdgeInsets.only( - left: 8, right: 8), - height: 56, - color: MyColors.containerBackColor, - child: Row( - children: [ - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: SizedBox( - height: 32, - width: 32, - child: CircleAvatar( - radius: 32, - backgroundColor: - Colors.transparent, - child: Padding( - padding: - const EdgeInsets.fromLTRB( - 2, - 2, - 2, - 2), // Border radius - child: ClipOval( - child: item - .imageUrl!.isEmpty - ? Image.asset( - ThemeImage - .wosulLogo) - : Image.network( - item.imageUrl!)), - ), - ), - ), - )), - Expanded( - child: ValueText(item.name!)), - Expanded( - child: ValueText(viewModel - .selectedCategoryDropDown - .name)), - Expanded( - child: ValueText( - item.price!.toString())), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: CustomSwitch( - value: item.isItemInStock!, - onToggle: (value) { - setState(() { - item.isItemInStock = value; - }); - _update(item.id!, value); - }, - ), - )), - Expanded( - child: ValueText( - DataTimeFormat.getFormatDate( - item.updatedAt!))), - Expanded( - child: Padding( - padding: const EdgeInsets.all(4), - child: Align( - alignment: Alignment.centerRight, - child: Container( - decoration: BoxDecoration( - borderRadius: - const BorderRadius.all( - Radius.circular(4)), - color: - MyColors.backFillColor), - child: getPopUpBuilder(item), - ), - ), - )) - ], - ), - ), - ); - } - }, - itemCount: data.length, - ) - ], - ), - if (viewModel.dataState == DataState.moreFetching) AppLoader(), - ], + ), ); + })); + } + + Widget showData(List data) { + return Column( + children: [ + ProductListView( + selectedCategoryName: viewModel.selectedCategoryName, + isPortrait: isPortrait, + data: data, + onUpdate: (data, value) { + _update(data.itemId, value); + }, + onDelete: (data) { + showDeletePopup(data.itemId); + }, + onView: (data) { + onNewProduct(true, true, data.itemId); + }, + onEdit: (data) { + onNewProduct(true, false, data.itemId); + }), + if (viewModel.dataState == DataState.moreFetching) AppLoader(), + ], + ); } bool _scrollNotification() { if (!viewModel.isLoading && _controller.position.extentAfter < 300) { - viewModel.fetch(); + viewModel.fetch(limit: viewModel.limit); } return true; } @@ -491,62 +212,48 @@ class _InventoryProductVCState extends BaseStatefulState { Future _delete(String id) async { Utils.progressDialogue(context); await viewModel.delete(id); - checkState(); + hideProgressBar(); + // checkState(); } Future _update(String id, bool value) async { Utils.progressDialogue(context); await viewModel.update(id, value); - checkState(); + hideProgressBar(); } void checkState() { Utils.hideProgressBar(context); } - Future actionPopUpItemSelected( - String value, StoreItems storeItems) async { - if (value == 'edit') { - final result = await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => AddNewInventoryProductVC( - categoryId: viewModel.selectedCategoryId, - isEdit: true, - isView: false, - storeItems: storeItems)), - ); + Future showDeletePopup(String itemId) async { + final result = await showDialog( + barrierColor: Colors.black26, + context: context, + builder: (context) { + return const DeleteRecordPopUp(); + }, + ); - if (!mounted) return; - bool a = result; - if (a) { - viewModel.fetch(isRefresh: true); - } - } else if (value == 'delete') { - final result = await showDialog( - barrierColor: Colors.black26, - context: context, - builder: (context) { - return const DeleteRecordPopUp(); - }, - ); + if (!mounted) return; + bool isDelete = result; + if (isDelete) { + _delete(itemId); + } + } - if (!mounted) return; - bool isDelete = result; - if (isDelete) { - _delete(storeItems.id!); - } - } else { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => AddNewInventoryProductVC( - categoryId: "", - isEdit: false, - isView: true, - storeItems: storeItems, - )), - ); + Future onNewProduct(bool isEdit, bool isView, String id) async { + final result = await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => AddNewInventoryProductVC( + productId: id, isEdit: isEdit, isView: isView)), + ); + + if (!mounted) return; + bool a = result; + if (a) { + viewModel.fetch(isRefresh: true, limit: viewModel.limit); } } @@ -561,36 +268,13 @@ class _InventoryProductVCState extends BaseStatefulState { } Widget getCategoriesDropdown() { - return Material( - color: MyColors.fillColor2, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: 42, - width: double.infinity, - child: DropdownSearch( - selectedItem: viewModel.selectedCategoryDropDown, - popupProps: const PopupProps.menu(), - clearButtonProps: const ClearButtonProps( - alignment: Alignment.centerRight, - padding: EdgeInsets.zero, - icon: Icon(Icons.clear, size: 12), - color: MyColors.black, - isVisible: true, - ), - items: viewModel.categories, - itemAsString: (ItemCategory u) => u.name, - onChanged: (ItemCategory? data) { - if (data != null) { - viewModel.getNewData(data); - } - }, - dropdownDecoratorProps: MyColors.dropDownStyle(), - ), - ), - ), - ); + return ItemCategoryDropdown( + fillColor: MyColors.white, + onChanged: (data) { + if (data != null) { + viewModel.getNewData(data); + } + }); } Widget addProductButton() { @@ -599,28 +283,7 @@ class _InventoryProductVCState extends BaseStatefulState { backGroundColor: MyColors.backColorBlue50, heading: AppLocalizations.of(context)!.add_product, onPressed: () async { - final result = await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => AddNewInventoryProductVC( - categoryId: "", - isEdit: false, - isView: false, - storeItems: StoreItems( - modifiers: ToMany(items: []), - ingredients: ToMany(items: []), - selectedModifiers: ToMany(items: []), - deliveryPartners: ToMany(items: []), - comboProduct: ToMany(items: []), - selectedCombos: ToMany(items: [])), - )), - ); - - if (!mounted) return; - - if (result != null) { - viewModel.fetch(isRefresh: true); - } + onNewProduct(false, false, ''); }, ); } @@ -636,33 +299,4 @@ class _InventoryProductVCState extends BaseStatefulState { }, ); } - - PopupMenuButton getPopUpBuilder(StoreItems item) { - return PopupMenuButton( - icon: const Icon(Icons.more_vert), - itemBuilder: (c) { - return [ - PopupMenuItem( - value: 'edit', - child: ValueText( - AppLocalizations.of(context)!.edit, - ), - ), - PopupMenuItem( - value: 'view', - child: ValueText( - AppLocalizations.of(context)!.view, - ), - ), - PopupMenuItem( - value: 'delete', - child: ValueText( - AppLocalizations.of(context)!.delete, - ), - ) - ]; - }, - onSelected: (String value) => actionPopUpItemSelected(value, item), - ); - } } diff --git a/lib/application/views/inventorymodule/productviews/SearchProductVC.dart b/lib/application/views/inventorymodule/productviews/SearchProductVC.dart index 38ba24c..274a406 100644 --- a/lib/application/views/inventorymodule/productviews/SearchProductVC.dart +++ b/lib/application/views/inventorymodule/productviews/SearchProductVC.dart @@ -1,9 +1,7 @@ -import 'dart:convert'; - import 'package:flutter/material.dart'; -import 'package:wosull/application/ViewModel/InventoryViewModel.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; import 'package:wosull/application/model/StockTransfer/ProductItemCategoryModel.dart'; +import 'package:wosull/application/repository/WosulRepository.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/theme/MyFonts.dart'; @@ -18,7 +16,7 @@ class _SearchProductVCState extends State { TextEditingController searchCountry = TextEditingController(); bool _isInAsyncCall = false; List productItems = List.empty(growable: true); - List filteredProductItems = List.empty(growable: true); + List filteredProductItems = []; bool isPortrait = false; @override @@ -34,7 +32,7 @@ class _SearchProductVCState extends State { elevation: 0, backgroundColor: const Color(0xffffffff), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(15.0), + borderRadius: BorderRadius.circular(8.0), ), child: OrientationBuilder(builder: (c, orientation) { isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; @@ -157,21 +155,19 @@ class _SearchProductVCState extends State { setState(() { _isInAsyncCall = true; }); - InventoryViewModel viewModel = InventoryViewModel(); + final viewModel = WosulRepository(); Map data = { 'store_id': sharedPrefs.storeId, 'search_value': filter }; - print(jsonEncode(data)); + await viewModel.getProductSearchStores(data).then((value) async { - if (value.success!) { - setState(() { - _isInAsyncCall = false; - filteredProductItems.clear(); - filteredProductItems.addAll(value.categories!); - }); - } + setState(() { + _isInAsyncCall = false; + filteredProductItems.clear(); + filteredProductItems.addAll(value); + }); }).onError((error, stackTrace) { setState(() { _isInAsyncCall = false; diff --git a/lib/application/views/inventorymodule/productviews/repo/ProductRepository.dart b/lib/application/views/inventorymodule/productviews/repo/ProductRepository.dart new file mode 100644 index 0000000..eabf59e --- /dev/null +++ b/lib/application/views/inventorymodule/productviews/repo/ProductRepository.dart @@ -0,0 +1,60 @@ +import 'package:wosull/application/model/Products/GetProductResponse.dart'; +import 'package:wosull/application/model/Products/ProductById.dart'; +import 'package:wosull/application/model/Products/SearchProductResponse.dart'; +import 'package:wosull/application/model/SimpleResponsModel.dart'; +import 'package:wosull/application/model/ingredients/AddProdcutModel.dart'; +import 'package:wosull/application/model/store/StoreItemsResponse.dart'; +import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/utils/Constants.dart'; + +class ProductRepository { + Future delete(String id) async { + Map data = {'productId': id}; + return await APIManager().getResponsePatch(Constants.DELETE_PRODUCT, data); + } + + Future update(String id, bool status) async { + Map data = {'productId': id, 'is_item_in_stock': status}; + return await APIManager() + .getResponsePatch(Constants.UPDATE_PRODUCT_STATUS, data); + } + + Future> search(Map data) async { + var items = []; + await APIManager().fetchData(Constants.SEARCH_PRODUCT, data).then((result) { + final value = SearchItemsResponse.fromJson(result); + if (value.success!) { + items.addAll(value.storeItems!); + } + }).onError((error, stackTrace) {}); + return items; + } + + Future> getProductItems(Map data) async { + var items = []; + await APIManager().fetchData(Constants.GET_ITEMS_URL, data).then((result) { + final value = GetProductResponse.fromJson(result); + if (value.success) { + items.addAll(value.storeItems); + } + }).onError((error, stackTrace) {}); + return items; + } + + Future updateProduct(Map map) async { + return await APIManager() + .getResponsePatch(Constants.UPDATE_PRODUCT_ITEM, map); + } + + Future addProduct(Map map) async { + final response = + await APIManager().fetchData(Constants.ADD_PRODUCT_ITEM, map); + return AddProductModel.fromJson(response); + } + + Future getProductById(String itemId) async { + final response = await APIManager() + .getResponseAuth("${Constants.GET_PRODUCT_BY_ID}/$itemId"); + return ProductById.fromJson(response); + } +} diff --git a/lib/application/views/inventorymodule/productviews/viewModels/AddIngredientViewModel.dart b/lib/application/views/inventorymodule/productviews/viewModels/AddIngredientViewModel.dart deleted file mode 100644 index e0f6b3c..0000000 --- a/lib/application/views/inventorymodule/productviews/viewModels/AddIngredientViewModel.dart +++ /dev/null @@ -1,379 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:wosull/application/localdb/SharedPrefs.dart'; -import 'package:wosull/application/model/Products/ItemProductModel.dart'; -import 'package:wosull/application/model/brands/GetBrandsModel.dart'; -import 'package:wosull/application/model/converters/DataTimeFormat.dart'; -import 'package:wosull/application/model/discount/StoreDiscountModel.dart'; -import 'package:wosull/application/model/inventory/AddIngredientModel.dart'; -import 'package:wosull/application/model/inventory/GetMeasurementCategory.dart'; -import 'package:wosull/application/model/inventory/category/ItemCategory.dart'; -import 'package:wosull/application/model/inventory/category/ItemCategoryResponse.dart'; -import 'package:wosull/application/model/store/GetStoreSupplier.dart'; -import 'package:wosull/application/model/store/StoreInvoicesModel.dart'; -import 'package:wosull/application/network/APIManager.dart'; -import 'package:wosull/application/utils/CRUDOperatoinState.dart'; -import 'package:wosull/application/utils/Constants.dart'; -import 'package:wosull/helpers/Utils.dart'; - -class AddIngredientViewModel with ChangeNotifier { - var addIngredient = AddIngredient(); - - // File? imageFile; - // bool isImageUploaded = false; - bool isLoading = false; - - var nameController = ''; - var productCode = ''; - var salePriceExclTax = ''; - var salePriceIncludeTax = ''; - var purchasePriceExclTax = ''; - var stockAlertQuantity = ''; - var quantityController = ''; - var descriptionController = ''; - var descriptionArabic = ''; - var barCodeController = ''; - - var isEditView = false; - - dynamic selectedCategory; - dynamic selectedDiscount; - dynamic selectedMeasurement; - dynamic selectedSupplier; - dynamic selectedBrand; - - var _crudOperationState = CRUDOperationState.uninitialized; - - CRUDOperationState get crudOperationState => _crudOperationState; - - void setInStock(bool value) { - addIngredient.isItemInStock = value; - notifyListeners(); - } - - void disposeData() { - isEditView = false; - selectedCategory = null; - addIngredient = AddIngredient(); - nameController = ''; - productCode = ''; - salePriceExclTax = ''; - salePriceIncludeTax = ''; - purchasePriceExclTax = ''; - stockAlertQuantity = ''; - quantityController = ''; - descriptionController = ''; - descriptionArabic = ''; - barCodeController = ''; - } - - void setData(AddIngredient ingredient) { - if (!isEditView) { - isEditView = true; - addIngredient = ingredient; - nameController = ingredient.name; - productCode = ingredient.productCode; - salePriceExclTax = ingredient.salePriceExclusiveTax.toString(); - salePriceIncludeTax = ingredient.salePriceInclusiveTax.toString(); - purchasePriceExclTax = ingredient.purchaseCost.toString(); - stockAlertQuantity = ingredient.stockAlertQuantity.toString(); - quantityController = ingredient.totalQuantity.toString(); - descriptionController = ingredient.details; - descriptionArabic = ingredient.itemDescriptionArabic; - barCodeController = ingredient.uniqueIdForStoreData.toString(); - } - } - - Future isValidate() async { - if (nameController.isEmpty) { - Utils.showMessage('Enter Ingredient Name'); - } else { - await addIngredientToServer(); - } - } - - Future getSubProducts(String categoryID) async { - String id = ""; - Map data = { - 'store_id': sharedPrefs.storeId, - 'category_id': categoryID, - }; - await APIManager() - .fetchData(Constants.ITEM_GET_PRODUCT_LIST_BY_CATEGORY, data) - .then((value) { - final values = ItemProductModel.fromJson(value); - if (values.success) { - id = values.product.id; - } else { - Utils.showMessage('Product not found against selected category'); - } - }).onError((error, stackTrace) {}); - - return id; - } - - setLoading(bool value) { - isLoading = value; - notifyListeners(); - } - - Future addIngredientToServer() async { - // addIngredient.productId = await getSubProducts(addIngredient.productId); - addIngredient.name = nameController; - addIngredient.stockAlertQuantity = int.parse(stockAlertQuantity); - addIngredient.productCode = productCode; - addIngredient.salePriceExclusiveTax = int.parse(salePriceIncludeTax); - addIngredient.price = int.parse(salePriceIncludeTax); - addIngredient.purchaseCost = int.parse(purchasePriceExclTax); - addIngredient.totalQuantity = int.parse(quantityController); - addIngredient.stockAlertQuantity = int.parse(stockAlertQuantity); - - await APIManager() - .fetchData(Constants.ADD_INGREDIENTS, addIngredient.toJson()) - .then((value) { - final response = AddIngredientModel.fromJson(value); - if (response.success) { - _crudOperationState = CRUDOperationState.add; - setLoading(false); - Utils.showMessage(response.message); - } else { - _crudOperationState = CRUDOperationState.error; - setLoading(false); - Utils.showMessage(response.message); - } - }).onError((error, stackTrace) { - setLoading(false); - }); - } - - // updateImage(String id) async { - // var request = http.MultipartRequest( - // 'POST', - // Uri.parse('${Constants.baseURL}api/store/update_ingredient_image'), - // ); - // Map headers = { - // "Authorization": Constants.auth, - // "Content-Type": "application/json" - // }; - // request.headers.addAll(headers); - // if (isImageUploaded) { - // request.files.add( - // http.MultipartFile( - // 'image_url', - // imageFile!.readAsBytes().asStream(), - // imageFile!.lengthSync(), - // filename: 'wosul', - // contentType: MediaType('image', 'jpeg'), - // ), - // ); - // } - // - // request.fields.addAll({ - // "item_id": id, - // }); - // - // var streamedResponse = await request.send(); - // var response = await http.Response.fromStream(streamedResponse); - // final result = jsonDecode(response.body) as Map; - // isLoading = false; - // notifyListeners(); - // if (result['success']) { - // _crudOperationState = CRUDOperationState.add; - // Utils.showMessage('Ingredient Added Successfully'); - // } - // } - - generateCode() { - String number = Utils.generateCode(); - barCodeController = number.toString(); - print(barCodeController); - notifyListeners(); - } - - void presentDatePicker(BuildContext context, bool isStart) { - // showDatePicker is a pre-made funtion of Flutter - showDatePicker( - context: context, - initialDate: DateTime.now(), - firstDate: DateTime(1965), - lastDate: DateTime(2030)) - .then((pickedDate) { - // Check if no date is selected - if (pickedDate == null) { - return; - } - if (isStart) { - addIngredient.manufacturerDate = - DataTimeFormat.formatDateFromPicket(pickedDate); - } else { - addIngredient.expiryDate = - DataTimeFormat.formatDateFromPicket(pickedDate); - } - notifyListeners(); - }); - } - - Future> getBrandsData() async { - var items = []; - - await APIManager() - .getResponseAuth(Constants.GET_BRANDS) - .then((value) { - final response = GetBrandsModel.fromJson(value); - if (response.success!) { - items.addAll(response.brands!); - if (isEditView) { - if (addIngredient.brand.isNotEmpty) { - selectedBrand = items.singleWhere( - (element) => element.name == addIngredient.brand); - } else { - selectedBrand = Brand(name: 'Choose'); - } - } - } - }) - .onError((error, stackTrace) {}) - .timeout(const Duration(minutes: 1)); - - return items; - } - - Future> getCategoriesData() async { - var items = []; - - await APIManager() - .fetchData( - Constants.GET_STORE_CATEGORY_LIST, Constants.getStorePayload()) - .then((value) { - final itemCategoryResponse = ItemCategoryResponse.fromJson(value); - if (itemCategoryResponse.success && - itemCategoryResponse.categories.isNotEmpty) { - items.addAll(itemCategoryResponse.categories); - if (isEditView) { - if (addIngredient.categoryId.isNotEmpty) { - selectedCategory = items.singleWhere( - (element) => element.id == addIngredient.categoryId); - addIngredient.categoryId = addIngredient.categoryId; - } else { - selectedCategory = ItemCategory(name: 'Choose'); - } - } else { - selectedCategory ??= items[0]; - addIngredient.categoryId = selectedCategory.id; - } - } - }).onError((error, stackTrace) { - print(error.toString()); - }); - - return items; - } - - Future> getSuppliersData() async { - var items = []; - - await APIManager() - .fetchData(Constants.GET_STORE_SUPPLIER, Constants.getStorePayload()) - .then((value) { - final response = GetStoreSupplier.fromJson(value); - if (response.success!) { - items.addAll(response.suppliers!); - if (isEditView) { - if (addIngredient.supplier.isNotEmpty) { - selectedSupplier = items.singleWhere( - (element) => element.name == addIngredient.supplier); - } else { - selectedSupplier = Supplier(name: 'Choose'); - } - } - } - }).onError((error, stackTrace) {}); - - return items; - } - - Future> getDiscount() async { - var items = []; - await APIManager() - .fetchData(Constants.GET_DISCOUNT, Constants.getStorePayload()) - .then((value) { - final response = StoreDiscountModel.fromJson(value); - if (response.success!) { - items.addAll(response.storeDiscount!); - if (isEditView) { - if (addIngredient.discount.isNotEmpty) { - selectedDiscount = items.singleWhere( - (element) => element.name == addIngredient.discount); - } else { - selectedDiscount = StoreDiscount(name: 'Choose'); - } - } - } - }).onError((error, stackTrace) {}); - - return items; - } - - Future> getMeasurementData() async { - var items = []; - - await APIManager() - .getResponseAuth(Constants.GET_MEASUREMENT_CATEGORY) - .then((value) { - final response = GetMeasurementCategoryModel.fromJson(value); - if (response.success!) { - items.addAll(response.measurements!); - if (isEditView) { - if (addIngredient.measurement.isNotEmpty) { - selectedMeasurement = items.singleWhere( - (element) => element.name == addIngredient.measurement); - } else { - selectedMeasurement = MeasurementCategory(name: 'Choose'); - } - } - } - }) - .onError((error, stackTrace) {}) - .timeout(const Duration(minutes: 1)); - - return items; - } - - void setIngredient(Brand? data) { - if (data != null) { - addIngredient.brand = data.name!; - } - notifyListeners(); - } - - void setMeasurement(MeasurementCategory? data) { - if (data != null) { - addIngredient.measurementCategory = data.name!; - } - notifyListeners(); - } - - void setSupplier(Supplier? data) { - if (data != null) { - addIngredient.supplier = data.name!; - } - notifyListeners(); - } - - void setSelectedCategory(ItemCategory? data) { - if (data != null) { - selectedCategory = data; - addIngredient.categoryId = data.id; - } else { - addIngredient.categoryId = ''; - } - notifyListeners(); - } - - void setIsEditView(bool isEdit, bool isView) { - if (isEdit || isView) { - isEditView = true; - } else { - isEditView = false; - } - } -} diff --git a/lib/application/views/inventorymodule/productviews/viewModels/AddProductViewModel.dart b/lib/application/views/inventorymodule/productviews/viewModels/AddProductViewModel.dart index e9c4bb1..75c85eb 100644 --- a/lib/application/views/inventorymodule/productviews/viewModels/AddProductViewModel.dart +++ b/lib/application/views/inventorymodule/productviews/viewModels/AddProductViewModel.dart @@ -1,5 +1,4 @@ import 'dart:convert'; -import 'dart:developer'; import 'dart:io'; import 'package:flutter/material.dart'; @@ -10,41 +9,38 @@ import 'package:objectbox/objectbox.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; import 'package:wosull/application/model/DeliveryPartner/GetDeliveryPartner.dart'; import 'package:wosull/application/model/DeliveryPartner/ItemsDeliveryPartner.dart'; -import 'package:wosull/application/model/Modifiers/GetModifiersModel.dart'; -import 'package:wosull/application/model/Products/ItemProductModel.dart'; +import 'package:wosull/application/model/Measurement/InventoryMeasurementModel.dart'; +import 'package:wosull/application/model/Measurement/MeasurementUnitModel.dart'; +import 'package:wosull/application/model/Modifiers/Modifier.dart'; +import 'package:wosull/application/model/Products/AddProduct.dart'; +import 'package:wosull/application/model/Products/ProductId.dart'; import 'package:wosull/application/model/converters/DataTimeFormat.dart'; import 'package:wosull/application/model/discount/StoreDiscountModel.dart'; -import 'package:wosull/application/model/inventory/AddIngredientModel.dart'; -import 'package:wosull/application/model/inventory/InventoryMeasurementModel.dart'; -import 'package:wosull/application/model/inventory/MeasurementUnitModel.dart'; +import 'package:wosull/application/model/ingredients/AddIngredient.dart'; import 'package:wosull/application/model/inventory/category/ItemCategory.dart'; -import 'package:wosull/application/model/inventory/category/ItemCategoryResponse.dart'; -import 'package:wosull/application/model/store/GetStoreSupplier.dart'; import 'package:wosull/application/model/store/StoreInvoicesModel.dart'; -import 'package:wosull/application/model/store/StoreItemsResponse.dart'; -import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/repository/WosulRepository.dart'; +import 'package:wosull/application/utils/CRUDOperatoinState.dart'; import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/inventorymodule/deliveryPartnerViews/repository/DeliveryPartnerRepository.dart'; +import 'package:wosull/application/views/inventorymodule/ingredientsViews/repo/IngredientRepository.dart'; +import 'package:wosull/application/views/inventorymodule/modifierviews/repo/ModifierRepository.dart'; +import 'package:wosull/application/views/inventorymodule/productviews/repo/ProductRepository.dart'; +import 'package:wosull/helpers/DatePicker.dart'; import 'package:wosull/helpers/Utils.dart'; class AddProductViewModel with ChangeNotifier { - var nameController = ''; - var productCode = ''; - var salePriceExclTax = ''; - var salePriceIncludeTax = ''; - var purchasePriceExclTax = ''; - var stockAlertQuantity = ''; - var quantityController = ''; - var descriptionController = ''; - var descriptionArabic = ''; - var barCodeController = ''; - List unitsController = []; + final repository = ProductRepository(); List selectedMod = []; List selectedPartners = []; + List selectedIngredientsMeasurement = []; dynamic selectedCategory; dynamic selectedDiscount; dynamic selectedSupplier; + dynamic selectedMeasurement; + dynamic selectedMeasurementUnit; var isLoadingData = false; File? imageFile; @@ -53,49 +49,43 @@ class AddProductViewModel with ChangeNotifier { var isEdit = false; var isView = false; - var storeItem = StoreItems( - isUnlimitedQuantity: false, - modifiers: ToMany(items: []), - ingredients: ToMany(items: []), - selectedModifiers: ToMany(items: []), - deliveryPartners: ToMany(items: []), - comboProduct: ToMany(items: []), - selectedCombos: ToMany(items: [])); + late AddProduct storeItem; + + var isLoadingFirst = true; + + var _crudOperation = CRUDOperationState.uninitialized; + + CRUDOperationState get crudOperation => _crudOperation; + + void setState(CRUDOperationState state) { + _crudOperation = state; + } void initDeliveryPartner() { - storeItem.deliveryPartners = ToMany(items: []); - storeItem.deliveryPartners!.add(ItemsDeliveryPartner()); + storeItem.deliveryPartners.add(ItemsDeliveryPartner()); + selectedPartners.add(DeliveryPartner(id: '', name: 'Choose Partner')); } void disposeData() { + isLoadingFirst = true; selectedPartners.clear(); selectedMod.clear(); - unitsController.clear(); - nameController = ''; - productCode = ''; - salePriceExclTax = ''; - salePriceIncludeTax = ''; - purchasePriceExclTax = ''; - stockAlertQuantity = ''; - quantityController = ''; - descriptionController = ''; - descriptionArabic = ''; - barCodeController = ''; + selectedIngredientsMeasurement.clear(); selectedCategory = null; selectedDiscount = null; selectedSupplier = null; + selectedMeasurement = null; + selectedMeasurementUnit = null; isLoadingData = false; imageFile = null; isImageUploaded = false; isEdit = false; - storeItem = StoreItems( + storeItem = AddProduct( isUnlimitedQuantity: false, - modifiers: ToMany(items: []), - ingredients: ToMany(items: []), - selectedModifiers: ToMany(items: []), - deliveryPartners: ToMany(items: []), - comboProduct: ToMany(items: []), - selectedCombos: ToMany(items: [])); + modifiers: [], + ingredients: [], + selectedModifiers: [], + deliveryPartners: []); } void editDeliveryPartner(int position, DeliveryPartner? partner) { @@ -103,17 +93,17 @@ class AddProductViewModel with ChangeNotifier { var deliveryPartner = ItemsDeliveryPartner(id: partner.id, name: partner.name, price: 0.0); var selected = DeliveryPartner(id: partner.id, name: partner.name); - if (storeItem.deliveryPartners!.isNotEmpty) { + if (storeItem.deliveryPartners.isNotEmpty) { selectedPartners[position] = selected; - storeItem.deliveryPartners![position] = deliveryPartner; + storeItem.deliveryPartners[position] = deliveryPartner; } else { selectedPartners.add(selected); - storeItem.deliveryPartners!.add(deliveryPartner); + storeItem.deliveryPartners.add(deliveryPartner); } } else { selectedPartners[position] = DeliveryPartner(id: '', name: 'Choose Partner'); - storeItem.deliveryPartners![position].name = ''; + storeItem.deliveryPartners[position].name = ''; } notifyListeners(); @@ -121,57 +111,43 @@ class AddProductViewModel with ChangeNotifier { void editDeliveryPartnerPrice(int position, String price) { if (price.isNotEmpty) { - storeItem.deliveryPartners![position].price = double.parse(price); + storeItem.deliveryPartners[position].price = double.parse(price); } else { - storeItem.deliveryPartners![position].price = 0; + storeItem.deliveryPartners[position].price = 0; } - - // notifyListeners(); } void addNewDeliveryPartner() { - if (storeItem.deliveryPartners!.isEmpty) { + if (storeItem.deliveryPartners.isEmpty) { storeItem.deliveryPartners = ToMany(items: []); } - storeItem.deliveryPartners!.add(ItemsDeliveryPartner()); + storeItem.deliveryPartners.add(ItemsDeliveryPartner()); selectedPartners.add(DeliveryPartner(id: '', name: 'Choose Partner')); notifyListeners(); } void removeDeliveryPartner(int position) { - if (storeItem.deliveryPartners!.isNotEmpty) { - storeItem.deliveryPartners!.removeAt(position); + if (storeItem.deliveryPartners.isNotEmpty) { + storeItem.deliveryPartners.removeAt(position); selectedPartners.removeAt(position); } notifyListeners(); } - void setDataOnEdit(StoreItems storeItems) { - if (!isEdit) { - isEdit = true; - selectedMod.clear(); - for (var mod in storeItems.modifiers!) { - selectedMod.add(mod.id); - } - storeItem = storeItems; - selectedPartners = []; - for (var mod in storeItem.deliveryPartners!) { - selectedPartners.add(DeliveryPartner(id: mod.id, name: mod.name)); - } - nameController = storeItems.name; - productCode = storeItems.itemNameArabic; - salePriceExclTax = storeItems.salePriceExclusiveTax.toString(); - salePriceIncludeTax = storeItems.price.toString(); - purchasePriceExclTax = storeItems.purchasePrice.toString(); - stockAlertQuantity = storeItems.stockAlertQuantity.toString(); - quantityController = storeItems.totalAddedQuantity.toString(); - descriptionController = storeItems.description.toString(); - descriptionArabic = storeItems.descriptionArabic.toString(); - barCodeController = storeItems.uniqueIdForStoreData.toString(); - - for (var item in storeItems.ingredients!) { - unitsController.add(item.defaultSalePrice!.toString()); - } + Future setDataOnEdit(bool isEdit, String itemId) async { + this.isEdit = isEdit; + if (isEdit) { + await getProductById(itemId); + notifyListeners(); + } else { + storeItem = AddProduct( + isUnlimitedQuantity: false, + modifiers: ToMany(items: []), + ingredients: ToMany(items: []), + selectedModifiers: ToMany(items: []), + deliveryPartners: ToMany(items: []), + ); + initDeliveryPartner(); } } @@ -201,177 +177,101 @@ class AddProductViewModel with ChangeNotifier { } } - void presentDatePicker(BuildContext context, bool isStart) { - // if (widget.isView) { - // return; - // } - // showDatePicker is a pre-made funtion of Flutter - showDatePicker( - context: context, - initialDate: DateTime.now(), - firstDate: DateTime(1965), - lastDate: DateTime(2030)) - .then((pickedDate) { - // Check if no date is selected - if (pickedDate == null) { - return; - } - if (isStart) { - storeItem.manufactureDate = - DataTimeFormat.formatDateFromPicket(pickedDate); - } else { - storeItem.expireDate = DataTimeFormat.formatDateFromPicket(pickedDate); - } - notifyListeners(); - }); + Future presentDatePicker(BuildContext context, bool isStart) async { + final pickedDate = await DatePicker.presentDatePicker(context, isStart); + if (pickedDate == null) { + return; + } + if (isStart) { + storeItem.manufactureDate = + DataTimeFormat.formatDateFromPicketINVOICE(pickedDate); + } else { + storeItem.expireDate = + DataTimeFormat.formatDateFromPicketINVOICE(pickedDate); + } + notifyListeners(); } - void isValidate(BuildContext context, bool isEdit) { - print(storeItem.isUnlimitedQuantity); - print(quantityController); - if (nameController.isEmpty) { + Future isValidate(BuildContext context, bool isEdit) async { + if (storeItem.name.isEmpty) { Utils.showMessage('Enter Product Name'); - } else if (salePriceIncludeTax.isEmpty) { + } else if (storeItem.price == 0) { Utils.showMessage('Enter Sale price incl Tax Name'); - } else if (barCodeController.isEmpty) { + } else if (storeItem.uniqueIdForStoreData.isEmpty) { Utils.showMessage('Enter bar code or Generate'); - } else if (descriptionController.isEmpty) { + } else if (storeItem.description.isEmpty) { Utils.showMessage('Enter Description'); } else if (!storeItem.isUnlimitedQuantity && - int.parse(quantityController) == 0) { + storeItem.totalAddedQuantity == 0) { Utils.showMessage('Enter Quantity'); } else { if (isEdit) { - updateProduct(context); + await updateProduct(); } else { - addProduct(context); + await addProduct(); } } } - Future updateProduct(BuildContext context) async { + Future updateProduct() async { isLoadingData = true; notifyListeners(); - storeItem.product_product_id = storeItem.id; + storeItem.product_product_id = storeItem.itemId; var productId = ProductId(); - productId.categoryId = storeItem.productId; - productId.productId = await getSubProducts(storeItem.productId); - storeItem.productIdUpdate = productId; - storeItem.name = nameController; - storeItem.itemNameArabic = productCode; - if (salePriceExclTax.isNotEmpty) { - storeItem.salePriceExclusiveTax = double.parse(salePriceExclTax); - } else { - storeItem.salePriceExclusiveTax = 0.0; - } + ItemCategory selected = selectedCategory; + productId.categoryId = selected.id; + productId.productId = await getSubProducts(selected.id); + storeItem.productId = productId; - if (salePriceIncludeTax.isNotEmpty) { - storeItem.price = double.parse(salePriceIncludeTax); - } else { - storeItem.price = 0.0; - } - - if (purchasePriceExclTax.isNotEmpty) { - storeItem.purchasePrice = double.parse(purchasePriceExclTax); - } else { - storeItem.purchasePrice = 0.0; - } - if (stockAlertQuantity.isNotEmpty) { - storeItem.stockAlertQuantity = int.parse(stockAlertQuantity); - } else { - storeItem.stockAlertQuantity = 0; - } - - if (quantityController.isNotEmpty) { - storeItem.totalAddedQuantity = int.parse(quantityController); - } else { - storeItem.totalAddedQuantity = 0; - } - - storeItem.description = descriptionController; - storeItem.descriptionArabic = descriptionArabic; - log(jsonEncode(storeItem.toJsonUpdateProduct())); - - await APIManager() - .getResponsePatch( - Constants.UPDATE_PRODUCT_ITEM, storeItem.toJsonUpdateProduct()) + await repository + .updateProduct(storeItem.toJsonUpdateProduct()) .then((value) { if (value.success) { Utils.showMessage(value.message); - Navigator.pop(context, true); + setState(CRUDOperationState.update); } else { + setState(CRUDOperationState.error); isLoadingData = false; notifyListeners(); Utils.showMessage(value.message); } }).onError((error, stackTrace) { + setState(CRUDOperationState.error); isLoadingData = false; notifyListeners(); }); } - Future addProduct(BuildContext context) async { + Future addProduct() async { isLoadingData = true; notifyListeners(); - storeItem.productId = await getSubProducts(storeItem.productId); - storeItem.name = nameController; - storeItem.itemNameArabic = productCode; - storeItem.isItemInStock = storeItem.isItemInStock; - if (salePriceExclTax.isNotEmpty) { - storeItem.salePriceExclusiveTax = double.parse(salePriceExclTax); - } else { - storeItem.salePriceExclusiveTax = 0.0; - } - - if (salePriceIncludeTax.isNotEmpty) { - storeItem.price = double.parse(salePriceIncludeTax); - } else { - storeItem.price = 0.0; - } - - if (purchasePriceExclTax.isNotEmpty) { - storeItem.purchasePrice = double.parse(purchasePriceExclTax); - } else { - storeItem.purchasePrice = 0.0; - } - if (stockAlertQuantity.isNotEmpty) { - storeItem.stockAlertQuantity = int.parse(stockAlertQuantity); - } else { - storeItem.stockAlertQuantity = 0; - } - - if (quantityController.isNotEmpty) { - storeItem.totalAddedQuantity = int.parse(quantityController); - } else { - storeItem.totalAddedQuantity = 0; - } - - storeItem.description = descriptionController; - storeItem.descriptionArabic = descriptionArabic; - log(jsonEncode(storeItem.toJsonProduct())); - await APIManager() - .fetchData(Constants.ADD_PRODUCT_ITEM, storeItem.toJsonProduct()) - .then((value) { - print(jsonEncode(value)); - final response = AddProductModel.fromJson(value); + storeItem.productIdSt = await getSubProducts(storeItem.productIdSt); + await repository.addProduct(storeItem.toJsonProduct()).then((response) { if (response.success) { if (response.product.id.isNotEmpty) { - updateImage(context, response.product.id); + if (isImageUploaded) { + updateImage(response.product.id); + } else { + Utils.showMessage('Product Added Successfully'); + setState(CRUDOperationState.add); + notifyListeners(); + } } else { Utils.showMessage('Product have issue'); } } else if (response.message == 897) { + setState(CRUDOperationState.error); isLoadingData = false; notifyListeners(); Utils.showMessage('Item Already Added'); } else { + setState(CRUDOperationState.error); isLoadingData = false; notifyListeners(); - print('error'); } }).onError((error, stackTrace) { - print(error.toString()); + setState(CRUDOperationState.error); isLoadingData = false; notifyListeners(); }); @@ -379,32 +279,24 @@ class AddProductViewModel with ChangeNotifier { Future getSubProducts(String categoryID) async { String id = ""; - Map data = { - 'store_id': sharedPrefs.storeId, - 'category_id': categoryID, - }; - print(jsonEncode(data)); - await APIManager() - .fetchData(Constants.ITEM_GET_PRODUCT_LIST_BY_CATEGORY, data) - .then((value) { - final values = ItemProductModel.fromJson(value); + await IngredientRepository().getSubProducts(categoryID).then((values) { if (values.success) { - id = values.product.id; + if (values.product.isNotEmpty) { + id = values.product.first.id; + } } else { isLoadingData = false; notifyListeners(); Utils.showMessage('Product not found against selected category'); } }).onError((error, stackTrace) { - print('getSubProducts'); isLoadingData = false; notifyListeners(); }); - return id; } - updateImage(BuildContext context, String id) async { + updateImage(String id) async { //var request = http.MultipartRequest('POST', Uri.parse(Constants.baseURL+'api/store/update_ingredient_image')); var request = http.MultipartRequest( 'POST', @@ -426,25 +318,25 @@ class AddProductViewModel with ChangeNotifier { contentType: MediaType('image', 'jpeg'), ), ); - } - request.fields.addAll({'item_id': id, 'type': "1"}); - var streamedResponse = await request.send(); - var response = await http.Response.fromStream(streamedResponse); - // final respStr = await streamedResponse.stream.bytesToString(); + request.fields.addAll({'item_id': id, 'type': "1"}); + var streamedResponse = await request.send(); + var response = await http.Response.fromStream(streamedResponse); + final result = jsonDecode(response.body) as Map; + if (result['success']) { + Utils.showMessage('Product Added Successfully'); + setState(CRUDOperationState.add); + } + } else { + setState(CRUDOperationState.add); + } isLoadingData = false; notifyListeners(); - final result = jsonDecode(response.body) as Map; - if (result['success']) { - Utils.showMessage('Product Added Successfully'); - Navigator.pop(context, true); - } } generateCode() { String number = Utils.generateCode(); - barCodeController = number; - storeItem.uniqueId = int.parse(number); + storeItem.uniqueIdForStoreData = number; notifyListeners(); } @@ -455,10 +347,9 @@ class AddProductViewModel with ChangeNotifier { Future> getIngredients() async { var items = []; - await APIManager().getResponseAuth(Constants.GET_INGREDIENTS).then((value) { - final response = GetIngredientModel.fromJson(value); - if (response.success) { - items.addAll(response.ingredient); + await WosulRepository().getIngredients().then((value) { + if (value.isNotEmpty) { + items.addAll(value); } }).onError((error, stackTrace) {}); return items; @@ -467,24 +358,19 @@ class AddProductViewModel with ChangeNotifier { Future> getDiscount() async { var items = []; - await APIManager() - .fetchData(Constants.GET_DISCOUNT, Constants.getStorePayload()) - .then((value) { - final response = StoreDiscountModel.fromJson(value); - if (response.success!) { - items.addAll(response.storeDiscount!); - - if (isEdit) { - for (var item in items) { - if (item.name! == storeItem.discount) { - selectedDiscount = item; - } - } + await WosulRepository().getDiscount().then((value) { + if (value.isNotEmpty) { + items.addAll(value); + if (isEdit) { + for (var item in items) { + if (item.name == storeItem.discount) { + selectedDiscount = item; } } - }) - .onError((error, stackTrace) {}) - .timeout(const Duration(minutes: 1)); + } + selectedDiscount ??= StoreDiscount(name: 'Choose'); + } + }).onError((error, stackTrace) {}); return items; } @@ -492,66 +378,52 @@ class AddProductViewModel with ChangeNotifier { Future> getSuppliersData() async { var items = []; - await APIManager() - .fetchData(Constants.GET_STORE_SUPPLIER, Constants.getStorePayload()) - .then((value) { - final response = GetStoreSupplier.fromJson(value); - if (response.success!) { - items.addAll(response.suppliers!); - print(storeItem.supplier); + await WosulRepository().getSuppliersData().then((value) { + if (value.isNotEmpty) { + items.addAll(value); if (isEdit) { selectedSupplier ??= items.singleWhere((element) => element.id! == storeItem.supplier); } - print(selectedSupplier); - if (selectedSupplier == null) { - selectedSupplier ??= Supplier(name: 'Choose'); - } + selectedSupplier ??= Supplier(name: 'Choose'); } }).onError((error, stackTrace) {}); - return items; } - Future> getCategoriesData(String categoryID) async { + Future> getCategoriesData() async { var items = []; - - final response = await APIManager().fetchData( - Constants.GET_STORE_CATEGORY_LIST, Constants.getStorePayload()); - final itemCategoryResponse = ItemCategoryResponse.fromJson(response); - if (itemCategoryResponse.success && - itemCategoryResponse.categories.isNotEmpty) { - items.addAll(itemCategoryResponse.categories); - // storeItem.productId = items[0].id!; - if (isEdit) { - if (selectedCategory == null) { - for (var item in items) { - if (item.id == categoryID) { - selectedCategory = item; - storeItem.productId = selectedCategory.id!; - } + await WosulRepository().getStoreCategoriesData().then((data) { + if (data.isNotEmpty) { + items.addAll(data); + if (isEdit) { + if (selectedCategory == null) { + selectedCategory = items.singleWhere( + (element) => element.id == storeItem.productId!.categoryId!); + storeItem.productIdSt = selectedCategory.id!; + } else { + storeItem.productIdSt = selectedCategory.id!; } } else { - storeItem.productId = selectedCategory.id!; + selectedCategory = items[0]; + storeItem.productIdSt = items.first.id; } - } else { - selectedCategory ??= items[0]; - storeItem.productId = selectedCategory.id!; } - } + }).onError((error, stackTrace) {}); return items; } Future> getMeasurement() async { var items = []; - Map data = { - 'store_id': sharedPrefs.storeId, - }; - - await APIManager().fetchData(Constants.GET_MEASUREMENT, data).then((value) { - final response = ProductMeasurementModel.fromJson(value); - if (response.success!) { - items.addAll(response.measurements!); + await WosulRepository().getMeasurement().then((data) { + if (data.isNotEmpty) { + items.addAll(data); + if (isEdit) { + final name = items + .singleWhere((element) => element.name == storeItem.measurement) + .name; + selectedMeasurement = Measurement(id: '', name: name ?? ''); + } } }).onError((error, stackTrace) {}); @@ -560,37 +432,33 @@ class AddProductViewModel with ChangeNotifier { Future> getAllPartners() async { var items = []; - - await APIManager() - .getResponseAuth( - Constants.getStoreDeliveryPartner + sharedPrefs.storeId) - .then((value) { - final response = GetDeliveryPartner.fromJson(value); - if (response.success!) { - items.addAll(response.deliveries!); - } - }) - .onError((error, stackTrace) {}) - .timeout(const Duration(minutes: 1)); - + await DeliveryPartnerRepository().getAllPartners().then((value) { + if (value.isNotEmpty) { + items.addAll(value); + } + }).onError((error, stackTrace) {}); return items; } - Future> getMeasurements() async { + Future> getMeasurements(bool isIngredient) async { var items = []; - - await APIManager() - .fetchData(Constants.GET_INVENTORY_MEASUREMENTS_UNITS, - Constants.getStorePayload()) - .then((value) { - final response = MeasurementUnitModel.fromJson(value); - if (response.success) { - items.addAll(response.measurementUnits); + await WosulRepository().getMeasurements().then((value) { + if (value.isNotEmpty) { + items.addAll(value); + if (isEdit && !isIngredient) { + final name = items + .singleWhere( + (element) => element.name == storeItem.measurementUnit) + .name; + selectedMeasurementUnit = MeasurementUnit(id: '', name: name ?? ''); + } else if (isEdit && isIngredient) { + for (var measurement in storeItem.ingredients) { + selectedIngredientsMeasurement + .add(MeasurementUnit(id: '', name: measurement.measurement)); } - }) - .onError((error, stackTrace) {}) - .timeout(const Duration(minutes: 1)); - + } + } + }).onError((error, stackTrace) {}); return items; } @@ -599,28 +467,24 @@ class AddProductViewModel with ChangeNotifier { Map data = { 'store_id': sharedPrefs.storeId, }; - - await APIManager() - .fetchData(Constants.GET_MODIFIERS, data) - .then((value) { - final response = GetModifiersModel.fromJson(value); - if (response.success!) { - items.addAll(response.modifiers!); - } - }) - .onError((error, stackTrace) {}) - .timeout(const Duration(minutes: 1)); - + await ModifierRepository().fetch(data).then((value) { + if (value.isNotEmpty) { + items.addAll(value); + } + }).onError((error, stackTrace) {}); return items; } void setMeasurementUnit(int position, MeasurementUnit? measurementUnit) { if (measurementUnit != null) { - storeItem.ingredients![position].measuringUnit = measurementUnit.name; + storeItem.ingredients[position].measuringUnit = measurementUnit.name; + selectedIngredientsMeasurement[position] = + MeasurementUnit(id: '', name: measurementUnit.name); } else { - storeItem.ingredients![position].measuringUnit = ""; + storeItem.ingredients[position].measuringUnit = ""; + selectedIngredientsMeasurement[position] = + MeasurementUnit(id: '', name: ''); } - notifyListeners(); } @@ -635,7 +499,7 @@ class AddProductViewModel with ChangeNotifier { void setSelectedCategory(ItemCategory? data) { if (data != null) { selectedCategory = data; - storeItem.productId = data.id; + storeItem.productIdSt = data.id; } } @@ -647,19 +511,20 @@ class AddProductViewModel with ChangeNotifier { void setIngredient(AddIngredient? data) { if (data != null) { - unitsController.add(data.defaultSalePrice.toString()); - storeItem.ingredients!.add(data); + selectedIngredientsMeasurement + .add(MeasurementUnit(id: '', name: 'Choose')); + storeItem.ingredients.add(data); } notifyListeners(); } void setModifier(Modifier itemsList) { if (selectedMod.contains(itemsList.id)) { - storeItem.modifiers!.removeWhere((element) => element.id == itemsList.id); + storeItem.modifiers.removeWhere((element) => element == itemsList.id); selectedMod.remove(itemsList.id); } else { selectedMod.add(itemsList.id); - storeItem.modifiers!.add(itemsList); + storeItem.modifiers.add(itemsList.id); } notifyListeners(); @@ -667,40 +532,88 @@ class AddProductViewModel with ChangeNotifier { void setMeasurement(Measurement? data) { if (data != null) { + selectedMeasurement = Measurement(id: '', name: data.name); storeItem.measurement = data.name!; } } void removeUnit(int position) { - unitsController.removeAt(position); - storeItem.ingredients!.removeAt(position); + selectedIngredientsMeasurement.removeAt(position); + storeItem.ingredients.removeAt(position); notifyListeners(); } void setPrice(String value) { if (value.isEmpty) { - salePriceExclTax = ''; + storeItem.salePriceExclusiveTax = 0.0; } else { - salePriceIncludeTax = value; - + storeItem.price = double.parse(value); int percentage = 15; double tax = (double.parse(value) * percentage) / 100; - - salePriceExclTax = (double.parse(value) - tax).toStringAsFixed(2); + storeItem.salePriceExclusiveTax = (double.parse(value) - tax); } - notifyListeners(); } void setIsUnlimitedQuantity(bool? value) { storeItem.isUnlimitedQuantity = value ?? false; - print(storeItem.isUnlimitedQuantity); notifyListeners(); } void setQuantity(String value) { storeItem.totalAddedQuantity = int.parse(value); - quantityController = value; - print(storeItem.totalAddedQuantity); + } + + Future getProductById(String itemId) async { + await ProductRepository().getProductById(itemId).then((response) { + if (response.success) { + storeItem = response.item; + selectedMod.clear(); + selectedMod.addAll(storeItem.modifiers); + selectedPartners = []; + for (var mod in storeItem.deliveryPartners) { + selectedPartners.add(DeliveryPartner(id: mod.id, name: mod.name)); + } + isLoadingFirst = false; + } + }).onError((error, stackTrace) { + isLoadingFirst = false; + }); + } + + void removeIngredient(int position) { + storeItem.ingredients.removeAt(position); + notifyListeners(); + } + + void updateIngredientUnitPrice(int position, String value) { + if (value.isNotEmpty) { + storeItem.ingredients[position].price = double.parse(value); + } + } + + void setMeasurementUnitProduct(MeasurementUnit? data) { + if (data != null) { + selectedMeasurementUnit = data; + storeItem.measurementUnit = data.name; + } else { + storeItem.measurementUnit = ''; + } + } + + void updatePurchasePrice(String value) { + if (value.isNotEmpty) { + storeItem.purchasePrice = double.parse(value); + } else { + storeItem.purchasePrice = 0; + } + } + + void updateStockAlert(String value) { + if (value.isNotEmpty) { + storeItem.stockAlertQuantity = int.parse(value); + } else { + storeItem.stockAlertQuantity = 0; + } } } diff --git a/lib/application/views/inventorymodule/productviews/viewModels/ProductViewModel.dart b/lib/application/views/inventorymodule/productviews/viewModels/ProductViewModel.dart index 9fdcac7..d6ada7c 100644 --- a/lib/application/views/inventorymodule/productviews/viewModels/ProductViewModel.dart +++ b/lib/application/views/inventorymodule/productviews/viewModels/ProductViewModel.dart @@ -1,20 +1,19 @@ import 'package:flutter/cupertino.dart'; import 'package:wosull/application/enum/DataState.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; -import 'package:wosull/application/model/Products/ItemProductModel.dart'; import 'package:wosull/application/model/inventory/category/ItemCategory.dart'; -import 'package:wosull/application/model/inventory/category/ItemCategoryResponse.dart'; import 'package:wosull/application/model/store/StoreItemsResponse.dart'; -import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/repository/WosulRepository.dart'; import 'package:wosull/application/utils/CRUDOperatoinState.dart'; -import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/inventorymodule/ingredientsViews/repo/IngredientRepository.dart'; +import 'package:wosull/application/views/inventorymodule/productviews/repo/ProductRepository.dart'; class ProductViewModel with ChangeNotifier { - bool _isFirstLoadRunning = true; + bool _isFirstLoadRunning = false; bool get isFirstLoadRunning => _isFirstLoadRunning; - - String selectedCategoryId = ""; + int limit = 10; + String selectedCategoryId = "All"; List _dataList = []; List _filteredList = []; @@ -30,11 +29,12 @@ class ProductViewModel with ChangeNotifier { DataState get dataState => _dataState; bool _didLastLoad = false; - bool _isLoading = false; + bool _isLoading = true; + final repository = ProductRepository(); bool get isLoading => _isLoading; String productId = ""; - late ItemCategory selectedCategoryDropDown; + String selectedCategoryName = 'All'; List categories = []; CRUDOperationState _crudOperationState = CRUDOperationState.uninitialized; @@ -42,64 +42,41 @@ class ProductViewModel with ChangeNotifier { CRUDOperationState get crudOperationState => _crudOperationState; void getCategory() async { - final response = await APIManager().fetchData( - Constants.GET_STORE_CATEGORY_LIST, Constants.getStorePayload()); - final itemCategoryResponse = ItemCategoryResponse.fromJson(response); - if (itemCategoryResponse.success && - itemCategoryResponse.categories.isNotEmpty) { - categories.addAll(itemCategoryResponse.categories); + await WosulRepository().getStoreCategoriesData().then((categories) { if (categories.isNotEmpty) { - selectedCategoryId = categories.first.id ?? ''; - selectedCategoryDropDown = categories.first; + categories.addAll(categories); + if (categories.isNotEmpty) { + selectedCategoryId = categories.first.id ?? ''; + // selectedCategoryDropDown = categories.first; + _isFirstLoadRunning = false; + getSubProducts(selectedCategoryId); + } + } else { + selectedCategoryId = ""; + _isLoading = false; _isFirstLoadRunning = false; - getSubProducts(selectedCategoryId); } - } else { - selectedCategoryId = ""; - selectedCategoryDropDown = ItemCategory( - name: "Choose", - id: '', - isVisibleInStore: false, - createdAt: '', - updatedAt: '', - description: '', - arabicName: '', - store_id: [], - image_url: '', - ); - _isLoading = false; - _isFirstLoadRunning = false; - } + }).onError((error, stackTrace) {}); } void getSubProducts(String categoryID, {bool isRefresh = false}) async { - _isLoading = true; - if (isRefresh) { - _isLoading = true; - } - notifyListeners(); - Map data = { - 'store_id': sharedPrefs.storeId, - 'category_id': categoryID, - }; - - final response = await APIManager() - .fetchData(Constants.ITEM_GET_PRODUCT_LIST_BY_CATEGORY, data); - - final values = ItemProductModel.fromJson(response); - - if (values.success) { - productId = values.product.id; - fetch(isRefresh: isRefresh); - } else { - _filteredList.clear(); - _dataList.clear(); - _isLoading = false; - notifyListeners(); - } + await IngredientRepository().getSubProducts(categoryID).then((values) { + if (values.success) { + if (values.product.isNotEmpty) { + productId = values.product.first.id; + } + fetch(isRefresh: isRefresh); + } else { + _filteredList.clear(); + _dataList.clear(); + _isLoading = false; + notifyListeners(); + } + }).onError((error, stackTrace) {}); } - fetch({bool isRefresh = false}) async { + fetch({bool isRefresh = false, int limit = 10}) async { + this.limit = limit; _isLoading = true; if (!isRefresh) { _dataState = (_dataState == DataState.uninitialized) @@ -117,24 +94,22 @@ class ProductViewModel with ChangeNotifier { 'product_id': productId, 'category_id': selectedCategoryId, 'page': _currentPageNumber, + 'limit': this.limit }; try { if (_didLastLoad) { _dataState = DataState.noMoreData; } else { - await APIManager() - .fetchData(Constants.GET_ITEMS_URL, data) - .then((result) { - final value = StoreItemsResponse.fromJson(result); + await repository.getProductItems(data).then((storeItems) { if (_dataState == DataState.refreshing) { _filteredList.clear(); _dataList.clear(); } - if (value.success!) { - _filteredList.addAll(value.storeItems!); - _dataList.addAll(value.storeItems!); - if (value.storeItems!.length < 10) { + if (storeItems.isNotEmpty) { + _filteredList.addAll(storeItems); + _dataList.addAll(storeItems); + if (storeItems.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; @@ -173,13 +148,10 @@ class ProductViewModel with ChangeNotifier { _dataState = DataState.searching; notifyListeners(); try { - await APIManager() - .fetchData(Constants.SEARCH_CATEGORY, data) - .then((result) { - final value = SearchItemsResponse.fromJson(result); + await repository.search(data).then((storeItems) { _filteredList.clear(); - if (value.success!) { - _filteredList.addAll(value.storeItems!); + if (storeItems.isNotEmpty) { + _filteredList.addAll(storeItems); } _dataState = DataState.fetched; }).onError((error, stackTrace) { @@ -194,13 +166,10 @@ class ProductViewModel with ChangeNotifier { } Future delete(String id) async { - Map data = {'productId': id}; - await APIManager() - .getResponsePatch(Constants.DELETE_PRODUCT, data) - .then((result) { + await repository.delete(id).then((result) { if (result.success) { - _filteredList.removeWhere((element) => element.id! == id); - _dataList.removeWhere((element) => element.id! == id); + _filteredList.removeWhere((element) => element.itemId == id); + _dataList.removeWhere((element) => element.itemId == id); _crudOperationState = CRUDOperationState.delete; } else { _crudOperationState = CRUDOperationState.error; @@ -214,14 +183,11 @@ class ProductViewModel with ChangeNotifier { } Future update(String id, bool status) async { - Map data = {'productId': id, 'is_item_in_stock': status}; - await APIManager() - .getResponsePatch(Constants.UPDATE_PRODUCT_STATUS, data) - .then((result) { + await repository.update(id, status).then((result) { if (result.success) { - int index = _filteredList.indexWhere((element) => element.id == id); + int index = _filteredList.indexWhere((element) => element.itemId == id); _filteredList[index].status = status; - int dataIndex = _dataList.indexWhere((element) => element.id == id); + int dataIndex = _dataList.indexWhere((element) => element.itemId == id); _dataList[dataIndex].status = status; _crudOperationState == CRUDOperationState.update; } else { @@ -235,8 +201,13 @@ class ProductViewModel with ChangeNotifier { } void getNewData(ItemCategory? value) { - selectedCategoryDropDown = value!; - selectedCategoryId = selectedCategoryDropDown.id; + if (value != null) { + selectedCategoryName = value.name; + selectedCategoryId = value.id; + } else { + selectedCategoryId = 'All'; + selectedCategoryName = 'All'; + } getSubProducts(selectedCategoryId, isRefresh: true); } } diff --git a/lib/application/views/inventorymodule/productviews/views/ProductListView.dart b/lib/application/views/inventorymodule/productviews/views/ProductListView.dart new file mode 100644 index 0000000..8b7926c --- /dev/null +++ b/lib/application/views/inventorymodule/productviews/views/ProductListView.dart @@ -0,0 +1,317 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/application/model/store/StoreItemsResponse.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeImage.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/helpers/Utils.dart'; +import 'package:wosull/widgets/CustomPopuoMenuButton.dart'; +import 'package:wosull/widgets/CustomSwitch.dart'; +import 'package:wosull/widgets/EmptyDataWidget.dart'; +import 'package:wosull/widgets/HeadingText.dart'; +import 'package:wosull/widgets/LineView.dart'; +import 'package:wosull/widgets/ListHeadingContainer.dart'; +import 'package:wosull/widgets/ValueText.dart'; + +class ProductListView extends StatelessWidget { + List data; + bool isPortrait; + String selectedCategoryName; + + final void Function(StoreItems itemCategory, bool status) onUpdate; + final void Function(StoreItems itemCategory) onDelete; + final void Function(StoreItems itemCategory) onView; + final void Function(StoreItems itemCategory) onEdit; + + ProductListView({ + super.key, + required this.selectedCategoryName, + required this.isPortrait, + required this.data, + required this.onUpdate, + required this.onDelete, + required this.onView, + required this.onEdit, + }); + + @override + Widget build(BuildContext context) { + return data.isEmpty + ? const EmptyDataWidget() + : Column( + children: [ + isPortrait + ? Container() + : ListHeadingContainer( + child: Row( + children: [ + Expanded( + child: HeadingText( + lang(context).thumbnail, + )), + Expanded(child: HeadingText(lang(context).name)), + Expanded(child: HeadingText(lang(context).category)), + Expanded(child: HeadingText(lang(context).price)), + Expanded( + child: Align( + alignment: Alignment.center, + child: HeadingText(lang(context).status), + )), + Expanded( + child: HeadingText(lang(context).updated_on)), + Expanded( + child: Padding( + padding: const EdgeInsets.only(right: 16), + child: Align( + alignment: Alignment.centerRight, + child: HeadingText(lang(context).action), + ), + )), + ], + ), + ), + ListView.builder( + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (c, position) { + final item = data[position]; + if (isPortrait) { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + elevation: 5, + color: MyColors.white, + child: Column( + children: [ + AppSpaces.verticalMedium, + Stack( + children: [ + Align( + alignment: Alignment.topCenter, + child: SizedBox( + height: 48, + width: 48, + child: CircleAvatar( + radius: 16, + backgroundColor: MyColors.fillColor, + child: Padding( + padding: + const EdgeInsets.fromLTRB(2, 2, 2, 2), + // Border radius + child: ClipOval( + child: item.imageUrl.isEmpty + ? Image.asset( + ThemeImage.wosulLogo) + : Image.network(item.imageUrl)), + ), + ), + ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.end, + children: [getPopUpBuilder(context, item)], + ), + ], + ), + AppSpaces.verticalMedium, + Container( + padding: const EdgeInsets.all(16), + child: Column( + children: [ + const LineView(), + AppSpaces.verticalMedium, + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + lang(context).name, + style: ThemeText.textStyleHeading, + ), + Text( + item.name, + style: ThemeText.textStyleValue, + ), + ], + ), + AppSpaces.verticalMedium, + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + lang(context).category, + style: ThemeText.textStyleHeading, + ), + Text( + selectedCategoryName, + style: ThemeText.textStyleValue, + ), + ], + ), + AppSpaces.verticalMedium, + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + lang(context).price, + style: ThemeText.textStyleHeading, + ), + Text( + item.price.toStringAsFixed(2), + style: ThemeText.textStyleValue, + ), + ], + ), + AppSpaces.verticalMedium, + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + lang(context).status, + style: ThemeText.textStyleHeading, + ), + CustomSwitch( + value: item.isItemInStock, + onToggle: (value) { + onUpdate(item, value); + }, + ) + ], + ), + AppSpaces.verticalMedium, + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + lang(context).updated_on, + style: ThemeText.textStyleHeading, + ), + Text( + DataTimeFormat.getFormatDate( + item.updatedAt), + style: ThemeText.textStyleValue, + ), + ], + ), + ], + ), + ) + ], + ), + ); + } else { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: ListHeadingContainer( + child: Row( + children: [ + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: SizedBox( + height: 32, + width: 32, + child: CircleAvatar( + radius: 32, + backgroundColor: Colors.transparent, + child: Padding( + padding: const EdgeInsets.fromLTRB( + 2, 2, 2, 2), // Border radius + child: ClipOval( + child: item.imageUrl.isEmpty + ? Image.asset(ThemeImage.wosulLogo) + : Image.network(item.imageUrl)), + ), + ), + ), + )), + Expanded(child: ValueText(item.name)), + Expanded(child: ValueText(selectedCategoryName)), + Expanded(child: ValueText(item.price.toString())), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: CustomSwitch( + value: item.isItemInStock, + onToggle: (value) { + onUpdate(item, value); + }, + ), + )), + Expanded( + child: ValueText(DataTimeFormat.getFormatDate( + item.updatedAt))), + Expanded( + child: Padding( + padding: const EdgeInsets.all(4), + child: Align( + alignment: Alignment.centerRight, + child: Container( + decoration: BoxDecoration( + borderRadius: const BorderRadius.all( + Radius.circular(4)), + color: MyColors.backFillColor), + child: getPopUpBuilder(context, item), + ), + ), + )) + ], + ), + ), + ); + } + }, + itemCount: data.length, + ) + ], + ); + } + + Future actionPopUpItemSelected( + String value, StoreItems storeItems) async { + if (value == 'edit') { + onEdit(storeItems); + } else if (value == 'delete') { + onDelete(storeItems); + } else { + onView(storeItems); + } + } + + getPopUpBuilder(BuildContext context, StoreItems item) { + return CustomPopupMenuButton( + items: [ + PopupMenuItem( + value: 'edit', + child: ValueText( + lang(context).edit, + ), + ), + PopupMenuItem( + value: 'view', + child: ValueText( + lang(context).view, + ), + ), + PopupMenuItem( + value: 'delete', + child: ValueText( + lang(context).delete, + ), + ) + ], + onSelected: (String value) => actionPopUpItemSelected(value, item), + ); + } +} diff --git a/lib/application/views/inventorymodule/productviews/widgets/GenerateBarCodeButton.dart b/lib/application/views/inventorymodule/productviews/widgets/GenerateBarCodeButton.dart new file mode 100644 index 0000000..7ade690 --- /dev/null +++ b/lib/application/views/inventorymodule/productviews/widgets/GenerateBarCodeButton.dart @@ -0,0 +1,31 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/widgets/ButtonText.dart'; + +class GenerateBarCodeButton extends StatelessWidget { + final void Function() onPressed; + bool? isEnable = true; + + GenerateBarCodeButton({ + super.key, + required this.onPressed, + this.isEnable = true, + }); + + @override + Widget build(BuildContext context) { + return ElevatedButton( + style: ElevatedButton.styleFrom( + elevation: 0, + padding: EdgeInsets.zero, + backgroundColor: MyColors.backColorBlue50, + minimumSize: const Size.fromHeight(44.0), // NEW + ), + onPressed: isEnable! ? onPressed : null, + child: ButtonText( + textColor: MyColors.blueThemeColor, + heading: 'Generate', + ), + ); + } +} diff --git a/lib/application/views/inventorymodule/stockReturn/repo/StockReturnRepository.dart b/lib/application/views/inventorymodule/stockReturn/repo/StockReturnRepository.dart new file mode 100644 index 0000000..cc68080 --- /dev/null +++ b/lib/application/views/inventorymodule/stockReturn/repo/StockReturnRepository.dart @@ -0,0 +1,30 @@ +import 'package:wosull/application/model/ReturnStock/ReturnStock.dart'; +import 'package:wosull/application/model/ReturnStock/ReturnStockResponse.dart'; +import 'package:wosull/application/model/SimpleResponsModel.dart'; +import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/utils/Constants.dart'; + +class StockReturnRepository { + Future> fetch(Map data) async { + var stock = []; + await APIManager().fetchData(Constants.getReturnStock, data).then((result) { + final value = ReturnStockResponse.fromJson(result); + if (value.success) { + stock.addAll(value.returnStock); + } + }).onError((error, stackTrace) {}); + + return stock; + } + + Future delete(String id) async { + Map data = {'modifier_option_id': id}; + return await APIManager() + .getResponsePatch(Constants.deleteModifierOption, data); + } + + Future addUpdateStockReturn( + Map map) async { + return await APIManager().fetchData(Constants.addStockReturn, map); + } +} diff --git a/lib/application/views/inventorymodule/stockReturn/viewmodels/NewStockReturnViewModel.dart b/lib/application/views/inventorymodule/stockReturn/viewmodels/NewStockReturnViewModel.dart new file mode 100644 index 0000000..646bba9 --- /dev/null +++ b/lib/application/views/inventorymodule/stockReturn/viewmodels/NewStockReturnViewModel.dart @@ -0,0 +1,455 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/model/Measurement/InventoryMeasurementModel.dart'; +import 'package:wosull/application/model/ReturnStock/ReturnStock.dart'; +import 'package:wosull/application/model/ReturnStock/ReturnStockCharges.dart'; +import 'package:wosull/application/model/StockTransfer/ProductItemCategoryModel.dart'; +import 'package:wosull/application/model/WosulSettings.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/application/model/discount/StoreDiscountModel.dart'; +import 'package:wosull/application/model/store/StoreInvoicesModel.dart'; +import 'package:wosull/application/repository/WosulRepository.dart'; +import 'package:wosull/application/utils/CRUDOperatoinState.dart'; +import 'package:wosull/application/views/inventorymodule/stockReturn/repo/StockReturnRepository.dart'; +import 'package:wosull/helpers/Utils.dart'; + +class NewStockReturnViewModel with ChangeNotifier { + bool isPortrait = true; + var isLoadingFirst = true; + List selectedProduct = []; + List selectedDiscount = []; + List selectedMeasurement = []; + List selectedTax = []; + List filteredProductItems = []; + late ReturnStock stockReturn; + var returnCharge = ReturnStockCharges(amount: '', name: ''); + var fetchDataHelper = WosulRepository(); + + bool _isLoading = false; + + bool get isLoading => _isLoading; + + var _crudOperation = CRUDOperationState.uninitialized; + + CRUDOperationState get crudOperation => _crudOperation; + + final repository = StockReturnRepository(); + + void setState(CRUDOperationState state) { + _crudOperation = state; + } + + void setLoading(bool value) { + _isLoading = value; + notifyListeners(); + } + + void disposeData() { + isLoadingFirst = true; + filteredProductItems.clear(); + selectedDiscount.clear(); + selectedMeasurement.clear(); + selectedTax.clear(); + selectedProduct.clear(); + stockReturn = ReturnStock(products: [], charges: []); + } + + Future initData(bool isEdit, ReturnStock stock) async { + stockReturn = stock; + if (isEdit) { + } else { + stockReturn = ReturnStock(products: [], charges: []); + addEmptyService(); + } + + final response = await fetchDataHelper.getAllProducts(); + filteredProductItems.addAll(response); + if (isEdit) { + for (var product in stock.products!) { + selectedProduct = []; + selectedDiscount = []; + selectedTax = []; + selectedMeasurement = []; + selectedProduct.add(getNewProduct(product)); + selectedDiscount.add(StoreDiscount( + categories: [], + products: [], + discountPercentage: product.discountPercentage?.toString() ?? '')); + selectedTax.add(VAT(name: 'VAT', value: product.vat?.toString() ?? '')); + selectedMeasurement.add(Measurement(name: product.measurement ?? '')); + } + } + isLoadingFirst = false; + notifyListeners(); + } + + Future isValidate() async { + if (stockReturn.supplierId == null) { + Utils.showMessage('Please select supplier'); + } else if (stockReturn.stockReturnDate == null) { + Utils.showMessage('Please select Return date'); + } else if (stockReturn.currency == null) { + Utils.showMessage('Please select currency'); + } else if (stockReturn.taxOption == null) { + Utils.showMessage('Please select tax option'); + } else if (stockReturn.products!.isEmpty) { + Utils.showMessage('Please choose product'); + } else { + await addUpdateStockReturn(); + } + } + + Future addUpdateStockReturn() async { + setLoading(true); + await repository + .addUpdateStockReturn(stockReturn.toJson()) + .then((response) { + Utils.showMessage(response.message); + if (response.success) { + setState(CRUDOperationState.add); + } else { + setState(CRUDOperationState.error); + } + setLoading(false); + }).onError((error, stackTrace) { + setLoading(false); + }); + } + + void addEmptyCharge() { + stockReturn.charges!.add(ReturnStockCharges(amount: '', name: '')); + } + + void presentDatePicker(BuildContext context) { + // showDatePicker is a pre-made funtion of Flutter + showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime.utc(1965, 1, 1), + lastDate: DateTime(2030)) + .then((pickedDate) { + // Check if no date is selected + if (pickedDate == null) { + return; + } + stockReturn.stockReturnDate = + DataTimeFormat.formatDateFromPicket(pickedDate); + + notifyListeners(); + }); + } + + void addEmptyService() { + selectedProduct.add(ProductItem(name: 'Choose')); + selectedDiscount.add(StoreDiscount( + categories: [], products: [], discountPercentage: "Choose")); + selectedTax.add(VAT(name: 'VAT', value: "Choose")); + selectedMeasurement.add(Measurement(name: "Choose")); + stockReturn.products!.add(StoreInvoiceProduct( + totalQuantity: 0, + price: 0.0, + vat: 0, + discountPercentage: 0.0, + tax: 0.0, + amount: 0.0, + )); + } + + String getTotalDiscount() { + var price = 0.0; + for (var product in stockReturn.products!) { + if (product.discountPercentage != null) { + try { + price += product.discountPercentage!; + } catch (e) { + price += product.discountPercentage!; + } + } + } + + stockReturn.totalDiscountAmount = price; + return price.toStringAsFixed(2); + } + + String getTotalVatDiscount() { + var price = 0.0; + for (var product in stockReturn.products!) { + price += product.tax ?? 0.0; + } + stockReturn.totalTaxableAmount = price; + stockReturn.totalExcludingVat = price; + return price.toStringAsFixed(2); + } + + getTotalVatPercentage() { + var price = 0.0; + for (var product in stockReturn.products!) { + price += product.vat ?? 0; + } + stockReturn.totalVat = price; + return price; + } + + String getTotalProductsPrice() { + var price = 0.0; + for (var product in stockReturn.products!) { + price += product.amount ?? 0.0; + } + for (var charge in stockReturn.charges!) { + price += double.parse(charge.amount) ?? 0.0; + } + + stockReturn.totalAmount = price; + return price.toStringAsFixed(2); + } + + Future> getDiscount() async { + var items = []; + await WosulRepository().getDiscount().then((discounts) { + items.addAll(discounts); + }).onError((error, stackTrace) {}); + + return items; + } + + Future> getTax() async { + var items = []; + await WosulRepository().getTax().then((vats) { + items.addAll(vats); + }).onError((error, stackTrace) {}); + + return items; + } + + Future> getMeasurement() async { + var items = []; + + await WosulRepository().getMeasurement().then((measurements) { + items.addAll(measurements); + }).onError((error, stackTrace) {}); + + return items; + } + + Future> getSupplier() async { + final response = await fetchDataHelper.getSuppliersData(); + return response; + } + + void onAddService() { + addEmptyService(); + notifyListeners(); + } + + void setMeasurement(Measurement? data, int position) { + if (data != null) { + stockReturn.products![position].measurement = data.name ?? ''; + } else { + stockReturn.products![position].measurement = ''; + } + } + + void setVat(VAT? data, int position) { + if (data != null) { + calculateVat(double.parse(data.value!), position); + } else { + calculateVat(0.0, position); + } + } + + void setDiscountType(int position, String? data) { + resetDiscount(position); + if (data != null) { + stockReturn.products![position].discountType = data; + } else { + stockReturn.products![position].discountType = ''; + } + notifyListeners(); + } + + void resetDiscount(int position) { + stockReturn.products![position].discountPercentage = 0.0; + stockReturn.products![position].amount = + stockReturn.products![position].amount! + + stockReturn.products![position].discountPercentage!; + if (stockReturn.products![position].tax != null) { + calculateVat(stockReturn.products![position].vat!.toDouble(), position); + } else { + calculateVat(0, position); + } + notifyListeners(); + } + + void addDiscount(double discount, int position) { + stockReturn.products![position].discountPercentage = discount; + if (stockReturn.products![position].tax != null) { + calculateVat(stockReturn.products![position].vat!.toDouble(), position); + } else { + calculateVat(0, position); + } + notifyListeners(); + } + + void onChangeAutoDiscount(StoreDiscount? data, int position) { + if (data != null) { + addDiscount(double.parse(data.discountPercentage!), position); + } else { + resetDiscount(position); + } + } + + void onChangeItemPrice(String value, position) { + if (value.isNotEmpty) { + stockReturn.products![position].price = double.parse(value); + if (stockReturn.products![position].discountPercentage != null) { + addDiscount( + stockReturn.products![position].discountPercentage!, position); + } else { + resetDiscount(position); + } + } + } + + void onChangeQuantity(int position, String value) { + if (value.isNotEmpty) { + stockReturn.products![position].totalQuantity = int.parse(value); + final unitPrice = + stockReturn.products![position].price ?? 0.0; // 1 pece value + final discount = + stockReturn.products![position].discountPercentage ?? 0.0; + if (discount > 0) { + stockReturn.products![position].amount = + stockReturn.products![position].totalQuantity! * unitPrice - + discount; + } else { + stockReturn.products![position].amount = + stockReturn.products![position].totalQuantity! * unitPrice; + } + var tax = getTaxCalu(position); + stockReturn.products![position].tax = tax; + stockReturn.products![position].amount = + stockReturn.products![position].amount! + + stockReturn.products![position].tax!; + } + notifyListeners(); + } + + void updateProduct(ProductItem? response, index) { + if (response != null) { + selectedProduct[index] = response; + final item = stockReturn.products![index]; + item.price = response.price!; + // if (response.total_quantity! > 0) { + // } else { + // item.amount = 0.0; + // } + + item.amount = (response.price! * response.total_quantity!).toDouble(); + item.name = response.name; + item.itemId = response.id; + stockReturn.products![index] = item; + + item.totalQuantity = response.total_quantity; + stockReturn.products![index].description = response.details!; + stockReturn.products![index].totalQuantity = response.total_quantity!; + stockReturn.products![index].price = response.price!; + } + + notifyListeners(); + } + + getNewProduct(StoreInvoiceProduct response) { + final item = ProductItem(); + item.price = response.price!; + // item.amount = (response.price! * response.total_quantity!).toDouble(); + item.name = response.name; + item.id = response.itemId; + item.total_quantity = response.totalQuantity ?? 1; + return item; + } + + double getTaxCalu(int position) { + double totalPrice = (stockReturn.products![position].totalQuantity! * + stockReturn.products![position].price!) - + (stockReturn.products![position].discountPercentage ?? 0.0); + var tax = (totalPrice * stockReturn.products![position].vat!); + tax = tax / 100; + return tax; + } + + void onChangeManualDiscount(String value, position) { + if (value.isNotEmpty) { + addDiscount(double.parse(value), position); + } else { + resetDiscount(position); + } + } + + void calculateVat(double data, int position) { + try { + var totalQuantity = stockReturn.products![position].totalQuantity!; + double totalPrice = + (totalQuantity.toDouble() * stockReturn.products![position].price!); + + totalPrice = totalPrice - + (stockReturn.products![position].discountPercentage ?? 0.0); + + stockReturn.products![position].vat = data.toInt(); + var tax = (totalPrice * data); + + tax = tax / 100; //Total tax + stockReturn.products![position].tax = tax; + stockReturn.products![position].amount = totalPrice + tax; + } catch (e) {} + notifyListeners(); + } + + void onRemoveItem(int position) { + selectedProduct.removeAt(position); + selectedMeasurement.removeAt(position); + selectedDiscount.removeAt(position); + selectedTax.removeAt(position); + stockReturn.products!.removeAt(position); + notifyListeners(); + } + + void updateCurrency(String? data) { + stockReturn.currency = data; + } + + void updateTaxOption(String? data) { + stockReturn.taxOption = data; + } + + void updateBillTo(Supplier? data) { + stockReturn.supplierId = data; + } + + void onChangeChargeAmount(String amount, int position) { + stockReturn.charges![position].amount = amount; + // if (amount.isNotEmpty) { + // stockReturn.totalAmount = stockReturn.totalAmount! + double.parse(amount); + // } else { + // stockReturn.totalAmount = stockReturn.totalAmount!; + // } + notifyListeners(); + } + + void removeCharge(int position) { + // stockReturn.totalAmount = stockReturn.totalAmount! - + // double.parse(stockReturn.charges![position].amount); + stockReturn.charges!.removeAt(position); + notifyListeners(); + } + + void addUpdateCharge() { + if (returnCharge.name.isNotEmpty || returnCharge.amount.isNotEmpty) { + // stockReturn.totalAmount = + // stockReturn.totalAmount! + double.parse(returnCharge.amount); + stockReturn.charges!.add(returnCharge); + returnCharge = ReturnStockCharges(amount: '', name: ''); + // returnCharge.amount = ''; + // returnCharge.name = ''; + notifyListeners(); + } + } +} diff --git a/lib/application/views/settings/viewModels/ReportsInvoiceViewModel.dart b/lib/application/views/inventorymodule/stockReturn/viewmodels/StockReturnViewModel.dart similarity index 52% rename from lib/application/views/settings/viewModels/ReportsInvoiceViewModel.dart rename to lib/application/views/inventorymodule/stockReturn/viewmodels/StockReturnViewModel.dart index 10446bb..0e919e7 100644 --- a/lib/application/views/settings/viewModels/ReportsInvoiceViewModel.dart +++ b/lib/application/views/inventorymodule/stockReturn/viewmodels/StockReturnViewModel.dart @@ -1,31 +1,41 @@ -import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; import 'package:wosull/application/enum/DataState.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; -import 'package:wosull/application/model/invoice/StoreInvoice.dart'; -import 'package:wosull/application/model/store/StoreInvoicesModel.dart'; -import 'package:wosull/application/network/APIManager.dart'; -import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/model/ReturnStock/ReturnStock.dart'; +import 'package:wosull/application/views/inventorymodule/stockReturn/repo/StockReturnRepository.dart'; -class ReportsInvoiceViewModel with ChangeNotifier { +class StockReturnViewModel with ChangeNotifier { + bool _isLoading = false; + + bool get isLoading => _isLoading; + int limit = 10; int _currentPageNumber = 1; + DataState _dataState = DataState.uninitialized; - bool _didLastLoad = false; - bool _isLoading = false; - bool get isLoading => _isLoading; + bool _didLastLoad = false; DataState get dataState => _dataState; + List _filteredList = []; - List _invoiceList = []; + List get filteredList => _filteredList; - List get invoiceList => _invoiceList; + final repository = StockReturnRepository(); - fetchInvoices({bool isRefresh = false}) async { + void setLoading(bool value) { + _isLoading = value; + notifyListeners(); + } + + fetch({bool isRefresh = false, int limit = 10}) async { + this.limit = limit; + _isLoading = true; if (!isRefresh) { _dataState = (_dataState == DataState.uninitialized) ? DataState.initialFetching : DataState.moreFetching; } else { + _didLastLoad = false; _currentPageNumber = 1; _dataState = DataState.refreshing; } @@ -33,26 +43,26 @@ class ReportsInvoiceViewModel with ChangeNotifier { Map data = { 'store_id': sharedPrefs.storeId, 'page': _currentPageNumber, + //'limit': this.limit }; + try { if (_didLastLoad) { _dataState = DataState.noMoreData; } else { - await APIManager() - .fetchData(Constants.GET_INVOICE, data) - .then((result) { - final value = StoreInvoicesModel.fromJson(result); + await repository.fetch(data).then((stock) { if (_dataState == DataState.refreshing) { - _invoiceList.clear(); + _filteredList.clear(); } - if (value.success!) { - _invoiceList.addAll(value.invoices!); - if (value.invoices!.length < 10) { + if (stock.isNotEmpty) { + _filteredList.addAll(stock); + if (stock.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; } } + _isLoading = false; _dataState = DataState.fetched; _currentPageNumber += 1; }).onError((error, stackTrace) { @@ -61,8 +71,18 @@ class ReportsInvoiceViewModel with ChangeNotifier { } notifyListeners(); } catch (e) { + _isLoading = false; _dataState = DataState.error; notifyListeners(); } } + + Future delete(String id) async { + await repository.delete(id).then((result) { + filteredList.removeWhere((element) => element.id == id); + notifyListeners(); + }).onError((error, stackTrace) { + notifyListeners(); + }); + } } diff --git a/lib/application/views/inventorymodule/stockReturn/views/NewStockReturnVC.dart b/lib/application/views/inventorymodule/stockReturn/views/NewStockReturnVC.dart new file mode 100644 index 0000000..12df54e --- /dev/null +++ b/lib/application/views/inventorymodule/stockReturn/views/NewStockReturnVC.dart @@ -0,0 +1,1159 @@ +import 'package:dropdown_search/dropdown_search.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:provider/provider.dart'; +import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/application/model/Measurement/InventoryMeasurementModel.dart'; +import 'package:wosull/application/model/ReturnStock/ReturnStock.dart'; +import 'package:wosull/application/model/StockTransfer/ProductItemCategoryModel.dart'; +import 'package:wosull/application/model/WosulSettings.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/application/model/discount/StoreDiscountModel.dart'; +import 'package:wosull/application/model/store/StoreInvoicesModel.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/AppLoader.dart'; +import 'package:wosull/application/utils/CRUDOperatoinState.dart'; +import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/inventorymodule/stockReturn/viewmodels/NewStockReturnViewModel.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeDropDown.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/widgets/BorderContainer.dart'; +import 'package:wosull/widgets/ChildContainer.dart'; +import 'package:wosull/widgets/CustomAddButton.dart'; +import 'package:wosull/widgets/CustomAppBar.dart'; +import 'package:wosull/widgets/CustomOptionalTitle.dart'; +import 'package:wosull/widgets/CustomRemoveItemButton.dart'; +import 'package:wosull/widgets/CustomSimpleButton.dart'; +import 'package:wosull/widgets/CustomTextAddProduct.dart'; +import 'package:wosull/widgets/CustomTextButtonIcon.dart'; +import 'package:wosull/widgets/CustomTextFieldForm.dart'; +import 'package:wosull/widgets/DropdownItemBuilder.dart'; +import 'package:wosull/widgets/HeadingContainer.dart'; +import 'package:wosull/widgets/HeadingText.dart'; +import 'package:wosull/widgets/MandatoryTitleText.dart'; +import 'package:wosull/widgets/PortraitContainer.dart'; +import 'package:wosull/widgets/WrapHeightContainer.dart'; + +class NewStockReturnVC extends StatefulWidget { + bool isEdit = false; + bool isView; + + late ReturnStock returnStock; + + NewStockReturnVC( + {super.key, + required this.isEdit, + required this.returnStock, + this.isView = false}); + + @override + State createState() => _NewStockReturnVCState(); +} + +class _NewStockReturnVCState extends State { + var viewModel = NewStockReturnViewModel(); + + @override + void initState() { + context + .read() + .initData(widget.isEdit, widget.returnStock); + super.initState(); + } + + @override + void dispose() { + viewModel.disposeData(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + viewModel = context.watch(); + return Scaffold( + backgroundColor: MyColors.fillColor, + resizeToAvoidBottomInset: true, + appBar: CustomAppBar(heading: 'Add Stock Return'), + body: OrientationBuilder(builder: (c, orientation) { + viewModel.isPortrait = + MediaQuery.of(context).orientation == Orientation.portrait; + return SingleChildScrollView( + child: viewModel.isLoadingFirst + ? AppLoader() + : Container( + color: MyColors.fillColor, + padding: const EdgeInsets.fromLTRB(12, 20, 12, 20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Row( + children: [ + Expanded( + flex: 2, + child: Card( + elevation: 5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: Padding( + padding: const EdgeInsets.all(15), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + viewModel.isPortrait + ? Column( + children: [ + getChooseBillTo(), + AppSpaces.verticalMedium, + getStockReturnDate(), + AppSpaces.verticalMedium, + getSelectedCurrencyWidget(), + AppSpaces.verticalMedium, + getChooseTaxOption(), + AppSpaces.verticalMedium, + ], + ) + : Row( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Expanded( + flex: 1, + child: Column( + crossAxisAlignment: + CrossAxisAlignment + .start, + children: [ + getChooseBillTo(), + AppSpaces.verticalMedium, + getStockReturnDate(), + AppSpaces.verticalMedium, + ], + ), + ), + AppSpaces.horizontalMedium, + Expanded( + flex: 1, + child: Column( + crossAxisAlignment: + CrossAxisAlignment + .start, + children: [ + getSelectedCurrencyWidget(), + AppSpaces.verticalMedium, + getChooseTaxOption(), + AppSpaces.verticalMedium, + ], + ), + ), + ], + ), + ], + ), + ), + )), + viewModel.isPortrait + ? Container() + : AppSpaces.horizontalMedium, + viewModel.isPortrait + ? Container() + : Expanded(flex: 1, child: getNotesCard()) + ], + ), + viewModel.isPortrait ? getNotesCard() : Container(), + AppSpaces.verticalLarge, + getCardAddProduct(), + AppSpaces.verticalLarge, + Visibility( + visible: !widget.isView, + child: SizedBox( + width: 120, + child: CustomSimpleButton( + textColor: MyColors.white, + isLoading: viewModel.isLoading, + backGroundColor: MyColors.blueThemeColor, + heading: AppLocalizations.of(context)!.save, + onPressed: () async { + await viewModel.isValidate(); + checkState(); + }, + ), + )), + ], + ), + ), + ); + }), + ); + } + + Widget getCardAddProduct() { + return Card( + elevation: 5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(4.0), + ), + child: Container( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)!.search_and_add_products, + style: ThemeText.textStylePageHeading, + ), + AppSpaces.verticalMedium, + viewModel.isPortrait + ? Container() + : BorderContainer( + child: Row( + children: [ + ChildContainer( + height: 48, + width: 150, + child: MandatoryTitleText( + hint: AppLocalizations.of(context)!.name_or_barcode, + ), + ), + Expanded( + child: HeadingContainer( + heading: AppLocalizations.of(context)!.quantity, + ), + ), + Expanded( + child: HeadingContainer( + heading: AppLocalizations.of(context)!.measurement, + ), + ), + HeadingContainer( + heading: AppLocalizations.of(context)!.unit_price, + width: 80, + ), + Expanded( + child: HeadingContainer( + heading: + AppLocalizations.of(context)!.discount_type, + ), + ), + Expanded( + child: HeadingContainer( + heading: AppLocalizations.of(context)!.discount, + ), + ), + Expanded( + child: HeadingContainer( + heading: AppLocalizations.of(context)!.select_tax, + ), + ), + HeadingContainer( + width: 80, + heading: 'Tax %', + ), + HeadingContainer( + heading: '', + width: 44, + ), + ], + ), + ), + ListView.builder( + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (c, position) { + if (viewModel.isPortrait) { + return WrapHeightContainer( + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + flex: 2, + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + PortraitContainer( + width: double.infinity, + child: Align( + alignment: Alignment.centerLeft, + child: MandatoryTitleText( + hint: AppLocalizations.of(context)! + .name_or_barcode, + ), + ), + ), + PortraitContainer( + width: double.infinity, + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + AppLocalizations.of(context)! + .quantity, + ), + ), + ), + PortraitContainer( + width: double.infinity, + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + AppLocalizations.of(context)! + .unit_price, + ), + ), + ), + PortraitContainer( + width: double.infinity, + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + AppLocalizations.of(context)! + .measurement, + ), + ), + ), + PortraitContainer( + width: double.infinity, + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + AppLocalizations.of(context)! + .discount_type, + ), + ), + ), + PortraitContainer( + width: double.infinity, + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + AppLocalizations.of(context)! + .discount, + ), + ), + ), + PortraitContainer( + width: double.infinity, + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + AppLocalizations.of(context)! + .select_tax, + ), + ), + ), + PortraitContainer( + width: double.infinity, + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + 'Tax %', + ), + ), + ), + ], + )), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + PortraitContainer( + width: double.infinity, + child: getItemsWidget(position), + ), + PortraitContainer( + width: double.infinity, + child: Center( + child: getProductQuantity(position), + ), + ), + PortraitContainer( + width: double.infinity, + child: Center( + child: getProductPrice(position), + ), + ), + PortraitContainer( + width: double.infinity, + child: Center( + child: getDiscountsTypes(position), + ), + ), + PortraitContainer( + width: double.infinity, + child: Center( + child: getDiscounts(position), + ), + ), + PortraitContainer( + width: double.infinity, + child: Center( + child: getTaxWidget(position), + ), + ), + PortraitContainer( + width: double.infinity, + child: Center( + child: getMeasurementWidget(position), + ), + ), + PortraitContainer( + width: double.infinity, + child: Align( + alignment: Alignment.centerRight, + child: getSingleItemTaxWidget(position), + ), + ), + ], + )), + ], + )), + getRemoveProductButton(position) + ], + ), + ); + } else { + return Container( + decoration: BoxDecoration( + borderRadius: const BorderRadius.all(Radius.circular( + 1.0) // <--- border radius here + ), + border: + Border.all(width: 1, color: MyColors.fillColorGray2), + color: MyColors.white, + ), + child: Row( + children: [ + ChildContainer( + width: 150, + child: getItemsWidget(position), + ), + Expanded( + child: ChildContainer( + child: Center( + child: getProductQuantity(position), + ), + ), + ), + Expanded( + child: ChildContainer( + child: getMeasurementWidget(position), + )), + ChildContainer( + width: 80, + child: Center( + child: getProductPrice(position), + ), + ), + Expanded( + child: ChildContainer( + child: getDiscountsTypes(position), + )), + Expanded( + child: ChildContainer( + child: getDiscounts(position), + )), + Expanded( + child: + ChildContainer(child: getTaxWidget(position))), + ChildContainer( + width: 80, + child: Center( + child: getSingleItemTaxWidget(position), + ), + ), + getRemoveProductButton(position) + ], + ), + ); + } + }, + itemCount: viewModel.stockReturn.products!.length, + ), + viewModel.isPortrait + ? BorderContainer( + backgroundColor: MyColors.white, + child: Row( + children: [ + Expanded( + child: PortraitContainer( + height: 48, + child: Center( + child: Text( + '', + style: MyColors.textStyleValue(), + ), + ), + )), + Expanded( + child: PortraitContainer( + height: 48, + child: Center( + child: Text( + '', + style: MyColors.textStyleValue(), + ), + ), + )), + getAddItemButtonWidget() + ], + ), + ) + : BorderContainer( + backgroundColor: MyColors.white, + child: Row( + children: [ + HeadingContainer( + width: 150, + heading: '', + ), + Expanded( + child: HeadingContainer( + heading: '', + ), + ), + Expanded( + child: HeadingContainer( + heading: '', + ), + ), + HeadingContainer( + heading: '', + width: 80, + ), + Expanded( + child: HeadingContainer( + heading: '', + ), + ), + Expanded( + child: HeadingContainer( + heading: '', + ), + ), + Expanded( + child: HeadingContainer( + heading: '', + ), + ), + HeadingContainer( + width: 80, + heading: '', + ), + getAddItemButtonWidget() + ], + ), + ), + AppSpaces.verticalLarge, + getChargesList(), + AppSpaces.verticalMedium, + Visibility(visible: !widget.isView, child: getChargeView()), + AppSpaces.verticalMedium, + Row( + children: [ + viewModel.isPortrait + ? Container() + : const Expanded(child: Text('')), + Expanded( + child: Row( + children: [ + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: Text( + AppLocalizations.of(context)!.discount, + style: ThemeText.textStyleAmountHeading, + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: Text( + "${sharedPrefs.currency} ${viewModel.getTotalDiscount()}", + style: ThemeText.textStyleAmountValue, + ), + )), + AppSpaces.horizontalMedium, + ], + )), + const SizedBox(width: 42) + ], + ), + AppSpaces.verticalMedium, + Row( + children: [ + viewModel.isPortrait + ? Container() + : const Expanded(child: Text('')), + Expanded( + child: Row( + children: [ + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: Text( + '${AppLocalizations.of(context)!.tax} (VAT ${viewModel.getTotalVatPercentage()}%)', + style: ThemeText.textStyleAmountHeading, + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: Text( + "${sharedPrefs.currency} ${viewModel.getTotalVatDiscount()}", + style: ThemeText.textStyleAmountValue, + ), + )), + AppSpaces.horizontalMedium, + ], + )), + const SizedBox(width: 42) + ], + ), + AppSpaces.verticalMedium, + Row( + children: [ + viewModel.isPortrait + ? Container() + : const Expanded(child: Text('')), + Expanded( + child: Row( + children: [ + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: Text( + AppLocalizations.of(context)!.total_amount, + style: ThemeText.textStyleAmountHeadingBlack, + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: Text( + "${sharedPrefs.currency} ${viewModel.getTotalProductsPrice()}", + style: ThemeText.textStyleAmountHeadingBlack, + ), + )), + AppSpaces.horizontalMedium, + ], + )), + const SizedBox(width: 42) + ], + ) + ], + ), + ), + ); + } + + getAddItemButtonWidget() { + return CustomAddButton(onPressed: () { + if (!widget.isView) { + viewModel.onAddService(); + } + }); + } + + Widget getMeasurementWidget(int position) { + return FutureBuilder( + future: viewModel.getMeasurement(), + builder: (c, s) { + if (s.hasData) { + var itemsList = s.data!; + return DropdownSearch( + enabled: !widget.isView, + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name ?? ''); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + selectedItem: viewModel.selectedMeasurement[position], + items: itemsList, + itemAsString: (Measurement u) => u.name!, + onChanged: (Measurement? data) { + viewModel.setMeasurement(data, position); + }, + dropdownDecoratorProps: + MyColors.dropDownStyleAddProduct(hint: 'Choose'), + ); + } else { + return AppLoader(); + } + }); + } + + Widget getTaxWidget(int position) { + return FutureBuilder( + future: viewModel.getTax(), + builder: (c, s) { + if (s.hasData) { + var itemsList = s.data!; + return DropdownSearch( + enabled: !widget.isView, + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name ?? ''); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + selectedItem: viewModel.selectedTax[position], + items: itemsList, + itemAsString: (VAT u) { + return u.value!; + }, + onChanged: (VAT? data) { + viewModel.setVat(data, position); + }, + dropdownDecoratorProps: + MyColors.dropDownStyleAddProduct(hint: 'Choose'), + ); + } else { + return AppLoader(); + } + }); + } + + Widget getDiscountsTypes(int position) { + return DropdownSearch( + enabled: !widget.isView, + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + selectedItem: + viewModel.stockReturn.products![position].discountType ?? 'Choose', + items: Constants.discountTypes, + itemAsString: (String u) => u, + onChanged: (String? data) { + viewModel.setDiscountType(position, data); + }, + dropdownDecoratorProps: MyColors.dropDownStyleAddProduct(hint: 'Choose'), + ); + } + + Widget getDiscounts(int position) { + if (viewModel.stockReturn.products![position].discountType == null) { + return Container( + height: 42, + ); + } else if (viewModel.stockReturn.products![position].discountType! == + Constants.discountTypes[0]) { + return autoDiscount(position); + } else if (viewModel.stockReturn.products![position].discountType! == + Constants.discountTypes[1]) { + return manualDiscount(position); + } else { + return Container( + height: 42, + ); + } + } + + Widget manualDiscount(int position) { + return CustomTextFieldForm( + readOnly: widget.isView, + initialValue: viewModel.stockReturn.products![position].discountPercentage + ?.toString() ?? + '', + onChanged: (String value) { + viewModel.onChangeManualDiscount(value, position); + }, + hintText: '', + ); + } + + Widget autoDiscount(int position) { + return FutureBuilder( + future: viewModel.getDiscount(), + builder: (c, s) { + if (s.hasData) { + var itemsList = s.data!; + return DropdownSearch( + enabled: !widget.isView, + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name ?? ''); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + selectedItem: viewModel.selectedDiscount[position], + items: itemsList, + itemAsString: (StoreDiscount u) => u.name ?? '', + onChanged: (StoreDiscount? data) { + viewModel.onChangeAutoDiscount(data, position); + }, + dropdownDecoratorProps: + MyColors.dropDownStyleAddProduct(hint: 'Choose'), + ); + } else { + return AppLoader(); + } + }); + } + + getProductPrice(int position) { + return CustomTextFieldForm( + readOnly: widget.isView, + key: Key( + (viewModel.stockReturn.products![position].price ?? '0').toString()), + keyboardType: TextInputType.number, + initialValue: + (viewModel.stockReturn.products![position].price ?? '0').toString(), + onChanged: (String value) { + viewModel.onChangeItemPrice(value, position); + }, + hintText: '', + ); + } + + getRemoveProductButton(int position) { + return CustomRemoveItemButton(onPressed: () { + if (!widget.isView) { + viewModel.onRemoveItem(position); + } + }); + } + + getProductQuantity(int position) { + return CustomTextFieldForm( + readOnly: widget.isView, + keyboardType: TextInputType.number, + key: Key((viewModel.stockReturn.products![position].totalQuantity ?? '0') + .toString()), + initialValue: + (viewModel.stockReturn.products![position].totalQuantity ?? '0') + .toString(), + onChanged: (String value) { + viewModel.onChangeQuantity(position, value); + }, + hintText: '', + ); + } + + getItemsWidget(int position) { + return DropdownSearch( + enabled: !widget.isView, + selectedItem: viewModel.selectedProduct[position], + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name ?? ''); + }, + searchFieldProps: ThemeDropDown.textFieldProps, + searchDelay: Duration.zero, + interceptCallBacks: false, + showSearchBox: true, + isFilterOnline: false, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 200), + ), + items: viewModel.filteredProductItems, + itemAsString: (ProductItem u) => u.name ?? '', + onChanged: (ProductItem? data) { + viewModel.updateProduct(data, position); + }, + dropdownDecoratorProps: MyColors.dropDownStyleAddProduct(hint: 'Choose'), + ); + } + + getSingleItemTaxWidget(int position) { + return CustomTextAddProduct( + viewModel.stockReturn.products![position].tax!.toStringAsFixed(2)); + } + + getSingleItemAmountWidget(int position) { + return CustomTextAddProduct( + viewModel.stockReturn.products![position].amount!.toStringAsFixed(2)); + } + + Widget getStockReturnDate() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const MandatoryTitleText( + hint: 'Stock Return Date', + ), + AppSpaces.verticalSmall, + getEndDateButton() + ], + ); + } + + Widget getEndDateButton() { + return CustomTextButtonIcon( + height: 48, + backgroundColor: MyColors.backFillColor, + icon: Icons.calendar_month, + heading: DataTimeFormat.getFormatDateString( + viewModel.stockReturn.stockReturnDate ?? ''), + onPressed: () { + if (!widget.isView) { + viewModel.presentDatePicker(context); + } + }, + ); + } + + getSelectedCurrencyWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + MandatoryTitleText(hint: AppLocalizations.of(context)!.currency), + AppSpaces.verticalSmall, + getSelectedCurrencyDropdown() + ], + ); + } + + getSelectedCurrencyDropdown() { + return DropdownSearch( + enabled: !widget.isView, + selectedItem: viewModel.stockReturn.currency, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: Constants.currencies, + itemAsString: (String u) => u, + onChanged: (String? data) { + viewModel.updateCurrency(data); + }, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose Currency'), + ); + } + + getChooseTaxOption() { + return Column( + children: [ + const MandatoryTitleText( + hint: 'Tax Option', + ), + AppSpaces.verticalSmall, + DropdownSearch( + enabled: !widget.isView, + selectedItem: viewModel.stockReturn.taxOption, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: Constants.taxOptions, + itemAsString: (String u) => u, + onChanged: (String? data) { + viewModel.updateTaxOption(data); + }, + dropdownDecoratorProps: + MyColors.dropDownStyleAddProduct(hint: 'Choose Tax Option'), + ) + ], + ); + } + + getChooseBillTo() { + return Column( + children: [ + MandatoryTitleText( + hint: AppLocalizations.of(context)!.bill_to, + ), + AppSpaces.verticalSmall, + getSuppliers() + ], + ); + } + + Widget getSuppliers() { + return FutureBuilder( + future: viewModel.getSupplier(), + builder: (c, s) { + if (s.hasData) { + var itemsList = s.data!; + return DropdownSearch( + enabled: !widget.isView, + selectedItem: viewModel.stockReturn.supplierId, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name ?? ''); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: itemsList, + itemAsString: (Supplier u) => u.name ?? '', + onChanged: (Supplier? data) { + viewModel.updateBillTo(data); + }, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), + ); + } else { + return AppLoader(); + } + }); + } + + getNotesCard() { + return Card( + elevation: 5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: Padding( + padding: const EdgeInsets.all(18), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.notes, + ), + AppSpaces.verticalSmall, + CustomTextFieldForm( + readOnly: widget.isView, + height: 160, + maxLines: 6, + initialValue: '', + onChanged: (value) { + viewModel.stockReturn.notes = value; + }, + hintText: AppLocalizations.of(context)!.notes), + ], + ), + ), + ); + } + + getChargesList() { + return ListView.builder( + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (c, position) { + return Container( + margin: const EdgeInsets.only(top: 8), + child: getRemoveChargeView(position), + ); + }, + itemCount: viewModel.stockReturn.charges!.length, + ); + } + + getChargeView() { + return Row( + children: [ + viewModel.isPortrait ? Container() : const Expanded(child: Text('')), + Expanded( + child: Row( + children: [ + Expanded( + child: CustomTextFieldForm( + initialValue: viewModel.returnCharge.name, + onChanged: (String value) { + viewModel.returnCharge.name = value; + }, + hintText: 'Charge', + )), + AppSpaces.horizontalMedium, + Expanded( + child: CustomTextFieldForm( + keyboardType: TextInputType.number, + onChanged: (String value) { + viewModel.returnCharge.amount = value; + }, + hintText: 'Amount', + )), + AppSpaces.horizontalMedium, + CustomAddButton( + iconColor: MyColors.blueThemeColor, + backgroundColor: MyColors.backColorBlue50, + onPressed: () { + viewModel.addUpdateCharge(); + }) + ], + )), + ], + ); + } + + getRemoveChargeView(int position) { + return Row( + children: [ + viewModel.isPortrait ? Container() : const Expanded(child: Text('')), + Expanded( + child: Row( + children: [ + Expanded( + child: CustomTextFieldForm( + readOnly: widget.isView, + initialValue: viewModel.stockReturn.charges![position].name, + onChanged: (String value) { + viewModel.stockReturn.charges![position].name = value; + }, + hintText: 'Charge', + )), + AppSpaces.horizontalMedium, + Expanded( + child: CustomTextFieldForm( + readOnly: widget.isView, + initialValue: viewModel.stockReturn.charges![position].amount, + onChanged: (String value) { + viewModel.onChangeChargeAmount(value, position); + }, + hintText: 'Amount', + )), + AppSpaces.horizontalMedium, + CustomRemoveItemButton(onPressed: () { + if (!widget.isView) { + viewModel.removeCharge(position); + } + }) + ], + )), + ], + ); + } + + void checkState() { + if (viewModel.crudOperation == CRUDOperationState.add) { + Navigator.pop(context, true); + } + } +} diff --git a/lib/application/views/inventorymodule/stockReturn/views/StockReturnVC.dart b/lib/application/views/inventorymodule/stockReturn/views/StockReturnVC.dart new file mode 100644 index 0000000..7b55019 --- /dev/null +++ b/lib/application/views/inventorymodule/stockReturn/views/StockReturnVC.dart @@ -0,0 +1,204 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:wosull/application/enum/DataState.dart'; +import 'package:wosull/application/model/ReturnStock/ReturnStock.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/AppLoader.dart'; +import 'package:wosull/application/views/inventorymodule/stockReturn/viewmodels/StockReturnViewModel.dart'; +import 'package:wosull/application/views/inventorymodule/stockReturn/views/NewStockReturnVC.dart'; +import 'package:wosull/application/views/inventorymodule/stockReturn/widgets/StockReturnListView.dart'; +import 'package:wosull/application/views/popups/DeleteRecordPopUp.dart'; +import 'package:wosull/base/BaseStatefulState.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/widgets/CustomSimpleButton.dart'; +import 'package:wosull/widgets/PageLimitDropDown.dart'; + +class StockReturnVC extends StatefulWidget { + const StockReturnVC({super.key}); + + @override + State createState() => _StockReturnVCState(); +} + +class _StockReturnVCState extends BaseStatefulState { + bool isPortrait = true; + + final viewModel = StockReturnViewModel(); + late ScrollController _controller; + + @override + Widget build(BuildContext context) { + _controller = ScrollController()..addListener(_scrollNotification); + return Scaffold( + backgroundColor: MyColors.fillColor, + resizeToAvoidBottomInset: true, + body: OrientationBuilder(builder: (c, orientation) { + isPortrait = MediaQuery.of(c).orientation == Orientation.portrait; + return SingleChildScrollView( + controller: _controller, + child: Container( + padding: const EdgeInsets.all(12), + child: Column( + children: [ + isPortrait + ? Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + 'Stock Return', + style: ThemeText.textStylePageHeading, + ), + AppSpaces.horizontalSmall, + Flexible(child: newStock()), + AppSpaces.horizontalSmall, + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + PageLimitDropdown(onChange: (value) { + viewModel.fetch( + isRefresh: true, + limit: int.parse(value!)); + }) + ], + ) + ], + ) + : Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + 'Stock Return', + style: ThemeText.textStylePageHeading, + ), + AppSpaces.horizontalSmall, + SizedBox( + width: 150, + child: newStock(), + ), + Flexible( + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + PageLimitDropdown(onChange: (value) { + viewModel.fetch( + isRefresh: true, + limit: int.parse(value!)); + }) + ], + )) + ], + ), + AppSpaces.verticalMedium, + ChangeNotifierProvider( + create: (context) => viewModel, + child: Consumer( + builder: (BuildContext context, + StockReturnViewModel controller, Widget? _) { + switch (controller.dataState) { + case DataState.uninitialized: + Future(() { + controller.fetch(); + }); + return showData(controller.filteredList); + case DataState.initialFetching: + return AppLoader(); + case DataState.moreFetching: + case DataState.refreshing: + return showData(controller.filteredList); + case DataState.error: + return const Center( + child: Text("Error"), + ); + case DataState.searching: + case DataState.fetched: + case DataState.noMoreData: + return showData(controller.filteredList); + } + }, + ), + ), + ], + ), + ), + ); + })); + } + + Widget showData(List data) { + return Column( + children: [ + StockReturnListView( + data: data, + isPortrait: isPortrait, + onDelete: (stock) { + showDeletePopUp(stock); + }, + onView: (stock) { + openStockReturn(true, stock, true); + }, + onEdit: (stock) { + openStockReturn(true, stock, false); + }), + if (viewModel.dataState == DataState.moreFetching) AppLoader(), + ], + ); + } + + bool _scrollNotification() { + if (!viewModel.isLoading && _controller.position.extentAfter < 300) { + viewModel.fetch(limit: viewModel.limit); + } + return true; + } + + Future showDeletePopUp(ReturnStock stock) async { + final result = await showDialog( + barrierColor: Colors.black26, + context: context, + builder: (context) { + return const DeleteRecordPopUp(); + }, + ); + + if (!mounted) return; + bool isDelete = result; + if (isDelete) { + _delete(stock.id!); + } + } + + Future _delete(String id) async { + progressDialogue(context); + await viewModel.delete(id); + hideProgressBar(); + } + + Widget newStock() { + return CustomSimpleButton( + heading: '+ New Stock Return', + textColor: MyColors.blueThemeColor, + backGroundColor: MyColors.backColorBlue50, + height: 38, + onPressed: () { + openStockReturn(false, ReturnStock(), false); + }, + ); + } + + Future openStockReturn( + bool isEdit, ReturnStock stock, bool? isView) async { + final response = await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => NewStockReturnVC( + isEdit: isEdit, returnStock: stock, isView: isView ?? false)), + ); + + if (!mounted) return; + + if (response != null) { + viewModel.fetch(isRefresh: true, limit: viewModel.limit); + } + } +} diff --git a/lib/application/views/inventorymodule/stockReturn/widgets/StockReturnListView.dart b/lib/application/views/inventorymodule/stockReturn/widgets/StockReturnListView.dart new file mode 100644 index 0000000..9713840 --- /dev/null +++ b/lib/application/views/inventorymodule/stockReturn/widgets/StockReturnListView.dart @@ -0,0 +1,236 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/model/ReturnStock/ReturnStock.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/Utils.dart'; +import 'package:wosull/widgets/ActionPopUpContainer.dart'; +import 'package:wosull/widgets/CustomPopuoMenuButton.dart'; +import 'package:wosull/widgets/EmptyDataWidget.dart'; +import 'package:wosull/widgets/HeadingText.dart'; +import 'package:wosull/widgets/ListHeadingContainer.dart'; +import 'package:wosull/widgets/ValueText.dart'; + +class StockReturnListView extends StatelessWidget { + List data; + bool isPortrait = false; + final void Function(ReturnStock item) onDelete; + final void Function(ReturnStock item) onView; + final void Function(ReturnStock item) onEdit; + + StockReturnListView( + {super.key, + required this.data, + required this.isPortrait, + required this.onDelete, + required this.onView, + required this.onEdit}); + + @override + Widget build(BuildContext context) { + return data.isEmpty + ? const EmptyDataWidget() + : Column( + children: [ + isPortrait + ? Container() + : ListHeadingContainer( + child: Row( + children: [ + Expanded( + child: HeadingText( + 'Stock Return Number', + )), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText(lang(context).bill_to), + )), + Expanded( + child: HeadingText( + 'Return Date', + )), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText(lang(context).total_amount), + )), + Expanded( + child: HeadingText(lang(context).created_on)), + Expanded( + child: HeadingText(lang(context).updated_on)), + Expanded( + child: Padding( + padding: const EdgeInsets.only(right: 16), + child: Align( + alignment: Alignment.centerRight, + child: HeadingText(lang(context).action), + ), + )), + ], + ), + ), + ListView.builder( + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (c, position) { + final stock = data[position]; + if (isPortrait) { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + elevation: 2, + color: MyColors.white, + child: Container( + padding: const EdgeInsets.fromLTRB(8, 0, 0, 8), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + child: Container( + padding: const EdgeInsets.only(top: 16), + child: Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + HeadingText( + 'Stock Return Number', + ), + AppSpaces.verticalMedium, + HeadingText( + 'Bill To', + ), + AppSpaces.verticalMedium, + HeadingText( + 'Return Date', + ), + AppSpaces.verticalMedium, + HeadingText('Total Amount'), + AppSpaces.verticalMedium, + HeadingText(lang(context).created_on), + AppSpaces.verticalMedium, + HeadingText(lang(context).updated_on), + ], + )), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + ValueText(stock.uniqueId.toString()), + AppSpaces.verticalMedium, + ValueText(stock.supplierId!.name ?? ''), + AppSpaces.verticalMedium, + ValueText(DataTimeFormat.getFormatDate( + stock.stockReturnDate!)), + AppSpaces.verticalMedium, + ValueText(stock.totalAmount! + .toStringAsFixed(2)), + AppSpaces.verticalMedium, + ValueText(DataTimeFormat.getFormatDate( + stock.createdAt!)), + AppSpaces.verticalMedium, + ValueText(DataTimeFormat.getFormatDate( + stock.updatedAt!)), + ], + )), + ], + ), + )), + getPopupMenuButton(context, position) + ], + ), + ), + ); + } else { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: ListHeadingContainer( + child: Row( + children: [ + Expanded( + child: ValueText(stock.uniqueId.toString())), + Expanded( + child: ValueText(stock.supplierId!.name ?? '')), + Expanded( + child: ValueText(DataTimeFormat.getFormatDate( + stock.stockReturnDate!))), + Expanded( + child: ValueText( + stock.totalAmount!.toStringAsFixed(2))), + Expanded( + child: ValueText(DataTimeFormat.getFormatDate( + stock.createdAt!))), + Expanded( + child: ValueText(DataTimeFormat.getFormatDate( + stock.updatedAt!))), + Expanded( + child: Padding( + padding: const EdgeInsets.all(4), + child: Align( + alignment: Alignment.centerRight, + child: ActionPopUpContainer( + child: getPopupMenuButton(context, position), + ), + ), + )) + ], + ), + ), + ); + } + }, + itemCount: data.length, + ) + ], + ); + } + + Future actionPopUpItemSelected(String value, ReturnStock item) async { + if (value == 'edit') { + onEdit(item); + } else if (value == 'delete') { + onDelete(item); + } else { + onView(item); + } + } + + getPopupMenuButton(BuildContext context, int position) { + return CustomPopupMenuButton( + items: [ + PopupMenuItem( + value: 'edit', + child: ValueText( + lang(context).edit, + ), + ), + PopupMenuItem( + value: 'view', + child: ValueText( + lang(context).view, + ), + ), + PopupMenuItem( + value: 'delete', + child: ValueText( + lang(context).delete, + ), + ) + ], + onSelected: (String value) => + actionPopUpItemSelected(value, data[position]), + ); + } +} diff --git a/lib/application/views/inventorymodule/stockTransferViews/InventoryNewStockTransferVC.dart b/lib/application/views/inventorymodule/stockTransferViews/InventoryNewStockTransferVC.dart index e99ce91..82d8132 100644 --- a/lib/application/views/inventorymodule/stockTransferViews/InventoryNewStockTransferVC.dart +++ b/lib/application/views/inventorymodule/stockTransferViews/InventoryNewStockTransferVC.dart @@ -3,24 +3,25 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:provider/provider.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/application/model/StockTransfer/ProductItemCategoryModel.dart'; import 'package:wosull/application/theme/MyColors.dart'; -import 'package:wosull/application/theme/MyFonts.dart'; import 'package:wosull/application/utils/AppLoader.dart'; import 'package:wosull/application/utils/CRUDOperatoinState.dart'; -import 'package:wosull/application/views/inventorymodule/productviews/SearchProductVC.dart'; import 'package:wosull/application/views/inventorymodule/stockTransferViews/viewModels/NewStockTransferVM.dart'; import 'package:wosull/base/BaseStatefulState.dart'; import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/ThemeDropDown.dart'; +import 'package:wosull/widgets/CustomAppBar.dart'; import 'package:wosull/widgets/CustomOptionalTitle.dart'; import 'package:wosull/widgets/CustomSimpleButton.dart'; import 'package:wosull/widgets/CustomTextFieldForm.dart'; +import 'package:wosull/widgets/DropdownItemBuilder.dart'; import 'package:wosull/widgets/MandatoryTitleText.dart'; import '../../../model/store/WosulStore.dart'; class InventoryNewStockTransferVC extends StatefulWidget { - InventoryNewStockTransferVC({Key? key}) : super(key: key); + const InventoryNewStockTransferVC({Key? key}) : super(key: key); @override State createState() => @@ -34,13 +35,12 @@ class _InventoryNewStockTransferVCState @override void initState() { - // TODO: implement initState + context.read().initData(); super.initState(); } @override void dispose() { - // TODO: implement dispose viewModel.disposeData(); super.dispose(); } @@ -49,24 +49,10 @@ class _InventoryNewStockTransferVCState Widget build(BuildContext context) { viewModel = context.watch(); return Scaffold( + backgroundColor: MyColors.white, resizeToAvoidBottomInset: true, - appBar: AppBar( - leading: BackButton( - color: Colors.black, - onPressed: () { - Navigator.pop(context); - }, // <-- SEE HERE - ), - centerTitle: true, - title: Text( - AppLocalizations.of(context)!.add_stock_transfer, - style: const TextStyle( - color: MyColors.textColorBlack, - fontFamily: MyFonts.Bold, - fontSize: 22), - ), - backgroundColor: MyColors.white, - elevation: 5, + appBar: CustomAppBar( + heading: AppLocalizations.of(context)!.add_stock_transfer, ), body: OrientationBuilder( builder: (c, orientation) { @@ -93,105 +79,27 @@ class _InventoryNewStockTransferVCState child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - MandatoryTitleText( - hint: - AppLocalizations.of(context)!.from_store), - AppSpaces.verticalSmall, - CustomTextFieldForm( - initialValue: sharedPrefs.store_name, - readOnly: true, - onChanged: (value) {}, - hintText: sharedPrefs.store_name), + getFromStoreWidget(), AppSpaces.verticalMedium, - CustomOptionalTitle( - hint: AppLocalizations.of(context)! - .transfer_reason), - AppSpaces.verticalSmall, - Material( - color: MyColors.backFillColor, - borderRadius: BorderRadius.circular(8), - child: SizedBox( - height: 42, - width: double.infinity, - child: Padding( - padding: const EdgeInsets.only( - left: 8, right: 8), - child: DropdownButton( - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normalButton, - color: MyColors.black), - value: viewModel.transferReasonValue, - hint: const Text('Choose Transfer Type', - style: TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normalButton, - color: MyColors.black)), - isExpanded: true, - underline: DropdownButtonHideUnderline( - child: Container()), - items: - viewModel.items.map((String items) { - return DropdownMenuItem( - value: items, - child: Text(items), - ); - }).toList(), - onChanged: (Object? value) { - viewModel.setTransferReason(value); - }, - ), - ), - ), - ), + getTransferTypeWidget(), AppSpaces.verticalMedium, - CustomOptionalTitle( - hint: AppLocalizations.of(context)!.name), - AppSpaces.verticalSmall, - CustomTextFieldForm( - readOnly: true, - onChanged: (value) { - viewModel.nameController = value; - }, - hintText: 'Enter Name'), + getNameWidget(), AppSpaces.verticalMedium, getQuantity(), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, getPrice(), isPortrait ? Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const SizedBox( - height: 8, - ), - MandatoryTitleText( - hint: AppLocalizations.of(context)! - .search_and_add_products), - const SizedBox( - height: 4, - ), - getProductDrop(), - const SizedBox( - height: 8, - ), - MandatoryTitleText( - hint: AppLocalizations.of(context)! - .to_store), - const SizedBox( - height: 4, - ), - getStoreDrop(), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, + getItemsWidget(), + AppSpaces.verticalMedium, + getToStoreWidget(), + AppSpaces.verticalMedium, getDescription(), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, getBarCode(), ], ) @@ -199,9 +107,7 @@ class _InventoryNewStockTransferVCState ], ), ), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, isPortrait ? Container() : Flexible( @@ -209,30 +115,12 @@ class _InventoryNewStockTransferVCState child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - MandatoryTitleText( - hint: AppLocalizations.of(context)! - .to_store), - const SizedBox( - height: 4, - ), - getStoreDrop(), - const SizedBox( - height: 8, - ), - MandatoryTitleText( - hint: AppLocalizations.of(context)! - .search_and_add_products), - const SizedBox( - height: 4, - ), - getProductDrop(), - const SizedBox( - height: 8, - ), + getToStoreWidget(), + AppSpaces.verticalMedium, + getItemsWidget(), + AppSpaces.verticalMedium, getDescription(), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, getBarCode(), ], ), @@ -292,60 +180,28 @@ class _InventoryNewStockTransferVCState } Widget getProductDrop() { - return Container( - height: 48, - padding: const EdgeInsets.only(right: 8), - decoration: BoxDecoration( - border: Border.all( - color: Colors.transparent, - width: 1, - ), - color: MyColors.backFillColor, - borderRadius: BorderRadius.circular(8.0), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Expanded( - child: TextButton( - onPressed: () { - showSheet(); - }, - child: Align( - alignment: Alignment.centerLeft, - child: Text( - viewModel.productItem.name ?? 'Choose Product', - textAlign: TextAlign.left, - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normalButton, - color: MyColors.black), - ), - ), - )), - const Icon( - // <-- Icon - Icons.arrow_drop_down, - size: 24.0, - color: MyColors.black, - ) - ], + return DropdownSearch( + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name ?? ''); + }, + searchFieldProps: ThemeDropDown.textFieldProps, + searchDelay: Duration.zero, + interceptCallBacks: false, + showSearchBox: true, + isFilterOnline: false, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 200), ), - ); - } - - void showSheet() async { - final result = await showDialog( - barrierColor: Colors.black26, - context: context, - builder: (context) { - return const SearchProductVC(); + items: viewModel.filteredProductItems, + itemAsString: (ProductItem u) => u.name ?? '', + onChanged: (ProductItem? data) { + viewModel.setProduct(data); }, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), ); - - if (!mounted) return; - viewModel.setProduct(result); } Widget getStoreDrop() { @@ -354,28 +210,25 @@ class _InventoryNewStockTransferVCState builder: (c, s) { if (s.hasData) { var stores = s.data ?? []; - return Material( - color: MyColors.backFillColor, - borderRadius: BorderRadius.circular(8), - child: SizedBox( - height: 42, - width: double.infinity, - child: Padding( - padding: const EdgeInsets.only(left: 8, right: 8), - child: DropdownSearch( - selectedItem: viewModel.selectedStoreDropDown, - popupProps: const PopupProps.menu(), - clearButtonProps: ThemeDropDown.clearButton, - items: stores, - itemAsString: (WosulStore u) => u.name, - onChanged: (WosulStore? data) { - viewModel.setSelectedStore(data); - }, - dropdownDecoratorProps: - MyColors.dropDownStyle(hint: 'Choose Store'), - ), - ), + return DropdownSearch( + selectedItem: viewModel.selectedStoreDropDown, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 200), ), + clearButtonProps: ThemeDropDown.clearButton, + items: stores, + itemAsString: (WosulStore u) => u.name, + onChanged: (WosulStore? data) { + viewModel.setSelectedStore(data); + }, + dropdownDecoratorProps: + MyColors.dropDownStyle(hint: 'Choose Store'), ); } else { return AppLoader(); @@ -388,12 +241,12 @@ class _InventoryNewStockTransferVCState crossAxisAlignment: CrossAxisAlignment.start, children: [ CustomOptionalTitle(hint: AppLocalizations.of(context)!.description), - const SizedBox( - height: 4, - ), + AppSpaces.verticalSmall, CustomTextFieldForm( + key: Key(viewModel.productItem.details ?? ''), + initialValue: viewModel.productItem.details ?? '', onChanged: (value) { - viewModel.descriptionController = value; + viewModel.productItem.details = value; }, hintText: 'Enter Description') ], @@ -410,8 +263,10 @@ class _InventoryNewStockTransferVCState ), AppSpaces.verticalSmall, CustomTextFieldForm( + key: Key(viewModel.productItem.total_quantity?.toString() ?? '0'), + initialValue: viewModel.productItem.total_quantity?.toString() ?? '0', onChanged: (value) { - viewModel.setQuantity(value); + viewModel.checkQuantity(value); }, hintText: 'Enter Quantity', ) @@ -426,8 +281,10 @@ class _InventoryNewStockTransferVCState CustomOptionalTitle(hint: AppLocalizations.of(context)!.price), AppSpaces.verticalSmall, CustomTextFieldForm( + key: Key(viewModel.productItem.price?.toStringAsFixed(2) ?? '0'), + initialValue: viewModel.productItem.price?.toStringAsFixed(2) ?? '0', onChanged: (value) { - viewModel.priceController = value; + viewModel.updateProductPrice(value); }, hintText: 'Enter Price', ) @@ -442,9 +299,11 @@ class _InventoryNewStockTransferVCState CustomOptionalTitle(hint: AppLocalizations.of(context)!.barcode), AppSpaces.verticalSmall, CustomTextFieldForm( - key: Key(viewModel.uniqueIdController.toString()), - initialValue: viewModel.uniqueIdController, - onChanged: (value) {}, + key: Key(viewModel.productItem.uniqueIdForStoreData ?? ''), + initialValue: viewModel.productItem.uniqueIdForStoreData ?? '', + onChanged: (value) { + viewModel.updateBarCode(value); + }, hintText: 'Enter Barcode', ) ], @@ -456,4 +315,87 @@ class _InventoryNewStockTransferVCState Navigator.pop(context, true); } } + + getToStoreWidget() { + return Column( + children: [ + MandatoryTitleText(hint: AppLocalizations.of(context)!.to_store), + AppSpaces.verticalSmall, + getStoreDrop(), + ], + ); + } + + getItemsWidget() { + return Column( + children: [ + MandatoryTitleText( + hint: AppLocalizations.of(context)!.search_and_add_products), + AppSpaces.verticalSmall, + getProductDrop(), + ], + ); + } + + getFromStoreWidget() { + return Column( + children: [ + MandatoryTitleText(hint: AppLocalizations.of(context)!.from_store), + AppSpaces.verticalSmall, + CustomTextFieldForm( + initialValue: sharedPrefs.store_name, + readOnly: true, + onChanged: (value) {}, + hintText: sharedPrefs.store_name), + ], + ); + } + + getTransferTypeWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.transfer_reason), + AppSpaces.verticalSmall, + DropdownSearch( + selectedItem: viewModel.selectedStoreDropDown, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 200), + ), + clearButtonProps: ThemeDropDown.clearButton, + items: viewModel.items, + itemAsString: (String u) => u, + onChanged: (String? data) { + viewModel.setTransferReason(data); + }, + dropdownDecoratorProps: + MyColors.dropDownStyle(hint: 'Choose Transfer Type'), + ), + ], + ); + } + + getNameWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle(hint: AppLocalizations.of(context)!.name), + AppSpaces.verticalSmall, + CustomTextFieldForm( + key: Key(viewModel.productItem.name ?? ''), + initialValue: viewModel.productItem.name ?? '', + onChanged: (value) { + viewModel.updateName(value); + }, + hintText: 'Enter Name'), + ], + ); + } } diff --git a/lib/application/views/inventorymodule/stockTransferViews/InventoryStockTransferVC.dart b/lib/application/views/inventorymodule/stockTransferViews/InventoryStockTransferVC.dart index 935e059..21dfc7f 100644 --- a/lib/application/views/inventorymodule/stockTransferViews/InventoryStockTransferVC.dart +++ b/lib/application/views/inventorymodule/stockTransferViews/InventoryStockTransferVC.dart @@ -1,9 +1,11 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:provider/provider.dart'; +import 'package:sizer/sizer.dart'; import 'package:wosull/application/enum/DataState.dart'; import 'package:wosull/application/model/StockTransfer/StockTransferDetailsModel.dart'; import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/AppError.dart'; import 'package:wosull/application/utils/AppLoader.dart'; import 'package:wosull/application/views/inventorymodule/stockTransferViews/InventoryNewStockTransferVC.dart'; import 'package:wosull/application/views/inventorymodule/stockTransferViews/StockTransferViewVC.dart'; @@ -14,6 +16,8 @@ import 'package:wosull/base/BaseStatefulState.dart'; import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/ThemeText.dart'; import 'package:wosull/widgets/CustomSimpleButton.dart'; +import 'package:wosull/widgets/PageLimitDropDown.dart'; +import 'package:wosull/widgets/SearchBox.dart'; class InventoryStockTransferVC extends StatefulWidget { const InventoryStockTransferVC({Key? key}) : super(key: key); @@ -48,22 +52,89 @@ class _InventoryStockTransferVCState return SingleChildScrollView( controller: _controller, child: Container( - padding: const EdgeInsets.all(12), + padding: const EdgeInsets.all(10), child: Column( children: [ - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Text( - AppLocalizations.of(context)!.stock_transfers, - style: ThemeText.textStylePageHeading, - ), - const SizedBox( - width: 8, - ), - getNewStockTransferBtn(), - ], - ), + isPortrait + ? Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)!.stock_transfers, + style: ThemeText.textStylePageHeading, + ), + AppSpaces.horizontalSmall, + Flexible(child: getNewStockTransferBtn()), + AppSpaces.horizontalSmall, + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + PageLimitDropdown(onChange: (value) { + viewModel.fetch( + isRefresh: true, + limit: int.parse(value!)); + }) + ], + ) + ], + ), + SizedBox( + height: 48, + child: SearchBox( + onEditingDone: (text) { + filterSearchResults(text); + }, + onChanged: (text) { + filterSearchResults(text); + }, + hint: AppLocalizations.of(context)!.search, + ), + ) + ], + ) + : Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)!.stock_transfers, + style: ThemeText.textStylePageHeading, + ), + AppSpaces.horizontalSmall, + SizedBox( + width: 140, + child: getNewStockTransferBtn(), + ), + AppSpaces.horizontalSmall, + SizedBox( + width: SizerUtil.deviceType == DeviceType.mobile + ? 200 + : 200, + height: 48, + child: SearchBox( + onEditingDone: (text) { + filterSearchResults(text); + }, + onChanged: (text) { + filterSearchResults(text); + }, + hint: AppLocalizations.of(context)!.search, + ), + ), + Flexible( + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + PageLimitDropdown(onChange: (value) { + viewModel.fetch( + isRefresh: true, + limit: int.parse(value!)); + }) + ], + )) + ], + ), AppSpaces.verticalMedium, ChangeNotifierProvider( create: (context) => viewModel, @@ -82,8 +153,8 @@ class _InventoryStockTransferVCState case DataState.refreshing: return showData(controller.filteredList); case DataState.error: - return const Center( - child: Text("Error"), + return AppError( + error: 'Error', ); case DataState.searching: case DataState.fetched: @@ -123,11 +194,21 @@ class _InventoryStockTransferVCState bool _scrollNotification() { if (!viewModel.isLoading && _controller.position.extentAfter < 300) { - viewModel.fetch(); + viewModel.fetch(limit: viewModel.limit); } return true; } + Future filterSearchResults(String query) async { + if (query.isNotEmpty) { + viewModel.search(searchValue: query); + } else { + Future.delayed(const Duration(milliseconds: 700), () { + viewModel.search(searchValue: ""); + }); + } + } + Future showDeletePopUp(String id) async { final result = await showDialog( barrierColor: Colors.black26, @@ -157,7 +238,7 @@ class _InventoryStockTransferVCState ); } }).onError((error, stackTrace) { - print(error.toString()); + print(stackTrace.toString()); hideProgressBar(); }); } @@ -175,24 +256,22 @@ class _InventoryStockTransferVCState } Widget getNewStockTransferBtn() { - return SizedBox( - width: 180, - child: CustomSimpleButton( - height: 38, - heading: AppLocalizations.of(context)!.new_stock_transfer, - textColor: MyColors.blueThemeColor, - backGroundColor: MyColors.backColorBlue50, - onPressed: () { - toNewStock(); - }, - ), + return CustomSimpleButton( + height: 38, + heading: AppLocalizations.of(context)!.new_stock_transfer, + textColor: MyColors.blueThemeColor, + backGroundColor: MyColors.backColorBlue50, + onPressed: () { + toNewStock(); + }, ); } void toNewStock() async { final result = await Navigator.push( context, - MaterialPageRoute(builder: (context) => InventoryNewStockTransferVC()), + MaterialPageRoute( + builder: (context) => const InventoryNewStockTransferVC()), ); if (!mounted) return; diff --git a/lib/application/views/inventorymodule/stockTransferViews/StockTransferViewVC.dart b/lib/application/views/inventorymodule/stockTransferViews/StockTransferViewVC.dart index 6743c64..88393f3 100644 --- a/lib/application/views/inventorymodule/stockTransferViews/StockTransferViewVC.dart +++ b/lib/application/views/inventorymodule/stockTransferViews/StockTransferViewVC.dart @@ -7,7 +7,12 @@ import 'package:wosull/application/theme/MyFonts.dart'; import 'package:wosull/application/theme/MySeparator.dart'; import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/widgets/BorderContainer.dart'; +import 'package:wosull/widgets/ChildContainer.dart'; +import 'package:wosull/widgets/CustomAppBar.dart'; +import 'package:wosull/widgets/HeadingContainer.dart'; import 'package:wosull/widgets/HeadingText.dart'; +import 'package:wosull/widgets/PortraitContainer.dart'; import 'package:wosull/widgets/ValueText.dart'; class StockTransferViewVC extends StatelessWidget { @@ -20,308 +25,280 @@ class StockTransferViewVC extends StatelessWidget { @override Widget build(BuildContext context) { - return MaterialApp( - debugShowCheckedModeBanner: false, - home: Scaffold( - resizeToAvoidBottomInset: true, - appBar: AppBar( - leading: BackButton( - color: Colors.black, - onPressed: () { - Navigator.pop(context); - }, // <-- SEE HERE - ), - centerTitle: true, - title: const Text( - 'Stock Transfer', - style: ThemeText.textStylePopUpHeading, - ), - backgroundColor: MyColors.white, - elevation: 5, - ), - body: OrientationBuilder(builder: (c, orientation) { - isPortrait = - MediaQuery.of(context).orientation == Orientation.portrait; - return SingleChildScrollView( - child: Container( - color: MyColors.white, - padding: const EdgeInsets.all(8), - child: Column( - children: [ - Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), + return Scaffold( + backgroundColor: MyColors.fillColor, + resizeToAvoidBottomInset: true, + appBar: CustomAppBar( + heading: 'Stock Transfer', + ), + body: OrientationBuilder(builder: (c, orientation) { + isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; + return SingleChildScrollView( + child: Container( + padding: const EdgeInsets.all(8), + child: Column( + children: [ + AppSpaces.verticalLarge, + Card( + elevation: 5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Container( + margin: const EdgeInsets.all(16), + child: isPortrait + ? Container( + padding: const EdgeInsets.all(16), + decoration: const BoxDecoration( + color: MyColors.fillColor2, + borderRadius: + BorderRadius.all(Radius.circular(8.0)), + ), + child: Column( + children: [ + getStockRefer(), + AppSpaces.verticalMedium, + getFromStoreCode(), + AppSpaces.verticalMedium, + getFromStore(), + AppSpaces.verticalMedium, + toStoreCode(), + AppSpaces.verticalMedium, + toStore(), + AppSpaces.verticalMedium, + Row( + children: [ + HeadingText( + AppLocalizations.of(context)! + .created_on, + ), + AppSpaces.horizontalMedium, + const Expanded( + child: + MySeparator(color: Colors.grey), + ), + AppSpaces.horizontalMedium, + ValueText( + DataTimeFormat.getFormatDate( + stockTransfer.createdAt!), + ) + ], + ), + AppSpaces.verticalMedium, + Row( + children: [ + HeadingText( + AppLocalizations.of(context)! + .updated_on, + ), + AppSpaces.horizontalMedium, + const Expanded( + child: + MySeparator(color: Colors.grey), + ), + AppSpaces.horizontalMedium, + ValueText( + DataTimeFormat.getFormatDate( + stockTransfer.updatedAt!), + ) + ], + ), + ], + ), + ) + : Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + child: Container( + padding: const EdgeInsets.all(16), + decoration: const BoxDecoration( + color: MyColors.fillColor2, + borderRadius: BorderRadius.all( + Radius.circular(8.0)), + ), + child: Column( + children: [ + getStockRefer(), + AppSpaces.verticalMedium, + getFromStoreCode(), + AppSpaces.verticalMedium, + getFromStore(), + AppSpaces.verticalMedium, + toStoreCode() + ], + ), + )), + AppSpaces.horizontalMedium, + Expanded( + child: Container( + padding: const EdgeInsets.all(16), + decoration: const BoxDecoration( + color: MyColors.fillColor2, + borderRadius: BorderRadius.all( + Radius.circular(8.0)), + ), + child: Column( + children: [ + toStore(), + AppSpaces.verticalMedium, + Row( + children: [ + HeadingText( + AppLocalizations.of(context)! + .created_on, + ), + const SizedBox( + width: 8, + ), + const Expanded( + child: MySeparator( + color: Colors.grey), + ), + const SizedBox( + width: 8, + ), + ValueText( + DataTimeFormat.getFormatDate( + stockTransfer.createdAt!), + ) + ], + ), + AppSpaces.verticalMedium, + Row( + children: [ + HeadingText( + AppLocalizations.of(context)! + .updated_on, + ), + const SizedBox( + width: 8, + ), + const Expanded( + child: MySeparator( + color: Colors.grey), + ), + const SizedBox( + width: 8, + ), + ValueText( + DataTimeFormat.getFormatDate( + stockTransfer.updatedAt!), + ) + ], + ), + ], + ), + )), + ], + ), + ), + ], + ), + ), + AppSpaces.verticalLarge, + Card( + elevation: 5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: Container( + width: double.infinity, + padding: const EdgeInsets.all(15), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ - Container( - margin: const EdgeInsets.all(16), - child: isPortrait - ? Container( - padding: const EdgeInsets.all(16), - decoration: const BoxDecoration( + const Text( + 'Product Information', + style: ThemeText.textStyleHeadingCart, + ), + AppSpaces.verticalLarge, + isPortrait + ? Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + margin: const EdgeInsets.only( + left: 80, right: 80), + height: 24, color: MyColors.fillColor2, - borderRadius: - BorderRadius.all(Radius.circular(8.0)), - ), - child: Column( - children: [ - getStockRefer(), - AppSpaces.verticalMedium, - getFromStoreCode(), - AppSpaces.verticalMedium, - getFromStore(), - AppSpaces.verticalMedium, - toStoreCode(), - AppSpaces.verticalMedium, - toStore(), - AppSpaces.verticalMedium, - Row( - children: [ - HeadingText( - AppLocalizations.of(context)! - .created_on, - ), - const SizedBox( - width: 8, - ), - const Expanded( - child: - MySeparator(color: Colors.grey), - ), - const SizedBox( - width: 8, - ), - ValueText( - DataTimeFormat.getFormatDate( - stockTransfer.createdAt!), - ) - ], - ), - AppSpaces.verticalMedium, - Row( - children: [ - HeadingText( - AppLocalizations.of(context)! - .updated_on, - ), - const SizedBox( - width: 8, - ), - const Expanded( - child: - MySeparator(color: Colors.grey), - ), - const SizedBox( - width: 8, - ), - ValueText( - DataTimeFormat.getFormatDate( - stockTransfer.updatedAt!), - ) - ], - ), - ], - ), - ) - : Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Expanded( - child: Container( - padding: const EdgeInsets.all(16), - decoration: const BoxDecoration( - color: MyColors.fillColor2, - borderRadius: BorderRadius.all( - Radius.circular(8.0)), + child: Center( + child: HeadingText( + 'Transferred Records', ), - child: Column( - children: [ - getStockRefer(), - const SizedBox( - height: 8, - ), - getFromStoreCode(), - const SizedBox( - height: 8, - ), - getFromStore(), - const SizedBox( - height: 8, - ), - toStoreCode() - ], - ), - )), - const SizedBox( - width: 8, ), - Expanded( - child: Container( - padding: const EdgeInsets.all(16), - decoration: const BoxDecoration( - color: MyColors.fillColor2, - borderRadius: BorderRadius.all( - Radius.circular(8.0)), - ), - child: Column( - children: [ - toStore(), - const SizedBox( - height: 8, - ), - Row( - children: [ - HeadingText( - AppLocalizations.of(context)! - .created_on, - ), - const SizedBox( - width: 8, - ), - const Expanded( - child: MySeparator( - color: Colors.grey), - ), - const SizedBox( - width: 8, - ), - ValueText( - DataTimeFormat.getFormatDate( - stockTransfer.createdAt!), - ) - ], - ), - const SizedBox( - height: 8, - ), - Row( - children: [ - HeadingText( - AppLocalizations.of(context)! - .updated_on, - ), - const SizedBox( - width: 8, - ), - const Expanded( - child: MySeparator( - color: Colors.grey), + ), + BorderContainer( + child: Row( + children: [ + Expanded( + child: Row( + children: [ + Container( + width: 44, + height: 48, + decoration: const BoxDecoration( + border: Border( + right: BorderSide( + width: 1.0, + color: MyColors + .fillColorGray2), + ), ), - const SizedBox( - width: 8, + child: Center( + child: ValueText( + '#', + ), ), - ValueText( - DataTimeFormat.getFormatDate( - stockTransfer.updatedAt!), - ) - ], - ), - ], - ), - )), - ], - ), - ), - ], - ), - ), - const SizedBox( - height: 12, - ), - Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(4.0), - ), - child: Container( - width: double.infinity, - padding: const EdgeInsets.all(8), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - const Text( - 'Product Information', - style: ThemeText.textStylePopUpHeading, - ), - const SizedBox( - height: 16, - ), - isPortrait - ? Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - margin: const EdgeInsets.only( - left: 80, right: 80), - height: 24, - color: MyColors.fillColor2, - child: Center( - child: HeadingText( - 'Transferred Records', - ), - ), - ), - Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular( - 1.0) // <--- border radius here ), - border: Border.all( - width: 1, - color: MyColors.fillColorGray2), - color: MyColors.fillColor2, - ), - height: 38, - child: Row( - children: [ - Expanded( - child: Row( - children: [ - Container( - width: 44, - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), + Expanded( + child: Container( + padding: const EdgeInsets.only( + left: 4, right: 4), + height: 48, + decoration: const BoxDecoration( + border: Border( + right: BorderSide( + width: 1.0, + color: MyColors + .fillColorGray2), ), - child: Center( - child: ValueText( - '#', - ), + ), + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + 'Status', ), ), - Expanded( - child: Container( - padding: const EdgeInsets.only( - left: 4, right: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), + )), + Expanded( + child: Container( + padding: const EdgeInsets.only( + left: 4), + height: 48, + decoration: const BoxDecoration( + border: Border( + right: BorderSide( + width: 1.0, + color: MyColors + .fillColorGray2), ), - child: Align( - alignment: - Alignment.centerLeft, - child: HeadingText( - 'Status', - ), + ), + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + 'Product Code', ), - )), - Expanded( - child: Container( + ), + )), + Expanded( + child: Container( padding: const EdgeInsets.only( left: 4), height: 48, @@ -337,649 +314,333 @@ class StockTransferViewVC extends StatelessWidget { alignment: Alignment.centerLeft, child: HeadingText( - 'Product Code', + 'Name & Description', ), ), - )), - Expanded( + ), + ), + Expanded( child: Container( - padding: - const EdgeInsets.only( - left: 4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: - Alignment.centerLeft, - child: HeadingText( - 'Name & Description', - ), - ), + padding: const EdgeInsets.only( + left: 4), + height: 48, + decoration: const BoxDecoration( + border: Border( + right: BorderSide( + width: 1.0, + color: MyColors + .fillColorGray2), ), ), - Expanded( - child: Container( - padding: const EdgeInsets.only( - left: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + 'Quantity', ), - child: Align( - alignment: - Alignment.centerLeft, - child: HeadingText( - 'Quantity', - ), - ), - )), - ], - )), - ], - ), + ), + )), + ], + )), + ], ), - Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all( - width: 1, - color: MyColors.fillColorGray2), - color: MyColors.white, - ), - height: 38, - child: Row( - children: [ - Expanded( - child: Row( - children: [ - getReferNo(), - Expanded( - child: Container( - padding: const EdgeInsets.only( - left: 4, right: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, + ), + BorderContainer( + backgroundColor: MyColors.white, + child: Row( + children: [ + Expanded( + child: Row( + children: [ + getReferNo(), + Expanded( + child: PortraitContainer( + child: Align( + alignment: Alignment.centerLeft, + child: Container( + height: 35, + decoration: const BoxDecoration( color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: - Alignment.centerLeft, - child: Container( - height: 35, - decoration: const BoxDecoration( - color: MyColors - .greenColor10, - borderRadius: - BorderRadius.all( - Radius.circular( - 10.0))), - child: const Padding( - padding: - EdgeInsets.all( - 10.0), - child: Text( - 'Accepted', - style: TextStyle( - fontFamily: - MyFonts - .Medium, - fontWeight: - FontWeight - .w500, - fontSize: 11, - color: MyColors - .greenColor), - ))), - ), - )), - getProductCode(), - getNameDesc(), - getQuantity(), - ], - )), - ], - ), - ), - const SizedBox( - height: 16, + .greenColor10, + borderRadius: + BorderRadius.all( + Radius.circular( + 10.0))), + child: const Padding( + padding: EdgeInsets.all( + 10.0), + child: Text( + 'Accepted', + style: TextStyle( + fontFamily: + MyFonts + .Medium, + fontWeight: + FontWeight + .w500, + fontSize: 10, + color: MyColors + .greenColor), + ))), + ), + )), + getProductCode(), + getNameDesc(), + getQuantity(), + ], + )), + ], ), - Container( - margin: const EdgeInsets.only( - left: 80, right: 80), - height: 24, - color: MyColors.fillColor2, - child: const Center( - child: Text( - 'Accept & Inward Records', - style: TextStyle( - color: MyColors.textColorBlack, - fontSize: MyFonts.normal, - fontFamily: MyFonts.Medium), - ), + ), + AppSpaces.verticalLarge, + Container( + margin: const EdgeInsets.only( + left: 80, right: 80), + height: 24, + color: MyColors.fillColor2, + child: Center( + child: HeadingText( + 'Accept & Inward Records', ), ), - Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all( - width: 1, - color: MyColors.fillColorGray2), - color: MyColors.fillColor2, - ), - height: 38, - child: Row( - children: [ - Expanded( - child: Row( - children: [ - Expanded( - child: Container( - padding: const EdgeInsets.only( - left: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: const Align( - alignment: - Alignment.centerLeft, - child: Text( - 'Accepted Quantity', - style: TextStyle( - fontFamily: - MyFonts.Medium, - fontWeight: - FontWeight.w500, - fontSize: 11, - color: MyColors - .textColorBlack20), - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.only( - left: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: const Align( - alignment: - Alignment.centerLeft, - child: Text( - 'Inward Type', - style: TextStyle( - fontFamily: - MyFonts.Medium, - fontWeight: - FontWeight.w500, - fontSize: 11, - color: MyColors - .textColorBlack20), - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.only( - left: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), + ), + BorderContainer( + child: Row( + children: [ + Expanded( + child: Row( + children: [ + Expanded( + child: PortraitContainer( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + 'Accepted Quantity', ), - child: const Align( - alignment: - Alignment.centerLeft, - child: Text( - 'Product Code', - style: TextStyle( - fontFamily: - MyFonts.Medium, - fontWeight: - FontWeight.w500, - fontSize: - MyFonts.normal, - color: MyColors - .textColorBlack20), - ), + ), + )), + Expanded( + child: PortraitContainer( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + 'Inward Type', ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.only( - left: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), + ), + )), + Expanded( + child: PortraitContainer( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + 'Product Code', ), - child: const Align( - alignment: - Alignment.centerLeft, - child: Text( - 'Name & Description', - style: TextStyle( - fontFamily: - MyFonts.Medium, - fontWeight: - FontWeight.w500, - fontSize: 11, - color: MyColors - .textColorBlack20), - ), + ), + )), + Expanded( + child: PortraitContainer( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + 'Name & Description', ), - )), - ], - )) - ], - ), + ), + )), + ], + )) + ], ), - Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all( - width: 1, - color: MyColors.fillColorGray2), - color: MyColors.white, - ), - height: 38, - child: Row( - children: [ - Expanded( - child: Row( - children: [ - acceptedQuantity(), - getInwardType(), - getProductCode(), - getNameDesc(), - ], - )) - ], - ), + ), + BorderContainer( + backgroundColor: MyColors.white, + child: Row( + children: [ + Expanded( + child: Row( + children: [ + acceptedQuantity(), + getInwardType(), + getProductCode(), + getNameDesc(), + ], + )) + ], ), - ], - ) - : Column( - children: [ - Row( - mainAxisAlignment: - MainAxisAlignment.spaceEvenly, + ), + ], + ) + : Column( + children: [ + Row( + mainAxisAlignment: + MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + child: Container( + margin: const EdgeInsets.only( + left: 80, right: 80), + height: 24, + color: MyColors.fillColor2, + child: Center( + child: HeadingText( + 'Transferred Records', + ), + ), + )), + Expanded( + child: Container( + margin: const EdgeInsets.only( + left: 80, right: 80), + height: 24, + color: MyColors.fillColor2, + child: Center( + child: HeadingText( + 'Accept & Inward Records', + ), + ), + )) + ], + ), + BorderContainer( + child: Row( children: [ Expanded( - child: Container( - margin: const EdgeInsets.only( - left: 80, right: 80), - height: 24, - color: MyColors.fillColor2, - child: Center( - child: HeadingText( - 'Transferred Records', + child: Row( + children: [ + HeadingContainer( + width: 44, + heading: '#', ), - ), + Expanded( + child: HeadingContainer( + heading: 'Status', + )), + Expanded( + child: HeadingContainer( + heading: 'Product Code', + )), + Expanded( + child: HeadingContainer( + heading: 'Name & Description', + )), + Expanded( + child: HeadingContainer( + heading: 'Quantity', + )), + ], )), Expanded( - child: Container( - margin: const EdgeInsets.only( - left: 80, right: 80), - height: 24, - color: MyColors.fillColor2, - child: Center( - child: HeadingText( - 'Accept & Inward Records', - ), - ), - )) + child: Row( + children: [ + Expanded( + child: HeadingContainer( + heading: 'Accepted Quantity', + )), + Expanded( + child: HeadingContainer( + heading: 'Inward Type', + )), + Expanded( + child: HeadingContainer( + heading: 'Product Code', + )), + Expanded( + child: HeadingContainer( + heading: + 'Name & Description')), + ], + )), ], ), - Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all( - width: 1, - color: MyColors.fillColorGray2), - color: MyColors.fillColor2, - ), - height: 48, - child: Row( - children: [ - Expanded( - child: Row( - children: [ - Container( - width: 44, - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, + ), + BorderContainer( + backgroundColor: MyColors.white, + child: Row( + children: [ + Expanded( + child: Row( + children: [ + getReferNo(), + Expanded( + child: ChildContainer( + child: Align( + alignment: Alignment.centerLeft, + child: Container( + height: 35, + decoration: const BoxDecoration( color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: HeadingText( - '#', - ), - ), + .greenColor10, + borderRadius: + BorderRadius.all( + Radius.circular( + 10.0))), + child: const Padding( + padding: EdgeInsets.all( + 10.0), + child: Text( + 'Accepted', + style: TextStyle( + fontFamily: + MyFonts + .Medium, + fontWeight: + FontWeight + .w500, + fontSize: 11, + color: MyColors + .greenColor), + ))), ), - Expanded( - child: Container( - padding: const EdgeInsets.only( - left: 4, right: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: - Alignment.centerLeft, - child: HeadingText( - 'Status', - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.only( - left: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: - Alignment.centerLeft, - child: HeadingText( - 'Product Code', - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.only( - left: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: - Alignment.centerLeft, - child: HeadingText( - 'Name & Description', - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.only( - left: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: - Alignment.centerLeft, - child: HeadingText( - 'Quantity', - ), - ), - )), - ], - )), - Expanded( - child: Row( - children: [ - Expanded( - child: Container( - padding: const EdgeInsets.only( - left: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: - Alignment.centerLeft, - child: HeadingText( - 'Accepted Quantity', - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.only( - left: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: - Alignment.centerLeft, - child: HeadingText( - 'Inward Type', - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.only( - left: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: - Alignment.centerLeft, - child: HeadingText( - 'Product Code', - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.only( - left: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: - Alignment.centerLeft, - child: HeadingText( - 'Name & Description'), - ), - )), - ], - )), - ], - ), + )), + getProductCode(), + getNameDesc(), + getQuantity(), + ], + )), + Expanded( + child: Row( + children: [ + acceptedQuantity(), + getInwardType(), + getProductCode(), + getNameDesc(), + ], + )), + ], ), - Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all( - width: 1, - color: MyColors.fillColorGray2), - color: MyColors.white, - ), - height: 48, - child: Row( - children: [ - Expanded( - child: Row( - children: [ - getReferNo(), - Expanded( - child: Container( - padding: const EdgeInsets.only( - left: 4, right: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: - Alignment.centerLeft, - child: Container( - height: 35, - decoration: const BoxDecoration( - color: MyColors - .greenColor10, - borderRadius: - BorderRadius.all( - Radius.circular( - 10.0))), - child: const Padding( - padding: - EdgeInsets.all( - 10.0), - child: Text( - 'Accepted', - style: TextStyle( - fontFamily: - MyFonts - .Medium, - fontWeight: - FontWeight - .w500, - fontSize: 11, - color: MyColors - .greenColor), - ))), - ), - )), - getProductCode(), - getNameDesc(), - getQuantity(), - ], - )), - Expanded( - child: Row( - children: [ - acceptedQuantity(), - getInwardType(), - getProductCode(), - getNameDesc(), - ], - )), - ], - ), - ) - ], - ) - ], - ), + ) + ], + ) + ], ), ), - ], - ), + ), + AppSpaces.verticalLarge, + Card( + elevation: 5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: Container( + width: double.infinity, + padding: const EdgeInsets.all(15), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + const Text( + 'Notes', + style: ThemeText.textStyleHeadingCart, + ), + AppSpaces.verticalLarge, + ], + ), + ), + ), + ], ), - ); - }), - ), + ), + ); + }), ); } @@ -989,15 +650,11 @@ class StockTransferViewVC extends StatelessWidget { HeadingText( 'Stock Transfer Reference', ), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, const Expanded( child: MySeparator(color: Colors.grey), ), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, ValueText('#${stockTransfer.uniqueId!.toString()}') ], ); @@ -1007,15 +664,11 @@ class StockTransferViewVC extends StatelessWidget { return Row( children: [ HeadingText('From Store Code'), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, const Expanded( child: MySeparator(color: Colors.grey), ), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, ValueText(stockTransfer.fromStore!.name.toUpperCase()) ], ); @@ -1025,15 +678,11 @@ class StockTransferViewVC extends StatelessWidget { return Row( children: [ HeadingText('From Store'), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, const Expanded( child: MySeparator(color: Colors.grey), ), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, ValueText(stockTransfer.fromStore?.name ?? '') ], ); @@ -1043,15 +692,11 @@ class StockTransferViewVC extends StatelessWidget { return Row( children: [ HeadingText('To Store Code'), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, const Expanded( child: MySeparator(color: Colors.grey), ), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, ValueText(stockTransfer.toStore!.name.toUpperCase()) ], ); @@ -1061,29 +706,19 @@ class StockTransferViewVC extends StatelessWidget { return Row( children: [ HeadingText('To Store'), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, const Expanded( child: MySeparator(color: Colors.grey), ), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, ValueText(stockTransfer.toStore!.name) ], ); } Widget getReferNo() { - return Container( + return ChildContainer( width: 44, - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide(width: 1.0, color: MyColors.fillColorGray2), - ), - ), child: Center( child: ValueText( stockTransfer.uniqueId!.toString(), @@ -1094,14 +729,7 @@ class StockTransferViewVC extends StatelessWidget { Widget getProductCode() { return Expanded( - child: Container( - padding: const EdgeInsets.only(left: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide(width: 1.0, color: MyColors.fillColorGray2), - ), - ), + child: ChildContainer( child: Align( alignment: Alignment.centerLeft, child: ValueText(stockTransfer.itemId!.productCode!), @@ -1111,14 +739,7 @@ class StockTransferViewVC extends StatelessWidget { Widget getNameDesc() { return Expanded( - child: Container( - padding: const EdgeInsets.only(left: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide(width: 1.0, color: MyColors.fillColorGray2), - ), - ), + child: ChildContainer( child: Align( alignment: Alignment.centerLeft, child: ValueText(stockTransfer.itemId!.name!), @@ -1128,14 +749,7 @@ class StockTransferViewVC extends StatelessWidget { Widget getQuantity() { return Expanded( - child: Container( - padding: const EdgeInsets.only(left: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide(width: 1.0, color: MyColors.fillColorGray2), - ), - ), + child: ChildContainer( child: Align( alignment: Alignment.centerLeft, child: ValueText(stockTransfer.itemId!.totalQuantity!.toString()), @@ -1145,14 +759,7 @@ class StockTransferViewVC extends StatelessWidget { Widget acceptedQuantity() { return Expanded( - child: Container( - padding: const EdgeInsets.only(left: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide(width: 1.0, color: MyColors.fillColorGray2), - ), - ), + child: ChildContainer( child: Align( alignment: Alignment.centerLeft, child: ValueText(stockTransfer.itemId!.totalQuantity!.toString()), @@ -1162,14 +769,7 @@ class StockTransferViewVC extends StatelessWidget { Widget getInwardType() { return Expanded( - child: Container( - padding: const EdgeInsets.only(left: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide(width: 1.0, color: MyColors.fillColorGray2), - ), - ), + child: ChildContainer( child: Align( alignment: Alignment.centerLeft, child: HeadingText( diff --git a/lib/application/views/inventorymodule/stockTransferViews/repo/StockTransferRepository.dart b/lib/application/views/inventorymodule/stockTransferViews/repo/StockTransferRepository.dart new file mode 100644 index 0000000..b710ba7 --- /dev/null +++ b/lib/application/views/inventorymodule/stockTransferViews/repo/StockTransferRepository.dart @@ -0,0 +1,65 @@ +import 'package:wosull/application/model/SimpleResponsModel.dart'; +import 'package:wosull/application/model/StockTransfer/SearchStockTransferResponse.dart'; +import 'package:wosull/application/model/StockTransfer/StockTransferDetailsModel.dart'; +import 'package:wosull/application/model/StockTransfer/ViewStockTransferModel.dart'; +import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/utils/Constants.dart'; + +class StockTransferRepository { + Future updateItem(Map data) async { + final response = + await APIManager().fetchData(Constants.UPDATE_STORE_ITEM, data); + return SimpleResponseModel.fromJson(response); + } + + Future addStock(Map data) async { + final response = + await APIManager().fetchData(Constants.ADD_STOCK_TRANSFER, data); + return SimpleResponseModel.fromJson(response); + } + + Future> getStockTransfers( + Map data) async { + var stocks = []; + await APIManager() + .fetchData(Constants.GET_STOCK_TRANSFER, data) + .then((result) { + final value = StockTransferDetailsModel.fromJson(result); + if (value.success) { + stocks.addAll(value.stockTransfers); + } + }).onError((error, stackTrace) {}); + return stocks; + } + + Future> search(Map data) async { + var stocks = []; + await APIManager() + .fetchData(Constants.searchStockTransfer, data) + .then((result) { + final value = SearchStockTransferResponse.fromJson(result); + if (value.success) { + stocks.addAll(value.stockTransfers); + } + }).onError((error, stackTrace) {}); + return stocks; + } + + Future delete(String id) async { + Map data = {'stockId': id}; + return await APIManager() + .getResponsePatch(Constants.DELETE_STOCK_TRANSFER, data); + } + + Future update(String id, String status) async { + Map data = {'stockId': id, 'status': status}; + return await APIManager() + .getResponsePatch(Constants.UPDATE_STOCK_TRANSFER, data); + } + + Future getStockTransferById(String id) async { + dynamic response = await APIManager() + .getResponseAuth('${Constants.GET_STOCK_TRANSFER_BY_ID}$id'); + return ViewStockTransferModel.fromJson(response); + } +} diff --git a/lib/application/views/inventorymodule/stockTransferViews/viewModels/NewStockTransferVM.dart b/lib/application/views/inventorymodule/stockTransferViews/viewModels/NewStockTransferVM.dart index c7a651b..bc13f77 100644 --- a/lib/application/views/inventorymodule/stockTransferViews/viewModels/NewStockTransferVM.dart +++ b/lib/application/views/inventorymodule/stockTransferViews/viewModels/NewStockTransferVM.dart @@ -1,17 +1,14 @@ -import 'dart:convert'; - import 'package:flutter/material.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; -import 'package:wosull/application/model/SimpleResponsModel.dart'; import 'package:wosull/application/model/StockTransfer/ProductItemCategoryModel.dart'; -import 'package:wosull/application/model/store/GetSpecificStores.dart'; import 'package:wosull/application/model/store/WosulStore.dart'; -import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/repository/WosulRepository.dart'; import 'package:wosull/application/utils/CRUDOperatoinState.dart'; -import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/inventorymodule/stockTransferViews/repo/StockTransferRepository.dart'; import 'package:wosull/helpers/Utils.dart'; class NewStockTransferVM with ChangeNotifier { + final repository = StockTransferRepository(); ProductItem productItem = ProductItem(); bool isPortrait = true; @@ -21,16 +18,11 @@ class NewStockTransferVM with ChangeNotifier { 'Customer Orders', 'Seasonal Demand', ]; - + List filteredProductItems = []; var transferReasonValue; var selectedStoreDropDown; late List stores; String notesController = ''; - String priceController = ''; - String nameController = ''; - String uniqueIdController = ''; - String quantityController = ''; - String descriptionController = ''; bool _isLoading = false; @@ -49,16 +41,19 @@ class NewStockTransferVM with ChangeNotifier { notifyListeners(); } + Future initData() async { + final response = await WosulRepository().getAllProducts(); + filteredProductItems.addAll(response); + notifyListeners(); + } + Future> getStores() async { var stores = []; Map data = { 'is_included': false, 'store_id': sharedPrefs.storeId, }; - await APIManager() - .fetchData(Constants.GET_SPECIFIC_STORES, data) - .then((response) { - final value = GetSpecificStores.fromJson(response); + await WosulRepository().getSpecificStoresById(data).then((value) { if (value.success) { stores.clear(); stores.add( @@ -86,23 +81,19 @@ class NewStockTransferVM with ChangeNotifier { Future updateItem() async { Map data = { 'from_store': sharedPrefs.storeId, - 'unique_id_for_store_data': uniqueIdController, - 'name': nameController, - 'total_quantity': quantityController, - 'details': descriptionController, - 'price': priceController, + 'unique_id_for_store_data': productItem.uniqueIdForStoreData, + 'name': productItem.name, + 'total_quantity': productItem.total_quantity, + 'details': notesController, + 'price': productItem.price, 'note_for_item': notesController, }; - print(jsonEncode(data)); - await APIManager() - .fetchData(Constants.UPDATE_STORE_ITEM, data) - .then((value) async { - final response = SimpleResponseModel.fromJson(value); + await repository.updateItem(data).then((response) async { if (response.success) { await addStock(); } else { setLoading(false); - Utils.showMessage(value.message); + Utils.showMessage(response.message); } }).onError((error, stackTrace) { setLoading(false); @@ -118,13 +109,8 @@ class NewStockTransferVM with ChangeNotifier { 'to_store': store.id, 'transfer_reason': transferReasonValue, }; - await APIManager() - .fetchData(Constants.ADD_STOCK_TRANSFER, data) - .then((value) async { - final response = SimpleResponseModel.fromJson(value); - + await repository.addStock(data).then((response) async { if (response.success) { - //success _crudOperationState = CRUDOperationState.add; } setLoading(false); @@ -135,13 +121,15 @@ class NewStockTransferVM with ChangeNotifier { void checkQuantity(String value) { if (productItem.total_quantity != null) { - if (int.parse(value) > productItem.total_quantity!) { - Utils.showMessage('You have exceeded the maximum quantity limit.'); - isEnableButton = false; - notifyListeners(); - } else { - isEnableButton = true; - notifyListeners(); + if (value.isNotEmpty) { + if (int.parse(value) > productItem.total_quantity!) { + Utils.showMessage('You have exceeded the maximum quantity limit.'); + isEnableButton = false; + notifyListeners(); + } else { + isEnableButton = true; + notifyListeners(); + } } } } @@ -158,11 +146,6 @@ class NewStockTransferVM with ChangeNotifier { void setProduct(result) { if (result != null) { productItem = result; - nameController = productItem.name!; - quantityController = productItem.total_quantity!.toString(); - priceController = productItem.price!.toString(); - uniqueIdController = productItem.uniqueIdForStoreData!; - descriptionController = productItem.details!; } notifyListeners(); @@ -170,14 +153,12 @@ class NewStockTransferVM with ChangeNotifier { void setSelectedStore(WosulStore? value) { if (value != null) { - print('hree'); selectedStoreDropDown = value; } notifyListeners(); } void setQuantity(String value) { - quantityController = value; if (value.isNotEmpty) { if (int.parse(value) > productItem.total_quantity!) { isEnableButton = false; @@ -186,4 +167,20 @@ class NewStockTransferVM with ChangeNotifier { } } } + + void updateProductPrice(String value) { + if (value.isNotEmpty) { + productItem.price = double.parse(value); + } else { + productItem.price = 0.0; + } + } + + void updateBarCode(String value) { + productItem.uniqueIdForStoreData = value; + } + + void updateName(String value) { + productItem.name = value; + } } diff --git a/lib/application/views/inventorymodule/stockTransferViews/viewModels/StockTransferViewModel.dart b/lib/application/views/inventorymodule/stockTransferViews/viewModels/StockTransferViewModel.dart index 66513b8..8f348e3 100644 --- a/lib/application/views/inventorymodule/stockTransferViews/viewModels/StockTransferViewModel.dart +++ b/lib/application/views/inventorymodule/stockTransferViews/viewModels/StockTransferViewModel.dart @@ -1,18 +1,15 @@ -import 'dart:convert'; - import 'package:flutter/cupertino.dart'; import 'package:wosull/application/enum/DataState.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; import 'package:wosull/application/model/StockTransfer/StockTransferDetailsModel.dart'; import 'package:wosull/application/model/StockTransfer/ViewStockTransferModel.dart'; -import 'package:wosull/application/network/APIManager.dart'; -import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/inventorymodule/stockTransferViews/repo/StockTransferRepository.dart'; class StockTransferViewModel with ChangeNotifier { bool _isLoading = false; bool get isLoading => _isLoading; - + int limit = 10; int _currentPageNumber = 1; DataState _dataState = DataState.uninitialized; @@ -24,7 +21,13 @@ class StockTransferViewModel with ChangeNotifier { List get filteredList => _filteredList; - fetch({bool isRefresh = false}) async { + List _dataList = []; + + List get dataList => _dataList; + final repository = StockTransferRepository(); + + fetch({bool isRefresh = false, int limit = 10}) async { + this.limit = limit; _isLoading = true; if (!isRefresh) { _dataState = (_dataState == DataState.uninitialized) @@ -39,22 +42,22 @@ class StockTransferViewModel with ChangeNotifier { Map data = { 'store_id': sharedPrefs.storeId, 'page': _currentPageNumber, + 'limit': this.limit }; try { if (_didLastLoad) { _dataState = DataState.noMoreData; } else { - await APIManager() - .fetchData(Constants.GET_STOCK_TRANSFER, data) - .then((result) { - final value = StockTransferDetailsModel.fromJson(result); + await repository.getStockTransfers(data).then((stockTransfers) { if (_dataState == DataState.refreshing) { _filteredList.clear(); + _dataList.clear(); } - if (value.success) { - _filteredList.addAll(value.stockTransfers); - if (value.stockTransfers.length < 10) { + if (stockTransfers.isNotEmpty) { + _filteredList.addAll(stockTransfers); + _dataList.addAll(stockTransfers); + if (stockTransfers.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; @@ -76,11 +79,40 @@ class StockTransferViewModel with ChangeNotifier { } } + search({String searchValue = ""}) async { + if (searchValue.isEmpty) { + _dataState = DataState.fetched; + _filteredList.clear(); + _filteredList.addAll(_dataList); + notifyListeners(); + } else { + Map data = { + 'store_id': sharedPrefs.storeId, + 'searchTerm': searchValue, + }; + _dataState = DataState.searching; + notifyListeners(); + try { + await repository.search(data).then((stockTransfers) { + _filteredList.clear(); + if (stockTransfers.isNotEmpty) { + _filteredList.addAll(stockTransfers); + } + _dataState = DataState.fetched; + }).onError((error, stackTrace) { + _dataState = DataState.error; + }); + notifyListeners(); + } catch (e) { + _dataState = DataState.error; + notifyListeners(); + } + } + } + Future delete(String id) async { Map data = {'stockId': id}; - await APIManager() - .getResponsePatch(Constants.DELETE_STOCK_TRANSFER, data) - .then((result) { + await repository.delete(id).then((result) { filteredList.removeWhere((element) => element.id == id); notifyListeners(); }).onError((error, stackTrace) { @@ -95,23 +127,17 @@ class StockTransferViewModel with ChangeNotifier { } else { status = 'Inactive'; } - Map data = {'stockId': id, 'status': status}; - print(jsonEncode(data)); - await APIManager() - .getResponsePatch(Constants.UPDATE_STOCK_TRANSFER, data) - .then((result) { + + await repository.update(id, status).then((result) { int index = _filteredList.indexWhere((element) => element.id == id); _filteredList[index].status = status; notifyListeners(); }).onError((error, stackTrace) { - print(error.toString()); notifyListeners(); }); } Future getStockTransferById(String id) async { - dynamic response = await APIManager() - .getResponseAuth('${Constants.GET_STOCK_TRANSFER_BY_ID}$id'); - return ViewStockTransferModel.fromJson(response); + return await repository.getStockTransferById(id); } } diff --git a/lib/application/views/inventorymodule/stockTransferViews/widgets/StockTransferListView.dart b/lib/application/views/inventorymodule/stockTransferViews/widgets/StockTransferListView.dart index 5834f05..5d7dea3 100644 --- a/lib/application/views/inventorymodule/stockTransferViews/widgets/StockTransferListView.dart +++ b/lib/application/views/inventorymodule/stockTransferViews/widgets/StockTransferListView.dart @@ -4,9 +4,12 @@ import 'package:wosull/application/model/converters/DataTimeFormat.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/Utils.dart'; +import 'package:wosull/widgets/ActionPopUpContainer.dart'; +import 'package:wosull/widgets/CustomPopuoMenuButton.dart'; import 'package:wosull/widgets/CustomSwitch.dart'; import 'package:wosull/widgets/EmptyDataWidget.dart'; import 'package:wosull/widgets/HeadingText.dart'; +import 'package:wosull/widgets/ListHeadingContainer.dart'; import 'package:wosull/widgets/ValueText.dart'; class StockTransferListView extends StatelessWidget { @@ -34,10 +37,7 @@ class StockTransferListView extends StatelessWidget { children: [ isPortrait ? Container() - : Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 50, - color: MyColors.containerBackColor, + : ListHeadingContainer( child: Row( children: [ Expanded( @@ -151,27 +151,7 @@ class StockTransferListView extends StatelessWidget { ], ), )), - PopupMenuButton( - icon: const Icon(Icons.more_vert), - itemBuilder: (c) { - return [ - PopupMenuItem( - value: 'view', - child: ValueText( - lang(context).view, - ), - ), - PopupMenuItem( - value: 'delete', - child: ValueText( - lang(context).delete, - ), - ) - ]; - }, - onSelected: (String value) => - actionPopUpItemSelected(value, stock), - ) + getActionButton(context, position) ], ), ), @@ -181,10 +161,7 @@ class StockTransferListView extends StatelessWidget { shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.0), ), - child: Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 56, - color: MyColors.containerBackColor, + child: ListHeadingContainer( child: Row( children: [ Expanded( @@ -212,32 +189,8 @@ class StockTransferListView extends StatelessWidget { padding: const EdgeInsets.all(4), child: Align( alignment: Alignment.centerRight, - child: Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular(4)), - color: MyColors.backFillColor), - child: PopupMenuButton( - icon: const Icon(Icons.more_vert), - itemBuilder: (c) { - return [ - PopupMenuItem( - value: 'view', - child: ValueText( - lang(context).view, - ), - ), - PopupMenuItem( - value: 'delete', - child: ValueText( - lang(context).delete, - ), - ) - ]; - }, - onSelected: (String value) => - actionPopUpItemSelected(value, stock), - ), + child: ActionPopUpContainer( + child: getActionButton(context, position), ), ), )) @@ -261,4 +214,25 @@ class StockTransferListView extends StatelessWidget { onView(stockTransfer); } } + + getActionButton(BuildContext context, int position) { + return CustomPopupMenuButton( + items: [ + PopupMenuItem( + value: 'view', + child: ValueText( + lang(context).view, + ), + ), + PopupMenuItem( + value: 'delete', + child: ValueText( + lang(context).delete, + ), + ) + ], + onSelected: (String value) => + actionPopUpItemSelected(value, data[position]), + ); + } } diff --git a/lib/application/views/inventorymodule/subCategoryViews/InventorySubCategoryVC.dart b/lib/application/views/inventorymodule/subCategoryViews/InventorySubCategoryVC.dart index b5f1fa9..9c129dc 100644 --- a/lib/application/views/inventorymodule/subCategoryViews/InventorySubCategoryVC.dart +++ b/lib/application/views/inventorymodule/subCategoryViews/InventorySubCategoryVC.dart @@ -3,8 +3,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:provider/provider.dart'; import 'package:wosull/application/model/inventory/ItemSubCategoryResponse.dart'; +import 'package:wosull/application/model/inventory/category/ItemCategory.dart'; import 'package:wosull/application/theme/MyColors.dart'; -import 'package:wosull/application/utils/AppLoader.dart'; import 'package:wosull/application/utils/CRUDOperatoinState.dart'; import 'package:wosull/application/views/inventorymodule/subCategoryViews/viewModels/AddSubCategoryViewModel.dart'; import 'package:wosull/base/BaseStatefulState.dart'; @@ -15,10 +15,9 @@ import 'package:wosull/widgets/CustomSimpleButton.dart'; import 'package:wosull/widgets/CustomSwitch.dart'; import 'package:wosull/widgets/CustomTextFieldForm.dart'; import 'package:wosull/widgets/DialogHeader.dart'; +import 'package:wosull/widgets/DropdownItemBuilder.dart'; import 'package:wosull/widgets/MandatoryTitleText.dart'; -import '../../../model/inventory/category/ItemCategory.dart'; - class InventorySubCategoryVC extends StatefulWidget { ItemSubCategory subCategory; bool isEdit = false; @@ -38,28 +37,28 @@ class _InventorySubCategoryVCState @override void dispose() { - // TODO: implement dispose viewModel.disposeData(); super.dispose(); } @override void initState() { - viewModel.getStores(); + context + .read() + .fillData(widget.isEdit, widget.subCategory); super.initState(); } @override Widget build(BuildContext context) { viewModel = context.watch(); - viewModel.fillData(widget.isEdit, widget.subCategory); return Directionality( textDirection: TextDirection.ltr, child: Dialog( elevation: 0, backgroundColor: const Color(0xffffffff), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(15.0), + borderRadius: BorderRadius.circular(8.0), ), child: OrientationBuilder(builder: (c, orientation) { isPortrait = MediaQuery.of(c).orientation == Orientation.portrait; @@ -78,25 +77,21 @@ class _InventorySubCategoryVCState DialogHeader( title: AppLocalizations.of(context)!.add_sub_category), Padding( - padding: const EdgeInsets.all(16), + padding: const EdgeInsets.all(12), child: Row( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.min, children: [ Flexible( - flex: 1, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ MandatoryTitleText( hint: AppLocalizations.of(context)!.category), - AppSpaces.horizontalSmall, - getCategoryWidget(context), - const SizedBox( - height: 8, - ), + AppSpaces.verticalSmall, + getCategoryWidget(), + AppSpaces.verticalMedium, getSubCategoryName(), isPortrait ? Column( @@ -106,25 +101,19 @@ class _InventorySubCategoryVCState MainAxisAlignment.start, children: [ getSubCategoryNameNotArabic(), - const SizedBox( - height: 12, - ), + AppSpaces.verticalLarge, CustomOptionalTitle( hint: AppLocalizations.of(context)! .status), - const SizedBox( - height: 12, - ), + AppSpaces.verticalLarge, Row( children: [ CustomOptionalTitle( hint: AppLocalizations.of( context)! .inactive), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, CustomSwitch( value: viewModel .activeInActiveStatus, @@ -133,27 +122,22 @@ class _InventorySubCategoryVCState .setActiveStatus(value); }, ), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, CustomOptionalTitle( hint: AppLocalizations.of( context)! .active) ], ), - const SizedBox( - height: 32, - ), + AppSpaces.verticalLarge, + AppSpaces.verticalLarge, ], ) : Container() ], ), ), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, isPortrait ? Container() : Flexible( @@ -164,25 +148,19 @@ class _InventorySubCategoryVCState mainAxisAlignment: MainAxisAlignment.start, children: [ getSubCategoryNameNotArabic(), - const SizedBox( - height: 12, - ), + AppSpaces.verticalLarge, CustomOptionalTitle( hint: AppLocalizations.of(context)! .status, ), - const SizedBox( - height: 12, - ), + AppSpaces.verticalLarge, Row( children: [ CustomOptionalTitle( hint: AppLocalizations.of(context)! .inactive), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, CustomSwitch( value: viewModel.activeInActiveStatus, @@ -190,9 +168,7 @@ class _InventorySubCategoryVCState viewModel.setActiveStatus(value); }, ), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, CustomOptionalTitle( hint: AppLocalizations.of(context)! @@ -208,7 +184,7 @@ class _InventorySubCategoryVCState SizedBox( width: 120, child: Padding( - padding: const EdgeInsets.only(right: 16), + padding: const EdgeInsets.only(right: 12), child: CustomSimpleButton( textColor: MyColors.white, isLoading: viewModel.isLoading, @@ -234,9 +210,7 @@ class _InventorySubCategoryVCState children: [ CustomOptionalTitle( hint: AppLocalizations.of(context)!.sub_category_name_ar), - const SizedBox( - height: 4, - ), + AppSpaces.verticalSmall, CustomTextFieldForm( onChanged: (value) { viewModel.arabicController = value; @@ -272,38 +246,27 @@ class _InventorySubCategoryVCState ); } - Widget getCategoryWidget(BuildContext context) { - return FutureBuilder( - future: viewModel.getCategoriesData(), - builder: (c, s) { - if (s.hasData) { - var itemsList = s.data!; - return Material( - color: MyColors.backFillColor, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: 48, - width: double.infinity, - child: DropdownSearch( - selectedItem: viewModel.selectedCategory, - popupProps: const PopupProps.menu(), - clearButtonProps: ThemeDropDown.clearButton, - items: itemsList, - itemAsString: (ItemCategory u) => u.name, - onChanged: (ItemCategory? data) { - viewModel.setCategory(data); - }, - dropdownDecoratorProps: MyColors.dropDownStyle(), - ), - ), - ), - ); - } else { - return AppLoader(); - } - }); + Widget getCategoryWidget() { + return DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + selectedItem: viewModel.selectedCategory, + items: viewModel.itemsList, + itemAsString: (ItemCategory u) => u.name, + onChanged: (category) { + viewModel.setCategory(category); + }, + dropdownDecoratorProps: MyColors.dropDownStyle( + hint: 'Choose', + ), + ); } Future addUpdateSubCategory() async { diff --git a/lib/application/views/inventorymodule/subCategoryViews/SubCategoryVC.dart b/lib/application/views/inventorymodule/subCategoryViews/SubCategoryVC.dart index 09012eb..b108980 100644 --- a/lib/application/views/inventorymodule/subCategoryViews/SubCategoryVC.dart +++ b/lib/application/views/inventorymodule/subCategoryViews/SubCategoryVC.dart @@ -2,6 +2,7 @@ import 'package:dropdown_search/dropdown_search.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:provider/provider.dart'; +import 'package:sizer/sizer.dart'; import 'package:wosull/application/enum/DataState.dart'; import 'package:wosull/application/model/inventory/ItemSubCategoryResponse.dart'; import 'package:wosull/application/model/inventory/category/ItemCategory.dart'; @@ -15,9 +16,14 @@ import 'package:wosull/application/views/inventorymodule/subCategoryViews/viewMo import 'package:wosull/application/views/inventorymodule/subCategoryViews/widgets/SubCategoryListView.dart'; import 'package:wosull/application/views/popups/DeleteRecordPopUp.dart'; import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeDropDown.dart'; import 'package:wosull/helpers/ThemeText.dart'; import 'package:wosull/helpers/Utils.dart'; import 'package:wosull/widgets/CustomSimpleButton.dart'; +import 'package:wosull/widgets/PageLimitDropDown.dart'; +import 'package:wosull/widgets/SearchBox.dart'; + +import '../../../../widgets/DropdownItemBuilder.dart'; class SubCategoryVC extends StatefulWidget { const SubCategoryVC({super.key}); @@ -34,100 +40,141 @@ class _SubCategoryVCState extends State { @override Widget build(BuildContext context) { _controller = ScrollController()..addListener(_scrollNotification); - return WillPopScope( - child: Scaffold( - backgroundColor: MyColors.fillColor, - resizeToAvoidBottomInset: true, - body: OrientationBuilder(builder: (c, orientation) { - isPortrait = - MediaQuery.of(context).orientation == Orientation.portrait; - return SingleChildScrollView( - controller: _controller, - child: Container( - padding: const EdgeInsets.all(12), - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - isPortrait - ? Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - const Text( - 'Sub Categories', - style: ThemeText.textStylePageHeading, - ), - const SizedBox( - width: 4, - ), - SizedBox( - width: 150, - child: getCategoriesDropdown()), - ], - ), - AppSpaces.verticalSmall, - SizedBox( - width: 140, - child: addSubCategoryButton(), - ), - ], - ) - : Row( + return Scaffold( + backgroundColor: MyColors.fillColor, + resizeToAvoidBottomInset: true, + body: OrientationBuilder(builder: (c, orientation) { + isPortrait = + MediaQuery.of(context).orientation == Orientation.portrait; + return SingleChildScrollView( + controller: _controller, + child: Container( + padding: const EdgeInsets.all(12), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + isPortrait + ? Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( mainAxisAlignment: MainAxisAlignment.start, children: [ - const Text( + Text( 'Sub Categories', style: ThemeText.textStylePageHeading, ), AppSpaces.horizontalSmall, - SizedBox( - width: 150, child: getCategoriesDropdown()), + Flexible( + child: SizedBox( + height: 38, + child: getCategory(), + )), + ], + ), + AppSpaces.verticalSmall, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible(child: addSubCategoryButton()), AppSpaces.horizontalSmall, - SizedBox( - width: 140, - child: addSubCategoryButton(), - ), + PageLimitDropdown(onChange: (value) { + viewModel.fetchCategories( + isRefresh: true, + limit: int.parse(value!)); + }) ], ), - AppSpaces.verticalMedium, - ChangeNotifierProvider( - create: (context) => viewModel, - child: Consumer( - builder: (BuildContext context, - SubCategoryViewModel controller, Widget? _) { - switch (controller.dataState) { - case DataState.uninitialized: - Future(() { - controller.fetchCategories(); - }); - return showList(controller.filteredList); - case DataState.initialFetching: - return AppLoader(); - case DataState.moreFetching: - case DataState.refreshing: - return showList(controller.filteredList); - case DataState.error: - return AppError(); - case DataState.searching: - case DataState.fetched: - case DataState.noMoreData: - return showList(controller.filteredList); - } - }, + AppSpaces.verticalSmall, + SizedBox( + height: 48, + child: SearchBox( + onEditingDone: (text) { + filterSearchResults(text); + }, + onChanged: (text) { + filterSearchResults(text); + }, + hint: AppLocalizations.of(context)!.search, + ), + ), + ], + ) + : Row( + children: [ + Text( + 'Sub Categories', + style: ThemeText.textStylePageHeading, + ), + AppSpaces.horizontalSmall, + SizedBox( + height: 38, width: 150, child: getCategory()), + AppSpaces.horizontalSmall, + SizedBox( + width: 140, + child: addSubCategoryButton(), + ), + SizedBox( + width: SizerUtil.deviceType == DeviceType.mobile + ? 200 + : 200, + height: 48, + child: SearchBox( + onEditingDone: (text) { + filterSearchResults(text); + }, + onChanged: (text) { + filterSearchResults(text); + }, + hint: AppLocalizations.of(context)!.search, + ), + ), + Flexible( + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + PageLimitDropdown(onChange: (value) { + viewModel.fetchCategories( + isRefresh: true, + limit: int.parse(value!)); + }) + ], + )) + ], ), - ) - ], - ), - ), - ); - })), - onWillPop: () { - viewModel.dispose(); - return Future.value(false); - }); + AppSpaces.verticalMedium, + ChangeNotifierProvider( + create: (context) => viewModel, + child: Consumer( + builder: (BuildContext context, + SubCategoryViewModel controller, Widget? _) { + switch (controller.dataState) { + case DataState.uninitialized: + Future(() { + controller.initData(); + }); + return showList(controller.filteredList); + case DataState.initialFetching: + return AppLoader(); + case DataState.moreFetching: + case DataState.refreshing: + return showList(controller.filteredList); + case DataState.error: + return AppError(); + case DataState.searching: + case DataState.fetched: + case DataState.noMoreData: + return showList(controller.filteredList); + } + }, + ), + ) + ], + ), + ), + ); + })); } Widget showList(List data) { @@ -135,6 +182,7 @@ class _SubCategoryVCState extends State { children: [ SubCategoryListView( data: data, + isPortrait: isPortrait, onUpdate: (item, value) { update(item.id, value); }, @@ -163,54 +211,46 @@ class _SubCategoryVCState extends State { ); } - Widget getCategoriesDropdown() { - return FutureBuilder( - future: viewModel.getCategory(), - builder: (context, snapshot) { - if (snapshot.hasData) { - var itemsData = snapshot.data ?? []; - return Material( - color: MyColors.fillColor2, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: 42, - width: double.infinity, - child: DropdownSearch( - selectedItem: viewModel.selectedCategoryDropDown, - popupProps: const PopupProps.menu(), - clearButtonProps: const ClearButtonProps( - alignment: Alignment.centerRight, - padding: EdgeInsets.zero, - icon: Icon(Icons.clear, size: 12), - color: MyColors.black, - isVisible: true, - ), - items: itemsData, - itemAsString: (ItemCategory u) => u.name, - onChanged: (ItemCategory? data) { - viewModel.fetchCategories(isRefresh: true, category: data); - }, - dropdownDecoratorProps: MyColors.dropDownStyle(), - ), - ), - ), - ); - } else { - return AppLoader(); - } + Widget getCategory() { + return DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: viewModel.itemsList, + itemAsString: (ItemCategory u) => u.name, + onChanged: (category) { + viewModel.fetchCategories(isRefresh: true, category: category); }, + dropdownDecoratorProps: + MyColors.dropDownStyle(hint: 'Choose', fillColor: MyColors.white), ); } bool _scrollNotification() { if (!viewModel.isLoading && _controller.position.extentAfter < 300) { - viewModel.fetchCategories(); + viewModel.fetchCategories(limit: viewModel.limit); } return true; } + Future filterSearchResults(String query) async { + if (query.isNotEmpty) { + viewModel.search(searchValue: query); + } else { + //doing duration so if there is any call of api in stack + //will not effect on empty + Future.delayed(const Duration(milliseconds: 700), () { + viewModel.search(searchValue: ""); + }); + } + } + Future showCategory(itemCategory) async { Utils.progressDialogue(context); await viewModel.viewCategory(itemCategory.id); diff --git a/lib/application/views/inventorymodule/subCategoryViews/ViewSubCategoryVC.dart b/lib/application/views/inventorymodule/subCategoryViews/ViewSubCategoryVC.dart index 7c97832..3861b58 100644 --- a/lib/application/views/inventorymodule/subCategoryViews/ViewSubCategoryVC.dart +++ b/lib/application/views/inventorymodule/subCategoryViews/ViewSubCategoryVC.dart @@ -6,6 +6,7 @@ import 'package:wosull/application/theme/MySeparator.dart'; import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/ThemeText.dart'; import 'package:wosull/helpers/Utils.dart'; +import 'package:wosull/widgets/DialogHeader.dart'; class ViewSubCategoryVC extends StatelessWidget { bool isPortrait = true; @@ -20,7 +21,7 @@ class ViewSubCategoryVC extends StatelessWidget { elevation: 0, backgroundColor: const Color(0xffffffff), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(15.0), + borderRadius: BorderRadius.circular(8.0), ), child: OrientationBuilder(builder: (c, orientation) { isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; @@ -36,37 +37,12 @@ class ViewSubCategoryVC extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end, children: [ - Row( - mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.max, - children: [ - Expanded( - child: Padding( - padding: const EdgeInsets.only(left: 16), - child: Text( - item.name, - style: ThemeText.textStylePopUpHeading, - ), - )), - Align( - alignment: Alignment.topRight, - child: IconButton( - onPressed: () { - Navigator.of(context).pop(); - }, - icon: const Icon(Icons.close)), - ), - ], - ), - Container( - height: 2, - color: MyColors.fillColorGray, - ), + DialogHeader(title: item.name), Container( - margin: const EdgeInsets.all(16), + margin: const EdgeInsets.all(12), child: isPortrait ? Container( - padding: const EdgeInsets.all(16), + padding: const EdgeInsets.all(12), decoration: const BoxDecoration( color: MyColors.fillColor2, borderRadius: @@ -75,23 +51,17 @@ class ViewSubCategoryVC extends StatelessWidget { child: Column( children: [ getCreated(context), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, getUpdatedOn(context), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, appliedOn(context), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, Row( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ Text( - lang(context).category_applicable_stores, + 'Sub-Category Applicable Stores', style: ThemeText.labelStyleTextField, ), AppSpaces.horizontalMedium, @@ -100,9 +70,7 @@ class ViewSubCategoryVC extends StatelessWidget { ), ], ), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, applicableStoreList() ], ), @@ -121,17 +89,15 @@ class ViewSubCategoryVC extends StatelessWidget { ), child: Column( children: [ + appliedOn(context), + AppSpaces.verticalMedium, getCreated(context), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, getUpdatedOn(context) ], ), )), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, Expanded( child: Container( padding: const EdgeInsets.all(16), @@ -144,31 +110,22 @@ class ViewSubCategoryVC extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ - appliedOn(context), - const SizedBox( - height: 8, - ), Row( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ Text( - lang(context) - .category_applicable_stores, + 'Sub-Category Applicable Stores', style: ThemeText.labelStyleTextField, ), - const SizedBox( - width: 8, - ), - const Expanded( + AppSpaces.horizontalMedium, + Expanded( child: MySeparator(color: Colors.grey), ), ], ), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, applicableStoreList() ], ), @@ -191,15 +148,11 @@ class ViewSubCategoryVC extends StatelessWidget { lang(context).created_on, style: ThemeText.labelStyleTextField, ), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, const Expanded( child: MySeparator(color: Colors.grey), ), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, Text( DataTimeFormat.getFormatDate(item.createdAt), style: ThemeText.textStyleViewValue, @@ -215,15 +168,11 @@ class ViewSubCategoryVC extends StatelessWidget { lang(context).updated_on, style: ThemeText.labelStyleTextField, ), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, const Expanded( child: MySeparator(color: Colors.grey), ), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, Text( DataTimeFormat.getFormatDate(item.updatedAt), style: ThemeText.textStyleViewValue, @@ -238,18 +187,14 @@ class ViewSubCategoryVC extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.center, children: [ Text( - lang(context).category_applied_on, + 'Sub-Category Applied On', style: ThemeText.labelStyleTextField, ), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalSmall, const Expanded( child: MySeparator(color: Colors.grey), ), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalSmall, Text( item.storeIds.length > 1 ? "All Stores" : "Specific Stores", style: ThemeText.textStyleViewValue, diff --git a/lib/application/views/inventorymodule/subCategoryViews/repo/SubCategoryRepository.dart b/lib/application/views/inventorymodule/subCategoryViews/repo/SubCategoryRepository.dart new file mode 100644 index 0000000..710b014 --- /dev/null +++ b/lib/application/views/inventorymodule/subCategoryViews/repo/SubCategoryRepository.dart @@ -0,0 +1,60 @@ +import 'package:wosull/application/model/SimpleResponsModel.dart'; +import 'package:wosull/application/model/inventory/ItemSubCategoryResponse.dart'; +import 'package:wosull/application/model/inventory/subCategory/SearchSubCategoryResponse.dart'; +import 'package:wosull/application/model/inventory/subCategory/ViewSubCateogryResponse.dart'; +import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/utils/Constants.dart'; + +class SubCategoryRepository { + Future addCategory(Map data) async { + return await APIManager().fetchData(Constants.ADD_SUB_CATEGORY, data); + } + + Future viewCategory(String id) async { + final value = await APIManager() + .getResponseAuth('${Constants.GET_SUB_CATEGORY_BY_ID}$id'); + return SubCategoryResponse.fromJson(value); + } + + Future deleteCategory(String id) async { + Map data = {'categoryId': id}; + return await APIManager() + .getResponsePatch(Constants.DELETE_SUB_CATEGORY, data); + } + + Future updateCategory(String id, bool value) async { + Map data = { + 'categoryId': id, + 'is_visible_in_store': value + }; + return await APIManager() + .getResponsePatch(Constants.UPDATE_SUB_CATEGORY, data); + } + + Future> search(Map data) async { + var subCategories = []; + await APIManager() + .fetchData(Constants.SEARCH_SUB_CATEGORY, data) + .then((result) { + final value = SearchSubCategoryResponse.fromJson(result); + if (value.success) { + subCategories.addAll(value.categories); + } + }).onError((error, stackTrace) {}); + return subCategories; + } + + Future> fetchCategories( + Map data) async { + var subCategories = []; + await APIManager() + .fetchData(Constants.GET_SUBCATEGORIES_URL, data) + .then((result) { + final value = ItemSubCategoriesResponse.fromJson(result); + if (value.success) { + subCategories.addAll(value.categories); + } + }).onError((error, stackTrace) {}); + return subCategories; + } +} diff --git a/lib/application/views/inventorymodule/subCategoryViews/viewModels/AddSubCategoryViewModel.dart b/lib/application/views/inventorymodule/subCategoryViews/viewModels/AddSubCategoryViewModel.dart index 3ef83b4..0ef0626 100644 --- a/lib/application/views/inventorymodule/subCategoryViews/viewModels/AddSubCategoryViewModel.dart +++ b/lib/application/views/inventorymodule/subCategoryViews/viewModels/AddSubCategoryViewModel.dart @@ -1,15 +1,11 @@ -import 'dart:convert'; - import 'package:flutter/material.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; -import 'package:wosull/application/model/SimpleResponsModel.dart'; import 'package:wosull/application/model/inventory/ItemSubCategoryResponse.dart'; import 'package:wosull/application/model/inventory/category/ItemCategory.dart'; -import 'package:wosull/application/model/inventory/category/ItemCategoryResponse.dart'; -import 'package:wosull/application/model/store/GetSpecificStores.dart'; -import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/repository/WosulRepository.dart'; import 'package:wosull/application/utils/CRUDOperatoinState.dart'; import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/inventorymodule/subCategoryViews/repo/SubCategoryRepository.dart'; import 'package:wosull/helpers/Utils.dart'; class AddSubCategoryViewModel with ChangeNotifier { @@ -21,9 +17,11 @@ class AddSubCategoryViewModel with ChangeNotifier { String categoryId = ''; String subCategoryId = ''; - + List itemsList = []; List storeIds = []; + final repository = SubCategoryRepository(); + var nameController = ''; var arabicController = ''; @@ -47,6 +45,21 @@ class AddSubCategoryViewModel with ChangeNotifier { activeInActiveStatus = true; } + Future fillData(bool isEdit, ItemSubCategory subCategory) async { + this.isEdit = isEdit; + if (isEdit && subCategoryId.isEmpty) { + subCategoryId = subCategory.id; + activeInActiveStatus = subCategory.isVisibleInStore; + categoryId = subCategory.categoryId; + nameController = subCategory.name; + arabicController = subCategory.arabicName; + } + final response = await WosulRepository().getCategoriesData(); + itemsList.addAll(response); + await getSelectedCategory(); + getStores(); + } + setSpecificStore(String id) { storeIds.add(id); notifyListeners(); @@ -83,17 +96,6 @@ class AddSubCategoryViewModel with ChangeNotifier { } } - void fillData(bool isEdit, ItemSubCategory subCategory) { - this.isEdit = isEdit; - if (isEdit && subCategoryId.isEmpty) { - subCategoryId = subCategory.id; - activeInActiveStatus = subCategory.isVisibleInStore; - categoryId = subCategory.categoryId; - nameController = subCategory.name; - arabicController = subCategory.arabicName; - } - } - Future addCategory() async { setLoading(true); if (storeIds.isEmpty) { @@ -110,69 +112,52 @@ class AddSubCategoryViewModel with ChangeNotifier { 'is_visible_in_store': activeInActiveStatus, }; - print(jsonEncode(data)); - await APIManager() - .fetchData(Constants.ADD_SUB_CATEGORY, data) - .then((value) { - final response = SimpleResponseModel.fromJson(value); + await repository.addCategory(data).then((response) { if (response.success) { _crudOperationState = CRUDOperationState.add; } setLoading(false); - }).onError((error, stackTrace) { - print(stackTrace.toString()); - }); + }).onError((error, stackTrace) {}); } - Future> getCategoriesData() async { - var items = []; - Map data = { - 'store_id': sharedPrefs.storeId, - }; - - await APIManager() - .fetchData(Constants.GET_STORE_CATEGORY, data) - .then((value) { - final response = ItemCategoryResponse.fromJson(value); - if (response.success) { - items.addAll(response.categories); - if (items.isNotEmpty) { - if (isEdit) { - if (selectedCategory == null) { - Future.forEach(items, (element) { - if (element.id == categoryId) { - selectedCategory = element; - return; - } - }); + Future getSelectedCategory() async { + if (itemsList.isNotEmpty) { + if (isEdit) { + if (selectedCategory == null) { + Future.forEach(itemsList, (element) { + if (element.id == categoryId) { + selectedCategory = element; + return; } - - categoryId = selectedCategory.id; - } else { - selectedCategory ??= items.first; - } - if (categoryId.isEmpty) { - categoryId = selectedCategory.id; - } + }); } + + categoryId = selectedCategory.id; + } else { + selectedCategory ??= itemsList.first; } - }).onError((error, stackTrace) {}); - return items; + if (categoryId.isEmpty) { + categoryId = selectedCategory.id; + } + } } Future getStores() async { - final value = await APIManager() - .fetchData(Constants.GET_SPECIFIC_STORES, Constants.getStorePayload()); - - final response = GetSpecificStores.fromJson(value); - if (response.success) { - storeIds.clear(); - for (var store in response.stores) { - storeIds.add(store.id); + await WosulRepository() + .getSpecificStoresById(Constants.getStorePayload()) + .then((response) { + if (response.success) { + storeIds.clear(); + for (var store in response.stores) { + storeIds.add(store.id); + } } - } - if (storeIds.isEmpty) { - storeIds.add(sharedPrefs.storeId); - } + if (storeIds.isEmpty) { + storeIds.add(sharedPrefs.storeId); + } + notifyListeners(); + }).onError((error, stackTrace) { + notifyListeners(); + }); } } diff --git a/lib/application/views/inventorymodule/subCategoryViews/viewModels/SubCategoryViewModel.dart b/lib/application/views/inventorymodule/subCategoryViews/viewModels/SubCategoryViewModel.dart index d48dba6..120cb33 100644 --- a/lib/application/views/inventorymodule/subCategoryViews/viewModels/SubCategoryViewModel.dart +++ b/lib/application/views/inventorymodule/subCategoryViews/viewModels/SubCategoryViewModel.dart @@ -1,28 +1,23 @@ -import 'dart:convert'; - -import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; import 'package:wosull/application/enum/DataState.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; import 'package:wosull/application/model/inventory/ItemSubCategoryResponse.dart'; import 'package:wosull/application/model/inventory/category/ItemCategory.dart'; -import 'package:wosull/application/model/inventory/category/ItemCategoryResponse.dart'; import 'package:wosull/application/model/inventory/category/ViewItemCategory.dart'; -import 'package:wosull/application/model/inventory/subCategory/ViewSubCateogryResponse.dart'; -import 'package:wosull/application/model/store/GetSpecificStores.dart'; -import 'package:wosull/application/model/store/WosulStore.dart'; -import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/repository/WosulRepository.dart'; import 'package:wosull/application/utils/CRUDOperatoinState.dart'; -import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/inventorymodule/subCategoryViews/repo/SubCategoryRepository.dart'; class SubCategoryViewModel with ChangeNotifier { int _currentPageNumber = 1; bool _isFirstLoadRunning = true; + int limit = 10; bool get isFirstLoadRunning => _isFirstLoadRunning; String productId = ""; - late ItemCategory selectedCategoryDropDown; + List itemsList = []; //using this state to handle for get data and pagination DataState _dataState = DataState.uninitialized; @@ -43,41 +38,22 @@ class SubCategoryViewModel with ChangeNotifier { final List _dataList = []; final List _filteredList = []; - List _storeList = []; - - List get storeList => _storeList; - List get dataList => _dataList; List get filteredList => _filteredList; late ViewItemCategory category; - Future> getCategory() async { - List categories = []; - await APIManager() - .fetchData(Constants.GET_STORE_CATEGORY, Constants.getStorePayload()) - .then((value) { - final itemCategoryResponse = ItemCategoryResponse.fromJson(value); - if (itemCategoryResponse.success && - itemCategoryResponse.categories.isNotEmpty) { - categories.addAll(itemCategoryResponse.categories); - } - selectedCategoryDropDown = ItemCategory( - name: "Choose", - id: '', - isVisibleInStore: false, - createdAt: '', - updatedAt: '', - description: '', - arabicName: '', - store_id: [], - image_url: '', - ); - }).onError((error, stackTrace) {}); - return categories; + final repository = SubCategoryRepository(); + + Future initData() async { + final response = await WosulRepository().getCategoriesData(); + itemsList.addAll(response); + fetchCategories(); } - fetchCategories({bool isRefresh = false, ItemCategory? category}) async { + fetchCategories( + {bool isRefresh = false, ItemCategory? category, int limit = 10}) async { + this.limit = limit; _isLoading = true; if (!isRefresh) { _dataState = (_dataState == DataState.uninitialized) @@ -95,32 +71,29 @@ class SubCategoryViewModel with ChangeNotifier { data = { 'store_id': sharedPrefs.storeId, 'page': _currentPageNumber, + 'limit': this.limit }; } else { data = { 'category_id': category.id, 'store_id': sharedPrefs.storeId, 'page': _currentPageNumber, + 'limit': this.limit }; } - print(jsonEncode(data)); try { if (_didLastLoad) { _dataState = DataState.noMoreData; } else { - await APIManager() - .fetchData(Constants.GET_SUBCATEGORIES_URL, data) - .then((result) { - print(jsonEncode(result)); - final value = ItemSubCategoriesResponse.fromJson(result); + await repository.fetchCategories(data).then((categories) { if (_dataState == DataState.refreshing) { _filteredList.clear(); _dataList.clear(); } - if (value.success) { - _filteredList.addAll(value.categories); - _dataList.addAll(value.categories); - if (value.categories.length < 10) { + if (categories.isNotEmpty) { + _filteredList.addAll(categories); + _dataList.addAll(categories); + if (categories.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; @@ -129,55 +102,53 @@ class SubCategoryViewModel with ChangeNotifier { _dataState = DataState.fetched; _currentPageNumber += 1; _isLoading = false; - print(_filteredList.length); notifyListeners(); }).onError((error, stackTrace) { - print(error.toString()); _dataState = DataState.error; _isLoading = false; notifyListeners(); }); } } catch (e) { - print(e.toString()); _isLoading = false; _dataState = DataState.error; notifyListeners(); } } - Future getSpecificStores(bool isEdit) async { - Map data = { - 'is_included': false, - 'store_id': sharedPrefs.storeId, - }; - await APIManager() - .fetchData(Constants.GET_SPECIFIC_STORES, data) - .then((response) { - final value = GetSpecificStores.fromJson(response); - if (value.stores.isEmpty) { - _storeList.add( - WosulStore(id: sharedPrefs.storeId, name: sharedPrefs.store_name)); - } else { - _storeList.addAll(value.stores); - } - - if (isEdit) { - _crudOperationState = CRUDOperationState.edit; - } else { - _crudOperationState = CRUDOperationState.add; + search({String searchValue = ""}) async { + if (searchValue.isEmpty) { + _dataState = DataState.fetched; + _filteredList.clear(); + _filteredList.addAll(_dataList); + notifyListeners(); + } else { + Map data = { + 'store_id': sharedPrefs.storeId, + 'searchTerm': searchValue + }; + _dataState = DataState.searching; + notifyListeners(); + try { + await repository.search(data).then((categories) { + _filteredList.clear(); + if (categories.isNotEmpty) { + _filteredList.addAll(categories); + } + _dataState = DataState.fetched; + }).onError((error, stackTrace) { + _dataState = DataState.error; + }); + notifyListeners(); + } catch (e) { + _dataState = DataState.error; + notifyListeners(); } - }).onError((error, stackTrace) { - _crudOperationState = CRUDOperationState.error; - }); + } } Future viewCategory(String id) async { - await APIManager() - .getResponseAuth('${Constants.GET_SUB_CATEGORY_BY_ID}$id') - .then((response) { - print(response); - final value = SubCategoryResponse.fromJson(response); + await repository.viewCategory(id).then((value) { if (value.success) { category = value.subCategory; _crudOperationState = CRUDOperationState.view; @@ -185,15 +156,12 @@ class SubCategoryViewModel with ChangeNotifier { _crudOperationState = CRUDOperationState.error; } }).onError((error, stackTrace) { - _crudOperationState == CRUDOperationState.error; + _crudOperationState = CRUDOperationState.error; }); } Future deleteCategory(String id) async { - Map data = {'categoryId': id}; - await APIManager() - .getResponsePatch(Constants.DELETE_SUB_CATEGORY, data) - .then((result) { + await repository.deleteCategory(id).then((result) { if (result.success) { _filteredList.removeWhere((element) => element.id == id); _dataList.removeWhere((element) => element.id == id); @@ -209,25 +177,19 @@ class SubCategoryViewModel with ChangeNotifier { } Future updateCategory(String id, bool value) async { - Map data = { - 'categoryId': id, - 'is_visible_in_store': value - }; - await APIManager() - .getResponsePatch(Constants.UPDATE_SUB_CATEGORY, data) - .then((result) { + await repository.updateCategory(id, value).then((result) { if (result.success) { + _crudOperationState = CRUDOperationState.update; int index = _filteredList.indexWhere((element) => element.id == id); _filteredList[index].isVisibleInStore = value; int dataIndex = _dataList.indexWhere((element) => element.id == id); _dataList[dataIndex].isVisibleInStore = value; - _crudOperationState == CRUDOperationState.update; } else { - _crudOperationState == CRUDOperationState.error; + _crudOperationState = CRUDOperationState.error; } - notifyListeners(); }).onError((error, stackTrace) { + _crudOperationState == CRUDOperationState.error; notifyListeners(); }); } diff --git a/lib/application/views/inventorymodule/subCategoryViews/widgets/SubCategoryListView.dart b/lib/application/views/inventorymodule/subCategoryViews/widgets/SubCategoryListView.dart index df91a26..8ee8c65 100644 --- a/lib/application/views/inventorymodule/subCategoryViews/widgets/SubCategoryListView.dart +++ b/lib/application/views/inventorymodule/subCategoryViews/widgets/SubCategoryListView.dart @@ -2,15 +2,19 @@ import 'package:flutter/material.dart'; import 'package:wosull/application/model/converters/DataTimeFormat.dart'; import 'package:wosull/application/model/inventory/ItemSubCategoryResponse.dart'; import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/Utils.dart'; +import 'package:wosull/widgets/ActionPopUpContainer.dart'; +import 'package:wosull/widgets/CustomPopuoMenuButton.dart'; import 'package:wosull/widgets/CustomSwitch.dart'; import 'package:wosull/widgets/EmptyDataWidget.dart'; import 'package:wosull/widgets/HeadingText.dart'; +import 'package:wosull/widgets/ListHeadingContainer.dart'; import 'package:wosull/widgets/ValueText.dart'; class SubCategoryListView extends StatelessWidget { List data; - + bool isPortrait; final void Function(ItemSubCategory itemCategory, bool status) onUpdate; final void Function(ItemSubCategory itemCategory) onDelete; final void Function(ItemSubCategory itemCategory) onView; @@ -18,6 +22,7 @@ class SubCategoryListView extends StatelessWidget { SubCategoryListView( {super.key, + required this.isPortrait, required this.data, required this.onUpdate, required this.onDelete, @@ -34,128 +39,184 @@ class SubCategoryListView extends StatelessWidget { ? const EmptyDataWidget() : Column( children: [ - Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 50, - color: MyColors.containerBackColor, - child: Row( - children: [ - Expanded(child: HeadingText(lang(context).name)), - Expanded( - child: Align( - alignment: Alignment.center, - child: HeadingText( - lang(context).status, - ), - )), - Expanded( - child: HeadingText( - lang(context).created_on, - )), - Expanded( - child: HeadingText( - lang(context).updated_on, - )), - Expanded( - child: Padding( - padding: const EdgeInsets.only(right: 16), - child: Align( - alignment: Alignment.centerRight, - child: HeadingText( - lang(context).action, - ), - ), - )), - ], - ), - ), - ListView.builder( - physics: const NeverScrollableScrollPhysics(), - padding: EdgeInsets.zero, - scrollDirection: Axis.vertical, - shrinkWrap: true, - itemBuilder: (c, position) { - return Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - child: Container( - padding: - const EdgeInsets.only(left: 8, right: 8), - height: 56, - color: MyColors.containerBackColor, + isPortrait + ? Container() + : ListHeadingContainer( child: Row( children: [ Expanded( - child: ValueText( - data[position].name, - )), + child: HeadingText(lang(context).name)), Expanded( child: Align( alignment: Alignment.centerLeft, - child: CustomSwitch( - value: - data[position].isVisibleInStore, - onToggle: (value) { - onUpdate(data[position], value); - }), + child: HeadingText( + lang(context).status, + ), )), Expanded( - child: ValueText( - DataTimeFormat.getFormatDate( - data[position].createdAt), + child: HeadingText( + lang(context).created_on, )), Expanded( - child: ValueText( - DataTimeFormat.getFormatDate( - data[position].updatedAt), + child: HeadingText( + lang(context).updated_on, )), Expanded( child: Padding( - padding: const EdgeInsets.all(4), + padding: const EdgeInsets.only(right: 16), child: Align( alignment: Alignment.centerRight, - child: Container( - width: 42, - height: 42, - decoration: BoxDecoration( - borderRadius: - const BorderRadius.all( - Radius.circular(4)), - color: MyColors.backFillColor), - child: PopupMenuButton( - padding: EdgeInsets.zero, - icon: const Icon(Icons.more_vert), - itemBuilder: (c) { - return [ - PopupMenuItem( - value: 'edit', - child: ValueText( - lang(context).edit), - ), - PopupMenuItem( - value: 'view', - child: ValueText( - lang(context).view), - ), - PopupMenuItem( - value: 'delete', - child: ValueText( - lang(context).delete), - ) - ]; - }, - onSelected: (String value) => - actionPopUpItemSelected(value, - data[position], position), - ), + child: HeadingText( + lang(context).action, ), ), - )) + )), ], ), ), - ); + ListView.builder( + physics: const NeverScrollableScrollPhysics(), + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, + shrinkWrap: true, + itemBuilder: (c, position) { + if (isPortrait) { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + elevation: 2, + color: MyColors.white, + child: Container( + padding: + const EdgeInsets.fromLTRB(8, 0, 0, 8), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + child: Container( + padding: const EdgeInsets.only(top: 16), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.end, + children: [ + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + HeadingText( + lang(context) + .sub_category_name, + ), + AppSpaces.verticalMedium, + HeadingText( + lang(context).created_on), + AppSpaces.verticalMedium, + HeadingText( + lang(context).updated_on), + AppSpaces.verticalMedium, + HeadingText( + lang(context).status), + ], + )), + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.end, + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + ValueText(data[position].name), + AppSpaces.verticalMedium, + ValueText(DataTimeFormat + .getFormatDate( + data[position] + .createdAt)), + AppSpaces.verticalMedium, + ValueText(DataTimeFormat + .getFormatDate( + data[position] + .updatedAt)), + AppSpaces.verticalSmall, + Row( + mainAxisAlignment: + MainAxisAlignment.end, + crossAxisAlignment: + CrossAxisAlignment.end, + children: [ + CustomSwitch( + value: data[position] + .isVisibleInStore, + onToggle: (value) { + onUpdate(data[position], + value); + }, + ) + ], + ), + ], + )), + ], + ), + )), + getPopupMenu(context, position) + ], + ), + ), + ); + } else { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: ListHeadingContainer( + child: Row( + children: [ + Expanded( + child: ValueText( + data[position].name, + )), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: CustomSwitch( + value: + data[position].isVisibleInStore, + onToggle: (value) { + onUpdate(data[position], value); + }), + )), + Expanded( + child: ValueText( + DataTimeFormat.getFormatDate( + data[position].createdAt), + )), + Expanded( + child: ValueText( + DataTimeFormat.getFormatDate( + data[position].updatedAt), + )), + Expanded( + child: Padding( + padding: const EdgeInsets.all(4), + child: Align( + alignment: Alignment.centerRight, + child: ActionPopUpContainer( + child: + getPopupMenu(context, position), + ), + ), + )) + ], + ), + ), + ); + } }, itemCount: data.length, ) @@ -175,4 +236,25 @@ class SubCategoryListView extends StatelessWidget { onView(itemCategory); } } + + getPopupMenu(BuildContext context, int position) { + return CustomPopupMenuButton( + onSelected: (String value) => + actionPopUpItemSelected(value, data[position], position), + items: [ + PopupMenuItem( + value: 'edit', + child: ValueText(lang(context).edit), + ), + PopupMenuItem( + value: 'view', + child: ValueText(lang(context).view), + ), + PopupMenuItem( + value: 'delete', + child: ValueText(lang(context).delete), + ) + ], + ); + } } diff --git a/lib/application/views/inventorymodule/viewmodel/ProductViewModel.dart b/lib/application/views/inventorymodule/viewmodel/ProductViewModel.dart index 2abc403..9702bfe 100644 --- a/lib/application/views/inventorymodule/viewmodel/ProductViewModel.dart +++ b/lib/application/views/inventorymodule/viewmodel/ProductViewModel.dart @@ -2,22 +2,28 @@ import 'package:flutter/cupertino.dart'; import 'package:wosull/application/enum/DataState.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; import 'package:wosull/application/model/inventory/Item.dart'; -import 'package:wosull/application/network/APIManager.dart'; -import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/settings/repo/ReportsRepository.dart'; class ProductViewModel with ChangeNotifier { + final repository = ReportsRepository(); + + bool _isLoading = false; + bool get isLoading => _isLoading; + int _currentPageNumber = 1; DataState _dataState = DataState.uninitialized; bool _didLastLoad = false; - + int limit = 10; DataState get dataState => _dataState; - List _dataList = []; + List _dataList = []; List get dataList => _dataList; - fetchReportsProducts({bool isRefresh = false}) async { + fetchReportsProducts({bool isRefresh = false, int limit = 10}) async { + this.limit = limit; + _isLoading = true; if (!isRefresh) { _dataState = (_dataState == DataState.uninitialized) ? DataState.initialFetching @@ -27,39 +33,39 @@ class ProductViewModel with ChangeNotifier { _dataState = DataState.refreshing; } notifyListeners(); - Map data = { + Map map = { 'store_id': sharedPrefs.storeId, 'page': _currentPageNumber, 'is_export': false, - 'limit': 10 + 'limit': this.limit }; try { if (_didLastLoad) { _dataState = DataState.noMoreData; } else { - await APIManager() - .getResponseAuth(Constants.GET_ITEMS_WITH_CATEGORY, data) - .then((result) { - final value = ReportProductModel.fromJson(result); + await repository.fetchReportsProduct(map).then((result) { if (_dataState == DataState.refreshing) { _dataList.clear(); } - if (value.success!) { - _dataList.addAll(value.storeItems!); - if (value.storeItems!.length < 10) { + if (result.isNotEmpty) { + _dataList.addAll(result); + if (result.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; } } + _isLoading = false; _dataState = DataState.fetched; _currentPageNumber += 1; }).onError((error, stackTrace) { _dataState = DataState.error; + _isLoading = false; }); } notifyListeners(); } catch (e) { + _isLoading = false; _dataState = DataState.error; notifyListeners(); } diff --git a/lib/application/views/kitchenmodule/views/KitchenMainTableVC.dart b/lib/application/views/kitchenmodule/views/KitchenMainTableVC.dart index b1b8011..9a74c0d 100644 --- a/lib/application/views/kitchenmodule/views/KitchenMainTableVC.dart +++ b/lib/application/views/kitchenmodule/views/KitchenMainTableVC.dart @@ -1,14 +1,15 @@ import 'package:flutter/material.dart'; import 'package:wosull/application/interfaces/DrawerWidgetSelect.dart'; import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/theme/MyFonts.dart'; import 'package:wosull/application/views/kitchenmodule/views/kitchen/KitchenViewVC.dart'; import 'package:wosull/application/views/kitchenmodule/views/table/KitchenTableVC.dart'; -import 'package:wosull/application/theme/MyFonts.dart'; +import 'package:wosull/helpers/ThemeText.dart'; class KitchenMainTableVC extends StatefulWidget { final DrawerWidgetSelect delegateDrawer; - KitchenMainTableVC({Key? key, required this.delegateDrawer}) + const KitchenMainTableVC({Key? key, required this.delegateDrawer}) : super(key: key); @override @@ -85,17 +86,9 @@ class _KitchenMainTableVCState extends State { ), TabBar( indicatorColor: Colors.white, - labelStyle: TextStyle( - fontSize: MyFonts.normalButton, - fontWeight: FontWeight.w500, - fontFamily: MyFonts.Bold, - color: MyColors.blueThemeColor), + labelStyle: ThemeText.tabLabelStyle, isScrollable: true, - unselectedLabelStyle: const TextStyle( - fontSize: MyFonts.normalButton, - fontWeight: FontWeight.w500, - fontFamily: MyFonts.Medium, - color: MyColors.textColorBlack), + unselectedLabelStyle: ThemeText.unSelectedTabLabelStyle, unselectedLabelColor: MyColors.textColorBlack, labelColor: MyColors.blueThemeColor, tabs: [ diff --git a/lib/application/views/kitchenmodule/views/KitchenMainVC.dart b/lib/application/views/kitchenmodule/views/KitchenMainVC.dart index b294bc4..6cce985 100644 --- a/lib/application/views/kitchenmodule/views/KitchenMainVC.dart +++ b/lib/application/views/kitchenmodule/views/KitchenMainVC.dart @@ -5,6 +5,7 @@ import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/theme/MyFonts.dart'; import 'package:wosull/application/views/kitchenmodule/views/kitchen/KitchenViewVC.dart'; import 'package:wosull/application/views/kitchenmodule/views/table/KitchenTableVC.dart'; +import 'package:wosull/helpers/ThemeText.dart'; class KitchenMainVC extends StatefulWidget { final DrawerWidgetSelect delegateDrawer; @@ -88,17 +89,9 @@ class _KitchenMainVCState extends State { ), TabBar( indicatorColor: Colors.white, - labelStyle: TextStyle( - fontSize: MyFonts.normalButton, - fontWeight: FontWeight.w500, - fontFamily: MyFonts.Bold, - color: MyColors.blueThemeColor), + labelStyle: ThemeText.tabLabelStyle, isScrollable: true, - unselectedLabelStyle: const TextStyle( - fontSize: MyFonts.normalButton, - fontWeight: FontWeight.w500, - fontFamily: MyFonts.Medium, - color: MyColors.textColorBlack), + unselectedLabelStyle: ThemeText.unSelectedTabLabelStyle, unselectedLabelColor: MyColors.textColorBlack, labelColor: MyColors.blueThemeColor, tabs: [ diff --git a/lib/application/views/kitchenmodule/views/kitchen/KitchenViewVC.dart b/lib/application/views/kitchenmodule/views/kitchen/KitchenViewVC.dart index c61496b..a3b70c2 100644 --- a/lib/application/views/kitchenmodule/views/kitchen/KitchenViewVC.dart +++ b/lib/application/views/kitchenmodule/views/kitchen/KitchenViewVC.dart @@ -8,7 +8,7 @@ import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/utils/AppError.dart'; import 'package:wosull/application/utils/AppLoader.dart'; import 'package:wosull/application/utils/Constants.dart'; -import 'package:wosull/application/views/kitchenmodule/viewModel/KitchenViewModel.dart'; +import 'package:wosull/application/views/kitchenmodule/views/kitchen/viewModel/KitchenViewModel.dart'; import 'package:wosull/application/views/kitchenmodule/views/kitchen/widgets/KitchenListView.dart'; import 'package:wosull/application/views/kitchenmodule/views/kitchen/widgets/offline/KitchenOfflineListView.dart'; import 'package:wosull/base/BaseStatefulState.dart'; @@ -43,6 +43,7 @@ class _KitchenViewVCState extends BaseStatefulState { @override Widget build(BuildContext context) { return Scaffold( + backgroundColor: MyColors.fillColor, resizeToAvoidBottomInset: true, body: OrientationBuilder(builder: (c, orientation) { isPortrait = @@ -50,8 +51,8 @@ class _KitchenViewVCState extends BaseStatefulState { return SingleChildScrollView( controller: _controller, child: Container( + width: double.infinity, padding: const EdgeInsets.all(12), - color: MyColors.fillColor, child: ChangeNotifierProvider( create: (context) => viewModel, child: Consumer( @@ -88,20 +89,18 @@ class _KitchenViewVCState extends BaseStatefulState { } Widget showDataOffline() { - print('called'); - return FutureBuilder( - future: objectbox.getOrdersList(Constants.preparing), - builder: (context, snapshot) { + return StreamBuilder( + stream: objectbox.getOrders(Constants.preparing), + builder: (ctx, snapshot) { if (snapshot.hasData) { if (viewModel.dbOrder.isEmpty) { viewModel.dbOrder.addAll(snapshot.data ?? []); } - print('called'); if (viewModel.dbOrder.isNotEmpty) { return KitchenOfflineListView( - onUpdate: (id) { - updateOrderStatus(id); + onUpdate: (order) { + viewModel.updateDB(order); }, viewModel: viewModel, kitchenOrders: viewModel.dbOrder, @@ -110,7 +109,7 @@ class _KitchenViewVCState extends BaseStatefulState { return const EmptyDataWidget(); } } else { - return Container(); + return AppLoader(); } }, ); @@ -118,6 +117,8 @@ class _KitchenViewVCState extends BaseStatefulState { Widget showData(List kitchenOrders) { return Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, children: [ // kitchenOrders.isEmpty // ? const EmptyDataWidget() @@ -687,7 +688,9 @@ class _KitchenViewVCState extends BaseStatefulState { } bool _scrollNotification() { - if (!viewModel.isLoading && _controller.position.extentAfter < 300) { + if (!viewModel.isLoading && + isConnected && + _controller.position.extentAfter < 300) { viewModel.fetch(); } return true; diff --git a/lib/application/views/kitchenmodule/views/kitchen/repo/KitchenRepository.dart b/lib/application/views/kitchenmodule/views/kitchen/repo/KitchenRepository.dart new file mode 100644 index 0000000..7e04170 --- /dev/null +++ b/lib/application/views/kitchenmodule/views/kitchen/repo/KitchenRepository.dart @@ -0,0 +1,29 @@ +import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/application/model/SimpleResponsModel.dart'; +import 'package:wosull/application/model/cart/GetHoldOrderModel.dart'; +import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/utils/Constants.dart'; + +class KitchenRepository { + Future> fetch(Map data) async { + var orders = []; + await APIManager() + .fetchData(Constants.GET_ORDER_BY_STATUS, data) + .then((result) { + final value = GetOrderByStatusModel.fromJson(result); + if (value.success!) { + orders.addAll(value.orderModel ?? []); + } + }).onError((error, stackTrace) {}); + return orders; + } + + Future update(String id) async { + Map data = { + 'store_id': sharedPrefs.storeId, + 'order_id': id, + 'status': Constants.ready, + }; + return await APIManager().fetchData(Constants.UPDATE_ORDER_STATUS, data); + } +} diff --git a/lib/application/views/kitchenmodule/viewModel/KitchenViewModel.dart b/lib/application/views/kitchenmodule/views/kitchen/viewModel/KitchenViewModel.dart similarity index 68% rename from lib/application/views/kitchenmodule/viewModel/KitchenViewModel.dart rename to lib/application/views/kitchenmodule/views/kitchen/viewModel/KitchenViewModel.dart index 2df316f..35298d4 100644 --- a/lib/application/views/kitchenmodule/viewModel/KitchenViewModel.dart +++ b/lib/application/views/kitchenmodule/views/kitchen/viewModel/KitchenViewModel.dart @@ -1,17 +1,17 @@ import 'dart:async'; -import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:wosull/application/enum/DataState.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; import 'package:wosull/application/model/Combo/GetComboModel.dart'; import 'package:wosull/application/model/CreateAndUpdateOrder.dart'; -import 'package:wosull/application/model/Modifiers/GetModifiersModel.dart'; -import 'package:wosull/application/model/SimpleResponsModel.dart'; +import 'package:wosull/application/model/Modifiers/ModifierOption.dart'; import 'package:wosull/application/model/cart/GetHoldOrderModel.dart'; import 'package:wosull/application/model/createOrder/OrderDetails.dart'; -import 'package:wosull/application/network/APIManager.dart'; + import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/kitchenmodule/views/kitchen/repo/KitchenRepository.dart'; +import 'package:wosull/main.dart'; class KitchenViewModel with ChangeNotifier { int _currentPageNumber = 1; @@ -32,17 +32,7 @@ class KitchenViewModel with ChangeNotifier { List dbOrder = []; - // bool autoRefresh = false; - // Timer? timer; - - // void cancelTimer() { - // timer?.cancel(); - // } - // - // void initTimer() { - // timer = Timer.periodic( - // const Duration(minutes: 1), (Timer t) => fetch(isRefresh: true)); - // } + final repository = KitchenRepository(); fetch({bool isRefresh = false}) async { _isLoading = true; @@ -66,18 +56,15 @@ class KitchenViewModel with ChangeNotifier { if (_didLastLoad) { _dataState = DataState.noMoreData; } else { - await APIManager() - .fetchData(Constants.GET_ORDER_BY_STATUS, data) - .then((result) { - final value = GetOrderByStatusModel.fromJson(result); + await repository.fetch(data).then((orders) { if (_dataState == DataState.refreshing) { _filteredList.clear(); _dataList.clear(); } - if (value.success!) { - _filteredList.addAll(value.orderModel!); - _dataList.addAll(value.orderModel!); - if (value.orderModel!.length < 10) { + if (orders.isNotEmpty) { + _filteredList.addAll(orders); + _dataList.addAll(orders); + if (orders.length < 10) { _didLastLoad = true; } else { _didLastLoad = false; @@ -99,19 +86,8 @@ class KitchenViewModel with ChangeNotifier { } Future update(String id) async { - Map data = { - 'store_id': sharedPrefs.storeId, - 'order_id': id, - 'status': Constants.ready, - }; - - print(jsonEncode(data)); - - await APIManager() - .fetchData(Constants.UPDATE_ORDER_STATUS, data) - .then((result) { - final response = SimpleResponseModel.fromJson(result); - if (response.success!) { + await repository.update(id).then((response) { + if (response.success) { _filteredList.removeWhere((element) => element.id! == id); _dataList.removeWhere((element) => element.id! == id); notifyListeners(); @@ -148,7 +124,7 @@ class KitchenViewModel with ChangeNotifier { Future checkAllItemsReady(List list) async { bool status = false; for (var order in list) { - for (var item in order.items!) { + for (var item in order.items) { if (!item.status) { return false; } @@ -176,10 +152,10 @@ class KitchenViewModel with ChangeNotifier { void setItemStatus(int index, int parent, int child, bool? value) { if (value == null) { - _filteredList[index].cart!.orderDetails![parent].items![child].status = + _filteredList[index].cart!.orderDetails![parent].items[child].status = false; } else { - _filteredList[index].cart!.orderDetails![parent].items![child].status = + _filteredList[index].cart!.orderDetails![parent].items[child].status = value; } notifyListeners(); @@ -187,23 +163,17 @@ class KitchenViewModel with ChangeNotifier { Future setItemStatusOffline( int index, int parent, int child, bool? value) async { - print(value); if (value == null) { - // await objectbox.updateOrder( - // dbOrder[index].obid, - // dbOrder[index].orderDetails[parent].productId!, - // dbOrder[index].orderDetails[parent].items[child].id, - // false); dbOrder[index].orderDetails[parent].items[child].status = false; } else { - // await objectbox.updateOrder( - // dbOrder[index].obid, - // dbOrder[index].orderDetails[parent].productId!, - // dbOrder[index].orderDetails[parent].items[child].id, - // true); dbOrder[index].orderDetails[parent].items[child].status = true; } - // print(dbOrder[index].orderDetails[parent].items[child].status); notifyListeners(); } + + Future updateDB(CreateAndUpdateOrder order) async { + dbOrder.removeWhere((element) => element.obid == order.obid); + order.orderStatus = Constants.ready; + await objectbox.updateOrder(order); + } } diff --git a/lib/application/views/kitchenmodule/views/kitchen/widgets/ItemsListView.dart b/lib/application/views/kitchenmodule/views/kitchen/widgets/ItemsListView.dart index 1c41fda..1f229e7 100644 --- a/lib/application/views/kitchenmodule/views/kitchen/widgets/ItemsListView.dart +++ b/lib/application/views/kitchenmodule/views/kitchen/widgets/ItemsListView.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:wosull/application/model/cart/GetHoldOrderModel.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/theme/MyFonts.dart'; -import 'package:wosull/application/views/kitchenmodule/viewModel/KitchenViewModel.dart'; +import 'package:wosull/application/views/kitchenmodule/views/kitchen/viewModel/KitchenViewModel.dart'; import 'package:wosull/application/views/popups/ViewItemNotesPopUp.dart'; import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/Utils.dart'; @@ -85,7 +85,7 @@ class ItemsListView extends StatelessWidget { .orderDetails![j] .items![position] .name, - style: const TextStyle( + style: TextStyle( fontSize: MyFonts.normal, fontFamily: MyFonts.Medium, color: MyColors.black), @@ -149,7 +149,7 @@ class ItemsListView extends StatelessWidget { .items![position] .quantity .toString(), - style: const TextStyle( + style: TextStyle( fontSize: MyFonts.normal, fontFamily: MyFonts.DMREGULAR, color: MyColors.black), @@ -174,7 +174,7 @@ class ItemsListView extends StatelessWidget { .orderDetails![j] .items![position] .comboProduct), - style: const TextStyle( + style: TextStyle( fontSize: MyFonts.normal, fontFamily: MyFonts.DMREGULAR, color: MyColors.black), diff --git a/lib/application/views/kitchenmodule/views/kitchen/widgets/KitchenListView.dart b/lib/application/views/kitchenmodule/views/kitchen/widgets/KitchenListView.dart index 33041d7..5cc334e 100644 --- a/lib/application/views/kitchenmodule/views/kitchen/widgets/KitchenListView.dart +++ b/lib/application/views/kitchenmodule/views/kitchen/widgets/KitchenListView.dart @@ -5,7 +5,7 @@ import 'package:wosull/application/model/converters/DataTimeFormat.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/theme/MyFonts.dart'; import 'package:wosull/application/utils/AppLoader.dart'; -import 'package:wosull/application/views/kitchenmodule/viewModel/KitchenViewModel.dart'; +import 'package:wosull/application/views/kitchenmodule/views/kitchen/viewModel/KitchenViewModel.dart'; import 'package:wosull/application/views/kitchenmodule/views/kitchen/widgets/ItemsListView.dart'; import 'package:wosull/application/views/kitchenmodule/views/kitchen/widgets/KitchenListViewHeader.dart'; import 'package:wosull/application/views/kitchenmodule/views/kitchen/widgets/ReadyToServeButton.dart'; @@ -50,22 +50,13 @@ class KitchenListView extends StatelessWidget { shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12.0), ), - color: DataTimeFormat.subtractTime( - kitchenOrders[i].createdAt!, kitchenOrders[i].timer ?? 10) - ? MyColors.pinkish - : MyColors.white, + color: MyColors.white, child: Container( padding: const EdgeInsets.all(12), child: Column( children: [ KitchenListViewHeader( - onEndTimer: () { - Future.delayed(Duration.zero, () async { - viewModel.setNotifier(); - }); - }, orderType: kitchenOrders[i].orderType!, - time: time, uniqueId: kitchenOrders[i].uniqueId!), AppSpaces.verticalMedium, Container( @@ -83,7 +74,7 @@ class KitchenListView extends StatelessWidget { alignment: Alignment.centerLeft, child: Text( lang(context).items, - style: const TextStyle( + style: TextStyle( fontSize: MyFonts.normalButton, fontWeight: FontWeight.w500, fontFamily: MyFonts.Bold, @@ -95,7 +86,7 @@ class KitchenListView extends StatelessWidget { alignment: Alignment.centerRight, child: Text( lang(context).qty, - style: const TextStyle( + style: TextStyle( fontSize: MyFonts.normalButton, fontWeight: FontWeight.w500, fontFamily: MyFonts.Bold, diff --git a/lib/application/views/kitchenmodule/views/kitchen/widgets/KitchenListViewHeader.dart b/lib/application/views/kitchenmodule/views/kitchen/widgets/KitchenListViewHeader.dart index d01fc8f..5a458b4 100644 --- a/lib/application/views/kitchenmodule/views/kitchen/widgets/KitchenListViewHeader.dart +++ b/lib/application/views/kitchenmodule/views/kitchen/widgets/KitchenListViewHeader.dart @@ -1,25 +1,17 @@ import 'package:flutter/material.dart'; -import 'package:flutter_countdown_timer/flutter_countdown_timer.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/theme/MyFonts.dart'; -import 'package:wosull/application/views/kitchenmodule/views/kitchen/widgets/TimerText.dart'; import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/ThemeText.dart'; import 'package:wosull/helpers/Utils.dart'; import 'package:wosull/widgets/CustomSimpleButton.dart'; class KitchenListViewHeader extends StatelessWidget { - int time; int uniqueId; String orderType; - final void Function() onEndTimer; KitchenListViewHeader( - {super.key, - required this.onEndTimer, - required this.orderType, - required this.time, - required this.uniqueId}); + {super.key, required this.orderType, required this.uniqueId}); @override Widget build(BuildContext context) { @@ -36,28 +28,6 @@ class KitchenListViewHeader extends StatelessWidget { style: ThemeText.textStylePopUpHeading, ), AppSpaces.horizontalSmall, - Container( - height: 14, - width: 2, - color: MyColors.fillColorGray2, - ), - AppSpaces.horizontalSmall, - CountdownTimer( - endWidget: TimerText( - title: '0h: 0m:,0s', - ), - onEnd: onEndTimer, - endTime: time, - widgetBuilder: (_, timer) { - if (timer == null) { - return TimerText(title: '0h: 0m:,0s'); - } - return TimerText( - title: - '${timer.hours ?? "0"}h: ${timer.min ?? "0"}m:,${timer.sec ?? "0"}s', - ); - }, - ), ], ), AppSpaces.verticalSmall, diff --git a/lib/application/views/kitchenmodule/views/kitchen/widgets/offline/KitchenOfflineItemListView.dart b/lib/application/views/kitchenmodule/views/kitchen/widgets/offline/KitchenOfflineItemListView.dart index 62c5363..3bcd33d 100644 --- a/lib/application/views/kitchenmodule/views/kitchen/widgets/offline/KitchenOfflineItemListView.dart +++ b/lib/application/views/kitchenmodule/views/kitchen/widgets/offline/KitchenOfflineItemListView.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:wosull/application/model/createOrder/OrderDetails.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/theme/MyFonts.dart'; -import 'package:wosull/application/views/kitchenmodule/viewModel/KitchenViewModel.dart'; +import 'package:wosull/application/views/kitchenmodule/views/kitchen/viewModel/KitchenViewModel.dart'; import 'package:wosull/application/views/popups/ViewItemNotesPopUp.dart'; import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/Utils.dart'; @@ -78,7 +78,7 @@ class KitchenOfflineItemList extends StatelessWidget { AppSpaces.horizontalSmall, Text( orderDetails![j].items![position].name, - style: const TextStyle( + style: TextStyle( fontSize: MyFonts.normal, fontFamily: MyFonts.Medium, color: MyColors.black), @@ -132,7 +132,7 @@ class KitchenOfflineItemList extends StatelessWidget { ]), Text( orderDetails![j].items![position].quantity.toString(), - style: const TextStyle( + style: TextStyle( fontSize: MyFonts.normal, fontFamily: MyFonts.DMREGULAR, color: MyColors.black), @@ -152,7 +152,7 @@ class KitchenOfflineItemList extends StatelessWidget { viewModel.getComboText(orderDetails![j] .items![position] .comboProduct), - style: const TextStyle( + style: TextStyle( fontSize: MyFonts.normal, fontFamily: MyFonts.DMREGULAR, color: MyColors.black), diff --git a/lib/application/views/kitchenmodule/views/kitchen/widgets/offline/KitchenOfflineListView.dart b/lib/application/views/kitchenmodule/views/kitchen/widgets/offline/KitchenOfflineListView.dart index 8c7426c..084feec 100644 --- a/lib/application/views/kitchenmodule/views/kitchen/widgets/offline/KitchenOfflineListView.dart +++ b/lib/application/views/kitchenmodule/views/kitchen/widgets/offline/KitchenOfflineListView.dart @@ -1,11 +1,14 @@ +import 'dart:convert'; + import 'package:auto_height_grid_view/auto_height_grid_view.dart'; import 'package:flutter/material.dart'; +import 'package:objectbox/objectbox.dart'; import 'package:wosull/application/model/CreateAndUpdateOrder.dart'; -import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/application/model/createOrder/OrderDetails.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/theme/MyFonts.dart'; import 'package:wosull/application/utils/AppLoader.dart'; -import 'package:wosull/application/views/kitchenmodule/viewModel/KitchenViewModel.dart'; +import 'package:wosull/application/views/kitchenmodule/views/kitchen/viewModel/KitchenViewModel.dart'; import 'package:wosull/application/views/kitchenmodule/views/kitchen/widgets/KitchenListViewHeader.dart'; import 'package:wosull/application/views/kitchenmodule/views/kitchen/widgets/ReadyToServeButton.dart'; import 'package:wosull/application/views/kitchenmodule/views/kitchen/widgets/offline/KitchenOfflineItemListView.dart'; @@ -19,7 +22,7 @@ class KitchenOfflineListView extends StatelessWidget { bool isPortrait; late KitchenViewModel viewModel; - final void Function(String id) onUpdate; + final void Function(CreateAndUpdateOrder order) onUpdate; KitchenOfflineListView( {super.key, @@ -47,29 +50,24 @@ class KitchenOfflineListView extends StatelessWidget { itemCount: kitchenOrders.length, crossAxisCount: isPortrait ? 1 : 2, builder: (BuildContext c, int i) { - int time = DataTimeFormat.getTime( - kitchenOrders[i].createdAt, kitchenOrders[i].timer ?? 0); + if (viewModel.dbOrder[i].orderDetails.isEmpty) { + viewModel.dbOrder[i].orderDetails = ToMany( + items: List.from(jsonDecode( + viewModel.dbOrder[i].orderDetailsOffline!)) + .map((i) => OrderDetails.fromJson(i)) + .toList()); + } return Card( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12.0), ), - color: DataTimeFormat.subtractTime( - kitchenOrders[i].createdAt, - kitchenOrders[i].timer ?? 10) - ? MyColors.pinkish - : MyColors.white, + color: MyColors.white, child: Container( padding: const EdgeInsets.all(12), child: Column( children: [ KitchenListViewHeader( - onEndTimer: () { - Future.delayed(Duration.zero, () async { - viewModel.setNotifier(); - }); - }, orderType: kitchenOrders[i].orderType!, - time: time, uniqueId: kitchenOrders[i].cartUniqueId), AppSpaces.verticalMedium, Container( @@ -87,7 +85,7 @@ class KitchenOfflineListView extends StatelessWidget { alignment: Alignment.centerLeft, child: Text( lang(context).items, - style: const TextStyle( + style: TextStyle( fontSize: MyFonts.normalButton, fontWeight: FontWeight.w500, fontFamily: MyFonts.Bold, @@ -99,7 +97,7 @@ class KitchenOfflineListView extends StatelessWidget { alignment: Alignment.centerRight, child: Text( lang(context).qty, - style: const TextStyle( + style: TextStyle( fontSize: MyFonts.normalButton, fontWeight: FontWeight.w500, fontFamily: MyFonts.Bold, @@ -136,7 +134,7 @@ class KitchenOfflineListView extends StatelessWidget { .checkAllItemsReady( kitchenOrders[i] .orderDetails)) { - // onUpdate(kitchenOrders[i].id!); + onUpdate(kitchenOrders[i]); } }); } else { diff --git a/lib/application/views/kitchenmodule/views/table/KitchenNewTableVC.dart b/lib/application/views/kitchenmodule/views/table/KitchenNewTableVC.dart index d7fd0c5..3acec1c 100644 --- a/lib/application/views/kitchenmodule/views/table/KitchenNewTableVC.dart +++ b/lib/application/views/kitchenmodule/views/table/KitchenNewTableVC.dart @@ -16,7 +16,6 @@ import 'package:wosull/widgets/MandatoryTitleText.dart'; class KitchenNewTableVC extends StatefulWidget { final bool isEdit; - final StoreTable storeTable; const KitchenNewTableVC( @@ -33,7 +32,6 @@ class _KitchenNewTableVCState extends BaseStatefulState { @override void initState() { - // TODO: implement initState super.initState(); } @@ -53,7 +51,7 @@ class _KitchenNewTableVCState extends BaseStatefulState { elevation: 0, backgroundColor: const Color(0xffffffff), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(15.0), + borderRadius: BorderRadius.circular(8.0), ), child: OrientationBuilder(builder: (c, orientation) { isPortrait = diff --git a/lib/application/views/kitchenmodule/views/table/KitchenTableVC.dart b/lib/application/views/kitchenmodule/views/table/KitchenTableVC.dart index 9380d12..b35067d 100644 --- a/lib/application/views/kitchenmodule/views/table/KitchenTableVC.dart +++ b/lib/application/views/kitchenmodule/views/table/KitchenTableVC.dart @@ -6,7 +6,7 @@ import 'package:wosull/application/model/tables/GetStoreTable.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/utils/AppError.dart'; import 'package:wosull/application/utils/AppLoader.dart'; -import 'package:wosull/application/views/kitchenmodule/viewModel/TablesViewModel.dart'; +import 'package:wosull/application/views/kitchenmodule/views/table/viewModels/TablesViewModel.dart'; import 'package:wosull/application/views/kitchenmodule/views/table/KitchenNewTableVC.dart'; import 'package:wosull/application/views/kitchenmodule/views/table/ViewTableVC.dart'; import 'package:wosull/application/views/kitchenmodule/views/table/widgets/TableListView.dart'; @@ -15,6 +15,7 @@ import 'package:wosull/base/BaseStatefulState.dart'; import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/ThemeText.dart'; import 'package:wosull/widgets/CustomSimpleButton.dart'; +import 'package:wosull/widgets/PageLimitDropDown.dart'; import 'package:wosull/widgets/SearchBox.dart'; class KitchenTableVC extends StatefulWidget { @@ -60,9 +61,7 @@ class _KitchenTableVCState extends BaseStatefulState { AppLocalizations.of(context)!.tables, style: ThemeText.textStylePageHeading, ), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalSmall, SizedBox( width: 120, child: CustomSimpleButton( @@ -88,11 +87,20 @@ class _KitchenTableVCState extends BaseStatefulState { AppLocalizations.of(context)!.new_table, ), ), + Flexible( + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + PageLimitDropdown(onChange: (value) { + viewModel.fetch( + isRefresh: true, + limit: int.parse(value!)); + }) + ], + )) ], ), - const SizedBox( - height: 4, - ), + AppSpaces.verticalSmall, SizedBox( height: 48, child: SearchBox( @@ -118,9 +126,7 @@ class _KitchenTableVCState extends BaseStatefulState { AppLocalizations.of(context)!.tables, style: ThemeText.textStylePageHeading, ), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalSmall, SizedBox( width: 120, child: CustomSimpleButton( @@ -146,12 +152,7 @@ class _KitchenTableVCState extends BaseStatefulState { }, ), ), - ], - )), - Expanded( - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ + AppSpaces.horizontalSmall, SizedBox( width: 240, height: 48, @@ -168,6 +169,17 @@ class _KitchenTableVCState extends BaseStatefulState { ), ], )), + Flexible( + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + PageLimitDropdown(onChange: (value) { + viewModel.fetch( + isRefresh: true, + limit: int.parse(value!)); + }) + ], + )) ], ), AppSpaces.verticalMedium, @@ -230,7 +242,7 @@ class _KitchenTableVCState extends BaseStatefulState { bool _scrollNotification() { if (!viewModel.isLoading && _controller.position.extentAfter < 300) { - viewModel.fetch(); + viewModel.fetch(limit: viewModel.limit); } return true; } diff --git a/lib/application/views/kitchenmodule/views/table/ViewTableVC.dart b/lib/application/views/kitchenmodule/views/table/ViewTableVC.dart index 7b2ca32..33e5038 100644 --- a/lib/application/views/kitchenmodule/views/table/ViewTableVC.dart +++ b/lib/application/views/kitchenmodule/views/table/ViewTableVC.dart @@ -20,7 +20,7 @@ class ViewTableVC extends StatelessWidget { elevation: 0, backgroundColor: const Color(0xffffffff), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(15.0), + borderRadius: BorderRadius.circular(8.0), ), child: OrientationBuilder(builder: (c, orientation) { isPortrait = @@ -61,7 +61,7 @@ class ViewTableVC extends StatelessWidget { child: Center( child: Text( storeTable.status, - style: const TextStyle( + style: TextStyle( fontFamily: MyFonts.Bold, fontWeight: FontWeight.w500, fontSize: MyFonts.normal, @@ -102,7 +102,7 @@ class ViewTableVC extends StatelessWidget { Text( AppLocalizations.of(context)! .table_name_or_Number, - style: const TextStyle( + style: TextStyle( fontFamily: MyFonts.Medium, fontSize: MyFonts.normalButton, color: MyColors.textColorPopUp), @@ -118,7 +118,7 @@ class ViewTableVC extends StatelessWidget { ), Text( storeTable.tableName, - style: const TextStyle( + style: TextStyle( fontFamily: MyFonts.DMREGULAR, fontSize: MyFonts.normalButton, color: MyColors.textColorGray), @@ -132,7 +132,7 @@ class ViewTableVC extends StatelessWidget { children: [ Text( AppLocalizations.of(context)!.no_of_occupants, - style: const TextStyle( + style: TextStyle( fontFamily: MyFonts.Medium, fontSize: MyFonts.normalButton, color: MyColors.textColorPopUp), @@ -148,7 +148,7 @@ class ViewTableVC extends StatelessWidget { ), Text( storeTable.noOfOccupants.toString(), - style: const TextStyle( + style: TextStyle( fontFamily: MyFonts.DMREGULAR, fontSize: MyFonts.normalButton, color: MyColors.textColorGray), @@ -162,7 +162,7 @@ class ViewTableVC extends StatelessWidget { children: [ Text( AppLocalizations.of(context)!.created_on, - style: const TextStyle( + style: TextStyle( fontFamily: MyFonts.Medium, fontSize: MyFonts.normalButton, color: MyColors.textColorPopUp), @@ -179,7 +179,7 @@ class ViewTableVC extends StatelessWidget { Text( DataTimeFormat.getFormatDate( storeTable.createdAt), - style: const TextStyle( + style: TextStyle( fontFamily: MyFonts.DMREGULAR, fontSize: MyFonts.normalButton, color: MyColors.textColorGray), @@ -193,7 +193,7 @@ class ViewTableVC extends StatelessWidget { children: [ Text( AppLocalizations.of(context)!.updated_on, - style: const TextStyle( + style: TextStyle( fontFamily: MyFonts.Medium, fontSize: MyFonts.normalButton, color: MyColors.textColorPopUp), @@ -210,7 +210,7 @@ class ViewTableVC extends StatelessWidget { Text( DataTimeFormat.getFormatDate( storeTable.updatedAt), - style: const TextStyle( + style: TextStyle( fontFamily: MyFonts.DMREGULAR, fontSize: MyFonts.normalButton, color: MyColors.textColorGray), diff --git a/lib/application/views/kitchenmodule/views/table/repo/TableRepository.dart b/lib/application/views/kitchenmodule/views/table/repo/TableRepository.dart new file mode 100644 index 0000000..0eccdec --- /dev/null +++ b/lib/application/views/kitchenmodule/views/table/repo/TableRepository.dart @@ -0,0 +1,46 @@ +import 'package:wosull/application/model/SimpleResponsModel.dart'; +import 'package:wosull/application/model/tables/GetStoreTable.dart'; +import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/utils/Constants.dart'; + +class TableRepository { + Future addNewTable(Map data) async { + return await APIManager().fetchData(Constants.ADD_STORE_TABLE, data); + } + + Future update(String id, String status) async { + Map data = {'tableId': id, "status": status}; + return await APIManager() + .getResponsePatch(Constants.UPDATE_STORE_TABLE, data); + } + + Future delete(String id) async { + Map data = {'tableId': id}; + return await APIManager() + .getResponsePatch(Constants.DELETE_STORE_TABLE, data); + } + + Future> search(Map data) async { + var tables = []; + await APIManager().fetchData(Constants.SEARCH_TABLE, data).then((result) { + final value = GetStoreTable.fromJson(result); + if (value.success) { + tables.addAll(value.storeTables); + } + }).onError((error, stackTrace) {}); + return tables; + } + + Future> fetch(Map data) async { + var tables = []; + await APIManager() + .fetchData(Constants.GET_STORE_TABLES, data) + .then((result) { + final value = GetStoreTable.fromJson(result); + if (value.success) { + tables.addAll(value.storeTables); + } + }).onError((error, stackTrace) {}); + return tables; + } +} diff --git a/lib/application/views/kitchenmodule/views/table/viewModels/NewTableViewModel.dart b/lib/application/views/kitchenmodule/views/table/viewModels/NewTableViewModel.dart index 35e9deb..fdf6365 100644 --- a/lib/application/views/kitchenmodule/views/table/viewModels/NewTableViewModel.dart +++ b/lib/application/views/kitchenmodule/views/table/viewModels/NewTableViewModel.dart @@ -1,11 +1,8 @@ -import 'dart:convert'; import 'package:flutter/cupertino.dart'; -import 'package:wosull/application/model/SimpleResponsModel.dart'; import 'package:wosull/application/model/tables/GetStoreTable.dart'; -import 'package:wosull/application/network/APIManager.dart'; import 'package:wosull/application/utils/CRUDOperatoinState.dart'; -import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/kitchenmodule/views/table/repo/TableRepository.dart'; import 'package:wosull/helpers/Utils.dart'; class NewTableViewModel with ChangeNotifier { @@ -24,6 +21,8 @@ class NewTableViewModel with ChangeNotifier { CRUDOperationState get crudOperationState => _crudOperation; + final repository = TableRepository(); + void setLoading(bool value) { _isLoading = value; notifyListeners(); @@ -31,7 +30,6 @@ class NewTableViewModel with ChangeNotifier { void setData(bool isEdit, StoreTable storeTable) { if (!this.isEdit) { - print('hree'); this.storeTable = storeTable; this.isEdit = true; tableNameController = storeTable.tableName; @@ -40,7 +38,6 @@ class NewTableViewModel with ChangeNotifier { } Future isValidate() async { - print(tableNameController); if (tableNameController.isEmpty) { Utils.showMessage('Enter table name'); } else if (noOnOccupantsController.isEmpty) { @@ -54,11 +51,7 @@ class NewTableViewModel with ChangeNotifier { setLoading(true); storeTable.tableName = tableNameController; storeTable.noOfOccupants = int.parse(noOnOccupantsController); - print(jsonEncode(storeTable.toJson())); - await APIManager() - .fetchData(Constants.ADD_STORE_TABLE, storeTable.toJson()) - .then((value) { - final response = SimpleResponseModel.fromJson(value); + await repository.addNewTable(storeTable.toJson()).then((response) { if (response.success) { _crudOperation = CRUDOperationState.add; } else { diff --git a/lib/application/views/kitchenmodule/viewModel/TablesViewModel.dart b/lib/application/views/kitchenmodule/views/table/viewModels/TablesViewModel.dart similarity index 73% rename from lib/application/views/kitchenmodule/viewModel/TablesViewModel.dart rename to lib/application/views/kitchenmodule/views/table/viewModels/TablesViewModel.dart index 7f2688c..53e936f 100644 --- a/lib/application/views/kitchenmodule/viewModel/TablesViewModel.dart +++ b/lib/application/views/kitchenmodule/views/table/viewModels/TablesViewModel.dart @@ -2,12 +2,12 @@ import 'package:flutter/cupertino.dart'; import 'package:wosull/application/enum/DataState.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; import 'package:wosull/application/model/tables/GetStoreTable.dart'; -import 'package:wosull/application/network/APIManager.dart'; -import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/kitchenmodule/views/table/repo/TableRepository.dart'; class TablesViewModel with ChangeNotifier { int _currentPageNumber = 1; DataState _dataState = DataState.uninitialized; + int limit = 10; bool _didLastLoad = false; bool _isLoading = false; @@ -22,7 +22,10 @@ class TablesViewModel with ChangeNotifier { List get filteredList => _filteredList; - fetch({bool isRefresh = false}) async { + final repository = TableRepository(); + + fetch({bool isRefresh = false, int limit = 10}) async { + this.limit = limit; _isLoading = true; if (!isRefresh) { _dataState = (_dataState == DataState.uninitialized) @@ -36,25 +39,23 @@ class TablesViewModel with ChangeNotifier { notifyListeners(); Map data = { 'store_id': sharedPrefs.storeId, - 'page': _currentPageNumber + 'page': _currentPageNumber, + 'limit': this.limit }; try { if (_didLastLoad) { _dataState = DataState.noMoreData; } else { - await APIManager() - .fetchData(Constants.GET_STORE_TABLES, data) - .then((result) { - final value = GetStoreTable.fromJson(result); + await repository.fetch(data).then((tables) { if (_dataState == DataState.refreshing) { _filteredList.clear(); _dataList.clear(); } - if (value.success) { - _filteredList.addAll(value.storeTables); - _dataList.addAll(value.storeTables); - if (value.storeTables.length < 10) { + if (tables.isNotEmpty) { + _filteredList.addAll(tables); + _dataList.addAll(tables); + if (tables.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; @@ -89,13 +90,10 @@ class TablesViewModel with ChangeNotifier { _dataState = DataState.searching; notifyListeners(); try { - await APIManager() - .fetchData(Constants.SEARCH_TABLE, data) - .then((result) { - final value = GetStoreTable.fromJson(result); + await repository.search(data).then((tables) { filteredList.clear(); - if (value.success) { - filteredList.addAll(value.storeTables); + if (tables.isNotEmpty) { + filteredList.addAll(tables); } _dataState = DataState.fetched; }).onError((error, stackTrace) { @@ -110,10 +108,7 @@ class TablesViewModel with ChangeNotifier { } Future delete(String id) async { - Map data = {'tableId': id}; - await APIManager() - .getResponsePatch(Constants.DELETE_STORE_TABLE, data) - .then((result) { + await repository.delete(id).then((result) { _filteredList.removeWhere((element) => element.id == id); _dataList.removeWhere((element) => element.id == id); notifyListeners(); @@ -129,10 +124,7 @@ class TablesViewModel with ChangeNotifier { } else { status = "Inactive"; } - Map data = {'tableId': id, "status": status}; - await APIManager() - .getResponsePatch(Constants.UPDATE_STORE_TABLE, data) - .then((result) { + await repository.update(id, status).then((result) { _filteredList.singleWhere((element) => element.id == id).status = status; _dataList.singleWhere((element) => element.id == id).status = status; notifyListeners(); diff --git a/lib/application/views/popups/CountryPopUp.dart b/lib/application/views/popups/CountryPopUp.dart index f4062f5..c1d9ab2 100644 --- a/lib/application/views/popups/CountryPopUp.dart +++ b/lib/application/views/popups/CountryPopUp.dart @@ -4,7 +4,7 @@ import 'package:wosull/application/model/auth/CountryModel.dart'; import 'package:wosull/application/model/auth/CountryResponse.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/theme/MyFonts.dart'; -import 'package:wosull/application/views/authModule/viewModel/CountryViewModel.dart'; +import 'package:wosull/application/views/authModule/registerViews/viewModel/CountryViewModel.dart'; class CountryPopUp extends StatefulWidget { const CountryPopUp({Key? key}) : super(key: key); diff --git a/lib/application/views/popups/DeleteRecordPopUp.dart b/lib/application/views/popups/DeleteRecordPopUp.dart index 6fcef98..6390763 100644 --- a/lib/application/views/popups/DeleteRecordPopUp.dart +++ b/lib/application/views/popups/DeleteRecordPopUp.dart @@ -21,7 +21,7 @@ class _DeleteRecordPopUpState extends State { elevation: 0, backgroundColor: const Color(0xffffffff), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(15.0), + borderRadius: BorderRadius.circular(8.0), ), child: OrientationBuilder(builder: (c, orientation) { isPortrait = diff --git a/lib/application/views/popups/SelectMultiStoresPopUp.dart b/lib/application/views/popups/SelectMultiStoresPopUp.dart index 307cd42..1f479ff 100644 --- a/lib/application/views/popups/SelectMultiStoresPopUp.dart +++ b/lib/application/views/popups/SelectMultiStoresPopUp.dart @@ -1,10 +1,14 @@ import 'package:flutter/material.dart'; -import 'package:wosull/application/ViewModel/InventoryViewModel.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; import 'package:wosull/application/model/store/WosulStore.dart'; +import 'package:wosull/application/repository/WosulRepository.dart'; import 'package:wosull/application/theme/MyColors.dart'; -import 'package:wosull/application/theme/MyFonts.dart'; +import 'package:wosull/application/utils/AppLoader.dart'; import 'package:wosull/base/BaseStatefulState.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/widgets/CustomSimpleButton.dart'; +import 'package:wosull/widgets/CustomTextFieldForm.dart'; +import 'package:wosull/widgets/DialogHeader.dart'; class SelectMultiStoresPopUp extends StatefulWidget { List selectedStore = []; @@ -17,7 +21,7 @@ class SelectMultiStoresPopUp extends StatefulWidget { class _SelectMultiStoresPopUpState extends BaseStatefulState { - InventoryViewModel viewModel = InventoryViewModel(); + final viewModel = WosulRepository(); TextEditingController searchCountry = TextEditingController(); bool _isInAsyncCall = true; List stores = List.empty(growable: true); @@ -83,88 +87,35 @@ class _SelectMultiStoresPopUpState elevation: 0, backgroundColor: const Color(0xffffffff), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(15.0), + borderRadius: BorderRadius.circular(8.0), ), child: OrientationBuilder(builder: (c, orientation) { isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; return SingleChildScrollView( - child: Container( + child: SizedBox( width: !isPortrait ? MediaQuery.of(context).size.width / 1.2 : double.infinity, - padding: const EdgeInsets.only(bottom: 16), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end, children: [ - Row( - mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.max, - children: [ - Expanded( - child: Padding( - padding: const EdgeInsets.only(left: 16), - child: Text( - 'Choose Stores', - style: MyColors.textStylePopUpHeading(), - ), - )), - Align( - alignment: Alignment.topRight, - child: IconButton( - onPressed: () { - Navigator.of(context).pop(); - }, - icon: Icon(Icons.close)), - ), - ], - ), - Container( - height: 2, - color: MyColors.fillColorGray, - ), + DialogHeader(title: 'Choose Stores'), Container( - padding: EdgeInsets.all(16), + padding: const EdgeInsets.all(12), child: Column( children: [ - SizedBox( - height: 48, - child: TextField( - onChanged: (value) { - filterSearchResults(value); - }, - style: TextStyle( - fontSize: MyFonts.normalButton, - fontFamily: MyFonts.DMREGULAR, - color: MyColors.textColorBlack), - decoration: InputDecoration( - contentPadding: - const EdgeInsets.symmetric(vertical: 0), - hintText: 'Search ', - fillColor: MyColors.fillColor, - filled: true, - prefixIcon: Icon(Icons.search), - focusedBorder: OutlineInputBorder( - borderSide: const BorderSide( - color: Colors.transparent, width: 1.0), - borderRadius: BorderRadius.circular(8.0), - ), - enabledBorder: OutlineInputBorder( - borderSide: const BorderSide( - width: 1, //<-- SEE HERE - color: Colors.transparent, - ), - borderRadius: BorderRadius.circular(8.0), - ), - )), + CustomTextFieldForm( + onChanged: (value) { + filterSearchResults(value); + }, + hintText: 'Search ', ), _isInAsyncCall - ? const Center( - child: CircularProgressIndicator(), - ) + ? AppLoader() : Container( margin: const EdgeInsets.only(top: 8), child: ListBody( @@ -172,7 +123,16 @@ class _SelectMultiStoresPopUpState .map((item) => CheckboxListTile( value: widget.selectedStore .contains(item.id), + side: const BorderSide( + color: + MyColors.fillColorGray2), + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular(4)), title: Text(item.name), + activeColor: + MyColors.blueThemeColor, + checkColor: Colors.white, controlAffinity: ListTileControlAffinity .leading, @@ -182,66 +142,63 @@ class _SelectMultiStoresPopUpState .toList(), ), ), - Row( - crossAxisAlignment: CrossAxisAlignment.end, - mainAxisAlignment: MainAxisAlignment.end, - children: [ - SizedBox( - width: 140, - child: Padding( - padding: const EdgeInsets.only(right: 16), - child: ElevatedButton( - style: ElevatedButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.circular(6.0), - ), - backgroundColor: MyColors.blueThemeColor, - minimumSize: - const Size.fromHeight(38), // NEW + isPortrait + ? Row( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Flexible( + child: CustomSimpleButton( + textColor: MyColors.white, + backGroundColor: + MyColors.blueThemeColor, + heading: 'Cancel', + onPressed: () { + _cancel(); + }), ), - onPressed: () { - _cancel(); - }, - child: Text( - 'Cancel', - style: TextStyle( - fontSize: MyFonts.normalButton, - color: MyColors.white, - fontFamily: MyFonts.Bold), - ), - ), - ), - ), - SizedBox( - width: 140, - child: Padding( - padding: const EdgeInsets.only(right: 16), - child: ElevatedButton( - style: ElevatedButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.circular(6.0), - ), - backgroundColor: MyColors.blueThemeColor, - minimumSize: - const Size.fromHeight(38), // NEW - ), - onPressed: () { - _submit(); - }, - child: Text( - 'Submit', - style: TextStyle( - fontSize: MyFonts.normalButton, - color: MyColors.white, - fontFamily: MyFonts.Bold), + AppSpaces.horizontalSmall, + Flexible( + child: CustomSimpleButton( + textColor: MyColors.white, + backGroundColor: + MyColors.blueThemeColor, + heading: 'Submit', + onPressed: () { + _submit(); + }), + ) + ], + ) + : Row( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + SizedBox( + width: 100, + child: CustomSimpleButton( + textColor: MyColors.white, + backGroundColor: + MyColors.blueThemeColor, + heading: 'Cancel', + onPressed: () { + _cancel(); + }), ), - ), - ), - ), - ], - ) + AppSpaces.horizontalSmall, + SizedBox( + width: 100, + child: CustomSimpleButton( + textColor: MyColors.white, + backGroundColor: + MyColors.blueThemeColor, + heading: 'Submit', + onPressed: () { + _submit(); + }), + ) + ], + ) ], ), ), diff --git a/lib/application/views/popups/ViewItemNotesPopUp.dart b/lib/application/views/popups/ViewItemNotesPopUp.dart index 02a4c2a..080864f 100644 --- a/lib/application/views/popups/ViewItemNotesPopUp.dart +++ b/lib/application/views/popups/ViewItemNotesPopUp.dart @@ -26,7 +26,7 @@ class _ViewItemNotesPopUpState extends State { elevation: 0, backgroundColor: const Color(0xffffffff), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(15.0), + borderRadius: BorderRadius.circular(8.0), ), child: OrientationBuilder(builder: (c, orientation) { isPortrait = diff --git a/lib/application/views/salesandordermodule/SalesAndOrderMainVC.dart b/lib/application/views/salesandordermodule/SalesAndOrderMainVC.dart index 64f2316..d9355d9 100644 --- a/lib/application/views/salesandordermodule/SalesAndOrderMainVC.dart +++ b/lib/application/views/salesandordermodule/SalesAndOrderMainVC.dart @@ -2,11 +2,10 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:wosull/application/interfaces/DrawerWidgetSelect.dart'; import 'package:wosull/application/theme/MyColors.dart'; -import 'package:wosull/application/theme/MyFonts.dart'; -import 'package:wosull/application/views/salesandordermodule/views/invoiceModule/InvoicesVC.dart'; +import 'package:wosull/application/views/salesandordermodule/views/invoiceModule/views/InvoicesVC.dart'; import 'package:wosull/application/views/salesandordermodule/views/ordersModule/OrderVC.dart'; import 'package:wosull/application/views/salesandordermodule/views/quotataionModule/QuotationsVC.dart'; -import 'package:wosull/application/views/transactions/TransactionVC.dart'; +import 'package:wosull/widgets/BackTabBarContainer.dart'; class SalesAndOrderMainVC extends StatefulWidget { final DrawerWidgetSelect delegateDrawer; @@ -22,7 +21,7 @@ class _SalesAndOrderMainVCState extends State { @override Widget build(BuildContext context) { return DefaultTabController( - length: 4, + length: 3, child: Scaffold( body: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -35,97 +34,34 @@ class _SalesAndOrderMainVCState extends State { width: double.infinity, color: MyColors.fillColorGray2, ), - Container( - width: double.infinity, - margin: const EdgeInsets.only(bottom: 6.0), - //Same as `blurRadius` i guess - decoration: const BoxDecoration( - color: Colors.white, - boxShadow: [ - BoxShadow( - color: Colors.grey, - offset: Offset(0.0, 1.0), //(x,y) - blurRadius: 6.0, - ), - ], - ), - child: Row( - children: [ - Container( - margin: const EdgeInsets.only(left: 8), - child: ElevatedButton.icon( - onPressed: () { - widget.delegateDrawer.goToHome(); - }, - icon: const Icon( - size: 16, - Icons.arrow_back_ios, - color: MyColors.textColorBlack, - ), - label: Text( - AppLocalizations.of(context)!.back, - style: const TextStyle( - color: MyColors.textColorBlack, - fontFamily: MyFonts.Medium, - fontSize: 14), - ), - style: ElevatedButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(5.0), - ), - elevation: 0, - backgroundColor: MyColors.backFillColor, - ), - ), - ), - const SizedBox(width: 8), - Container( - margin: const EdgeInsets.only(bottom: 6.0, top: 6.0), - height: 25, - width: 1, - color: MyColors.fillColorGray2, - ), - Flexible( - child: TabBar( - indicatorColor: Colors.white, - labelStyle: TextStyle( - fontSize: MyFonts.normalButton, - fontWeight: FontWeight.w500, - fontFamily: MyFonts.Bold, - color: MyColors.blueThemeColor), - isScrollable: true, - unselectedLabelStyle: const TextStyle( - fontSize: MyFonts.normalButton, - fontWeight: FontWeight.w500, - fontFamily: MyFonts.Medium, - color: MyColors.textColorBlack), - unselectedLabelColor: MyColors.textColorBlack, - labelColor: MyColors.blueThemeColor, - tabs: [ - Tab( - text: AppLocalizations.of(context)!.order, - ), - Tab( - text: AppLocalizations.of(context)!.invoices, - ), - Tab( - text: AppLocalizations.of(context)!.quotations, - ), - Tab( - text: AppLocalizations.of(context)!.transactions, - ), - ], - )) - ], - ), + BackTabBarContainer( + onPressed: () { + widget.delegateDrawer.goToHome(); + }, + tabs: [ + Tab( + text: AppLocalizations.of(context)!.order, + ), + Tab( + text: AppLocalizations.of(context)!.invoices, + ), + Tab( + text: AppLocalizations.of(context)!.quotations, + ), + // Tab( + // text: AppLocalizations.of(context)!.transactions, + // ), + ], ), Expanded( child: TabBarView( children: [ - OrderVC(), - const InvoicesVC(), + const OrderVC(), + InvoicesVC( + filter: 'All', + ), const QuotationsVC(), - const TransactionVC() + //TransactionVC() ], )) ], diff --git a/lib/application/views/salesandordermodule/viewModel/QuotationViewModel.dart b/lib/application/views/salesandordermodule/viewModel/QuotationViewModel.dart index 4725d74..f5f5801 100644 --- a/lib/application/views/salesandordermodule/viewModel/QuotationViewModel.dart +++ b/lib/application/views/salesandordermodule/viewModel/QuotationViewModel.dart @@ -2,14 +2,15 @@ import 'package:flutter/cupertino.dart'; import 'package:wosull/application/enum/DataState.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; import 'package:wosull/application/model/invoice/QuotationInvioceModel.dart'; -import 'package:wosull/application/network/APIManager.dart'; -import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/salesandordermodule/views/quotataionModule/repo/QuotationRepository.dart'; class QuotationViewModel with ChangeNotifier { + final repository = QuotationRepository(); + int _currentPageNumber = 1; String filterValue = 'All'; DataState _dataState = DataState.uninitialized; - + int limit = 10; bool _didLastLoad = false; bool _isLoading = false; @@ -23,7 +24,8 @@ class QuotationViewModel with ChangeNotifier { List get filteredList => _filteredList; - fetch({bool isRefresh = false, String filter = 'All'}) async { + fetch({bool isRefresh = false, String filter = 'All', int limit = 10}) async { + this.limit = limit; _isLoading = true; filterValue = filter; if (!isRefresh) { @@ -40,28 +42,24 @@ class QuotationViewModel with ChangeNotifier { 'store_id': sharedPrefs.storeId, 'page': _currentPageNumber, 'quotation_status': filterValue, + 'limit': this.limit }; try { if (_didLastLoad) { _dataState = DataState.noMoreData; } else { - await APIManager() - .fetchData(Constants.GET_QUOTATION, data) - .then((result) { - final value = QuotationInvoiceModel.fromJson(result); + await repository.fetchQuotations(data).then((value) { if (_dataState == DataState.refreshing) { _filteredList.clear(); _dataList.clear(); } - if (value.success!) { - _filteredList.addAll(value.invoices!); - _dataList.addAll(value.invoices!); - if (value.invoices!.length < 10) { - _didLastLoad = true; - } else { - _didLastLoad = false; - } + _filteredList.addAll(value); + _dataList.addAll(value); + if (value.length < this.limit) { + _didLastLoad = true; + } else { + _didLastLoad = false; } _dataState = DataState.fetched; _currentPageNumber += 1; @@ -79,11 +77,35 @@ class QuotationViewModel with ChangeNotifier { } } + search({String searchValue = ""}) async { + if (searchValue.isEmpty) { + _dataState = DataState.fetched; + _filteredList.clear(); + _filteredList.addAll(_dataList); + notifyListeners(); + } else { + _dataState = DataState.searching; + notifyListeners(); + try { + await repository.search(searchValue, filterValue).then((result) { + _filteredList.clear(); + if (result.isNotEmpty) { + _filteredList.addAll(result); + } + _dataState = DataState.fetched; + }).onError((error, stackTrace) { + _dataState = DataState.error; + }); + notifyListeners(); + } catch (e) { + _dataState = DataState.error; + notifyListeners(); + } + } + } + Future delete(String id) async { - Map data = {'quotationId': id}; - await APIManager() - .getResponsePatch(Constants.DELETE_QUOTATION, data) - .then((result) { + await repository.delete(id).then((result) { filteredList.removeWhere((element) => element.id! == id); dataList.removeWhere((element) => element.id! == id); notifyListeners(); @@ -93,10 +115,7 @@ class QuotationViewModel with ChangeNotifier { } Future update(String id, String status) async { - Map data = {'quotationId': id, "status": status}; - await APIManager() - .getResponsePatch(Constants.UPDATE_QUOTATION, data) - .then((result) { + await repository.update(id, status).then((result) { fetch(isRefresh: true, filter: filterValue); }).onError((error, stackTrace) { notifyListeners(); diff --git a/lib/application/views/salesandordermodule/views/ReturnInvoiceVC.dart b/lib/application/views/salesandordermodule/views/ReturnInvoiceVC.dart index 19f0689..3105ed6 100644 --- a/lib/application/views/salesandordermodule/views/ReturnInvoiceVC.dart +++ b/lib/application/views/salesandordermodule/views/ReturnInvoiceVC.dart @@ -1,19 +1,30 @@ -import 'dart:developer'; - import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:wosull/application/ViewModel/InventoryViewModel.dart'; -import 'package:wosull/application/model/SimpleResponsModel.dart'; -import 'package:wosull/application/model/invoice/ReturnDamageInvoiceModel.dart'; +import 'package:provider/provider.dart'; import 'package:wosull/application/model/invoice/StoreInvoice.dart'; -import 'package:wosull/application/model/store/StoreInvoicesModel.dart'; import 'package:wosull/application/theme/MyColors.dart'; -import 'package:wosull/application/theme/MyFonts.dart'; -import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/utils/AppLoader.dart'; +import 'package:wosull/application/utils/CRUDOperatoinState.dart'; import 'package:wosull/application/views/inventorymodule/productviews/SearchProductVC.dart'; +import 'package:wosull/application/views/salesandordermodule/views/invoiceModule/viewModels/ReturnDamageInvoiceViewModel.dart'; import 'package:wosull/base/BaseStatefulState.dart'; import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/widgets/BorderContainer.dart'; +import 'package:wosull/widgets/ChildContainer.dart'; +import 'package:wosull/widgets/CustomAddButton.dart'; +import 'package:wosull/widgets/CustomAppBar.dart'; +import 'package:wosull/widgets/CustomCheckBox.dart'; +import 'package:wosull/widgets/CustomRemoveItemButton.dart'; +import 'package:wosull/widgets/CustomSimpleButton.dart'; +import 'package:wosull/widgets/CustomTextAddProduct.dart'; +import 'package:wosull/widgets/CustomTextButtonIcon.dart'; +import 'package:wosull/widgets/CustomTextFieldForm.dart'; +import 'package:wosull/widgets/HeadingContainer.dart'; +import 'package:wosull/widgets/HeadingText.dart'; +import 'package:wosull/widgets/PortraitContainer.dart'; +import 'package:wosull/widgets/TransprentBorderContainer.dart'; +import 'package:wosull/widgets/WrapHeightContainer.dart'; class ReturnInvoiceVC extends StatefulWidget { StoreInvoice storeInvoice; @@ -27,45 +38,28 @@ class ReturnInvoiceVC extends StatefulWidget { } class _ReturnInvoiceVCState extends BaseStatefulState { - bool isPortrait = true; - bool isLoadingData = false; - List selectedProduct = []; - List quantityControllers = []; - final returnDamageOrder = ReturnDamageInvoiceModel(); - final viewModel = InventoryViewModel(); + var viewModel = ReturnDamageInvoiceViewModel(); @override void initState() { + context + .read() + .initData(widget.isReturn, widget.storeInvoice); super.initState(); - returnDamageOrder.returnDamageOrderDetails - .addAll(widget.storeInvoice.products); } @override Widget build(BuildContext context) { + viewModel = context.watch(); return Scaffold( backgroundColor: MyColors.fillColor, resizeToAvoidBottomInset: true, - appBar: AppBar( - leading: BackButton( - color: Colors.black, - onPressed: () { - Navigator.pop(context); - }, // <-- SEE HERE - ), - centerTitle: true, - title: Text( - widget.isReturn ? "Return Invoice" : "Damage Invoice", - style: const TextStyle( - color: MyColors.textColorBlack, - fontFamily: MyFonts.Bold, - fontSize: 22), - ), - backgroundColor: MyColors.white, - elevation: 5, + appBar: CustomAppBar( + heading: viewModel.isReturn ? "Return Invoice" : "Damage Invoice", ), body: OrientationBuilder(builder: (c, orientation) { - isPortrait = MediaQuery.of(c).orientation == Orientation.portrait; + viewModel.isPortrait = + MediaQuery.of(c).orientation == Orientation.portrait; return SingleChildScrollView( child: Container( padding: const EdgeInsets.all(12), @@ -74,13 +68,12 @@ class _ReturnInvoiceVCState extends BaseStatefulState { mainAxisAlignment: MainAxisAlignment.start, children: [ Text( - widget.isReturn ? "Return Invoice" : "Damage Invoice", + viewModel.isReturn ? "Return Invoice" : "Damage Invoice", style: ThemeText.textStylePageHeading, ), - const SizedBox( - height: 12, - ), + AppSpaces.verticalLarge, Card( + elevation: 5, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(4.0), ), @@ -93,206 +86,52 @@ class _ReturnInvoiceVCState extends BaseStatefulState { Text( AppLocalizations.of(context)! .search_and_add_products, - style: const TextStyle( - color: MyColors.textColorBlack, - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.bold, - fontSize: 14), - ), - const SizedBox( - height: 12, + style: ThemeText.textStylePageHeading, ), - isPortrait + AppSpaces.verticalLarge, + viewModel.isPortrait ? Container() - : Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all( - width: 1, - color: MyColors.fillColorGray2), - color: MyColors.containerBackColor, - ), - height: 48, + : BorderContainer( + backgroundColor: MyColors.backFillColor, child: Row( children: [ - Container( - padding: const EdgeInsets.only(left: 4), + HeadingContainer( width: 84, - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .return_txt, - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.bold, - fontSize: MyFonts.normal, - color: - MyColors.textColorBlack20), - ), - ), + heading: AppLocalizations.of(context)! + .return_txt, ), Expanded( - child: Container( - padding: const EdgeInsets.only( - left: 4, right: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .name_or_barcode, - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.bold, - fontSize: MyFonts.normal, - color: - MyColors.textColorBlack20), - ), - ), + child: HeadingContainer( + heading: AppLocalizations.of(context)! + .name_or_barcode, )), Expanded( - child: Container( - padding: const EdgeInsets.only(left: 8), - height: 48, - width: 100, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .description, - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.bold, - fontSize: MyFonts.normal, - color: - MyColors.textColorBlack20), - ), - ), - )), + child: HeadingContainer( + width: 100, + heading: + AppLocalizations.of(context)! + .description), + ), Expanded( - child: Container( - padding: const EdgeInsets.only(left: 4), - height: 48, + child: HeadingContainer( width: 60, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .quantity, - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.bold, - fontSize: MyFonts.normal, - color: - MyColors.textColorBlack20), - ), - ), + heading: AppLocalizations.of(context)! + .quantity, )), Expanded( - child: Container( - padding: const EdgeInsets.only(left: 4), - height: 48, + child: HeadingContainer( width: 60, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .unit_price, - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.bold, - fontSize: MyFonts.normal, - color: - MyColors.textColorBlack20), - ), - ), + heading: AppLocalizations.of(context)! + .unit_price, )), - Container( - padding: const EdgeInsets.only(left: 4), + HeadingContainer( width: 84, - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .amount, - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.bold, - fontSize: MyFonts.normal, - color: - MyColors.textColorBlack20), - ), - ), + heading: AppLocalizations.of(context)! + .amount, ), - Container( + HeadingContainer( width: 44, - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: const Center( - child: Text( - '', - style: TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.bold, - fontSize: MyFonts.normal, - color: - MyColors.textColorBlack20), - ), - ), + heading: '', ) ], ), @@ -303,1123 +142,273 @@ class _ReturnInvoiceVCState extends BaseStatefulState { physics: const NeverScrollableScrollPhysics(), shrinkWrap: true, itemBuilder: (c, position) { - selectedProduct.add( - widget.storeInvoice.products[position].name ?? - ''); - quantityControllers.add(TextEditingController( - text: widget.storeInvoice.products[position] - .totalQuantity - ?.toString() ?? - '')); + if (viewModel.isPortrait) { + return WrapHeightContainer( + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Container( + width: 44, + height: 59, + decoration: const BoxDecoration( + border: Border( + bottom: BorderSide( + width: 1.0, + color: MyColors.fillColorGray2), + )), + child: Align( + alignment: Alignment.center, + child: returnCheckBoxWidget(position), + )), - if (isPortrait) { - return Container( - padding: - const EdgeInsets.fromLTRB(8, 0, 0, 8), - color: MyColors.containerBackColor, - child: Row( - crossAxisAlignment: - CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Expanded( - flex: 2, - child: Container( - padding: - const EdgeInsets.only(top: 8), - child: Row( - crossAxisAlignment: - CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.start, - children: [ - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.start, - children: [ - Container( - padding: - const EdgeInsets.all( - 4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - left: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: Alignment - .centerLeft, - child: Text( - AppLocalizations.of( - context)! - .name_or_barcode, - style: const TextStyle( - fontFamily: - MyFonts.Bold, - fontWeight: - FontWeight - .bold, - fontSize: 11, - color: MyColors - .textColorBlack20), - ), - ), - ), - Container( - padding: - const EdgeInsets.all( - 4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - left: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - bottom: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: Alignment - .centerLeft, - child: Text( - AppLocalizations.of( - context)! - .description, - style: const TextStyle( - fontFamily: - MyFonts.Bold, - fontWeight: - FontWeight - .bold, - fontSize: 11, - color: MyColors - .textColorBlack20), - ), - ), - ), - Container( - padding: - const EdgeInsets.all( - 4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - left: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: Alignment - .centerLeft, - child: Text( - AppLocalizations.of( - context)! - .quantity, - style: const TextStyle( - fontFamily: - MyFonts.Bold, - fontWeight: - FontWeight - .bold, - fontSize: 11, - color: MyColors - .textColorBlack20), - ), - ), - ), - Container( - padding: - const EdgeInsets.all( - 4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - left: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: Alignment - .centerLeft, - child: Text( - AppLocalizations.of( - context)! - .unit_price, - style: const TextStyle( - fontFamily: - MyFonts.Bold, - fontWeight: - FontWeight - .bold, - fontSize: 11, - color: MyColors - .textColorBlack20), - ), - ), - ), - Container( - padding: - const EdgeInsets.all( - 4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - left: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - bottom: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: Alignment - .centerLeft, - child: Text( - AppLocalizations.of( - context)! - .amount, - style: const TextStyle( - fontFamily: - MyFonts.Bold, - fontWeight: - FontWeight - .bold, - fontSize: 11, - color: MyColors - .textColorBlack20), - ), + Expanded( + flex: 2, + child: Container( + decoration: const BoxDecoration( + border: Border( + left: BorderSide( + width: 1.0, + color: + MyColors.fillColorGray2), + ), + ), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + PortraitContainer( + width: double.infinity, + child: Align( + alignment: + Alignment.centerLeft, + child: HeadingText( + AppLocalizations.of( + context)! + .name_or_barcode, ), ), - ], - )), - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.start, - children: [ - Container( - height: 48, - padding: - const EdgeInsets.only( - right: 8), - decoration: BoxDecoration( - border: Border.all( - color: Colors - .transparent, - width: 1, - ), - color: - MyColors.fillColor2, - borderRadius: - BorderRadius - .circular(8.0), - ), - child: Row( - mainAxisAlignment: - MainAxisAlignment - .spaceBetween, - crossAxisAlignment: - CrossAxisAlignment - .stretch, - children: [ - Expanded( - child: TextButton( - onPressed: () { - showSheet( - position); - }, - child: Align( - alignment: Alignment - .centerLeft, - child: Text( - selectedProduct[ - position] - .isEmpty - ? 'Choose' - : selectedProduct[ - position], - textAlign: - TextAlign - .left, - style: const TextStyle( - fontFamily: - MyFonts - .Bold, - fontSize: - 10, - color: MyColors - .textColorBlack), - ), - ), - )), - const Icon( - // <-- Icon - Icons - .arrow_drop_down, - size: 24.0, - color: - MyColors.black, - ) - ], + ), + PortraitContainer( + width: double.infinity, + child: Align( + alignment: + Alignment.centerLeft, + child: HeadingText( + AppLocalizations.of( + context)! + .description, ), ), - Container( - padding: - const EdgeInsets.all( - 4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: TextField( - style: const TextStyle( - fontFamily: MyFonts - .DMREGULAR, - fontSize: MyFonts - .normal, - color: MyColors - .black), - decoration: - InputDecoration( - contentPadding: - const EdgeInsets - .fromLTRB( - 4, 0, 4, 0), - hintText: '', - fillColor: MyColors - .fillColor2, - filled: true, - focusedBorder: - OutlineInputBorder( - borderSide: - const BorderSide( - color: Colors - .transparent, - width: - 1.0), - borderRadius: - BorderRadius - .circular( - 8.0), - ), - enabledBorder: - OutlineInputBorder( - borderSide: - const BorderSide( - width: 1, - //<-- SEE HERE - color: Colors - .transparent, - ), - borderRadius: - BorderRadius - .circular( - 4.0), - ), - ), - ), + ), + PortraitContainer( + width: double.infinity, + child: Align( + alignment: + Alignment.centerLeft, + child: HeadingText( + AppLocalizations.of( + context)! + .quantity, ), ), - Container( - padding: - const EdgeInsets.all( - 4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: TextField( - keyboardType: - TextInputType - .number, - controller: - quantityControllers[ - position], - onChanged: (value) { - onChangeQuantity( - position, - value); - }, - style: const TextStyle( - fontFamily: MyFonts - .DMREGULAR, - fontSize: MyFonts - .normal, - color: MyColors - .black), - decoration: - InputDecoration( - contentPadding: - const EdgeInsets - .fromLTRB( - 4, 0, 4, 0), - hintText: '', - fillColor: MyColors - .fillColor2, - filled: true, - focusedBorder: - OutlineInputBorder( - borderSide: - const BorderSide( - color: Colors - .transparent, - width: - 1.0), - borderRadius: - BorderRadius - .circular( - 8.0), - ), - enabledBorder: - OutlineInputBorder( - borderSide: - const BorderSide( - width: 1, - //<-- SEE HERE - color: Colors - .transparent, - ), - borderRadius: - BorderRadius - .circular( - 4.0), - ), - ), - ), + ), + PortraitContainer( + width: double.infinity, + child: Align( + alignment: + Alignment.centerLeft, + child: HeadingText( + AppLocalizations.of( + context)! + .unit_price, ), ), - Container( - padding: - const EdgeInsets.all( - 4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: TextField( - style: const TextStyle( - fontFamily: MyFonts - .DMREGULAR, - fontSize: MyFonts - .normal, - color: MyColors - .black), - decoration: - InputDecoration( - contentPadding: - const EdgeInsets - .fromLTRB( - 4, 0, 4, 0), - hintText: '', - fillColor: MyColors - .fillColor2, - filled: true, - focusedBorder: - OutlineInputBorder( - borderSide: - const BorderSide( - color: Colors - .transparent, - width: - 1.0), - borderRadius: - BorderRadius - .circular( - 8.0), - ), - enabledBorder: - OutlineInputBorder( - borderSide: - const BorderSide( - width: 1, - //<-- SEE HERE - color: Colors - .transparent, - ), - borderRadius: - BorderRadius - .circular( - 4.0), - ), - ), - ), + ), + PortraitContainer( + width: double.infinity, + child: Align( + alignment: + Alignment.centerLeft, + child: HeadingText( + AppLocalizations.of( + context)! + .amount, ), ), - Container( - padding: - const EdgeInsets.all( - 4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - bottom: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: Text( + ), + ], + )), + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + PortraitContainer( + width: double.infinity, + child: getItemsWidget( + position)), + PortraitContainer( + width: double.infinity, + child: getDescriptionWidget( + position), + ), + PortraitContainer( + width: double.infinity, + child: getQuantityWidget( + position), + ), + PortraitContainer( + width: double.infinity, + child: getUnitPriceWidget( + position), + ), + PortraitContainer( + width: double.infinity, + child: Align( + alignment: + Alignment.centerLeft, + child: CustomTextAddProduct( widget - .storeInvoice - .products[ - position] - .amount! - .toStringAsFixed( - 2) ?? - 0.toString(), - style: const TextStyle( - fontFamily: - MyFonts.Bold, - fontWeight: - FontWeight - .bold, - fontSize: 11, - color: MyColors - .textColorBlack20), - ), - ), + .storeInvoice + .products[ + position] + .amount! + .toStringAsFixed( + 2)), ), - ], - )), - ], - ), - )), - SizedBox( - width: 44, - height: 48, - child: Center( - child: Container( - width: 32, - height: 32, - decoration: const BoxDecoration( - borderRadius: - BorderRadius.all( - Radius.circular(4)), - color: - MyColors.fillColorGray2), - child: IconButton( - icon: const Icon( - size: 18, - Icons.close, - color: - MyColors.textColorBlack, ), - onPressed: () { - onRemoveItem(position); - }), - ), - )) - ], - ), - ); + ], + )), + ], + ), + )), + // getRemoveButtonWidget(position) + ], + )); } else { - return Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all( - width: 1, - color: MyColors.fillColorGray2), - color: MyColors.white, - ), + return BorderContainer( + backgroundColor: Colors.transparent, child: Row( children: [ - Container( - padding: const EdgeInsets.only(left: 4), + ChildContainer( width: 84, - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Align( - alignment: Alignment.centerLeft, - child: CheckboxListTile( - value: widget.storeInvoice - .products[position].isChecked, - controlAffinity: - ListTileControlAffinity.leading, - onChanged: (isChecked) { - setState(() { - onCheck(position, isChecked!); - }); - }, - ), - ), + child: returnCheckBoxWidget(position), ), Expanded( - child: Container( - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - height: 48, - padding: const EdgeInsets.all(4), - child: Container( - decoration: BoxDecoration( - border: Border.all( - color: Colors.transparent, - width: 1, - ), - color: MyColors.fillColor2, - borderRadius: - BorderRadius.circular(8.0), - ), - child: Row( - children: [ - Expanded( - child: TextButton( - onPressed: () { - showSheet(position); - }, - child: Align( - alignment: - Alignment.centerLeft, - child: Text( - selectedProduct[position] - .isEmpty - ? 'Choose' - : selectedProduct[ - position], - textAlign: TextAlign.left, - style: const TextStyle( - fontFamily: - MyFonts.Bold, - fontSize: 10, - color: MyColors - .textColorBlack), - ), - ), - )), - const Icon( - // <-- Icon - Icons.arrow_drop_down, - size: 24.0, - color: MyColors.black, - ) - ], - ), - ), + child: ChildContainer( + child: getItemsWidget(position), )), Expanded( - child: Container( - padding: const EdgeInsets.all(4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Container( - padding: - const EdgeInsets.only(left: 4), - decoration: BoxDecoration( - borderRadius: const BorderRadius - .all( - Radius.circular( - 4.0) // <--- border radius here - ), - color: MyColors.disableColor), - child: Align( - alignment: Alignment.centerLeft, - child: Text( - widget - .storeInvoice - .products[position] - .description ?? - "", - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normal, - color: MyColors.black), - ), - ), - ), + child: ChildContainer( + child: getDescriptionWidget(position), )), Expanded( - child: Container( - padding: const EdgeInsets.all(4), - height: 48, + child: ChildContainer( width: 60, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: TextField( - keyboardType: TextInputType.number, - controller: - quantityControllers[position], - onChanged: (value) { - onChangeQuantity(position, value); - }, - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normal, - color: MyColors.black), - decoration: InputDecoration( - contentPadding: - const EdgeInsets.fromLTRB( - 4, 0, 4, 0), - fillColor: MyColors.fillColor2, - filled: true, - focusedBorder: OutlineInputBorder( - borderSide: const BorderSide( - color: Colors.transparent, - width: 1.0), - borderRadius: - BorderRadius.circular(8.0), - ), - enabledBorder: OutlineInputBorder( - borderSide: const BorderSide( - width: 1, //<-- SEE HERE - color: Colors.transparent, - ), - borderRadius: - BorderRadius.circular(4.0), - ), - ), - ), - ), + child: getQuantityWidget(position), )), Expanded( - child: Container( - padding: const EdgeInsets.all(4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Container( - padding: - const EdgeInsets.only(left: 4), - decoration: BoxDecoration( - borderRadius: const BorderRadius - .all( - Radius.circular( - 4.0) // <--- border radius here - ), - color: MyColors.disableColor), - child: Align( - alignment: Alignment.centerLeft, - child: Text( - widget.storeInvoice - .products[position].price! - .toStringAsFixed(2), - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normal, - color: MyColors.black), - ), - ), - ), + child: ChildContainer( + child: getPriceWidget(position), )), - Container( - padding: const EdgeInsets.only(left: 4), + ChildContainer( width: 84, - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), child: Align( alignment: Alignment.centerLeft, - child: Text( - widget.storeInvoice + child: CustomTextAddProduct( + viewModel.storeInvoice .products[position].amount! .toStringAsFixed(2), - style: MyColors.textStyleHeading(), ), ), ), - SizedBox( - width: 44, - height: 48, - child: Center( - child: Container( - width: 32, - height: 32, - decoration: const BoxDecoration( - borderRadius: - BorderRadius.all( - Radius.circular(4)), - color: - MyColors.fillColorGray2), - child: IconButton( - icon: const Icon( - size: 18, - Icons.close, - color: - MyColors.textColorBlack, - ), - onPressed: () { - onRemoveItem(position); - }), - ), - )), + //getRemoveButtonWidget(position) ], ), ); } }, - itemCount: widget.storeInvoice.products.length, + itemCount: viewModel.storeInvoice.products.length, ), - isPortrait - ? Container( - margin: const EdgeInsets.fromLTRB(8, 0, 0, 8), - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all( - width: 1, - color: MyColors.fillColorGray2), - color: Colors.white, - ), - height: 48, + viewModel.isPortrait + ? BorderContainer( + backgroundColor: Colors.transparent, child: Row( children: [ + // getAddButtonWidget(), + SizedBox( + width: 45, + height: 44, + child: HeadingContainer( + heading: '', + )), Expanded( - child: Container( + child: HeadingContainer( height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: Text( - '', - style: MyColors.textStyleValue(), - ), - ), + heading: 'Grand Total', )), Expanded( - child: Container( - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: Text( - getTotalProductsPrice(), - style: MyColors.textStyleValue(), - ), - ), - )), - Center( - child: Container( - margin: const EdgeInsets.all(5), - width: 32, - height: 32, - decoration: const BoxDecoration( - borderRadius: BorderRadius.all( - Radius.circular(4)), - color: MyColors.fillColorGray2), - child: IconButton( - icon: const Icon( - size: 14, - Icons.add, - color: MyColors.textColorBlack, - ), - onPressed: () { - setState(() { - selectedProduct.clear(); - quantityControllers.clear(); - - widget.storeInvoice.products - .add(StoreInvoiceProduct( - totalQuantity: 0, - price: 0.0, - vat: 0, - discountPercentage: 0.0, - tax: 0.0, - amount: 0.0, - )); - }); - }), - ), - ), + child: HeadingContainer( + heading: viewModel + .getTotalProductsPrice())), ], ), ) - : Container( - margin: const EdgeInsets.fromLTRB(0, 0, 0, 8), - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all( - width: 1, - color: MyColors.fillColorGray2), - color: Colors.white, - ), - height: 48, + : BorderContainer( + backgroundColor: Colors.transparent, child: Row( children: [ + HeadingContainer( + width: 84, + heading: '', + ), Expanded( - child: Container( + child: HeadingContainer( height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: Text( - '', - style: MyColors.textStyleValue(), - ), - ), + heading: '', )), Expanded( - child: Container( - padding: const EdgeInsets.only(left: 8), + child: HeadingContainer( height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: Text( - '', - style: MyColors.textStyleValue(), - ), - ), + heading: '', )), Expanded( - child: Container( + child: HeadingContainer( height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: Text( - '', - style: MyColors.textStyleValue(), - ), - ), + heading: '', )), Expanded( - child: Container( + child: HeadingContainer( height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: Text( - '', - style: MyColors.textStyleValue(), - ), - ), + heading: '', )), - Container( + ChildContainer( width: 84, - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: Text( - getTotalProductsPrice(), - style: MyColors.textStyleHeading(), - ), - ), - ), - Center( - child: Container( - margin: const EdgeInsets.all(5), - width: 34, - height: 32, - decoration: const BoxDecoration( - borderRadius: BorderRadius.all( - Radius.circular(4)), - color: MyColors.fillColorGray2), - child: IconButton( - icon: const Icon( - size: 14, - Icons.add, - color: MyColors.textColorBlack, - ), - onPressed: () { - setState(() { - selectedProduct.clear(); - quantityControllers.clear(); - - widget.storeInvoice.products - .add(StoreInvoiceProduct( - totalQuantity: 0, - price: 0.0, - vat: 0, - discountPercentage: 0.0, - tax: 0.0, - amount: 0.0, - )); - }); - }), - ), + child: CustomTextAddProduct( + viewModel.getTotalProductsPrice()), ), + // getAddButtonWidget(), ], ), ), - const SizedBox( - height: 20, - ), + AppSpaces.verticalLarge, Row( children: [ - const Expanded(child: Text('')), + viewModel.isPortrait + ? Container() + : const Expanded(child: Text('')), Expanded( child: Row( children: [ @@ -1428,11 +417,7 @@ class _ReturnInvoiceVCState extends BaseStatefulState { alignment: Alignment.centerRight, child: Text( AppLocalizations.of(context)!.discount, - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.w500, - fontSize: MyFonts.normal, - color: MyColors.textColorBlack20), + style: ThemeText.textStyleAmountHeading, ), )), AppSpaces.horizontalMedium, @@ -1440,12 +425,8 @@ class _ReturnInvoiceVCState extends BaseStatefulState { child: Align( alignment: Alignment.centerRight, child: Text( - getTotalDiscount(), - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.w500, - fontSize: MyFonts.normal, - color: MyColors.textColorBlack20), + viewModel.getTotalDiscount(), + style: ThemeText.textStyleAmountValue, ), )), ], @@ -1455,7 +436,9 @@ class _ReturnInvoiceVCState extends BaseStatefulState { AppSpaces.verticalSmall, Row( children: [ - const Expanded(child: Text('')), + viewModel.isPortrait + ? Container() + : const Expanded(child: Text('')), Expanded( child: Row( children: [ @@ -1464,11 +447,7 @@ class _ReturnInvoiceVCState extends BaseStatefulState { alignment: Alignment.centerRight, child: Text( '${AppLocalizations.of(context)!.tax} (VAT %)', - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.w500, - fontSize: MyFonts.normal, - color: MyColors.textColorBlack20), + style: ThemeText.textStyleAmountHeading, ), )), AppSpaces.horizontalMedium, @@ -1476,12 +455,8 @@ class _ReturnInvoiceVCState extends BaseStatefulState { child: Align( alignment: Alignment.centerRight, child: Text( - getTotalVatDiscount(), - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.w500, - fontSize: MyFonts.normal, - color: MyColors.textColorBlack20), + viewModel.getTotalVatDiscount(), + style: ThemeText.textStyleAmountValue, ), )), ], @@ -1491,7 +466,9 @@ class _ReturnInvoiceVCState extends BaseStatefulState { AppSpaces.verticalSmall, Row( children: [ - const Expanded(child: Text('')), + viewModel.isPortrait + ? Container() + : const Expanded(child: Text('')), Expanded( child: Row( children: [ @@ -1501,11 +478,8 @@ class _ReturnInvoiceVCState extends BaseStatefulState { child: Text( AppLocalizations.of(context)! .total_amount, - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.bold, - fontSize: 13, - color: MyColors.black), + style: + ThemeText.textStyleAmountHeadingBlack, ), )), AppSpaces.horizontalMedium, @@ -1513,13 +487,10 @@ class _ReturnInvoiceVCState extends BaseStatefulState { child: Align( alignment: Alignment.centerRight, child: Text( - widget.storeInvoice.totalAmount! + viewModel.storeInvoice.totalAmount! .toStringAsFixed(2), - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.bold, - fontSize: 13, - color: MyColors.black), + style: + ThemeText.textStyleAmountValueBlack, ), )), ], @@ -1530,74 +501,33 @@ class _ReturnInvoiceVCState extends BaseStatefulState { ), ), ), - const SizedBox( - height: 12, - ), - isLoadingData - ? const Row( + AppSpaces.verticalLarge, + viewModel.isLoadingData + ? Row( crossAxisAlignment: CrossAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end, - children: [ - Center( - child: CircularProgressIndicator(), - ) - ], + children: [AppLoader()], ) - : Row( - crossAxisAlignment: CrossAxisAlignment.end, - mainAxisAlignment: MainAxisAlignment.end, - children: [ - SizedBox( - width: 180, - child: ElevatedButton( - style: ElevatedButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(6.0), - ), - backgroundColor: MyColors.blueThemeColor, - minimumSize: - const Size.fromHeight(38), // NEW - ), - onPressed: () { - _update(); - }, - child: Text( - widget.isReturn - ? 'Return whole order' - : "Damage whole order", - style: const TextStyle( - fontSize: MyFonts.normalButton, - color: MyColors.white, - fontFamily: MyFonts.Bold), - ), - )), - const SizedBox( - width: 12, - ), - SizedBox( - width: 100, - child: ElevatedButton( - style: ElevatedButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(6.0), - ), - backgroundColor: MyColors.blueThemeColor, - minimumSize: const Size.fromHeight(38), // NEW - ), - onPressed: () { - returnInvoice(); - }, - child: Text( - AppLocalizations.of(context)!.save, - style: const TextStyle( - fontSize: MyFonts.normalButton, - color: MyColors.white, - fontFamily: MyFonts.Bold), + : viewModel.isPortrait + ? Column( + children: [ + getWholeOrderButton(), + getOnlyItemsButton() + ], + ) + : Row( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + SizedBox( + width: 180, child: getWholeOrderButton()), + AppSpaces.horizontalMedium, + SizedBox( + width: 180, + child: getOnlyItemsButton(), ), - ), + ], ) - ], - ) ], ), ), @@ -1605,196 +535,129 @@ class _ReturnInvoiceVCState extends BaseStatefulState { })); } - Future returnInvoice() async { - bool isChecked = false; - for (var product in widget.storeInvoice.products) { - isChecked = product.isChecked!; - if (isChecked) { - break; - } - } - - if (!isChecked) { - showMessage('Please select item for return'); - } else { - for (var product in widget.storeInvoice.products) { - isChecked = product.isChecked!; - } - if (widget.storeInvoice.products.length == 1) { - _update(); - return; - } - - if (isChecked) { - _update(); - return; - } - - getTotalProductsPrice(); - getTotalDiscount(); - getTotalVatDiscount(); - returnDamageOrder.status = widget.isReturn ? 'Return' : 'Damage'; - setState(() { - isLoadingData = true; - }); - log(returnDamageOrder.toJson().toString()); - await viewModel - .getData(Constants.RETURN_OR_DAMAGE + widget.storeInvoice.id!, - returnDamageOrder.toJson()) - .then((value) { - setState(() { - isLoadingData = false; - }); - final response = SimpleResponseModel.fromJson(value); - if (response.success!) { - Navigator.pop(context, true); - } - }).onError((error, stackTrace) { - print('bestSeller ' + error.toString()); - }); + void checkState() { + if (viewModel.crudOperation == CRUDOperationState.update) { + Navigator.pop(context, true); } } - Future _update() async { - setState(() { - isLoadingData = true; - }); + getItemsWidget(int position) { + return CustomTextButtonIcon( + backgroundColor: MyColors.backFillColor, + onPressed: () { + showSheet(position); + }, + heading: viewModel.selectedProduct[position].isEmpty + ? 'Choose' + : viewModel.selectedProduct[position], + icon: Icons.arrow_drop_down); + } - Map data = { - 'invoiceId': widget.storeInvoice.id!, - 'status': widget.isReturn ? 'Return' : 'Damage' - }; - final response = - await viewModel.getResponsePatch(Constants.UPDATE_INVOICE, data); - setState(() { - isLoadingData = false; - }); + void showSheet(int index) async { + final result = await showDialog( + barrierColor: Colors.black26, + context: context, + builder: (context) { + return const SearchProductVC(); + }, + ); - if (response.success!) { - Navigator.pop(context, true); + if (!mounted) return; + try { + viewModel.updateProduct(result, index); + } catch (e) { + print(e); } } - void onRemoveItem(int position) { - setState(() { - selectedProduct.clear(); - quantityControllers.clear(); - if (widget.storeInvoice.products.length > 1) { - returnDamageOrder.details.add(widget.storeInvoice.products[position]); - - widget.storeInvoice.products.removeAt(position); - returnDamageOrder.returnDamageOrderDetails.removeAt(position); - } + getRemoveButtonWidget(int position) { + return CustomRemoveItemButton(onPressed: () { + viewModel.onRemoveItem(position); }); } - String getTotalProductsPrice() { - var price = 0.0; - for (var product in widget.storeInvoice.products) { - price += product.amount ?? 0.0; - } - returnDamageOrder.total!.totalAmount = price; - widget.storeInvoice.totalAmount = price; - returnDamageOrder.total!.totalExcludingAmount = price; - returnDamageOrder.total!.totalTaxableAmount = price; - return price.toStringAsFixed(2); + returnCheckBoxWidget(int position) { + return Align( + alignment: Alignment.center, + child: CustomCheckBox( + value: viewModel.storeInvoice.products[position].isChecked ?? false, + onChange: (bool? value) { + viewModel.onCheck(position, value ?? false); + }, + ), + ); } - String getTotalDiscount() { - var price = 0.0; - for (var product in widget.storeInvoice.products) { - if (product.discountPercentage != null) { - try { - price += product.discountPercentage!; - } catch (e) { - price += product.discountPercentage!; - } - } - } - returnDamageOrder.total!.totalDiscount = price; - widget.storeInvoice.totalDiscount = price; - return price.toStringAsFixed(2); + getQuantityWidget(int position) { + return Center( + child: CustomTextFieldForm( + keyboardType: TextInputType.number, + initialValue: viewModel.quantityControllers[position], + onChanged: (value) { + viewModel.onChangeQuantity(position, value); + }, + hintText: '', + ), + ); } - String getTotalVatDiscount() { - var price = 0.0; - for (var product in widget.storeInvoice.products) { - price += product.tax ?? 0.0; - } - returnDamageOrder.total!.totalVat = price; - widget.storeInvoice.totalTaxExcluding = price; - return price.toStringAsFixed(2); + getUnitPriceWidget(int position) { + return Center( + child: CustomTextFieldForm( + onChanged: (String value) {}, + hintText: '', + ), + ); } - double getTaxCalu(int position) { - var totalQuantity = int.parse(quantityControllers[position].text); - double totalPrice = - totalQuantity * widget.storeInvoice.products[position].price!; - var tax = (totalPrice * widget.storeInvoice.products[position].vat!); - tax = tax / 100; + getDescriptionWidget(int position) { + return TransparentBorderContainer( + backgroundColor: MyColors.disableColor, + child: Align( + alignment: Alignment.centerLeft, + child: CustomTextAddProduct( + viewModel.storeInvoice.products[position].description ?? "", + ), + ), + ); + } - return tax; + getPriceWidget(int position) { + return TransparentBorderContainer( + backgroundColor: MyColors.disableColor, + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText(viewModel.storeInvoice.products[position].price! + .toStringAsFixed(2)), + ), + ); } - void onChangeQuantity(int position, String value) { - setState(() { - final unitPrice = - widget.storeInvoice.products[position].price!; // 1 pece value - final discount = - widget.storeInvoice.products[position].discountPercentage ?? 0.0; - if (discount > 0) { - widget.storeInvoice.products[position].amount = - int.parse(value) * unitPrice - discount; - } else { - widget.storeInvoice.products[position].amount = - int.parse(value) * unitPrice; - } - var tax = getTaxCalu(position); - widget.storeInvoice.products[position].tax = tax; - widget.storeInvoice.products[position].amount = - widget.storeInvoice.products[position].amount! + - widget.storeInvoice.products[position].tax!; + getAddButtonWidget() { + return CustomAddButton(onPressed: () { + viewModel.onAddNewProduct(); }); } - void showSheet(int index) async { - final result = await showDialog( - barrierColor: Colors.black26, - context: context, - builder: (context) { - return const SearchProductVC(); - }, - ); - - if (!mounted) return; - try { - // setState(() { - // ProductItem response = result; - // selectedProduct[index] = response.name!; - // final item = addInvoice.products[index]; - // item.price = response.price!; - // item.amount = (response.price! * response.total_quantity!).toDouble(); - // item.name = response.name; - // item.itemId = response.id; - // // addInvoice.products[index] = item; - // item.totalQuantity = response.total_quantity; - // // descriptionsControllers[index].text = response.details!; - // quantityControllers[index].text = response.total_quantity!.toString(); - // // uniPriceControllers[index].text = response.price!.toString(); - // }); - } catch (e) { - print(e); - } + getOnlyItemsButton() { + return CustomSimpleButton( + textColor: MyColors.white, + backGroundColor: MyColors.blueThemeColor, + onPressed: () async { + await viewModel.returnInvoice(); + checkState(); + }, + heading: viewModel.isReturn ? 'Return Items' : "Damage Items"); } - void onCheck(int position, bool isChecked) { - widget.storeInvoice.products[position].isChecked = isChecked; - - if (isChecked) { - returnDamageOrder.details.add(widget.storeInvoice.products[position]); - } else { - returnDamageOrder.details.removeWhere((element) => - element.itemId! == widget.storeInvoice.products[position].itemId!); - } + getWholeOrderButton() { + return CustomSimpleButton( + textColor: MyColors.white, + backGroundColor: MyColors.blueThemeColor, + onPressed: () async { + await viewModel.update(); + checkState(); + }, + heading: viewModel.isReturn ? 'Return Invoice' : "Damage Invoice"); } } diff --git a/lib/application/views/salesandordermodule/views/invoiceModule/InvoicesVC.dart b/lib/application/views/salesandordermodule/views/invoiceModule/InvoicesVC.dart deleted file mode 100644 index b2cb8b0..0000000 --- a/lib/application/views/salesandordermodule/views/invoiceModule/InvoicesVC.dart +++ /dev/null @@ -1,893 +0,0 @@ -import 'package:dropdown_search/dropdown_search.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:provider/provider.dart'; -import 'package:sizer/sizer.dart'; -import 'package:wosull/application/enum/DataState.dart'; -import 'package:wosull/application/model/converters/DataTimeFormat.dart'; -import 'package:wosull/application/model/invoice/StoreInvoice.dart'; -import 'package:wosull/application/model/store/StoreInvoicesModel.dart'; -import 'package:wosull/application/network/APIManager.dart'; -import 'package:wosull/application/theme/MyColors.dart'; -import 'package:wosull/application/theme/MyFonts.dart'; -import 'package:wosull/application/utils/AppError.dart'; -import 'package:wosull/application/utils/AppLoader.dart'; -import 'package:wosull/application/utils/Constants.dart'; -import 'package:wosull/application/views/popups/DeleteRecordPopUp.dart'; -import 'package:wosull/application/views/salesandordermodule/viewModel/InvoiceViewModel.dart'; -import 'package:wosull/application/views/salesandordermodule/views/AddInvoiceAndPrintVC.dart'; -import 'package:wosull/application/views/salesandordermodule/views/ReturnInvoiceVC.dart'; -import 'package:wosull/application/views/salesandordermodule/views/invoiceModule/NewInvoiceVC.dart'; -import 'package:wosull/base/BaseStatefulState.dart'; -import 'package:wosull/helpers/AppSpaces.dart'; -import 'package:wosull/helpers/ThemeText.dart'; -import 'package:wosull/widgets/CustomSimpleButton.dart'; -import 'package:wosull/widgets/EmptyDataWidget.dart'; -import 'package:wosull/widgets/ValueText.dart'; - -class InvoicesVC extends StatefulWidget { - const InvoicesVC({Key? key}) : super(key: key); - - @override - State createState() => _InvoicesVCState(); -} - -class _InvoicesVCState extends BaseStatefulState { - bool isPortrait = true; - - final viewModel = InvoiceViewModel(); - - late ScrollController _controller; - - @override - void initState() { - super.initState(); - } - - @override - Widget build(BuildContext context) { - _controller = ScrollController()..addListener(_scrollNotification); - return Scaffold( - backgroundColor: MyColors.fillColor, - resizeToAvoidBottomInset: true, - body: OrientationBuilder(builder: (c, orientation) { - isPortrait = MediaQuery.of(c).orientation == Orientation.portrait; - - return SingleChildScrollView( - controller: _controller, - child: Container( - padding: const EdgeInsets.all(12), - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Text( - AppLocalizations.of(context)!.invoices, - style: ThemeText.textStylePageHeading, - ), - const SizedBox( - width: 8, - ), - Container( - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - ), - height: 42, - padding: const EdgeInsets.only(left: 8, right: 0), - width: SizerUtil.deviceType == DeviceType.mobile - ? 120 - : 100, - child: DropdownSearch( - popupProps: const PopupProps.menu( - constraints: BoxConstraints(maxHeight: 200), - ), - items: Constants.invoiceFilterType, - itemAsString: (String u) => u, - onChanged: (String? data) { - viewModel.fetch(isRefresh: true, filter: data!); - }, - dropdownDecoratorProps: const DropDownDecoratorProps( - baseStyle: TextStyle( - fontFamily: MyFonts.Bold, - fontSize: 11, - color: MyColors.textColorBlack), - dropdownSearchDecoration: InputDecoration( - border: InputBorder.none, hintText: 'All'), - ), - ), - ), - const SizedBox( - width: 8, - ), - SizedBox( - width: 120, - child: CustomSimpleButton( - height: 42, - textColor: MyColors.blueThemeColor, - backGroundColor: MyColors.backColorBlue50, - onPressed: () { - newInvoice(false, StoreInvoice(products: [])); - }, - heading: AppLocalizations.of(context)!.new_invoices, - ), - ), - ], - ), - AppSpaces.verticalLarge, - ChangeNotifierProvider( - create: (context) => viewModel, - child: Consumer( - builder: (BuildContext context, - InvoiceViewModel controller, Widget? _) { - switch (controller.dataState) { - case DataState.uninitialized: - Future(() { - controller.fetch(); - }); - return showData(controller.filteredList); - case DataState.initialFetching: - return AppLoader(); - case DataState.moreFetching: - case DataState.refreshing: - return showData(controller.filteredList); - case DataState.error: - return AppError(); - case DataState.searching: - case DataState.fetched: - case DataState.noMoreData: - return showData(controller.filteredList); - } - }, - ), - ), - ], - ), - ), - ); - })); - } - - Widget showData(List data) { - return Column( - children: [ - data.isEmpty - ? const EmptyDataWidget() - : Column( - children: [ - isPortrait - ? Container() - : Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 50, - color: MyColors.containerBackColor, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - Expanded( - child: Text( - AppLocalizations.of(context)!.number, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 10, - fontWeight: FontWeight.w300, - color: MyColors.black), - )), - Expanded( - child: Text( - AppLocalizations.of(context)!.reference_no, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 10, - fontWeight: FontWeight.w300, - color: MyColors.black), - )), - Expanded( - child: Text( - AppLocalizations.of(context)!.bill_to, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 10, - fontWeight: FontWeight.w300, - color: MyColors.black), - )), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)!.invoice_date, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 10, - fontWeight: FontWeight.w300, - color: MyColors.black), - ), - )), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .invoice_due_Date, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 10, - fontWeight: FontWeight.w300, - color: MyColors.black), - ), - )), - Expanded( - child: Align( - alignment: Alignment.center, - child: Text( - AppLocalizations.of(context)!.amount, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 10, - fontWeight: FontWeight.w300, - color: MyColors.black), - ), - )), - Container( - width: 120, - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .switch_status, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 10, - fontWeight: FontWeight.w300, - color: MyColors.black), - ), - )), - const SizedBox( - width: 10, - ), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)!.status, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 10, - fontWeight: FontWeight.w300, - color: MyColors.black), - ), - )), - const SizedBox( - width: 10, - ), - Container( - width: 46, - child: Text( - AppLocalizations.of(context)!.action, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 10, - fontWeight: FontWeight.w300, - color: MyColors.black), - ), - ), - ], - ), - ), - ListView.builder( - padding: EdgeInsets.zero, - scrollDirection: Axis.vertical, - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - itemBuilder: (c, position) { - final invoice = data[position]; - if (isPortrait) { - return Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - child: Container( - padding: const EdgeInsets.fromLTRB(16, 0, 0, 16), - color: MyColors.containerBackColor, - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Expanded( - flex: 2, - child: Container( - padding: const EdgeInsets.only(top: 16), - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.start, - children: [ - Row( - children: [ - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .number, - style: MyColors - .textStyleHeading(), - ), - )), - Expanded( - child: Align( - alignment: - Alignment.centerRight, - child: Text( - invoice.invoiceNumber! - .toString(), - style: - MyColors.textStyleValue(), - ), - )) - ], - ), - Row( - children: [ - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .reference_no, - style: MyColors - .textStyleHeading(), - ), - )), - Expanded( - child: Align( - alignment: - Alignment.centerRight, - child: Text( - invoice.invoiceReference! - .toString(), - style: - MyColors.textStyleValue(), - ), - )) - ], - ), - Row( - children: [ - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .bill_to, - style: MyColors - .textStyleHeading(), - ), - )), - Expanded( - child: Align( - alignment: - Alignment.centerRight, - child: Text( - invoice.supplier!.name ?? "", - style: - MyColors.textStyleValue(), - ), - )) - ], - ), - Row( - children: [ - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .invoice_date, - style: MyColors - .textStyleHeading(), - ), - )), - Expanded( - child: Align( - alignment: - Alignment.centerRight, - child: Text( - DataTimeFormat.getFormatDate( - invoice.invoiceDate!), - style: - MyColors.textStyleValue(), - ), - )) - ], - ), - Row( - children: [ - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .invoice_due_Date, - style: MyColors - .textStyleHeading(), - ), - )), - Expanded( - child: Align( - alignment: - Alignment.centerRight, - child: Text( - DataTimeFormat.getFormatDate( - invoice.invoiceDueDate!), - style: - MyColors.textStyleValue(), - ), - )) - ], - ), - Row( - children: [ - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .amount, - style: MyColors - .textStyleHeading(), - ), - )), - Expanded( - child: Align( - alignment: - Alignment.centerRight, - child: Text( - invoice.totalAmount! - .toStringAsFixed(2), - style: - MyColors.textStyleValue(), - ), - )) - ], - ), - Row( - children: [ - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .status, - style: MyColors - .textStyleHeading(), - ), - )), - Expanded( - child: Align( - alignment: - Alignment.centerRight, - child: Text( - invoice.status!.toString(), - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: - FontWeight.w500, - fontSize: MyFonts.normal, - color: - MyColors.greenColor), - ), - )) - ], - ), - Row( - children: [ - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .switch_status, - style: MyColors - .textStyleHeading(), - ), - )), - Expanded( - child: Align( - alignment: - Alignment.centerRight, - child: Container( - decoration: BoxDecoration( - color: MyColors.fillColor, - borderRadius: - BorderRadius.circular( - 8), - ), - height: 38, - padding: - const EdgeInsets.only( - left: 8, right: 8), - width: SizerUtil.deviceType == - DeviceType.mobile - ? 120 - : 100, - child: DropdownButton( - hint: const Text('Select'), - style: MyColors - .textStyleValue(), - isExpanded: true, - underline: - DropdownButtonHideUnderline( - child: Container()), - items: Constants - .invoiceStatusType - .map((String items) { - return DropdownMenuItem( - value: items, - child: ValueText(items), - ); - }).toList(), - onChanged: (Object? value) { - _update(invoice.id!, - value.toString()); - }, - ), - ), - )) - ], - ), - ], - ), - )), - PopupMenuButton( - icon: const Icon(Icons.more_vert), - itemBuilder: (c) { - return [ - PopupMenuItem( - value: 'edit', - child: ValueText( - AppLocalizations.of(context)!.edit, - ), - ), - PopupMenuItem( - value: 'return', - child: ValueText( - AppLocalizations.of(context)! - .return_txt, - ), - ), - PopupMenuItem( - value: 'damage', - child: ValueText( - "Damage", - ), - ), - PopupMenuItem( - value: 'view', - child: ValueText( - AppLocalizations.of(context)! - .print_or_download, - ), - ), - PopupMenuItem( - value: 'delete', - child: ValueText( - AppLocalizations.of(context)!.delete, - ), - ) - ]; - }, - onSelected: (String value) => - actionPopUpItemSelected(value, invoice), - ) - ], - ), - ), - ); - } else { - return Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - child: Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 56, - color: MyColors.containerBackColor, - child: Row( - children: [ - Expanded( - child: Text( - invoice.invoiceNumber.toString(), - style: MyColors.textStyleValue())), - Expanded( - child: Text( - invoice.invoiceReference.toString(), - style: MyColors.textStyleValue(), - )), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - invoice.supplier != null - ? invoice.supplier!.name ?? "" - : invoice.customer!.name ?? '', - style: MyColors.textStyleValue(), - ), - )), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - DataTimeFormat.getFormatDate( - invoice.invoiceDate!), - style: MyColors.textStyleValue(), - ), - )), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - DataTimeFormat.getFormatDate( - invoice.invoiceDueDate!), - style: MyColors.textStyleValue(), - ), - ), - ), - Expanded( - child: Align( - alignment: Alignment.center, - child: Text( - invoice.totalAmount!.toStringAsFixed(2), - style: MyColors.textStyleValue(), - ), - )), - SizedBox( - width: 120, - child: Align( - alignment: Alignment.centerLeft, - child: Container( - decoration: BoxDecoration( - color: MyColors.fillColor, - borderRadius: - BorderRadius.circular(8), - ), - height: 38, - padding: const EdgeInsets.only( - left: 8, right: 8), - width: 120, - child: DropdownButton( - hint: ValueText('Select'), - style: MyColors.textStyleValue(), - isExpanded: true, - underline: - DropdownButtonHideUnderline( - child: Container()), - items: Constants.invoiceStatusType - .map((String items) { - return DropdownMenuItem( - value: items, - child: ValueText(items), - ); - }).toList(), - onChanged: (Object? value) { - _update( - invoice.id!, value.toString()); - }, - ), - ), - )), - const SizedBox( - width: 16, - ), - Expanded( - child: Container( - height: 38, - decoration: const BoxDecoration( - color: MyColors.greenColor10, - borderRadius: BorderRadius.all( - Radius.circular(10.0))), - child: Padding( - padding: const EdgeInsets.all(10.0), - child: Center( - child: Text( - invoice.status!, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: MyFonts.normal, - fontWeight: FontWeight.w700, - color: MyColors.greenColor), - ), - ))), - ), - Padding( - padding: const EdgeInsets.all(4), - child: Align( - alignment: Alignment.centerRight, - child: Container( - width: 42, - height: 42, - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular(4)), - color: MyColors.backFillColor), - child: PopupMenuButton( - padding: EdgeInsets.zero, - icon: const Icon(Icons.more_vert), - itemBuilder: (c) { - return [ - PopupMenuItem( - value: 'edit', - child: ValueText( - AppLocalizations.of(context)! - .edit, - ), - ), - PopupMenuItem( - value: 'return', - child: ValueText( - AppLocalizations.of(context)! - .return_txt, - ), - ), - PopupMenuItem( - value: 'damage', - child: ValueText( - 'Damage', - ), - ), - PopupMenuItem( - value: 'view', - child: ValueText( - AppLocalizations.of(context)! - .print_or_download, - ), - ), - PopupMenuItem( - value: 'delete', - child: ValueText( - AppLocalizations.of(context)! - .delete, - ), - ) - ]; - }, - onSelected: (String value) => - actionPopUpItemSelected( - value, invoice), - ), - ), - ), - ) - ], - ), - ), - ); - } - }, - itemCount: data.length, - ), - ], - ), - if (viewModel.dataState == DataState.moreFetching) AppLoader(), - ], - ); - } - - bool _scrollNotification() { - if (!viewModel.isLoading && _controller.position.extentAfter < 300) { - viewModel.fetch(); - } - return true; - } - - Future _delete(String id) async { - progressDialogue(context); - await viewModel.delete(id); - hideProgressBar(); - } - - Future _update(String id, String value) async { - progressDialogue(context); - await viewModel.update(id, value); - hideProgressBar(); - } - - Future actionPopUpItemSelected( - String value, StoreInvoice invoice) async { - if (value == 'edit') { - newInvoice(true, invoice); - } else if (value == 'return') { - final result = await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => ReturnInvoiceVC( - storeInvoice: invoice, - isReturn: true, - )), - ); - if (!mounted) return; - if (result) { - viewModel.fetch(isRefresh: true); - } - } else if (value == 'damage') { - final result = await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => ReturnInvoiceVC( - storeInvoice: invoice, - isReturn: false, - )), - ); - if (!mounted) return; - if (result) { - viewModel.fetch(isRefresh: true); - } - } else if (value == 'delete') { - final result = await showDialog( - barrierColor: Colors.black26, - context: context, - builder: (context) { - return const DeleteRecordPopUp(); - }, - ); - - if (!mounted) return; - if (result) { - _delete(invoice.id!); - } - } else { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => AddInvoiceAndPrintVC(id: invoice.id!)), - ); - } - } - - void newInvoice(bool isEdit, StoreInvoice invoice) async { - if (isEdit) { - progressDialogue(context); - await APIManager() - .getResponseAuth("${Constants.GET_INVOICE_BY_ID}/${invoice.id}") - .then((value) async { - hideProgressBar(); - final response = StoreInvoicesByIdModel.fromJson(value); - if (response.success!) { - toNewInvoice(isEdit, response.invoice!); - } - }).onError((error, stackTrace) { - print(error.toString()); - hideProgressBar(); - }); - } else { - toNewInvoice(isEdit, invoice); - } - } - - void toNewInvoice(bool isEdit, StoreInvoice invoice) async { - final result = await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => NewInvoiceVC( - isEdit: isEdit, - storeInvoice: invoice, - )), - ); - - if (!mounted) return; - if (result != null) {} - viewModel.fetch(isRefresh: true); - } -} diff --git a/lib/application/views/salesandordermodule/views/invoiceModule/NewInvoiceVC.dart b/lib/application/views/salesandordermodule/views/invoiceModule/NewInvoiceVC.dart deleted file mode 100644 index 936a864..0000000 --- a/lib/application/views/salesandordermodule/views/invoiceModule/NewInvoiceVC.dart +++ /dev/null @@ -1,2845 +0,0 @@ -import 'dart:math'; - -import 'package:dropdown_search/dropdown_search.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:wosull/application/ViewModel/InventoryViewModel.dart'; -import 'package:wosull/application/localdb/SharedPrefs.dart'; -import 'package:wosull/application/model/StockTransfer/ProductItemCategoryModel.dart'; -import 'package:wosull/application/model/WosulSettings.dart'; -import 'package:wosull/application/model/converters/DataTimeFormat.dart'; -import 'package:wosull/application/model/inventory/InventoryMeasurementModel.dart'; -import 'package:wosull/application/model/invoice/StoreInvoice.dart'; -import 'package:wosull/application/model/store/GetStoreCurrency.dart'; -import 'package:wosull/application/model/store/StoreInvoicesModel.dart'; -import 'package:wosull/application/network/APIManager.dart'; -import 'package:wosull/application/theme/MyColors.dart'; -import 'package:wosull/application/theme/MyFonts.dart'; -import 'package:wosull/application/utils/AppLoader.dart'; -import 'package:wosull/application/utils/Constants.dart'; -import 'package:wosull/base/BaseStatefulState.dart'; -import 'package:wosull/helpers/AppSpaces.dart'; -import 'package:wosull/helpers/ThemeDropDown.dart'; -import 'package:wosull/helpers/ThemeText.dart'; -import 'package:wosull/widgets/CustomOptionalTitle.dart'; -import 'package:wosull/widgets/CustomSimpleButton.dart'; -import 'package:wosull/widgets/CustomSwitch.dart'; -import 'package:wosull/widgets/CustomTextButtonIcon.dart'; -import 'package:wosull/widgets/CustomTextFieldForm.dart'; -import 'package:wosull/widgets/HeadingContainer.dart'; -import 'package:wosull/widgets/MandatoryTitleText.dart'; - -import '../../../../model/customers/GetStoreCustomer.dart'; -import '../../../../model/discount/StoreDiscountModel.dart'; -import '../../../inventorymodule/productviews/SearchProductVC.dart'; -import '../AddInvoiceAndPrintVC.dart'; - -class NewInvoiceVC extends StatefulWidget { - StoreInvoice storeInvoice; - - bool isEdit = false; - - NewInvoiceVC({Key? key, required this.isEdit, required this.storeInvoice}) - : super(key: key); - - @override - State createState() => _NewInvoiceVCState(); -} - -class _NewInvoiceVCState extends BaseStatefulState { - bool isPortrait = true; - - final viewModel = InventoryViewModel(); - late StoreInvoice addInvoice = StoreInvoice(products: []); - - //var selectedSupplier; - List selectedProduct = []; - - var isLoadingFirst = false; - var isLoadingData = false; - - List selectedDiscount = []; - List selectedMeasurement = []; - List selectedTax = []; - var selectedCurrency; - var selectedCustomerCompany; - var selectedStatus; - var statusTypes = [ - 'Open', - 'Paid Partially', - 'Paid', - 'Cancelled', - ]; - var selectedInvoiceFor = "Customer"; - var chooseInvoiceForTypes = [ - 'Customer', - 'Company', - ]; - - @override - void initState() { - // TODO: implement initState - super.initState(); - if (widget.isEdit) { - setState(() { - isLoadingFirst = true; - }); - addInvoice = widget.storeInvoice; - if (widget.storeInvoice.supplier != null) { - selectedCustomerCompany = StoreCustomer( - id: widget.storeInvoice.supplier!.id ?? "", - name: widget.storeInvoice.supplier!.name ?? "Choose"); - addInvoice.customerId = widget.storeInvoice.supplier!.id ?? ""; - } else if (widget.storeInvoice.customer != null) { - selectedCustomerCompany = StoreCustomer( - id: widget.storeInvoice.customer!.id ?? "", - name: widget.storeInvoice.customer!.name ?? "Choose"); - addInvoice.customerId = widget.storeInvoice.customer!.id ?? ""; - } - - if (widget.storeInvoice.invoiceFor!.isNotEmpty) { - selectedInvoiceFor = widget.storeInvoice.invoiceFor!.first; - } - - for (var product in addInvoice.products) { - selectedProduct.add(widget.isEdit ? product.name ?? '' : ''); - selectedDiscount.add(StoreDiscount( - categories: [], - products: [], - discountPercentage: widget.isEdit - ? product.discountPercentage?.toString() ?? '' - : "0.0")); - selectedTax.add(VAT( - name: 'VAT', - value: widget.isEdit ? product.vat?.toString() ?? '' : "0.0")); - selectedMeasurement.add(Measurement( - name: widget.isEdit ? product.measurement ?? '' : "Choose")); - } - - setState(() { - isLoadingFirst = false; - }); - } else { - addInvoice.products.add(StoreInvoiceProduct( - totalQuantity: 0, - price: 0.0, - vat: 0, - discountPercentage: 0.0, - tax: 0.0, - amount: 0.0, - )); - - selectedProduct.add(''); - selectedDiscount.add(StoreDiscount( - categories: [], products: [], discountPercentage: "Choose")); - - selectedTax.add(VAT(name: 'VAT', value: "Choose")); - - selectedMeasurement.add(Measurement(name: "Choose")); - getRandomNumber(); - getRandomInvoiceRef(); - } - } - - void getRandomNumber() { - setState(() { - var rng = Random(); - var code = rng.nextInt(900000) + 100000; - addInvoice.invoiceNumber = code; - }); - } - - void getRandomInvoiceRef() { - setState(() { - var rng = Random(); - var code = rng.nextInt(900000) + 100000; - addInvoice.invoiceReference = code.toString(); - }); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - resizeToAvoidBottomInset: true, - appBar: AppBar( - leading: BackButton( - color: Colors.black, - onPressed: () { - Navigator.pop(context); - }, // <-- SEE HERE - ), - centerTitle: true, - title: Text( - widget.isEdit - ? AppLocalizations.of(context)!.edit_invoice - : AppLocalizations.of(context)!.add_invoice, - style: ThemeText.textStylePopUpHeading, - ), - backgroundColor: MyColors.white, - elevation: 5, - ), - body: OrientationBuilder(builder: (c, orientation) { - isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; - return SingleChildScrollView( - child: Container( - color: MyColors.white, - padding: const EdgeInsets.all(4), - child: isLoadingFirst - ? const Center( - child: CircularProgressIndicator(), - ) - : Column( - children: [ - Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - child: Padding( - padding: const EdgeInsets.all(15), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - Expanded( - flex: 1, - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - getChooseInvoiceFor(), - AppSpaces.verticalLarge, - getInvoiceDate(), - AppSpaces.verticalLarge, - getDefaultStatus(), - isPortrait - ? Column( - crossAxisAlignment: - CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.start, - children: [ - AppSpaces.verticalLarge, - getInvoiceFor(), - AppSpaces.verticalLarge, - getInvoiceNumber(), - AppSpaces.verticalLarge, - getInvoiceDueDate(), - AppSpaces.verticalLarge, - getInvoiceReferNo(), - AppSpaces.verticalLarge, - getDefaultStatus(), - AppSpaces.verticalLarge, - getVatNumber(), - ], - ) - : Container() - ], - ), - ), - isPortrait - ? Container() - : AppSpaces.horizontalMedium, - isPortrait - ? Container() - : Expanded( - flex: 2, - child: Column( - mainAxisAlignment: - MainAxisAlignment.start, - children: [ - Row( - crossAxisAlignment: - CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment - .start, - children: [ - getInvoiceFor(), - AppSpaces.verticalLarge, - getInvoiceDueDate(), - AppSpaces.verticalLarge, - CustomOptionalTitle( - hint: AppLocalizations - .of(context)! - .currency), - AppSpaces.verticalSmall, - getSelectedCurrencyDropdown() - ], - )), - AppSpaces.horizontalMedium, - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment - .start, - children: [ - getInvoiceNumber(), - AppSpaces.verticalLarge, - getInvoiceReferNo(), - AppSpaces.verticalLarge, - getVatNumber() - ], - )), - ], - ), - ], - )), - ], - ), - AppSpaces.verticalLarge, - Row( - children: [ - CustomSwitch( - value: addInvoice.productStock ?? false, - onToggle: (value) { - setState(() { - addInvoice.productStock = value; - }); - }, - ), - AppSpaces.horizontalSmall, - Text( - AppLocalizations.of(context)! - .update_product_stock, - style: const TextStyle( - fontSize: MyFonts.normalButton, - fontFamily: MyFonts.Medium, - color: MyColors.black), - ), - ], - ), - AppSpaces.verticalMedium, - Text( - AppLocalizations.of(context)! - .option_enable_product_invoice, - style: const TextStyle( - fontSize: MyFonts.normalButton, - fontFamily: MyFonts.Medium, - color: MyColors.black), - ), - ], - ), - ), - ), - AppSpaces.verticalLarge, - Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - child: Padding( - padding: const EdgeInsets.all(15), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - CustomOptionalTitle( - hint: AppLocalizations.of(context)!.terms, - ), - AppSpaces.verticalSmall, - CustomTextFieldForm( - height: 100, - maxLines: 5, - initialValue: addInvoice.terms ?? '', - onChanged: (value) {}, - hintText: AppLocalizations.of(context)!.terms) - ], - ), - ), - ), - AppSpaces.verticalLarge, - Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(4.0), - ), - child: Container( - padding: const EdgeInsets.all(3), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Text( - AppLocalizations.of(context)! - .search_and_add_products, - style: const TextStyle( - color: MyColors.textColorBlack, - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.bold, - fontSize: 14), - ), - const SizedBox( - height: 12, - ), - isPortrait - ? Container() - : Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all( - width: 1, - color: MyColors.fillColorGray2), - color: MyColors.backFillColor, - ), - height: 48, - child: Row( - children: [ - HeadingContainer( - heading: - AppLocalizations.of(context)! - .name_or_barcode, - height: 48, - width: 110, - ), - HeadingContainer( - heading: - AppLocalizations.of(context)! - .description, - height: 48, - width: 100, - ), - HeadingContainer( - heading: - AppLocalizations.of(context)! - .quantity, - height: 48, - width: 60, - ), - HeadingContainer( - heading: - AppLocalizations.of(context)! - .unit_price, - height: 48, - width: 80, - ), - Expanded( - child: HeadingContainer( - heading: - AppLocalizations.of(context)! - .discount_type, - ), - ), - Expanded( - child: HeadingContainer( - heading: - AppLocalizations.of(context)! - .discount, - ), - ), - Expanded( - child: HeadingContainer( - heading: - AppLocalizations.of(context)! - .select_tax, - ), - ), - Expanded( - child: HeadingContainer( - heading: - AppLocalizations.of(context)! - .measurement, - ), - ), - HeadingContainer( - heading: 'Tax %', - ), - HeadingContainer( - heading: - AppLocalizations.of(context)! - .amount, - width: 54, - height: 48, - ), - HeadingContainer( - heading: '', - width: 44, - height: 48, - ), - ], - ), - ), - ListView.builder( - padding: EdgeInsets.zero, - scrollDirection: Axis.vertical, - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - itemBuilder: (c, position) { - if (isPortrait) { - return Container( - padding: - const EdgeInsets.fromLTRB(8, 0, 0, 8), - color: MyColors.containerBackColor, - child: Row( - crossAxisAlignment: - CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.start, - children: [ - Expanded( - flex: 2, - child: Container( - padding: const EdgeInsets.only( - top: 8), - child: Row( - crossAxisAlignment: - CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.start, - children: [ - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment - .start, - mainAxisAlignment: - MainAxisAlignment - .start, - children: [ - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - left: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: Alignment - .centerLeft, - child: Text( - AppLocalizations.of( - context)! - .name_or_barcode, - style: const TextStyle( - fontFamily: - MyFonts - .Bold, - fontWeight: - FontWeight - .bold, - fontSize: 11, - color: MyColors - .textColorBlack20), - ), - ), - ), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - left: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - bottom: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: Alignment - .centerLeft, - child: Text( - AppLocalizations.of( - context)! - .description, - style: const TextStyle( - fontFamily: - MyFonts - .Bold, - fontWeight: - FontWeight - .bold, - fontSize: 11, - color: MyColors - .textColorBlack20), - ), - ), - ), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - left: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: Alignment - .centerLeft, - child: Text( - AppLocalizations.of( - context)! - .quantity, - style: const TextStyle( - fontFamily: - MyFonts - .Bold, - fontWeight: - FontWeight - .bold, - fontSize: 11, - color: MyColors - .textColorBlack20), - ), - ), - ), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - left: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: Alignment - .centerLeft, - child: Text( - AppLocalizations.of( - context)! - .unit_price, - style: const TextStyle( - fontFamily: - MyFonts - .Bold, - fontWeight: - FontWeight - .bold, - fontSize: 11, - color: MyColors - .textColorBlack20), - ), - ), - ), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - left: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: Alignment - .centerLeft, - child: Text( - AppLocalizations.of( - context)! - .discount_type, - style: const TextStyle( - fontFamily: - MyFonts - .Bold, - fontWeight: - FontWeight - .bold, - fontSize: 11, - color: MyColors - .textColorBlack20), - ), - ), - ), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - left: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: Alignment - .centerLeft, - child: Text( - AppLocalizations.of( - context)! - .discount, - style: const TextStyle( - fontFamily: - MyFonts - .Bold, - fontWeight: - FontWeight - .bold, - fontSize: 11, - color: MyColors - .textColorBlack20), - ), - ), - ), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - left: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: Alignment - .centerLeft, - child: Text( - AppLocalizations.of( - context)! - .select_tax, - style: const TextStyle( - fontFamily: - MyFonts - .Bold, - fontWeight: - FontWeight - .bold, - fontSize: 11, - color: MyColors - .textColorBlack20), - ), - ), - ), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - left: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: Alignment - .centerLeft, - child: Text( - AppLocalizations.of( - context)! - .measurement, - style: const TextStyle( - fontFamily: - MyFonts - .Bold, - fontWeight: - FontWeight - .bold, - fontSize: 11, - color: MyColors - .textColorBlack20), - ), - ), - ), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - left: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: const Align( - alignment: Alignment - .centerLeft, - child: Text( - 'Tax %', - style: TextStyle( - fontFamily: - MyFonts - .Bold, - fontWeight: - FontWeight - .bold, - fontSize: 11, - color: MyColors - .textColorBlack20), - ), - ), - ), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - left: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - bottom: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: Alignment - .centerLeft, - child: Text( - AppLocalizations.of( - context)! - .amount, - style: const TextStyle( - fontFamily: - MyFonts - .Bold, - fontWeight: - FontWeight - .bold, - fontSize: 11, - color: MyColors - .textColorBlack20), - ), - ), - ), - ], - )), - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment - .start, - mainAxisAlignment: - MainAxisAlignment - .start, - children: [ - Container( - height: 48, - padding: - const EdgeInsets - .only( - right: 8), - decoration: - BoxDecoration( - border: Border.all( - color: Colors - .transparent, - width: 1, - ), - color: MyColors - .backFillColor, - borderRadius: - BorderRadius - .circular( - 8.0), - ), - child: Row( - mainAxisAlignment: - MainAxisAlignment - .spaceBetween, - crossAxisAlignment: - CrossAxisAlignment - .stretch, - children: [ - Expanded( - child: - TextButton( - onPressed: () { - showSheet( - position); - }, - child: Align( - alignment: - Alignment - .centerLeft, - child: Text( - selectedProduct[position] - .isEmpty - ? 'Choose' - : selectedProduct[ - position], - textAlign: - TextAlign - .left, - style: const TextStyle( - fontFamily: - MyFonts - .Bold, - fontSize: - 10, - color: MyColors - .textColorBlack), - ), - ), - )), - const Icon( - // <-- Icon - Icons - .arrow_drop_down, - size: 24.0, - color: MyColors - .black, - ) - ], - ), - ), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: - getProductDescription( - position), - ), - ), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: - getProductQuantity( - position), - ), - ), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: - getProductPrice( - position), - ), - ), - getDiscountsTypes( - context, position), - getDiscounts( - context, position), - getTaxWidget( - context, position), - getMeasurementWidget( - context, position), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - bottom: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: Text( - addInvoice - .products[ - position] - .tax! - .toStringAsFixed( - 2) ?? - 0.toString(), - style: const TextStyle( - fontFamily: - MyFonts - .Bold, - fontWeight: - FontWeight - .bold, - fontSize: 11, - color: MyColors - .textColorBlack20), - ), - ), - ), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - bottom: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: Text( - addInvoice - .products[ - position] - .amount! - .toStringAsFixed( - 2) ?? - 0.toString(), - style: const TextStyle( - fontFamily: - MyFonts - .Bold, - fontWeight: - FontWeight - .bold, - fontSize: 11, - color: MyColors - .textColorBlack20), - ), - ), - ), - ], - )), - ], - ), - )), - getRemoveProductButton(position) - ], - ), - ); - } else { - return Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all( - width: 1, - color: MyColors.fillColorGray2), - color: MyColors.white, - ), - child: Row( - children: [ - Container( - width: 110, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - height: 48, - padding: const EdgeInsets.all(4), - child: Container( - decoration: BoxDecoration( - border: Border.all( - color: Colors.transparent, - width: 1, - ), - color: MyColors.backFillColor, - borderRadius: - BorderRadius.circular(8.0), - ), - child: Row( - children: [ - Expanded( - child: TextButton( - onPressed: () { - showSheet(position); - }, - child: Align( - alignment: - Alignment.centerLeft, - child: Text( - selectedProduct[ - position] - .isEmpty - ? 'Choose' - : selectedProduct[ - position], - textAlign: - TextAlign.left, - style: const TextStyle( - fontFamily: - MyFonts.Bold, - fontSize: 10, - color: MyColors - .textColorBlack), - ), - ), - )), - const Icon( - // <-- Icon - Icons.arrow_drop_down, - size: 14.0, - color: MyColors.black, - ) - ], - ), - ), - ), - Container( - padding: const EdgeInsets.all(4), - height: 48, - width: 100, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: getProductDescription( - position), - ), - ), - Container( - padding: const EdgeInsets.all(4), - height: 48, - width: 60, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: - getProductQuantity(position), - ), - ), - Container( - padding: const EdgeInsets.all(4), - height: 48, - width: 80, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: getProductPrice(position), - ), - ), - Expanded( - child: getDiscountsTypes( - context, position)), - Expanded( - child: getDiscounts( - context, position)), - Expanded( - child: getTaxWidget( - context, position)), - Expanded( - child: getMeasurementWidget( - context, position)), - Container( - width: 44, - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: Text( - addInvoice.products[position] - .tax == - null - ? "0.0" - : addInvoice - .products[position].tax! - .toStringAsFixed(2), - style: - MyColors.textStyleHeading(), - ), - ), - ), - Container( - width: 54, - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: Text( - addInvoice - .products[position].amount! - .toStringAsFixed(2), - style: - MyColors.textStyleHeading(), - ), - ), - ), - getRemoveProductButton(position) - ], - ), - ); - } - }, - itemCount: addInvoice.products.length, - ), - isPortrait - ? Container( - margin: - const EdgeInsets.fromLTRB(8, 0, 0, 8), - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all( - width: 1, - color: MyColors.fillColorGray2), - color: Colors.white, - ), - height: 48, - child: Row( - children: [ - Expanded( - child: Container( - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: Text( - '', - style: - MyColors.textStyleValue(), - ), - ), - )), - Expanded( - child: Container( - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: Text( - getTotalProductsPrice(), - style: - MyColors.textStyleValue(), - ), - ), - )), - Center( - child: Container( - margin: const EdgeInsets.all(5), - width: 32, - height: 32, - decoration: const BoxDecoration( - borderRadius: - BorderRadius.all( - Radius.circular(4)), - color: - MyColors.fillColorGray2), - child: IconButton( - icon: const Icon( - size: 14, - Icons.add, - color: - MyColors.textColorBlack, - ), - onPressed: () { - onAddService(); - }), - ), - ), - ], - ), - ) - : Container( - margin: - const EdgeInsets.fromLTRB(0, 0, 0, 8), - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all( - width: 1, - color: MyColors.fillColorGray2), - color: Colors.white, - ), - height: 48, - child: Row( - children: [ - Expanded( - child: Container( - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: Text( - '', - style: - MyColors.textStyleValue(), - ), - ), - )), - Expanded( - child: Container( - padding: - const EdgeInsets.only(left: 8), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: Text( - '', - style: - MyColors.textStyleValue(), - ), - ), - )), - Expanded( - child: Container( - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: Text( - '', - style: - MyColors.textStyleValue(), - ), - ), - )), - Expanded( - child: Container( - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: Text( - '', - style: - MyColors.textStyleValue(), - ), - ), - )), - Expanded( - child: Container( - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: Text( - '', - style: - MyColors.textStyleValue(), - ), - ), - )), - Expanded( - child: Container( - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: Text( - '', - style: - MyColors.textStyleValue(), - ), - ), - )), - Expanded( - child: Container( - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: Text( - '', - style: - MyColors.textStyleValue(), - ), - ), - )), - Container( - width: 44, - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: Text( - '', - style: - MyColors.textStyleHeading(), - ), - ), - ), - Container( - width: 54, - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: Text( - getTotalProductsPrice(), - style: - MyColors.textStyleHeading(), - ), - ), - ), - Center( - child: Container( - margin: const EdgeInsets.all(5), - width: 34, - height: 32, - decoration: const BoxDecoration( - borderRadius: - BorderRadius.all( - Radius.circular(4)), - color: - MyColors.fillColorGray2), - child: IconButton( - icon: const Icon( - size: 14, - Icons.add, - color: - MyColors.textColorBlack, - ), - onPressed: () { - onAddService(); - }), - ), - ), - ], - ), - ), - AppSpaces.verticalLarge, - Row( - children: [ - const Expanded(child: Text('')), - Expanded( - child: Row( - children: [ - Expanded( - child: Align( - alignment: Alignment.centerRight, - child: Text( - AppLocalizations.of(context)! - .discount, - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.w500, - fontSize: MyFonts.normal, - color: MyColors.textColorBlack20), - ), - )), - const SizedBox( - width: 8, - ), - Expanded( - child: Align( - alignment: Alignment.centerRight, - child: Text( - getTotalDiscount(), - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.w500, - fontSize: MyFonts.normal, - color: MyColors.textColorBlack20), - ), - )), - ], - )), - ], - ), - AppSpaces.verticalSmall, - Row( - children: [ - const Expanded(child: Text('')), - Expanded( - child: Row( - children: [ - Expanded( - child: Align( - alignment: Alignment.centerRight, - child: Text( - '${AppLocalizations.of(context)!.tax} (VAT ${getTotalVatPercentage()}%)', - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.w500, - fontSize: MyFonts.normal, - color: MyColors.textColorBlack20), - ), - )), - const SizedBox( - width: 8, - ), - Expanded( - child: Align( - alignment: Alignment.centerRight, - child: Text( - getTotalVatDiscount(), - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.w500, - fontSize: MyFonts.normal, - color: MyColors.textColorBlack20), - ), - )), - ], - )), - ], - ), - AppSpaces.verticalSmall, - Row( - children: [ - const Expanded(child: Text('')), - Expanded( - child: Row( - children: [ - Expanded( - child: Align( - alignment: Alignment.centerRight, - child: Text( - AppLocalizations.of(context)! - .total_amount, - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.bold, - fontSize: 13, - color: MyColors.black), - ), - )), - const SizedBox( - width: 8, - ), - Expanded( - child: Align( - alignment: Alignment.centerRight, - child: Text( - addInvoice.totalAmount! - .toStringAsFixed(2), - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.bold, - fontSize: 13, - color: MyColors.black), - ), - )), - ], - )), - ], - ) - ], - ), - ), - ), - AppSpaces.verticalLarge, - isLoadingData - ? const Row( - crossAxisAlignment: CrossAxisAlignment.end, - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Center( - child: CircularProgressIndicator(), - ) - ], - ) - : Row( - crossAxisAlignment: CrossAxisAlignment.end, - mainAxisAlignment: MainAxisAlignment.end, - children: [ - SizedBox( - width: 110, - child: CustomSimpleButton( - backGroundColor: MyColors.blueThemeColor, - textColor: MyColors.white, - height: 38, - heading: 'Add Service', - onPressed: () { - onAddService(); - }, - )), - AppSpaces.horizontalMedium, - SizedBox( - width: 110, - child: CustomSimpleButton( - backGroundColor: MyColors.blueThemeColor, - textColor: MyColors.white, - height: 38, - heading: widget.isEdit - ? AppLocalizations.of(context)! - .edit_invoice - : AppLocalizations.of(context)! - .add_invoice, - onPressed: () { - isValidate(false); - }, - )), - AppSpaces.horizontalMedium, - SizedBox( - width: 160, - child: CustomSimpleButton( - backGroundColor: MyColors.blueThemeColor, - textColor: MyColors.white, - height: 38, - heading: AppLocalizations.of(context)! - .add_invoice_and_print, - onPressed: () { - isValidate(true); - }, - ), - ) - ], - ) - ], - ), - ), - ); - }), - ); - } - - void isValidate(bool isPrint) { - addInvoice.invoiceFor = []; - addInvoice.invoiceFor!.add(selectedInvoiceFor); - - if (addInvoice.invoiceFor!.isEmpty) { - showMessage('Select Invoice for'); - } else if (addInvoice.customerId!.isEmpty) { - showMessage('Select $selectedInvoiceFor'); - } else if (addInvoice.status == null) { - showMessage('Select Status'); - } else if (addInvoice.products.isEmpty) { - showMessage('Add At least One Product'); - } else if (selectedProduct[0].isEmpty) { - showMessage('Add At least One Product'); - } else { - addUpdateInvoice(isPrint); - } - } - - Widget getMeasurementWidget(BuildContext context, int position) { - return FutureBuilder( - future: getMeasurement(), - builder: (c, s) { - if (s.hasData) { - var itemsList = s.data!; - return Container( - padding: const EdgeInsets.all(4), - decoration: const BoxDecoration( - border: Border( - right: BorderSide(width: 1.0, color: MyColors.fillColorGray2), - ), - ), - child: Material( - color: MyColors.backFillColor, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: 48, - width: double.infinity, - child: DropdownSearch( - selectedItem: selectedMeasurement[position], - popupProps: const PopupProps.menu(), - clearButtonProps: const ClearButtonProps( - alignment: Alignment.centerRight, - padding: EdgeInsets.zero, - icon: Icon(Icons.clear, size: 12), - color: MyColors.black, - isVisible: true, - ), - items: itemsList, - itemAsString: (Measurement u) => u.name!, - onChanged: (Measurement? data) { - setState(() {}); - }, - dropdownDecoratorProps: - MyColors.dropDownStyle(hint: 'Choose'), - ), - ), - ), - ), - ); - } else { - return AppLoader(); - } - }); - } - - Future> getMeasurement() async { - var items = []; - - await viewModel - .getData(Constants.GET_MEASUREMENT, Constants.getStorePayload()) - .then((value) { - final response = InvoiceMeasurementModel.fromJson(value); - if (response.success!) { - items.addAll(response.measurements!); - } - }) - .onError((error, stackTrace) {}) - .timeout(const Duration(minutes: 1)); - - return items; - } - - Widget getTaxWidget(BuildContext context, int position) { - return FutureBuilder( - future: getTax(), - builder: (c, s) { - if (s.hasData) { - var itemsList = s.data!; - return Container( - padding: const EdgeInsets.all(4), - decoration: const BoxDecoration( - border: Border( - right: BorderSide(width: 1.0, color: MyColors.fillColorGray2), - ), - ), - child: Material( - color: MyColors.backFillColor, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: 48, - width: double.infinity, - child: DropdownSearch( - selectedItem: selectedTax[position], - popupProps: const PopupProps.menu(), - clearButtonProps: ThemeDropDown.clearButton, - items: itemsList, - itemAsString: (VAT u) { - return u.value!; - }, - onChanged: (VAT? data) { - if (data != null) { - calculateVat(double.parse(data.value!), position); - } else { - calculateVat(0.0, position); - } - }, - dropdownDecoratorProps: - MyColors.dropDownStyle(hint: 'Choose'), - ), - ), - ), - ), - ); - } else { - return AppLoader(); - } - }); - } - - Future> getTax() async { - var items = []; - await viewModel - .getResponse(Constants.GET_WOSUL_SETTINGS) - .then((value) { - final response = WosulSettings.fromJson(value); - if (response.success!) { - items.addAll(response.wosulSettings!.first.vatTaxes!); - } - }) - .onError((error, stackTrace) {}) - .timeout(const Duration(minutes: 1)); - - return items; - } - - Widget getCompanyWidget(BuildContext context) { - return FutureBuilder( - future: getCompany(), - builder: (c, s) { - if (s.hasData) { - var itemsList = s.data!; - return Material( - color: MyColors.backFillColor, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: 48, - width: double.infinity, - child: DropdownSearch( - selectedItem: selectedCustomerCompany, - popupProps: const PopupProps.menu(), - clearButtonProps: ThemeDropDown.clearButton, - items: itemsList, - itemAsString: (StoreCustomer u) { - return u.name!; - }, - onChanged: (StoreCustomer? data) { - setState(() { - if (data != null) { - selectedCustomerCompany = data; - addInvoice.customerId = data.id!; - } - }); - }, - dropdownDecoratorProps: - MyColors.dropDownStyle(hint: 'Choose'), - ), - ), - ), - ); - } else { - return AppLoader(); - } - }); - } - - Future> getCompany() async { - var items = []; - - Map data = { - 'store': sharedPrefs.storeId, - }; - - await viewModel.getData(Constants.GET_STORE_CUSTOMER, data).then((value) { - final response = GetStoreCustomer.fromJson(value); - if (response.success!) { - items.addAll(response.topOrders!); - // if (widget.isEdit) { - // for (var customer in response.topOrders!) { - // if (customer.id! == addInvoice.customerId!) { - // selectedCustomerCompany = - // StoreCustomer(name: customer.name!, id: customer.id!); - // } - // } - // } else { - selectedCustomerCompany ??= StoreCustomer(name: "Choose", id: ""); - // } - } - }).onError((error, stackTrace) {}); - - return items; - } - - Widget getDiscountsTypes(BuildContext context, int position) { - return Container( - padding: const EdgeInsets.all(4), - decoration: const BoxDecoration( - border: Border( - right: BorderSide(width: 1.0, color: MyColors.fillColorGray2), - ), - ), - child: Material( - color: MyColors.backFillColor, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: 48, - width: double.infinity, - child: DropdownSearch( - selectedItem: - addInvoice.products[position].discountType ?? 'Choose', - popupProps: const PopupProps.menu( - fit: FlexFit.tight, - constraints: BoxConstraints(maxHeight: 110)), - clearButtonProps: ThemeDropDown.clearButton, - items: Constants.discountTypes, - itemAsString: (String u) => u, - onChanged: (String? data) { - setDiscountType(position, data); - }, - dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), - ), - ), - ), - ), - ); - } - - Widget getDiscounts(BuildContext context, int position) { - if (addInvoice.products[position].discountType == null) { - return Container( - height: 42, - ); - } else if (addInvoice.products[position].discountType! == - Constants.discountTypes[0]) { - return autoDiscount(position); - } else if (addInvoice.products[position].discountType! == - Constants.discountTypes[1]) { - return manualDiscount(position); - } else { - return Container( - height: 42, - ); - } - } - - Widget manualDiscount(int position) { - return Container( - padding: const EdgeInsets.all(4), - decoration: const BoxDecoration( - border: Border( - right: BorderSide(width: 1.0, color: MyColors.fillColorGray2), - ), - ), - child: CustomTextFieldForm( - initialValue: - addInvoice.products[position].discountPercentage?.toString() ?? '', - onChanged: (String value) { - if (value.isNotEmpty) { - addDiscount(double.parse(value), position); - } else { - resetDiscount(position); - } - }, - hintText: '', - ), - ); - } - - Widget autoDiscount(int position) { - return FutureBuilder( - future: getDiscount(), - builder: (c, s) { - if (s.hasData) { - var itemsList = s.data!; - return Container( - padding: const EdgeInsets.all(4), - decoration: const BoxDecoration( - border: Border( - right: BorderSide(width: 1.0, color: MyColors.fillColorGray2), - ), - ), - child: Material( - color: MyColors.backFillColor, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: isPortrait ? 42 : 48, - width: double.infinity, - child: DropdownSearch( - selectedItem: selectedDiscount[position], - popupProps: const PopupProps.menu(), - clearButtonProps: ThemeDropDown.clearButton, - items: itemsList, - itemAsString: (StoreDiscount u) => u.name ?? '', - onChanged: (StoreDiscount? data) { - if (data != null) { - addDiscount( - double.parse(data.discountPercentage!), position); - } else { - resetDiscount(position); - } - // calculateDiscount(data, position); - }, - dropdownDecoratorProps: - MyColors.dropDownStyle(hint: 'Choose'), - ), - ), - ), - ), - ); - } else { - return AppLoader(); - } - }); - } - - Future> getDiscount() async { - var items = []; - await viewModel - .getData(Constants.GET_DISCOUNT, Constants.getStorePayload()) - .then((value) { - final response = StoreDiscountModel.fromJson(value); - if (response.success!) { - items.addAll(response.storeDiscount!); - } - }).onError((error, stackTrace) {}); - - return items; - } - - void showSheet(int index) async { - final result = await showDialog( - barrierColor: Colors.black26, - context: context, - builder: (context) { - return const SearchProductVC(); - }, - ); - - if (!mounted) return; - try { - setState(() { - ProductItem response = result; - selectedProduct[index] = response.name!; - final item = addInvoice.products[index]; - item.price = response.price!; - if (response.total_quantity! > 0) { - item.amount = (response.price! * response.total_quantity!).toDouble(); - } else { - item.amount = 0.0; - } - - item.name = response.name; - item.itemId = response.id; - addInvoice.products[index] = item; - - item.totalQuantity = response.total_quantity; - addInvoice.products[index].description = response.details!; - addInvoice.products[index].totalQuantity = response.total_quantity!; - addInvoice.products[index].price = response.price!; - }); - } catch (e) {} - } - - void _presentDatePicker(bool isStart) { - // showDatePicker is a pre-made funtion of Flutter - showDatePicker( - context: context, - initialDate: DateTime.now(), - firstDate: DateTime(1965), - lastDate: DateTime(2030)) - .then((pickedDate) { - // Check if no date is selected - if (pickedDate == null) { - return; - } - setState(() { - if (isStart) { - addInvoice.invoiceDate = - DataTimeFormat.formatDateFromPicketINVOICE(pickedDate); - } else { - addInvoice.invoiceDueDate = - DataTimeFormat.formatDateFromPicketINVOICE(pickedDate); - } - }); - }); - } - - Widget getDefaultStatus() { - return Column( - children: [ - MandatoryTitleText( - hint: AppLocalizations.of(context)!.default_status, - ), - AppSpaces.verticalSmall, - Material( - color: MyColors.backFillColor, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: 48, - width: double.infinity, - child: DropdownSearch( - selectedItem: addInvoice.status ?? 'Choose', - popupProps: const PopupProps.menu( - constraints: BoxConstraints(maxHeight: 200), - ), - items: statusTypes, - itemAsString: (String u) => u, - onChanged: (String? data) { - setState(() { - addInvoice.status = data!; - }); - }, - dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), - ), - ), - ), - ), - ], - ); - } - - Widget getInvoiceDate() { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - CustomOptionalTitle( - hint: AppLocalizations.of(context)!.invoice_date, - ), - AppSpaces.verticalSmall, - getEndDateButton() - ], - ); - } - - Widget getEndDateButton() { - return CustomTextButtonIcon( - height: 48, - backgroundColor: MyColors.backFillColor, - icon: Icons.calendar_month, - heading: addInvoice.invoiceDate == null - ? 'dd/mm/yyyy' - : (addInvoice.invoiceDate!.contains("T") - ? DataTimeFormat.getFormatDateString(addInvoice.invoiceDate!) - : 'dd/mm/yyyy'), - onPressed: () { - _presentDatePicker(true); - }, - ); - } - - Widget getInvoiceDueDate() { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - CustomOptionalTitle( - hint: AppLocalizations.of(context)!.invoice_due_Date, - ), - AppSpaces.verticalSmall, - getStartDateButton() - ], - ); - } - - Widget getStartDateButton() { - return CustomTextButtonIcon( - height: 48, - backgroundColor: MyColors.backFillColor, - icon: Icons.calendar_month, - heading: addInvoice.invoiceDueDate == null - ? 'dd/mm/yyyy' - : (addInvoice.invoiceDueDate!.contains("T") - ? DataTimeFormat.getFormatDateString(addInvoice.invoiceDueDate!) - : 'dd/mm/yyyy'), - onPressed: () { - _presentDatePicker(false); - }, - ); - } - - Widget getInvoiceReferNo() { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - CustomOptionalTitle( - hint: AppLocalizations.of(context)!.invoice_reference, - ), - AppSpaces.verticalSmall, - CustomTextFieldForm( - readOnly: true, - key: Key(addInvoice.invoiceReference.toString()), - initialValue: addInvoice.invoiceReference.toString(), - onChanged: (value) { - addInvoice.invoiceReference = value; - }, - hintText: 'Enter Invoice Reference') - ], - ); - } - - String getTotalProductsPrice() { - var price = 0.0; - for (var product in addInvoice.products) { - price += product.amount ?? 0.0; - } - - addInvoice.totalAmount = price; - return price.toStringAsFixed(2); - } - - void calculateVat(double data, int position) { - setState(() { - try { - var totalQuantity = addInvoice.products[position].totalQuantity!; - double totalPrice = - (totalQuantity.toDouble() * addInvoice.products[position].price!); - - totalPrice = totalPrice - - (addInvoice.products[position].discountPercentage ?? 0.0); - - addInvoice.products[position].vat = data.toInt(); - var tax = (totalPrice * data); - - tax = tax / 100; //Total tax - addInvoice.products[position].tax = tax; - - addInvoice.products[position].amount = totalPrice + tax; - // if (addInvoice.products[position].discountPercentage != null) { - // addInvoice.products[position].amount = - // addInvoice.products[position].amount! - - // addInvoice.products[position].discountPercentage!; - // } - } catch (e) {} - - // if (data > 0) { - // - // } else { - // addInvoice.products[position].vat = 0; - // addInvoice.products[position].amount = - // addInvoice.products[position].amount! - - // addInvoice.products[position].tax!; - // addInvoice.products[position].tax = 0.0; - // } - }); - } - - void onRemoveItem(int position) { - setState(() { - selectedProduct.removeAt(position); - selectedMeasurement.removeAt(position); - selectedDiscount.removeAt(position); - selectedTax.removeAt(position); - addInvoice.products.removeAt(position); - }); - } - - void onChangeQuantity(int position, String value) { - setState(() { - if (value.isNotEmpty) { - addInvoice.products[position].totalQuantity = int.parse(value); - final unitPrice = - addInvoice.products[position].price ?? 0.0; // 1 pece value - final discount = - addInvoice.products[position].discountPercentage ?? 0.0; - if (discount > 0) { - addInvoice.products[position].amount = - addInvoice.products[position].totalQuantity! * unitPrice - - discount; - } else { - addInvoice.products[position].amount = - addInvoice.products[position].totalQuantity! * unitPrice; - } - var tax = getTaxCalu(position); - addInvoice.products[position].tax = tax; - addInvoice.products[position].amount = - addInvoice.products[position].amount! + - addInvoice.products[position].tax!; - } - }); - } - - void clearDiscount(int position) {} - - String getTotalDiscount() { - var price = 0.0; - for (var product in addInvoice.products) { - if (product.discountPercentage != null) { - try { - price += product.discountPercentage!; - } catch (e) { - price += product.discountPercentage!; - } - } - } - - addInvoice.totalDiscount = price; - return price.toStringAsFixed(2); - } - - String getTotalVatDiscount() { - var price = 0.0; - for (var product in addInvoice.products) { - price += product.tax ?? 0.0; - } - addInvoice.totalTax = price; - //addInvoice.totalTaxExcluding = price; - return price.toStringAsFixed(2); - } - - getTotalVatPercentage() { - var price = 0; - for (var product in addInvoice.products) { - price += product.vat ?? 0; - } - addInvoice.totalVat = price; - return price; - } - - double getTaxCalu(int position) { - double totalPrice = (addInvoice.products[position].totalQuantity! * - addInvoice.products[position].price!) - - (addInvoice.products[position].discountPercentage ?? 0.0); - var tax = (totalPrice * addInvoice.products[position].vat!); - tax = tax / 100; - return tax; - } - - void addUpdateInvoice(bool isPrint) async { - setState(() { - isLoadingData = true; - }); - - // addInvoice.invoiceNumber = int.parse(invoiceNumberController.text); - // addInvoice.invoiceReference = invoiceRefController.text; - // addInvoice.vatNumber = invoiceVatNumberController.text; - // addInvoice.terms = invoiceTermsController.text; - - var map = addInvoice.toJson(); - await viewModel.getData(Constants.ADD_INVOICE, map).then((value) { - final response = StoreInvoicesByIdModel.fromJson(value); - if (response.success!) { - showMessage(response.message ?? ''); - if (isPrint) { - Navigator.pop(context, true); - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => AddInvoiceAndPrintVC( - id: response.invoice!.id!, - )), - ); - } else { - Navigator.pop(context, true); - } - } - }).onError((error, stackTrace) { - setState(() { - isLoadingData = false; - }); - }).timeout(const Duration(minutes: 1)); - } - - void onAddService() { - setState(() { - selectedProduct.add(''); - selectedDiscount.add(StoreDiscount( - categories: [], products: [], discountPercentage: "0.0")); - selectedTax.add(VAT(name: 'VAT', value: "0.0")); - selectedMeasurement.add(Measurement(name: "Choose")); - addInvoice.products.add(StoreInvoiceProduct( - totalQuantity: 0, - price: 0.0, - vat: 0, - discountPercentage: 0.0, - tax: 0.0, - amount: 0.0, - )); - }); - } - - getChooseInvoiceFor() { - return Column( - children: [ - const MandatoryTitleText( - hint: 'Choose Invoice For', - ), - AppSpaces.verticalSmall, - Material( - color: MyColors.backFillColor, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: 48, - width: double.infinity, - child: DropdownSearch( - selectedItem: selectedInvoiceFor ?? "Choose", - popupProps: const PopupProps.menu( - constraints: BoxConstraints(maxHeight: 100), - ), - items: chooseInvoiceForTypes, - itemAsString: (String u) => u, - onChanged: (String? data) { - setState(() { - selectedInvoiceFor = data!; - - addInvoice.invoiceFor ??= []; - addInvoice.invoiceFor!.clear(); - addInvoice.invoiceFor!.add(data); - }); - }, - dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), - ), - ), - ), - ), - ], - ); - } - - getInvoiceFor() { - return Column( - children: [ - MandatoryTitleText( - hint: 'Choose $selectedInvoiceFor', - ), - AppSpaces.verticalSmall, - getCompanyWidget(context) - ], - ); - } - - getSelectedCurrencyDropdown() { - return FutureBuilder( - future: getCurrency(), - builder: (c, snapShot) { - if (snapShot.hasData) { - var currency = snapShot.data!; - return Material( - color: MyColors.backFillColor, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: 48, - width: double.infinity, - child: DropdownSearch( - selectedItem: selectedCurrency, - popupProps: const PopupProps.menu( - constraints: BoxConstraints(maxHeight: 200), - ), - items: currency, - itemAsString: (Currency u) => u.name!, - onChanged: (Currency? data) { - setState(() { - addInvoice.currencyId = data!; - }); - }, - dropdownDecoratorProps: - MyColors.dropDownStyle(hint: 'Choose Currency'), - ), - ), - ), - ); - } else { - return AppLoader(); - } - }); - } - - getInvoiceNumber() { - return Column( - children: [ - CustomOptionalTitle( - hint: AppLocalizations.of(context)!.invoice_number, - ), - AppSpaces.verticalSmall, - CustomTextFieldForm( - readOnly: true, - key: Key((addInvoice.invoiceNumber ?? 0).toString()), - initialValue: (addInvoice.invoiceNumber ?? 0).toString(), - onChanged: (String value) {}, - hintText: 'Enter Invoice Number', - ), - ], - ); - } - - getVatNumber() { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - CustomOptionalTitle( - hint: AppLocalizations.of(context)!.vat_number, - ), - AppSpaces.verticalSmall, - CustomTextFieldForm( - initialValue: (addInvoice.vatNumber ?? ""), - onChanged: (String value) { - addInvoice.vatNumber = value; - }, - hintText: 'Enter VAT Number', - ), - ], - ); - } - - getProductDescription(int position) { - return CustomTextFieldForm( - key: Key(addInvoice.products[position].description ?? ''), - initialValue: addInvoice.products[position].description ?? '', - onChanged: (String value) { - addInvoice.products[position].description = value; - }, - hintText: '', - ); - } - - getProductQuantity(int position) { - return CustomTextFieldForm( - keyboardType: TextInputType.number, - key: Key((addInvoice.products[position].totalQuantity ?? '0').toString()), - initialValue: - (addInvoice.products[position].totalQuantity ?? '0').toString(), - onChanged: (String value) { - onChangeQuantity(position, value); - }, - hintText: '', - ); - } - - getProductPrice(int position) { - return CustomTextFieldForm( - key: Key((addInvoice.products[position].price ?? '0').toString()), - keyboardType: TextInputType.number, - initialValue: (addInvoice.products[position].price ?? '0').toString(), - onChanged: (String value) { - addInvoice.products[position].price = double.parse(value); - if (addInvoice.products[position].discountPercentage != null) { - addDiscount( - addInvoice.products[position].discountPercentage!, position); - } else { - resetDiscount(position); - } - }, - hintText: '', - ); - } - - getRemoveProductButton(int position) { - return SizedBox( - width: 44, - height: 48, - child: Center( - child: Container( - width: 32, - height: 32, - decoration: const BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(4)), - color: MyColors.fillColorGray2), - child: IconButton( - icon: const Icon( - size: 14, - Icons.close, - color: MyColors.textColorBlack, - ), - onPressed: () { - onRemoveItem(position); - }), - ), - )); - } - - Future> getCurrency() async { - var currencies = []; - await APIManager() - .fetchData(Constants.GET_STORE_CURRENCY, Constants.getStorePayload()) - .then((value) async { - final response = GetStoreCurrency.fromJson(value); - if (response.success) { - currencies.addAll(response.currencies); - - for (var currency in currencies) { - if (currency.id == addInvoice.currencyId!.id!) { - selectedCurrency = Currency(name: currency.name!, id: currency.id!); - } - } - } - }).onError((error, stackTrace) {}); - - return currencies; - } - - void setDiscountType(int position, String? data) { - setState(() { - resetDiscount(position); - if (data != null) { - addInvoice.products[position].discountType = data; - } else { - addInvoice.products[position].discountType = ''; - } - }); - } - - void calculateDiscount(StoreDiscount? data, int position) { - setState(() { - if (data != null) { - addDiscount(double.parse(data.discountPercentage!), position); - } else { - resetDiscount(position); - } - }); - } - - void addDiscount(double discount, int position) { - setState(() { - addInvoice.products[position].discountPercentage = discount; - if (addInvoice.products[position].tax != null) { - calculateVat(addInvoice.products[position].vat!.toDouble(), position); - } else { - calculateVat(0, position); - // addInvoice.products[position].amount = - // addInvoice.products[position].amount! - - // addInvoice.products[position].discountPercentage!; - } - }); - } - - void resetDiscount(int position) { - setState(() { - addInvoice.products[position].discountPercentage = 0.0; - addInvoice.products[position].amount = - addInvoice.products[position].amount! + - addInvoice.products[position].discountPercentage!; - if (addInvoice.products[position].tax != null) { - calculateVat(addInvoice.products[position].vat!.toDouble(), position); - } else { - calculateVat(0, position); - // addInvoice.products[position].amount = - // addInvoice.products[position].amount! - - // addInvoice.products[position].discountPercentage!; - } - // addInvoice.products[position].amount = - // addInvoice.products[position].amount! + - // addInvoice.products[position].discountPercentage!; - // addInvoice.products[position].discountPercentage = 0.0; - }); - } -} diff --git a/lib/application/views/salesandordermodule/views/invoiceModule/repo/InvoiceRepository.dart b/lib/application/views/salesandordermodule/views/invoiceModule/repo/InvoiceRepository.dart new file mode 100644 index 0000000..fe13ee5 --- /dev/null +++ b/lib/application/views/salesandordermodule/views/invoiceModule/repo/InvoiceRepository.dart @@ -0,0 +1,28 @@ +import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/application/model/SimpleResponsModel.dart'; +import 'package:wosull/application/model/invoice/Account.dart'; +import 'package:wosull/application/model/invoice/StoreIncomeAccountResponse.dart'; +import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/utils/Constants.dart'; + +class InvoiceRepository { + Future> getAccounts() async { + var items = []; + await APIManager() + .getResponseAuth( + "${Constants.getStoreIncomeAccounts}/${sharedPrefs.storeId}") + .then((result) { + final value = StoreIncomeAccountResponse.fromJson(result); + if (value.status) { + items.addAll(value.accounts); + } + }).onError((error, stackTrace) {}); + return items; + } + + Future updateInvoicePayment(data) async { + final result = + await APIManager().fetchData(Constants.updateInvoicePayment, data); + return SimpleResponseModel.fromJson(result); + } +} diff --git a/lib/application/views/salesandordermodule/viewModel/InvoiceViewModel.dart b/lib/application/views/salesandordermodule/views/invoiceModule/viewModels/InvoiceViewModel.dart similarity index 72% rename from lib/application/views/salesandordermodule/viewModel/InvoiceViewModel.dart rename to lib/application/views/salesandordermodule/views/invoiceModule/viewModels/InvoiceViewModel.dart index 64fd238..7d9d083 100644 --- a/lib/application/views/salesandordermodule/viewModel/InvoiceViewModel.dart +++ b/lib/application/views/salesandordermodule/views/invoiceModule/viewModels/InvoiceViewModel.dart @@ -12,7 +12,7 @@ class InvoiceViewModel with ChangeNotifier { int _currentPageNumber = 1; String filterValue = 'All'; DataState _dataState = DataState.uninitialized; - + int limit = 10; bool _didLastLoad = false; bool _isLoading = false; @@ -26,7 +26,12 @@ class InvoiceViewModel with ChangeNotifier { List get filteredList => _filteredList; - fetch({bool isRefresh = false, String filter = 'All'}) async { + void initData(String filter) { + filterValue = filter; + } + + fetch({bool isRefresh = false, String filter = 'All', int limit = 10}) async { + this.limit = limit; _isLoading = true; filterValue = filter; if (!isRefresh) { @@ -43,6 +48,7 @@ class InvoiceViewModel with ChangeNotifier { 'store_id': sharedPrefs.storeId, 'page': _currentPageNumber, 'invoice_status': filterValue, + 'limit': this.limit }; print(jsonEncode(data)); try { @@ -60,7 +66,7 @@ class InvoiceViewModel with ChangeNotifier { if (value.success!) { _filteredList.addAll(value.invoices!); _dataList.addAll(value.invoices!); - if (value.invoices!.length < 10) { + if (value.invoices!.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; @@ -82,6 +88,40 @@ class InvoiceViewModel with ChangeNotifier { } } + search({String searchValue = ""}) async { + if (searchValue.isEmpty) { + _dataState = DataState.fetched; + _filteredList.clear(); + _filteredList.addAll(_dataList); + notifyListeners(); + } else { + Map data = { + 'store_id': sharedPrefs.storeId, + 'searchTerm': searchValue + }; + _dataState = DataState.searching; + notifyListeners(); + try { + await APIManager() + .fetchData(Constants.searchInvoice, data) + .then((result) { + final value = StoreInvoicesModel.fromJson(result); + _filteredList.clear(); + if (value.success!) { + _filteredList.addAll(value.invoices!); + } + _dataState = DataState.fetched; + }).onError((error, stackTrace) { + _dataState = DataState.error; + }); + notifyListeners(); + } catch (e) { + _dataState = DataState.error; + notifyListeners(); + } + } + } + Future delete(String id) async { Map data = {'invoiceId': id}; await APIManager() diff --git a/lib/application/views/salesandordermodule/views/invoiceModule/viewModels/MakePaymentViewModel.dart b/lib/application/views/salesandordermodule/views/invoiceModule/viewModels/MakePaymentViewModel.dart new file mode 100644 index 0000000..c81db85 --- /dev/null +++ b/lib/application/views/salesandordermodule/views/invoiceModule/viewModels/MakePaymentViewModel.dart @@ -0,0 +1,144 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/application/model/invoice/Account.dart'; +import 'package:wosull/application/model/invoice/PaymentMethod.dart'; +import 'package:wosull/application/model/invoice/StoreInvoice.dart'; +import 'package:wosull/application/repository/WosulRepository.dart'; +import 'package:wosull/application/utils/CRUDOperatoinState.dart'; +import 'package:wosull/application/views/salesandordermodule/views/invoiceModule/repo/InvoiceRepository.dart'; +import 'package:wosull/helpers/Utils.dart'; + +class MakePaymentViewModel with ChangeNotifier { + bool isPortrait = false; + final repository = InvoiceRepository(); + bool isLoading = false; + List accounts = []; + List paymentMethod = []; + late StoreInvoice storeInvoice; + + var _crudOperation = CRUDOperationState.uninitialized; + + CRUDOperationState get crudOperation => _crudOperation; + + setState(CRUDOperationState state) { + _crudOperation = state; + } + + var date = ''; + var amount = ''; + var notes = ''; + + var selectedAccount; + var selectedPaymentMethod; + + void setLoading(bool value) { + isLoading = value; + notifyListeners(); + } + + void disposeData() { + _crudOperation = CRUDOperationState.uninitialized; + selectedAccount = null; + selectedPaymentMethod = null; + date = ''; + amount = ''; + notes = ''; + accounts.clear(); + paymentMethod.clear(); + } + + Future initData(StoreInvoice storeInvoice) async { + this.storeInvoice = storeInvoice; + amount = this.storeInvoice.totalAmount?.toStringAsFixed(2) ?? ''; + await getPaymentMethods(); + await getAccounts(); + notifyListeners(); + } + + Future isValidate() async { + if (date.isEmpty) { + Utils.showMessage('Please Fill Transaction Date!'); + } else if (selectedAccount == null) { + Utils.showMessage('Please Select Account'); + } else if (amount.isEmpty) { + Utils.showMessage('Please enter amount'); + } else if (selectedPaymentMethod == null) { + Utils.showMessage('Please select payment Method'); + } else { + await updateInvoicePayment(); + } + } + + Future updateInvoicePayment() async { + Account account = selectedAccount; + PaymentMethod paymentMethod = selectedPaymentMethod; + var data = { + 'account': account.id, + 'payment_method': paymentMethod.paymentMethod, + 'transaction_date': date, + 'amount': amount, + 'notes': notes, + 'invoice_id': storeInvoice.id + }; + setLoading(true); + await repository.updateInvoicePayment(data).then((value) { + Utils.showMessage(value.message); + if (value.success) { + setState(CRUDOperationState.update); + } else { + setState(CRUDOperationState.error); + } + setLoading(false); + }).onError((error, stackTrace) { + setState(CRUDOperationState.error); + setLoading(false); + }); + } + + void presentDatePicker(BuildContext context) { + // showDatePicker is a pre-made funtion of Flutter + showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime(1965), + lastDate: DateTime.now()) + .then((pickedDate) { + // Check if no date is selected + if (pickedDate == null) { + return; + } + date = DataTimeFormat.formatDateFromPicket(pickedDate); + + notifyListeners(); + }); + } + + Future getPaymentMethods() async { + await WosulRepository().getPaymentMethods().then((value) { + if (value.isNotEmpty) { + paymentMethod.addAll(value); + } + }); + } + + Future getAccounts() async { + await repository.getAccounts().then((value) { + if (value.isNotEmpty) { + accounts.addAll(value); + selectedAccount = accounts.first; + } + }); + } + + void setPaymentMethod(PaymentMethod? data) { + selectedPaymentMethod = data; + } + + void setAccount(Account? data) { + selectedAccount = data; + } + + void updateAmount(String value) { + amount = value; + } +} diff --git a/lib/application/views/salesandordermodule/views/invoiceModule/viewModels/NewInvoiceViewModel.dart b/lib/application/views/salesandordermodule/views/invoiceModule/viewModels/NewInvoiceViewModel.dart new file mode 100644 index 0000000..2b0f18f --- /dev/null +++ b/lib/application/views/salesandordermodule/views/invoiceModule/viewModels/NewInvoiceViewModel.dart @@ -0,0 +1,516 @@ +import 'dart:math'; + +import 'package:flutter/material.dart'; +import 'package:wosull/application/model/Measurement/InventoryMeasurementModel.dart'; +import 'package:wosull/application/model/StockTransfer/ProductItemCategoryModel.dart'; +import 'package:wosull/application/model/WosulSettings.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/application/model/customers/GetStoreCustomer.dart'; +import 'package:wosull/application/model/discount/StoreDiscountModel.dart'; +import 'package:wosull/application/model/invoice/StoreInvoice.dart'; +import 'package:wosull/application/model/store/GetStoreCurrency.dart'; +import 'package:wosull/application/model/store/StoreInvoicesModel.dart'; +import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/repository/WosulRepository.dart'; +import 'package:wosull/application/utils/CRUDOperatoinState.dart'; +import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/helpers/Utils.dart'; + +class NewInvoiceViewModel with ChangeNotifier { + late StoreInvoice addInvoice = StoreInvoice(products: []); + bool isPortrait = true; + bool isEdit = true; + String invoiceId = ''; + List selectedProduct = []; + + var isLoadingFirst = false; + var isLoadingData = false; + + var _crudOperation = CRUDOperationState.uninitialized; + + CRUDOperationState get crudOperation => _crudOperation; + + List selectedDiscount = []; + List selectedMeasurement = []; + List selectedTax = []; + + var selectedCurrency; + var selectedCustomerCompany; + var selectedStatus; + + var selectedInvoiceFor = Constants.chooseInvoiceForTypes[0]; + + //data lists + List measurements = []; + List taxes = []; + List companies = []; + List storeDiscounts = []; + List currencies = []; + List filteredProductItems = []; + + disposeData() { + addInvoice = StoreInvoice(products: []); + isLoadingData = false; + measurements.clear(); + taxes.clear(); + selectedProduct.clear(); + companies.clear(); + storeDiscounts.clear(); + currencies.clear(); + filteredProductItems.clear(); + selectedCurrency = null; + selectedCustomerCompany = null; + selectedStatus = null; + selectedDiscount.clear(); + selectedMeasurement.clear(); + selectedTax.clear(); + } + + void setLoading(bool value) { + isLoadingData = value; + notifyListeners(); + } + + Future getInvoiceById(String id) async { + await APIManager() + .getResponseAuth("${Constants.GET_INVOICE_BY_ID}/$id") + .then((value) async { + final response = StoreInvoicesByIdModel.fromJson(value); + if (response.success!) { + await setInvoiceData(response.invoice); + } + notifyListeners(); + }).onError((error, stackTrace) { + isLoadingFirst = false; + notifyListeners(); + }); + } + + Future initData(bool isEdit, StoreInvoice storeInvoice) async { + this.isEdit = isEdit; + isLoadingFirst = true; + if (isEdit) { + await getInvoiceById(storeInvoice.id ?? ''); + } else { + addInvoice.status = 'New'; + addEmptyService(); + getRandomNumber(); + getRandomInvoiceRef(); + } + await getMeasurement(); + await getTax(); + await getCompany(); + await getDiscount(); + await getCurrency(); + await getProducts(); + isLoadingFirst = false; + + notifyListeners(); + } + + void getRandomNumber() { + var rng = Random(); + var code = rng.nextInt(900000) + 100000; + addInvoice.invoiceNumber = code; + } + + void getRandomInvoiceRef() { + var rng = Random(); + var code = rng.nextInt(900000) + 100000; + addInvoice.invoiceReference = code.toString(); + } + + Future isValidate(bool isPrint) async { + addInvoice.invoiceFor = []; + addInvoice.invoiceFor!.add(selectedInvoiceFor); + + if (addInvoice.invoiceFor!.isEmpty) { + Utils.showMessage('Select Invoice for'); + } else if (addInvoice.customerId!.isEmpty) { + Utils.showMessage('Select $selectedInvoiceFor'); + } else if (addInvoice.products.isEmpty) { + Utils.showMessage('Add At least One Product'); + } else if (selectedProduct[0].isEmpty) { + Utils.showMessage('Add At least One Product'); + } else { + await addUpdateInvoice(isPrint); + } + } + + Future getTax() async { + final response = await WosulRepository().getTax(); + taxes.addAll(response); + } + + Future getMeasurement() async { + final response = await WosulRepository().getMeasurement(); + measurements.addAll(response); + } + + Future getDiscount() async { + final response = await WosulRepository().getDiscount(); + storeDiscounts.addAll(response); + } + + void calculateVat(double data, int position) { + try { + var totalQuantity = addInvoice.products[position].totalQuantity!; + double totalPrice = + (totalQuantity.toDouble() * addInvoice.products[position].price!); + + totalPrice = totalPrice - + (addInvoice.products[position].discountPercentage ?? 0.0); + + addInvoice.products[position].vat = data.toInt(); + var tax = (totalPrice * data); + + tax = tax / 100; //Total tax + addInvoice.products[position].tax = tax; + + addInvoice.products[position].amount = totalPrice + tax; + } catch (e) {} + notifyListeners(); + } + + void onRemoveItem(int position) { + selectedProduct.removeAt(position); + selectedMeasurement.removeAt(position); + selectedDiscount.removeAt(position); + selectedTax.removeAt(position); + addInvoice.products.removeAt(position); + notifyListeners(); + } + + void onChangeQuantity(int position, String value) { + if (value.isNotEmpty) { + addInvoice.products[position].totalQuantity = int.parse(value); + final unitPrice = + addInvoice.products[position].price ?? 0.0; // 1 pece value + final discount = addInvoice.products[position].discountPercentage ?? 0.0; + if (discount > 0) { + addInvoice.products[position].amount = + addInvoice.products[position].totalQuantity! * unitPrice - discount; + } else { + addInvoice.products[position].amount = + addInvoice.products[position].totalQuantity! * unitPrice; + } + var tax = getTaxCalu(position); + addInvoice.products[position].tax = tax; + addInvoice.products[position].amount = + addInvoice.products[position].amount! + + addInvoice.products[position].tax!; + } + notifyListeners(); + } + + void clearDiscount(int position) {} + + String getTotalDiscount() { + var price = 0.0; + for (var product in addInvoice.products) { + if (product.discountPercentage != null) { + try { + price += product.discountPercentage!; + } catch (e) { + price += product.discountPercentage!; + } + } + } + + addInvoice.totalDiscount = price; + return price.toStringAsFixed(2); + } + + String getTotalVatDiscount() { + var price = 0.0; + for (var product in addInvoice.products) { + price += product.tax ?? 0.0; + } + addInvoice.totalTax = price; + //addInvoice.totalTaxExcluding = price; + return price.toStringAsFixed(2); + } + + getTotalVatPercentage() { + var price = 0; + for (var product in addInvoice.products) { + price += product.vat ?? 0; + } + addInvoice.totalVat = price; + return price; + } + + String getTotalProductsPrice() { + var price = 0.0; + for (var product in addInvoice.products) { + price += product.amount ?? 0.0; + } + + addInvoice.totalAmount = price; + return price.toStringAsFixed(2); + } + + double getTaxCalu(int position) { + double totalPrice = (addInvoice.products[position].totalQuantity! * + addInvoice.products[position].price!) - + (addInvoice.products[position].discountPercentage ?? 0.0); + var tax = (totalPrice * addInvoice.products[position].vat!); + tax = tax / 100; + return tax; + } + + Future addUpdateInvoice(bool isPrint) async { + setLoading(true); + + var map = addInvoice.toJson(); + await APIManager().fetchData(Constants.ADD_INVOICE, map).then((value) { + final response = StoreInvoicesByIdModel.fromJson(value); + if (response.success!) { + Utils.showMessage(response.message ?? ''); + invoiceId = response.invoice!.id ?? ''; + if (isPrint) { + _crudOperation = CRUDOperationState.view; + } else { + _crudOperation = CRUDOperationState.add; + // Navigator.pop(context, true); + } + setLoading(false); + } + }).onError((error, stackTrace) { + _crudOperation = CRUDOperationState.error; + setLoading(false); + }); + } + + void addEmptyService() { + selectedProduct.add(''); + selectedDiscount.add(StoreDiscount( + categories: [], products: [], discountPercentage: "Choose")); + selectedTax.add(VAT(name: 'VAT', value: "Choose")); + selectedMeasurement.add(Measurement(name: "Choose")); + addInvoice.products.add(StoreInvoiceProduct( + totalQuantity: 0, + price: 0.0, + vat: 0, + discountPercentage: 0.0, + tax: 0.0, + amount: 0.0, + )); + } + + void onAddService() { + addEmptyService(); + notifyListeners(); + } + + void setDiscountType(int position, String? data) { + resetDiscount(position); + if (data != null) { + addInvoice.products[position].discountType = data; + } else { + addInvoice.products[position].discountType = ''; + } + notifyListeners(); + } + + void calculateDiscount(StoreDiscount? data, int position) { + if (data != null) { + addDiscount(double.parse(data.discountPercentage!), position); + } else { + resetDiscount(position); + } + notifyListeners(); + } + + void addDiscount(double discount, int position) { + addInvoice.products[position].discountPercentage = discount; + if (addInvoice.products[position].tax != null) { + calculateVat(addInvoice.products[position].vat!.toDouble(), position); + } else { + calculateVat(0, position); + } + notifyListeners(); + } + + void resetDiscount(int position) { + addInvoice.products[position].discountPercentage = 0.0; + addInvoice.products[position].amount = + addInvoice.products[position].amount! + + addInvoice.products[position].discountPercentage!; + if (addInvoice.products[position].tax != null) { + calculateVat(addInvoice.products[position].vat!.toDouble(), position); + } else { + calculateVat(0, position); + } + notifyListeners(); + } + + Future getCurrency() async { + final response = await WosulRepository().getCurrency(); + currencies.addAll(response); + if (isEdit) { + for (var currency in currencies) { + if (currency.id == addInvoice.currencyId!.id!) { + selectedCurrency = Currency(name: currency.name!, id: currency.id!); + } + } + } + } + + Future getCompany() async { + final response = await WosulRepository().getCompany(); + companies.addAll(response); + if (isEdit) {} + selectedCustomerCompany ??= StoreCustomer(name: "Choose", id: ""); + } + + void presentDatePicker(BuildContext context, bool isStart) { + // showDatePicker is a pre-made funtion of Flutter + showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime(1965), + lastDate: DateTime(2030)) + .then((pickedDate) { + // Check if no date is selected + if (pickedDate == null) { + return; + } + if (isStart) { + addInvoice.invoiceDate = + DataTimeFormat.formatDateFromPicketINVOICE(pickedDate); + } else { + addInvoice.invoiceDueDate = + DataTimeFormat.formatDateFromPicketINVOICE(pickedDate); + } + notifyListeners(); + }); + } + + void setVat(VAT? data, int position) { + if (data != null) { + calculateVat(double.parse(data.value!), position); + } else { + calculateVat(0.0, position); + } + } + + void changeCustomer(StoreCustomer? data) { + if (data != null) { + selectedCustomerCompany = data; + addInvoice.customerId = data.id!; + } + } + + void onChangeManualDiscount(String value, position) { + if (value.isNotEmpty) { + addDiscount(double.parse(value), position); + } else { + resetDiscount(position); + } + } + + void onChangeAutoDiscount(StoreDiscount? data, int position) { + if (data != null) { + addDiscount(double.parse(data.discountPercentage!), position); + } else { + resetDiscount(position); + } + } + + void updateProduct(result, index) { + ProductItem response = result; + selectedProduct[index] = response.name!; + final item = addInvoice.products[index]; + item.price = response.price!; + + if (response.total_quantity! > 0) { + item.amount = (response.price! * response.total_quantity!).toDouble(); + } else { + item.amount = 0.0; + } + + item.name = response.name; + item.itemId = response.id; + addInvoice.products[index] = item; + + item.totalQuantity = response.total_quantity; + addInvoice.products[index].description = response.details!; + addInvoice.products[index].totalQuantity = response.total_quantity!; + addInvoice.products[index].price = response.price!; + notifyListeners(); + } + + void onChangeInvoiceFor(String? data) { + selectedInvoiceFor = data!; + + addInvoice.invoiceFor ??= []; + addInvoice.invoiceFor!.clear(); + addInvoice.invoiceFor!.add(data); + notifyListeners(); + } + + void onChangeItemPrice(String value, position) { + if (value.isNotEmpty) { + addInvoice.products[position].price = double.parse(value); + if (addInvoice.products[position].discountPercentage != null) { + addDiscount( + addInvoice.products[position].discountPercentage!, position); + } else { + resetDiscount(position); + } + } + } + + void updateStockProduct(bool value) { + addInvoice.productStock = value; + notifyListeners(); + } + + void setMeasurement(Measurement? data, int position) { + if (data != null) { + addInvoice.products[position].measurement = data.name ?? ''; + } else { + addInvoice.products[position].measurement = ''; + } + } + + Future setInvoiceData(StoreInvoice? invoice) async { + addInvoice = invoice!; + if (addInvoice.invoiceFor!.first == Constants.chooseInvoiceForTypes[1]) { + selectedCustomerCompany = StoreCustomer( + id: addInvoice.supplier!.id ?? "", + name: addInvoice.supplier!.name ?? "Choose"); + addInvoice.customerId = addInvoice.supplier!.id ?? ""; + } else if (addInvoice.customer != null) { + selectedCustomerCompany = StoreCustomer( + id: addInvoice.customer!.id ?? "", + name: addInvoice.customer!.name ?? "Choose"); + addInvoice.customerId = addInvoice.customer!.id ?? ""; + } + + if (addInvoice.invoiceFor!.isNotEmpty) { + selectedInvoiceFor = addInvoice.invoiceFor!.first; + } + + for (var product in addInvoice.products) { + selectedProduct = []; + selectedDiscount = []; + selectedTax = []; + selectedMeasurement = []; + selectedProduct.add(product.name ?? ''); + selectedDiscount.add(StoreDiscount( + categories: [], + products: [], + discountPercentage: product.discountPercentage?.toString() ?? '')); + selectedTax.add(VAT(name: 'VAT', value: product.vat?.toString() ?? '')); + selectedMeasurement.add(Measurement(name: product.measurement ?? '')); + } + isLoadingFirst = false; + } + + Future getProducts() async { + final response = await WosulRepository().getAllProducts(); + filteredProductItems.addAll(response); + } +} diff --git a/lib/application/views/salesandordermodule/views/invoiceModule/viewModels/ReturnDamageInvoiceViewModel.dart b/lib/application/views/salesandordermodule/views/invoiceModule/viewModels/ReturnDamageInvoiceViewModel.dart new file mode 100644 index 0000000..0204197 --- /dev/null +++ b/lib/application/views/salesandordermodule/views/invoiceModule/viewModels/ReturnDamageInvoiceViewModel.dart @@ -0,0 +1,227 @@ +import 'dart:developer'; + +import 'package:flutter/material.dart'; +import 'package:wosull/application/model/SimpleResponsModel.dart'; +import 'package:wosull/application/model/StockTransfer/ProductItemCategoryModel.dart'; +import 'package:wosull/application/model/invoice/ReturnDamageInvoiceModel.dart'; +import 'package:wosull/application/model/invoice/StoreInvoice.dart'; +import 'package:wosull/application/model/store/StoreInvoicesModel.dart'; +import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/utils/CRUDOperatoinState.dart'; +import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/helpers/Utils.dart'; + +class ReturnDamageInvoiceViewModel with ChangeNotifier { + bool isPortrait = true; + bool isLoadingData = false; + List selectedProduct = []; + List quantityControllers = []; + var returnDamageOrder = ReturnDamageInvoiceModel(); + late StoreInvoice storeInvoice; + bool isReturn = false; + + var _crudOperation = CRUDOperationState.uninitialized; + + CRUDOperationState get crudOperation => _crudOperation; + + void setLoading(bool value) { + isLoadingData = value; + notifyListeners(); + } + + void initData(bool isReturn, StoreInvoice storeInvoice) { + this.isReturn = isReturn; + this.storeInvoice = storeInvoice; + returnDamageOrder.returnDamageOrderDetails.addAll(storeInvoice.products); + + for (var product in storeInvoice.products) { + selectedProduct.add(product.name ?? ''); + quantityControllers.add(product.totalQuantity?.toString() ?? ''); + } + notifyListeners(); + } + + Future returnInvoice() async { + bool isChecked = false; + for (var product in storeInvoice.products) { + isChecked = product.isChecked!; + if (isChecked) { + break; + } + } + + if (!isChecked) { + Utils.showMessage('Please select item for return'); + } else { + for (var product in storeInvoice.products) { + isChecked = product.isChecked!; + } + if (storeInvoice.products.length == 1) { + await update(); + return; + } + + if (isChecked) { + await update(); + return; + } + + getTotalProductsPrice(); + getTotalDiscount(); + getTotalVatDiscount(); + returnDamageOrder.status = isReturn ? 'Return' : 'Damage'; + setLoading(true); + log(returnDamageOrder.toJson().toString()); + await APIManager() + .fetchData(Constants.RETURN_OR_DAMAGE + storeInvoice.id!, + returnDamageOrder.toJson()) + .then((value) { + final response = SimpleResponseModel.fromJson(value); + if (response.success) { + _crudOperation = CRUDOperationState.update; + // Navigator.pop(context, true); + } else { + _crudOperation = CRUDOperationState.error; + } + setLoading(false); + }).onError((error, stackTrace) { + print('bestSeller ' + error.toString()); + }); + } + } + + Future update() async { + setLoading(true); + Map data = { + 'invoiceId': storeInvoice.id!, + 'status': isReturn ? 'Return' : 'Damage' + }; + final response = + await APIManager().getResponsePatch(Constants.UPDATE_INVOICE, data); + + if (response.success) { + _crudOperation = CRUDOperationState.update; + // Navigator.pop(context, true); + } else { + _crudOperation = CRUDOperationState.error; + } + setLoading(false); + } + + void onRemoveItem(int position) { + selectedProduct.removeAt(position); + quantityControllers.removeAt(position); + if (storeInvoice.products.length > 1) { + returnDamageOrder.details.add(storeInvoice.products[position]); + storeInvoice.products.removeAt(position); + returnDamageOrder.returnDamageOrderDetails.removeAt(position); + } + } + + String getTotalProductsPrice() { + var price = 0.0; + for (var product in storeInvoice.products) { + price += product.amount ?? 0.0; + } + returnDamageOrder.total!.totalAmount = price; + storeInvoice.totalAmount = price; + returnDamageOrder.total!.totalExcludingAmount = price; + returnDamageOrder.total!.totalTaxableAmount = price; + return price.toStringAsFixed(2); + } + + String getTotalDiscount() { + var price = 0.0; + for (var product in storeInvoice.products) { + if (product.discountPercentage != null) { + try { + price += product.discountPercentage!; + } catch (e) { + price += product.discountPercentage!; + } + } + } + returnDamageOrder.total!.totalDiscount = price; + storeInvoice.totalDiscount = price; + return price.toStringAsFixed(2); + } + + String getTotalVatDiscount() { + var price = 0.0; + for (var product in storeInvoice.products) { + price += product.tax ?? 0.0; + } + returnDamageOrder.total!.totalVat = price; + storeInvoice.totalTaxExcluding = price; + return price.toStringAsFixed(2); + } + + double getTaxCalu(int position) { + var totalQuantity = int.parse(quantityControllers[position]); + double totalPrice = totalQuantity * storeInvoice.products[position].price!; + var tax = (totalPrice * storeInvoice.products[position].vat!); + tax = tax / 100; + + return tax; + } + + void onChangeQuantity(int position, String value) { + final unitPrice = storeInvoice.products[position].price!; // 1 pece value + final discount = storeInvoice.products[position].discountPercentage ?? 0.0; + if (discount > 0) { + storeInvoice.products[position].amount = + int.parse(value) * unitPrice - discount; + } else { + storeInvoice.products[position].amount = int.parse(value) * unitPrice; + } + var tax = getTaxCalu(position); + storeInvoice.products[position].tax = tax; + storeInvoice.products[position].amount = + storeInvoice.products[position].amount! + + storeInvoice.products[position].tax!; + notifyListeners(); + } + + void onCheck(int position, bool isChecked) { + storeInvoice.products[position].isChecked = isChecked; + + if (isChecked) { + returnDamageOrder.details.add(storeInvoice.products[position]); + } else { + returnDamageOrder.details.removeWhere((element) => + element.itemId! == storeInvoice.products[position].itemId!); + } + notifyListeners(); + } + + void onAddNewProduct() { + selectedProduct.clear(); + quantityControllers.clear(); + + storeInvoice.products.add(StoreInvoiceProduct( + totalQuantity: 0, + price: 0.0, + vat: 0, + discountPercentage: 0.0, + tax: 0.0, + amount: 0.0, + )); + + notifyListeners(); + } + + void updateProduct(result, index) { + ProductItem response = result; + selectedProduct[index] = response.name!; + final item = storeInvoice.products[index]; + item.price = response.price!; + item.amount = (response.price! * response.total_quantity!).toDouble(); + item.name = response.name; + item.itemId = response.id; + // addInvoice.products[index] = item; + item.totalQuantity = response.total_quantity; + // descriptionsControllers[index].text = response.details!; + quantityControllers[index] = response.total_quantity!.toString(); + // uniPriceControllers[index].text = response.price!.toString(); + } +} diff --git a/lib/application/views/salesandordermodule/views/AddInvoiceAndPrintVC.dart b/lib/application/views/salesandordermodule/views/invoiceModule/views/AddInvoiceAndPrintVC.dart similarity index 56% rename from lib/application/views/salesandordermodule/views/AddInvoiceAndPrintVC.dart rename to lib/application/views/salesandordermodule/views/invoiceModule/views/AddInvoiceAndPrintVC.dart index 8421853..2ee5354 100644 --- a/lib/application/views/salesandordermodule/views/AddInvoiceAndPrintVC.dart +++ b/lib/application/views/salesandordermodule/views/invoiceModule/views/AddInvoiceAndPrintVC.dart @@ -7,10 +7,13 @@ import 'package:wosull/application/network/APIManager.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/utils/AppLoader.dart'; import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/salesandordermodule/views/invoiceModule/views/InvoiceMakePaymentVC.dart'; import 'package:wosull/application/views/salesandordermodule/views/invoiceModule/widgets/InvoiceItemListView.dart'; import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/ThemeImage.dart'; import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/widgets/CustomAppBar.dart'; +import 'package:wosull/widgets/CustomSimpleButton.dart'; import 'package:wosull/widgets/IconButton.dart'; import 'package:wosull/widgets/QRCodeGenerate.dart'; @@ -24,16 +27,10 @@ class AddInvoiceAndPrintVC extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( + backgroundColor: MyColors.fillColor, resizeToAvoidBottomInset: true, - appBar: AppBar( - leading: BackButton( - color: MyColors.black1, - onPressed: () { - Navigator.pop(context); - }, // <-- SEE HERE - ), - backgroundColor: MyColors.white, - elevation: 0, + appBar: CustomAppBar( + heading: '', ), body: FutureBuilder( future: getInvoiceById(), @@ -46,14 +43,15 @@ class AddInvoiceAndPrintVC extends StatelessWidget { MediaQuery.of(context).orientation == Orientation.portrait; return SingleChildScrollView( child: Container( - width: double.infinity, color: MyColors.white, + width: double.infinity, padding: const EdgeInsets.all(12), child: Column( mainAxisAlignment: MainAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end, children: [ Container( + color: MyColors.white, margin: isPortrait ? EdgeInsets.zero : const EdgeInsets.fromLTRB(80, 0, 80, 0), @@ -72,22 +70,27 @@ class AddInvoiceAndPrintVC extends StatelessWidget { icon: Icons.print, ), ), - // AppSpaces.horizontalSmall, - // SizedBox( - // width: 150, - // child: CustomIconButton( - // textColor: MyColors.white, - // backgroundColor: MyColors.blueThemeColor, - // heading: AppLocalizations.of(context)!.download, - // onPressed: () {}, - // icon: Icons.download, - // ), - // ), + AppSpaces.horizontalSmall, + SizedBox( + width: 130, + child: CustomSimpleButton( + textColor: MyColors.white, + backGroundColor: MyColors.blueThemeColor, + heading: + storeInvoice.status!.toLowerCase() == 'paid' + ? "Payment History" + : "Make Payment", + onPressed: () { + showMakePayment(context); + }, + ), + ), ], ), ), AppSpaces.verticalLarge, Container( + color: MyColors.white, margin: isPortrait ? const EdgeInsets.only(top: 20) : const EdgeInsets.fromLTRB(80, 0, 80, 0), @@ -104,7 +107,7 @@ class AddInvoiceAndPrintVC extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Image.asset(ThemeImage.logo), + Image.asset(ThemeImage.wosulLogo, width: 80), AppSpaces.verticalMedium, QRCodeGenerate( code: '123', @@ -130,7 +133,9 @@ class AddInvoiceAndPrintVC extends StatelessWidget { CrossAxisAlignment.end, children: [ Text( - storeInvoice.supplier != null + storeInvoice.invoiceFor! + .first == + "Company" ? storeInvoice .supplier!.name ?? '' @@ -148,7 +153,8 @@ class AddInvoiceAndPrintVC extends StatelessWidget { ), AppSpaces.verticalMedium, Text( - storeInvoice.supplier != null + storeInvoice.invoiceFor!.first == + "Company" ? storeInvoice .supplier!.address ?? 'N/A' @@ -171,7 +177,8 @@ class AddInvoiceAndPrintVC extends StatelessWidget { ), AppSpaces.horizontalSmall, Text( - storeInvoice.supplier != null + storeInvoice.invoiceFor!.first == + "Company" ? storeInvoice .supplier!.email ?? 'N/A' @@ -196,7 +203,9 @@ class AddInvoiceAndPrintVC extends StatelessWidget { ), AppSpaces.horizontalSmall, Text( - storeInvoice.supplier != null + storeInvoice.invoiceFor! + .first == + "Company" ? storeInvoice.supplier! .contact ?? 'N/A' @@ -251,7 +260,6 @@ class AddInvoiceAndPrintVC extends StatelessWidget { isPortrait ? Container( margin: const EdgeInsets.only(top: 12), - width: 300, child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: @@ -264,7 +272,8 @@ class AddInvoiceAndPrintVC extends StatelessWidget { CrossAxisAlignment.end, children: [ Text( - storeInvoice.supplier != null + storeInvoice.invoiceFor?.first == + "Company" ? storeInvoice.supplier!.name ?? 'N/A' : storeInvoice.customer!.name ?? @@ -280,7 +289,8 @@ class AddInvoiceAndPrintVC extends StatelessWidget { ), AppSpaces.verticalMedium, Text( - storeInvoice.supplier != null + storeInvoice.invoiceFor!.first == + "Company" ? storeInvoice.supplier!.address ?? 'N/A' : storeInvoice.customer!.address ?? @@ -301,7 +311,8 @@ class AddInvoiceAndPrintVC extends StatelessWidget { ), AppSpaces.horizontalSmall, Text( - storeInvoice.supplier != null + storeInvoice.invoiceFor!.first == + "Company" ? storeInvoice .supplier!.email ?? 'N/A' @@ -326,7 +337,8 @@ class AddInvoiceAndPrintVC extends StatelessWidget { ), AppSpaces.horizontalSmall, Text( - storeInvoice.supplier != null + storeInvoice.invoiceFor!.first == + "Company" ? storeInvoice .supplier!.contact ?? 'N/A' @@ -377,15 +389,10 @@ class AddInvoiceAndPrintVC extends StatelessWidget { ), ) : Container(), - Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Expanded( - flex: 2, - child: Container( - padding: const EdgeInsets.only(top: 16), - child: Row( + isPortrait + ? Column( + children: [ + Row( children: [ Expanded( child: Column( @@ -426,7 +433,8 @@ class AddInvoiceAndPrintVC extends StatelessWidget { MainAxisAlignment.end, children: [ Text( - storeInvoice.supplier != null + storeInvoice.invoiceFor!.first == + "Company" ? storeInvoice .supplier!.name ?? 'N/A' @@ -437,7 +445,8 @@ class AddInvoiceAndPrintVC extends StatelessWidget { ), AppSpaces.verticalMedium, Text( - storeInvoice.supplier != null + storeInvoice.invoiceFor!.first == + "Company" ? storeInvoice .supplier!.email ?? 'N/A' @@ -448,7 +457,8 @@ class AddInvoiceAndPrintVC extends StatelessWidget { ), AppSpaces.verticalMedium, Text( - storeInvoice.supplier != null + storeInvoice.invoiceFor!.first == + "Company" ? storeInvoice .supplier!.contact ?? 'N/A' @@ -466,13 +476,8 @@ class AddInvoiceAndPrintVC extends StatelessWidget { ) ], ), - )), - const Spacer(), - Expanded( - flex: 2, - child: Container( - padding: const EdgeInsets.only(top: 16), - child: Row( + AppSpaces.verticalMedium, + Row( children: [ Expanded( child: Column( @@ -524,22 +529,199 @@ class AddInvoiceAndPrintVC extends StatelessWidget { ], ), ], - ), - )), - ], - ), + ) + ], + ) + : Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + flex: 2, + child: Container( + padding: + const EdgeInsets.only(top: 16), + child: Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + Text( + AppLocalizations.of( + context)! + .cust_name, + style: + ThemeText.robotoHeading, + ), + AppSpaces.verticalMedium, + Text( + AppLocalizations.of( + context)! + .email_address, + style: + ThemeText.robotoHeading, + ), + AppSpaces.verticalMedium, + Text( + AppLocalizations.of( + context)! + .telephone, + style: + ThemeText.robotoHeading, + ), + AppSpaces.verticalMedium, + Text( + AppLocalizations.of( + context)! + .vat_number, + style: + ThemeText.robotoHeading, + ), + ], + )), + Column( + crossAxisAlignment: + CrossAxisAlignment.end, + mainAxisAlignment: + MainAxisAlignment.end, + children: [ + Text( + storeInvoice.invoiceFor! + .first == + "Company" + ? storeInvoice.supplier! + .name ?? + 'N/A' + : storeInvoice.customer! + .name ?? + 'N/A', + style: + ThemeText.robotoValue, + ), + AppSpaces.verticalMedium, + Text( + storeInvoice.invoiceFor!.first == + "Company" + ? storeInvoice.supplier! + .email ?? + 'N/A' + : storeInvoice.customer! + .email ?? + 'N/A', + style: + ThemeText.robotoValue, + ), + AppSpaces.verticalMedium, + Text( + storeInvoice.invoiceFor! + .first == + "Company" + ? storeInvoice.supplier! + .contact ?? + 'N/A' + : storeInvoice.customer! + .contact ?? + 'N/A', + style: + ThemeText.robotoValue, + ), + AppSpaces.verticalMedium, + Text( + storeInvoice.vatNumber ?? + '', + style: + ThemeText.robotoValue, + ), + ], + ) + ], + ), + )), + const Spacer(), + Expanded( + flex: 2, + child: Container( + padding: + const EdgeInsets.only(top: 16), + child: Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + Text( + AppLocalizations.of( + context)! + .invoice_no, + style: ThemeText + .robotoHeading), + AppSpaces.verticalMedium, + Text( + AppLocalizations.of( + context)! + .invoice_issue_date, + style: ThemeText + .robotoHeading), + AppSpaces.verticalMedium, + Text( + AppLocalizations.of( + context)! + .date_of_supply, + style: ThemeText + .robotoHeading), + ], + )), + Column( + crossAxisAlignment: + CrossAxisAlignment.end, + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + Text( + storeInvoice.uniqueId! + .toString(), + style: ThemeText + .robotoValue), + AppSpaces.verticalMedium, + Text( + DataTimeFormat + .getFormatDateString( + storeInvoice + .invoiceDate!), + style: ThemeText + .robotoValue), + AppSpaces.verticalMedium, + Text( + DataTimeFormat + .getFormatDateString( + storeInvoice + .invoiceDueDate!), + style: ThemeText + .robotoValue), + ], + ), + ], + ), + )), + ], + ), AppSpaces.verticalLarge, - InvoiceItemListView(storeInvoice.products), + InvoiceItemListView( + storeInvoice.products, + isPortrait: isPortrait, + ), AppSpaces.verticalLarge, - Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Expanded( - flex: 1, - child: Container( - padding: const EdgeInsets.only(top: 16), - child: Row( + isPortrait + ? Column( + children: [ + Row( children: [ Expanded( child: Column( @@ -571,38 +753,37 @@ class AddInvoiceAndPrintVC extends StatelessWidget { )), Column( crossAxisAlignment: - CrossAxisAlignment.start, + CrossAxisAlignment.end, mainAxisAlignment: - MainAxisAlignment.start, + MainAxisAlignment.end, children: [ Text( AppLocalizations.of(context)! .bank_name, + textAlign: TextAlign.right, style: ThemeText.robotoValue), AppSpaces.verticalMedium, - const Text('N/A', + Text('N/A', + textAlign: TextAlign.right, style: ThemeText.robotoValue), AppSpaces.verticalMedium, - const Text( + Text( 'N/A', + textAlign: TextAlign.right, style: ThemeText.robotoValue, ), AppSpaces.verticalMedium, - const Text( + Text( 'N/A', + textAlign: TextAlign.right, style: ThemeText.robotoValue, ), ], ), ], ), - )), - AppSpaces.horizontalMedium, - Expanded( - flex: 1, - child: Container( - padding: const EdgeInsets.only(top: 16), - child: Column( + AppSpaces.verticalMedium, + Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: @@ -617,8 +798,9 @@ class AddInvoiceAndPrintVC extends StatelessWidget { ), const Spacer(), Text( - storeInvoice.totalTaxExcluding! - .toString(), + storeInvoice.totalTaxExcluding + ?.toStringAsFixed(2) ?? + '', style: ThemeText.robotoValue, ), ], @@ -649,8 +831,9 @@ class AddInvoiceAndPrintVC extends StatelessWidget { style: ThemeText.robotoHeading, )), Text( - storeInvoice.totalTaxableAmount! - .toString(), + storeInvoice.totalTaxableAmount + ?.toStringAsFixed(2) ?? + '', style: ThemeText.robotoValue, ), ], @@ -666,7 +849,9 @@ class AddInvoiceAndPrintVC extends StatelessWidget { ), ), Text( - storeInvoice.totalTax!.toString(), + storeInvoice.totalTax + ?.toStringAsFixed(2) ?? + '', style: ThemeText.robotoValue, ), ], @@ -688,10 +873,207 @@ class AddInvoiceAndPrintVC extends StatelessWidget { ], ), ], - ), - )), - ], - ), + ) + ], + ) + : Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + flex: 1, + child: Container( + padding: + const EdgeInsets.only(top: 16), + child: Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + Text( + AppLocalizations.of( + context)! + .bank_name, + style: ThemeText + .robotoHeading), + AppSpaces.verticalMedium, + Text( + AppLocalizations.of( + context)! + .iban_number, + style: ThemeText + .robotoHeading), + AppSpaces.verticalMedium, + Text( + AppLocalizations.of( + context)! + .name, + style: ThemeText + .robotoHeading), + AppSpaces.verticalMedium, + Text( + AppLocalizations.of( + context)! + .comments, + style: ThemeText + .robotoHeading), + ], + )), + Column( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + Text( + AppLocalizations.of( + context)! + .bank_name, + style: ThemeText + .robotoValue), + AppSpaces.verticalMedium, + Text('N/A', + style: ThemeText + .robotoValue), + AppSpaces.verticalMedium, + Text( + 'N/A', + style: + ThemeText.robotoValue, + ), + AppSpaces.verticalMedium, + Text( + 'N/A', + style: + ThemeText.robotoValue, + ), + ], + ), + ], + ), + )), + AppSpaces.horizontalMedium, + Expanded( + flex: 1, + child: Container( + padding: + const EdgeInsets.only(top: 16), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + Row( + children: [ + Text( + AppLocalizations.of( + context)! + .total_excluding_vat, + style: + ThemeText.robotoHeading, + ), + const Spacer(), + Text( + storeInvoice + .totalTaxExcluding + ?.toStringAsFixed( + 2) ?? + '', + style: + ThemeText.robotoValue, + ), + ], + ), + AppSpaces.verticalMedium, + Row( + children: [ + Text( + AppLocalizations.of( + context)! + .discount, + style: + ThemeText.robotoHeading, + ), + const Spacer(), + Text( + storeInvoice.totalDiscount! + .toString(), + style: + ThemeText.robotoValue, + ), + ], + ), + AppSpaces.verticalMedium, + Row( + children: [ + Expanded( + child: Text( + AppLocalizations.of( + context)! + .total_taxable_amount_excluding, + style: + ThemeText.robotoHeading, + )), + Text( + storeInvoice + .totalTaxableAmount + ?.toStringAsFixed( + 2) ?? + '', + style: + ThemeText.robotoValue, + ), + ], + ), + AppSpaces.verticalMedium, + Row( + children: [ + Expanded( + child: Text( + AppLocalizations.of( + context)! + .total_vat, + style: ThemeText + .robotoHeading, + ), + ), + Text( + storeInvoice.totalTax + ?.toStringAsFixed( + 2) ?? + '', + style: + ThemeText.robotoValue, + ), + ], + ), + AppSpaces.verticalMedium, + Row( + children: [ + Text( + AppLocalizations.of( + context)! + .total_amount_due, + style: ThemeText.robotoBig, + ), + const Spacer(), + Text( + storeInvoice.totalAmount! + .toString(), + style: ThemeText.robotoBig, + ), + ], + ), + ], + ), + )), + ], + ), AppSpaces.verticalLarge, Container( width: double.infinity, @@ -736,4 +1118,18 @@ class AddInvoiceAndPrintVC extends StatelessWidget { return true; } + + Future showMakePayment(BuildContext context) async { + final result = await showDialog( + barrierColor: Colors.black26, + context: context, + builder: (context) { + return InvoiceMakePaymentVC(storeInvoice); + }, + ); + + if (result != null) { + Navigator.pop(context, true); + } + } } diff --git a/lib/application/views/salesandordermodule/views/invoiceModule/views/InvoiceMakePaymentVC.dart b/lib/application/views/salesandordermodule/views/invoiceModule/views/InvoiceMakePaymentVC.dart new file mode 100644 index 0000000..c7e85a8 --- /dev/null +++ b/lib/application/views/salesandordermodule/views/invoiceModule/views/InvoiceMakePaymentVC.dart @@ -0,0 +1,469 @@ +import 'package:dropdown_search/dropdown_search.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:provider/provider.dart'; +import 'package:wosull/application/model/invoice/Account.dart'; +import 'package:wosull/application/model/invoice/PaymentMethod.dart'; +import 'package:wosull/application/model/invoice/StoreInvoice.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/CRUDOperatoinState.dart'; +import 'package:wosull/application/views/salesandordermodule/views/invoiceModule/viewModels/MakePaymentViewModel.dart'; +import 'package:wosull/application/views/salesandordermodule/views/invoiceModule/widgets/AmountWidget.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeDropDown.dart'; +import 'package:wosull/helpers/ThemePadding.dart'; +import 'package:wosull/widgets/BorderContainer.dart'; +import 'package:wosull/widgets/ChildContainer.dart'; +import 'package:wosull/widgets/CustomOptionalTitle.dart'; +import 'package:wosull/widgets/CustomSimpleButton.dart'; +import 'package:wosull/widgets/CustomTextButtonIcon.dart'; +import 'package:wosull/widgets/CustomTextFieldForm.dart'; +import 'package:wosull/widgets/DialogHeader.dart'; +import 'package:wosull/widgets/DropdownItemBuilder.dart'; +import 'package:wosull/widgets/HeadingContainer.dart'; +import 'package:wosull/widgets/MandatoryTitleText.dart'; +import 'package:wosull/widgets/ValueText.dart'; + +class InvoiceMakePaymentVC extends StatefulWidget { + late StoreInvoice storeInvoice; + + InvoiceMakePaymentVC(this.storeInvoice, {super.key}); + + @override + State createState() => _InvoiceMakePaymentVCState(); +} + +class _InvoiceMakePaymentVCState extends State { + var viewModel = MakePaymentViewModel(); + + @override + void initState() { + if (widget.storeInvoice.status!.toLowerCase() != "paid") { + context.read().initData(widget.storeInvoice); + } + super.initState(); + } + + @override + void dispose() { + viewModel.disposeData(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + viewModel = context.watch(); + return Directionality( + textDirection: TextDirection.ltr, + child: Dialog( + elevation: 0, + backgroundColor: const Color(0xffffffff), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: OrientationBuilder(builder: (c, orientation) { + viewModel.isPortrait = + MediaQuery.of(c).orientation == Orientation.portrait; + + return SingleChildScrollView( + child: Container( + width: !viewModel.isPortrait + ? MediaQuery.of(context).size.width / 1.2 + : double.infinity, + padding: const EdgeInsets.only(bottom: ThemePadding.medium), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + DialogHeader(title: 'Make Payment'), + Padding( + padding: const EdgeInsets.all(ThemePadding.medium), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + widget.storeInvoice.paymentHistory!.isNotEmpty + ? getPaymentHistory() + : Container(), + widget.storeInvoice.paymentHistory!.isNotEmpty + ? AppSpaces.verticalLarge + : Container(), + Row( + children: [ + Expanded( + child: AmountWidget( + title: 'Total Amount', + amount: widget.storeInvoice.totalAmount + ?.toStringAsFixed(2) ?? + '', + )), + AppSpaces.horizontalSmall, + Expanded( + child: AmountWidget( + title: 'Paid Amount', + amount: widget.storeInvoice.totalPaidAmount + ?.toStringAsFixed(2) ?? + '', + )), + AppSpaces.horizontalSmall, + Expanded( + child: AmountWidget( + title: 'Pending Amount', + amount: widget.storeInvoice.totalPendingAmount + ?.toStringAsFixed(2) ?? + '', + )), + ], + ), + AppSpaces.verticalMedium, + Visibility( + visible: + widget.storeInvoice.status!.toLowerCase() != + 'paid', + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Flexible(child: getTransactionDate()), + AppSpaces.horizontalMedium, + Flexible(child: getAccountWidget()), + ], + ), + AppSpaces.verticalMedium, + Row( + children: [ + Flexible(child: getAmountWidget()), + AppSpaces.horizontalMedium, + Flexible(child: getPaymentMethodWidget()), + ], + ), + AppSpaces.verticalMedium, + const CustomOptionalTitle(hint: 'Notes'), + AppSpaces.verticalSmall, + CustomTextFieldForm( + height: 100, + maxLines: 5, + onChanged: (value) {}, + hintText: 'Notes') + ], + )) + ], + ), + ), + Visibility( + visible: + widget.storeInvoice.status!.toLowerCase() != 'paid', + child: Padding( + padding: const EdgeInsets.only(right: 12), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + SizedBox( + width: 120, + child: CustomSimpleButton( + textColor: MyColors.white, + backGroundColor: MyColors.blueThemeColor, + onPressed: () { + Navigator.pop(context); + }, + heading: AppLocalizations.of(context)!.cancel, + ), + ), + AppSpaces.horizontalMedium, + SizedBox( + width: 120, + child: CustomSimpleButton( + textColor: MyColors.white, + isLoading: viewModel.isLoading, + backGroundColor: MyColors.blueThemeColor, + onPressed: () async { + await viewModel.isValidate(); + checkState(); + }, + heading: 'Continue', + ), + ), + ], + ), + ), + ) + ], + ), + ), + ); + }), + )); + } + + getTransactionDate() { + return Column( + children: [ + const MandatoryTitleText(hint: 'Transaction Date'), + AppSpaces.verticalSmall, + CustomTextButtonIcon( + backgroundColor: MyColors.backFillColor, + heading: viewModel.date.isEmpty ? 'dd/mm/yyy' : viewModel.date, + onPressed: () { + viewModel.presentDatePicker(context); + }, + icon: Icons.calendar_today) + ], + ); + } + + getAccountWidget() { + return Column( + children: [ + const MandatoryTitleText(hint: 'Account'), + AppSpaces.verticalSmall, + DropdownSearch( + selectedItem: viewModel.selectedAccount, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: viewModel.accounts, + itemAsString: (Account u) => u.name, + onChanged: (Account? data) { + viewModel.setAccount(data); + }, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), + ) + ], + ); + } + + getAmountWidget() { + return Column( + children: [ + const MandatoryTitleText(hint: 'Amount'), + AppSpaces.verticalSmall, + CustomTextFieldForm( + initialValue: + widget.storeInvoice.totalAmount?.toStringAsFixed(2) ?? '', + onChanged: (value) { + viewModel.updateAmount(value); + }, + hintText: 'Enter amount') + ], + ); + } + + getPaymentMethodWidget() { + return Column( + children: [ + const MandatoryTitleText(hint: 'Account'), + AppSpaces.verticalSmall, + DropdownSearch( + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.paymentMethod!); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: viewModel.paymentMethod, + itemAsString: (PaymentMethod u) => u.paymentMethod!, + onChanged: (PaymentMethod? data) { + viewModel.setPaymentMethod(data); + }, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), + ) + ], + ); + } + + getPaymentHistory() { + return Column( + children: [ + // viewModel.isPortrait + // ? Container() + // : + BorderContainer( + child: Row( + children: [ + Expanded( + child: HeadingContainer( + heading: 'Date', + ), + ), + Expanded( + child: HeadingContainer( + heading: AppLocalizations.of(context)!.amount, + ), + ), + Expanded( + child: HeadingContainer( + heading: AppLocalizations.of(context)!.payment_mode, + ), + ), + Expanded( + child: HeadingContainer( + heading: AppLocalizations.of(context)!.notes, + ), + ), + ], + ), + ), + ListView.builder( + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (c, position) { + // if (viewModel.isPortrait) { + // return WrapHeightContainer( + // child: Row( + // crossAxisAlignment: CrossAxisAlignment.start, + // mainAxisAlignment: MainAxisAlignment.start, + // children: [ + // Expanded( + // flex: 2, + // child: Container( + // padding: const EdgeInsets.only(bottom: 8), + // child: Row( + // crossAxisAlignment: CrossAxisAlignment.start, + // mainAxisAlignment: MainAxisAlignment.start, + // children: [ + // Expanded( + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // mainAxisAlignment: MainAxisAlignment.start, + // children: [ + // PortraitContainer( + // width: double.infinity, + // child: Align( + // alignment: Alignment.centerLeft, + // child: HeadingText( + // 'Date', + // ), + // ), + // ), + // PortraitContainer( + // width: double.infinity, + // child: Align( + // alignment: Alignment.centerLeft, + // child: HeadingText( + // AppLocalizations.of(context)!.amount, + // ), + // ), + // ), + // PortraitContainer( + // width: double.infinity, + // child: Align( + // alignment: Alignment.centerLeft, + // child: HeadingText( + // AppLocalizations.of(context)! + // .payment_mode, + // ), + // ), + // ), + // PortraitContainer( + // width: double.infinity, + // child: Align( + // alignment: Alignment.centerLeft, + // child: HeadingText( + // AppLocalizations.of(context)!.notes, + // ), + // ), + // ), + // ], + // )), + // Expanded( + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // mainAxisAlignment: MainAxisAlignment.start, + // children: [ + // PortraitContainer( + // width: double.infinity, + // child: Center( + // child: getPaymentDateWidget(position), + // ), + // ), + // PortraitContainer( + // width: double.infinity, + // child: Center( + // child: getPaymentAmountWidget(position), + // ), + // ), + // PortraitContainer( + // width: double.infinity, + // child: Center( + // child: getPaymentAmountMethod(position), + // ), + // ), + // PortraitContainer( + // width: double.infinity, + // child: Center( + // child: getPaymentAmountNotes(position), + // ), + // ), + // ], + // )), + // ], + // ), + // )), + // ], + // ), + // ); + // } else { + return BorderContainer( + backgroundColor: MyColors.white, + child: Row( + children: [ + Expanded( + child: ChildContainer( + child: getPaymentDateWidget(position))), + Expanded( + child: ChildContainer( + child: getPaymentAmountWidget(position), + )), + Expanded( + child: ChildContainer( + child: getPaymentAmountMethod(position), + )), + Expanded( + child: ChildContainer( + child: getPaymentAmountNotes(position), + )), + ], + ), + ); + //} + }, + itemCount: widget.storeInvoice.paymentHistory!.length, + ), + ], + ); + } + + getPaymentDateWidget(int position) { + return ValueText(widget.storeInvoice.paymentHistory![position].date); + } + + getPaymentAmountWidget(int position) { + return ValueText(widget.storeInvoice.paymentHistory![position].amount + .toStringAsFixed(2)); + } + + getPaymentAmountMethod(int position) { + return ValueText( + widget.storeInvoice.paymentHistory![position].paymentMethod); + } + + getPaymentAmountNotes(int position) { + return ValueText(widget.storeInvoice.paymentHistory![position].notes); + } + + void checkState() { + if (viewModel.crudOperation == CRUDOperationState.update) { + Navigator.pop(context, true); + } + } +} diff --git a/lib/application/views/salesandordermodule/views/invoiceModule/views/InvoicesVC.dart b/lib/application/views/salesandordermodule/views/invoiceModule/views/InvoicesVC.dart new file mode 100644 index 0000000..b7b6e7b --- /dev/null +++ b/lib/application/views/salesandordermodule/views/invoiceModule/views/InvoicesVC.dart @@ -0,0 +1,338 @@ +import 'package:dropdown_search/dropdown_search.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:provider/provider.dart'; +import 'package:sizer/sizer.dart'; +import 'package:wosull/application/enum/DataState.dart'; +import 'package:wosull/application/model/invoice/StoreInvoice.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/AppError.dart'; +import 'package:wosull/application/utils/AppLoader.dart'; +import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/popups/DeleteRecordPopUp.dart'; +import 'package:wosull/application/views/salesandordermodule/views/ReturnInvoiceVC.dart'; +import 'package:wosull/application/views/salesandordermodule/views/invoiceModule/viewModels/InvoiceViewModel.dart'; +import 'package:wosull/application/views/salesandordermodule/views/invoiceModule/views/AddInvoiceAndPrintVC.dart'; +import 'package:wosull/application/views/salesandordermodule/views/invoiceModule/views/NewInvoiceVC.dart'; +import 'package:wosull/application/views/salesandordermodule/views/invoiceModule/widgets/InvoiceListView.dart'; +import 'package:wosull/base/BaseStatefulState.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeDropDown.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/widgets/CustomSimpleButton.dart'; +import 'package:wosull/widgets/DropdownItemBuilder.dart'; +import 'package:wosull/widgets/PageLimitDropDown.dart'; +import 'package:wosull/widgets/SearchBox.dart'; + +class InvoicesVC extends StatefulWidget { + String filter = 'All'; + + InvoicesVC({Key? key, this.filter = 'All'}) : super(key: key); + + @override + State createState() => _InvoicesVCState(); +} + +class _InvoicesVCState extends BaseStatefulState { + bool isPortrait = true; + + final viewModel = InvoiceViewModel(); + + late ScrollController _controller; + + @override + void initState() { + context.read().initData(widget.filter); + super.initState(); + } + + @override + Widget build(BuildContext context) { + _controller = ScrollController()..addListener(_scrollNotification); + return Scaffold( + backgroundColor: MyColors.fillColor, + resizeToAvoidBottomInset: true, + body: OrientationBuilder(builder: (c, orientation) { + isPortrait = MediaQuery.of(c).orientation == Orientation.portrait; + + return SingleChildScrollView( + controller: _controller, + child: Container( + padding: const EdgeInsets.all(12), + child: Column( + children: [ + isPortrait + ? Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)!.invoices, + style: ThemeText.textStylePageHeading, + ), + AppSpaces.horizontalSmall, + Flexible( + child: SizedBox( + height: 38, + child: getDropdownFilterType(), + ), + ), + AppSpaces.horizontalSmall, + Flexible( + child: getAddInvoiceButton(), + ), + ], + ), + AppSpaces.verticalSmall, + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Flexible( + child: SizedBox( + height: 48, + child: getSearchBox(), + ), + ), + AppSpaces.horizontalSmall, + getPageLimit() + ], + ), + ], + ) + : Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)!.invoices, + style: ThemeText.textStylePageHeading, + ), + AppSpaces.horizontalSmall, + SizedBox( + height: 38, + width: 160, + child: getDropdownFilterType(), + ), + AppSpaces.horizontalSmall, + SizedBox( + width: 120, + child: getAddInvoiceButton(), + ), + AppSpaces.horizontalSmall, + SizedBox( + width: SizerUtil.deviceType == DeviceType.mobile + ? 200 + : 240, + height: 48, + child: getSearchBox(), + ), + Flexible( + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [getPageLimit()], + )) + ], + ), + AppSpaces.verticalLarge, + ChangeNotifierProvider( + create: (context) => viewModel, + child: Consumer( + builder: (BuildContext context, + InvoiceViewModel controller, Widget? _) { + switch (controller.dataState) { + case DataState.uninitialized: + Future(() { + controller.fetch(filter: widget.filter); + }); + return showData(controller.filteredList); + case DataState.initialFetching: + return AppLoader(); + case DataState.moreFetching: + case DataState.refreshing: + return showData(controller.filteredList); + case DataState.error: + return AppError(); + case DataState.searching: + case DataState.fetched: + case DataState.noMoreData: + return showData(controller.filteredList); + } + }, + ), + ), + ], + ), + ), + ); + })); + } + + Widget showData(List data) { + return Column( + children: [ + InvoiceListView( + isPortrait: isPortrait, + data: data, + onEdit: (invoice) { + toNewInvoice(true, invoice); + }, + onReturn: (invoice) { + onReturnDamage(invoice, true); + }, + onDamage: (invoice) { + onReturnDamage(invoice, false); + }, + onUpdate: (invoice, value) { + _update(invoice.id ?? '', value ?? ''); + }, + onPrintDownload: (invoice) { + onPrint(invoice.id ?? ''); + }, + onDelete: (invoice) { + onDelete(invoice); + }), + if (viewModel.dataState == DataState.moreFetching) AppLoader(), + ], + ); + } + + bool _scrollNotification() { + if (!viewModel.isLoading && _controller.position.extentAfter < 300) { + viewModel.fetch(limit: viewModel.limit); + } + return true; + } + + Future _delete(String id) async { + progressDialogue(context); + await viewModel.delete(id); + hideProgressBar(); + } + + Future _update(String id, String value) async { + progressDialogue(context); + await viewModel.update(id, value); + hideProgressBar(); + } + + Future onReturnDamage(StoreInvoice invoice, bool isReturn) async { + final result = await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => ReturnInvoiceVC( + storeInvoice: invoice, + isReturn: isReturn, + )), + ); + if (!mounted) return; + if (result) { + viewModel.fetch(isRefresh: true); + } + } + + onDelete(StoreInvoice invoice) async { + final result = await showDialog( + barrierColor: Colors.black26, + context: context, + builder: (context) { + return const DeleteRecordPopUp(); + }, + ); + + if (!mounted) return; + if (result) { + _delete(invoice.id!); + } + } + + Future onPrint(String invoiceId) async { + final result = await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => AddInvoiceAndPrintVC(id: invoiceId)), + ); + if (!mounted) return; + if (result != null) { + viewModel.fetch(isRefresh: true, limit: viewModel.limit); + } + } + + void toNewInvoice(bool isEdit, StoreInvoice invoice) async { + final result = await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => NewInvoiceVC( + isEdit: isEdit, + storeInvoice: invoice, + )), + ); + + if (!mounted) return; + if (result != null) { + viewModel.fetch(isRefresh: true, limit: viewModel.limit); + } + } + + getDropdownFilterType() { + return DropdownSearch( + selectedItem: viewModel.filterValue, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item); + }, + menuProps: ThemeDropDown.menuProps, + constraints: const BoxConstraints(maxHeight: 200), + ), + clearButtonProps: ThemeDropDown.clearButton, + items: Constants.invoiceFilterType, + itemAsString: (String u) => u, + onChanged: (String? data) { + viewModel.fetch(isRefresh: true, filter: data!); + }, + dropdownDecoratorProps: + MyColors.dropDownStyle(hint: 'All', fillColor: MyColors.white), + ); + } + + getAddInvoiceButton() { + return CustomSimpleButton( + textColor: MyColors.blueThemeColor, + backGroundColor: MyColors.backColorBlue50, + onPressed: () { + toNewInvoice(false, StoreInvoice(products: [])); + }, + heading: AppLocalizations.of(context)!.new_invoices, + ); + } + + getSearchBox() { + return SearchBox( + onEditingDone: (text) { + filterSearchResults(text); + }, + onChanged: (text) { + filterSearchResults(text); + }, + hint: AppLocalizations.of(context)!.search, + ); + } + + Future filterSearchResults(String query) async { + if (query.isNotEmpty) { + viewModel.search(searchValue: query); + } else { + //doing duration so if there is any call of api in stack + //will not effect on empty + Future.delayed(const Duration(milliseconds: 700), () { + viewModel.search(searchValue: ""); + }); + } + } + + getPageLimit() { + return PageLimitDropdown(onChange: (value) { + viewModel.fetch(isRefresh: true, limit: int.parse(value!)); + }); + } +} diff --git a/lib/application/views/salesandordermodule/views/invoiceModule/views/NewInvoiceVC.dart b/lib/application/views/salesandordermodule/views/invoiceModule/views/NewInvoiceVC.dart new file mode 100644 index 0000000..7b42031 --- /dev/null +++ b/lib/application/views/salesandordermodule/views/invoiceModule/views/NewInvoiceVC.dart @@ -0,0 +1,1472 @@ +import 'package:dropdown_search/dropdown_search.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:provider/provider.dart'; +import 'package:wosull/application/model/Measurement/InventoryMeasurementModel.dart'; +import 'package:wosull/application/model/StockTransfer/ProductItemCategoryModel.dart'; +import 'package:wosull/application/model/WosulSettings.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/application/model/invoice/StoreInvoice.dart'; +import 'package:wosull/application/model/store/GetStoreCurrency.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/AppLoader.dart'; +import 'package:wosull/application/utils/CRUDOperatoinState.dart'; +import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/salesandordermodule/views/invoiceModule/viewModels/NewInvoiceViewModel.dart'; +import 'package:wosull/base/BaseStatefulState.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeDropDown.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/widgets/BorderContainer.dart'; +import 'package:wosull/widgets/ChildContainer.dart'; +import 'package:wosull/widgets/CustomAddButton.dart'; +import 'package:wosull/widgets/CustomAppBar.dart'; +import 'package:wosull/widgets/CustomOptionalTitle.dart'; +import 'package:wosull/widgets/CustomRemoveItemButton.dart'; +import 'package:wosull/widgets/CustomSimpleButton.dart'; +import 'package:wosull/widgets/CustomSwitch.dart'; +import 'package:wosull/widgets/CustomTextAddProduct.dart'; +import 'package:wosull/widgets/CustomTextButtonIcon.dart'; +import 'package:wosull/widgets/CustomTextFieldForm.dart'; +import 'package:wosull/widgets/DropdownItemBuilder.dart'; +import 'package:wosull/widgets/HeadingContainer.dart'; +import 'package:wosull/widgets/HeadingText.dart'; +import 'package:wosull/widgets/MandatoryTitleText.dart'; +import 'package:wosull/widgets/PortraitContainer.dart'; +import 'package:wosull/widgets/TransprentBorderContainer.dart'; +import 'package:wosull/widgets/WrapHeightContainer.dart'; + +import '../../../../../model/customers/GetStoreCustomer.dart'; +import '../../../../../model/discount/StoreDiscountModel.dart'; +import 'AddInvoiceAndPrintVC.dart'; + +class NewInvoiceVC extends StatefulWidget { + StoreInvoice storeInvoice; + + bool isEdit = false; + + NewInvoiceVC({Key? key, required this.isEdit, required this.storeInvoice}) + : super(key: key); + + @override + State createState() => _NewInvoiceVCState(); +} + +class _NewInvoiceVCState extends BaseStatefulState { + var viewModel = NewInvoiceViewModel(); + + @override + void initState() { + context + .read() + .initData(widget.isEdit, widget.storeInvoice); + super.initState(); + } + + @override + void dispose() { + viewModel.disposeData(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + viewModel = context.watch(); + return Scaffold( + backgroundColor: MyColors.fillColor, + resizeToAvoidBottomInset: true, + appBar: CustomAppBar( + heading: widget.isEdit + ? AppLocalizations.of(context)!.edit_invoice + : AppLocalizations.of(context)!.add_invoice), + body: OrientationBuilder(builder: (c, orientation) { + viewModel.isPortrait = + MediaQuery.of(context).orientation == Orientation.portrait; + return SingleChildScrollView( + child: Container( + padding: const EdgeInsets.all(8), + child: viewModel.isLoadingFirst + ? AppLoader() + : Column( + children: [ + AppSpaces.verticalLarge, + Container( + margin: const EdgeInsets.all(4), + decoration: BoxDecoration( + border: Border.all( + color: Colors.transparent, + width: 1, + ), + color: const Color(0xFFadd8e6), + borderRadius: BorderRadius.circular(8.0), + ), + width: double.infinity, + child: const Padding( + padding: EdgeInsets.all(15), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + 'Hello Dear Merchant,', + style: ThemeText.textStyleHeading, + ), + AppSpaces.verticalSmall, + Text( + 'We would like to inform you that Simplified tax invoices are released if an invoice to customer option is selected. Tax invoices are released if an invoice to company option is selected.', + style: ThemeText.textStyleHeading, + ), + ], + ), + ), + ), + AppSpaces.verticalMedium, + Card( + elevation: 5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: Padding( + padding: const EdgeInsets.all(15), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Expanded( + flex: 1, + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + getChooseInvoiceFor(), + AppSpaces.verticalLarge, + getInvoiceDate(), + AppSpaces.verticalLarge, + getSelectedCurrencyWidget(), + viewModel.isPortrait + ? Column( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + AppSpaces.verticalLarge, + getInvoiceFor(), + AppSpaces.verticalLarge, + getInvoiceNumber(), + AppSpaces.verticalLarge, + getInvoiceDueDate(), + AppSpaces.verticalLarge, + getInvoiceReferNo(), + AppSpaces.verticalLarge, + getVatNumber(), + // AppSpaces.verticalLarge, + // getVatNumber(), + ], + ) + : Container() + ], + ), + ), + viewModel.isPortrait + ? Container() + : AppSpaces.horizontalMedium, + viewModel.isPortrait + ? Container() + : Expanded( + flex: 2, + child: Column( + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + Row( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment + .start, + children: [ + getInvoiceFor(), + AppSpaces.verticalLarge, + getInvoiceDueDate(), + AppSpaces.verticalLarge, + getVatNumber() + ], + )), + AppSpaces.horizontalMedium, + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment + .start, + children: [ + getInvoiceNumber(), + AppSpaces.verticalLarge, + getInvoiceReferNo(), + // AppSpaces.verticalLarge, + // getVatNumber() + ], + )), + ], + ), + ], + )), + ], + ), + AppSpaces.verticalLarge, + getStockUpdateOptionWidget() + ], + ), + ), + ), + AppSpaces.verticalLarge, + Card( + elevation: 5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: Padding( + padding: const EdgeInsets.all(15), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.terms, + ), + AppSpaces.verticalSmall, + CustomTextFieldForm( + height: 100, + maxLines: 5, + initialValue: + viewModel.addInvoice.terms ?? '', + onChanged: (value) {}, + hintText: AppLocalizations.of(context)!.terms) + ], + ), + ), + ), + AppSpaces.verticalLarge, + Card( + elevation: 5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: Container( + padding: const EdgeInsets.fromLTRB(8, 16, 8, 16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)! + .search_and_add_products, + style: ThemeText.textStyleHeadingCart, + ), + AppSpaces.verticalMedium, + viewModel.isPortrait + ? Container() + : BorderContainer( + child: Row( + children: [ + HeadingContainer( + heading: + AppLocalizations.of(context)! + .name_or_barcode, + height: 48, + width: 150, + ), + HeadingContainer( + heading: + AppLocalizations.of(context)! + .description, + height: 48, + width: 100, + ), + HeadingContainer( + heading: + AppLocalizations.of(context)! + .quantity, + height: 48, + width: 60, + ), + HeadingContainer( + heading: + AppLocalizations.of(context)! + .unit_price, + height: 48, + width: 80, + ), + Expanded( + child: HeadingContainer( + heading: + AppLocalizations.of(context)! + .discount_type, + ), + ), + Expanded( + child: HeadingContainer( + heading: + AppLocalizations.of(context)! + .discount, + ), + ), + Expanded( + child: HeadingContainer( + heading: + AppLocalizations.of(context)! + .select_tax, + ), + ), + Expanded( + child: HeadingContainer( + heading: + AppLocalizations.of(context)! + .measurement, + ), + ), + HeadingContainer( + heading: 'Tax %', + ), + HeadingContainer( + heading: + AppLocalizations.of(context)! + .amount, + width: 54, + height: 48, + ), + HeadingContainer( + heading: '', + width: 44, + height: 48, + ), + ], + ), + ), + ListView.builder( + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (c, position) { + if (viewModel.isPortrait) { + return WrapHeightContainer( + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + Container( + height: 59, + decoration: const BoxDecoration( + border: Border( + bottom: BorderSide( + width: 1.0, + color: MyColors + .fillColorGray2), + ), + ), + child: getRemoveProductButton( + position), + ), + Expanded( + flex: 2, + child: Container( + decoration: const BoxDecoration( + border: Border( + left: BorderSide( + width: 1.0, + color: MyColors + .fillColorGray2), + ), + ), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment + .start, + mainAxisAlignment: + MainAxisAlignment + .start, + children: [ + PortraitContainer( + width: + double.infinity, + child: Align( + alignment: Alignment + .centerLeft, + child: HeadingText( + AppLocalizations.of( + context)! + .name_or_barcode, + ), + ), + ), + PortraitContainer( + width: + double.infinity, + child: Align( + alignment: Alignment + .centerLeft, + child: HeadingText( + AppLocalizations.of( + context)! + .description, + ), + ), + ), + PortraitContainer( + width: + double.infinity, + child: Align( + alignment: Alignment + .centerLeft, + child: HeadingText( + AppLocalizations.of( + context)! + .quantity, + ), + ), + ), + PortraitContainer( + width: + double.infinity, + child: Align( + alignment: Alignment + .centerLeft, + child: HeadingText( + AppLocalizations.of( + context)! + .unit_price, + ), + ), + ), + PortraitContainer( + width: + double.infinity, + child: Align( + alignment: Alignment + .centerLeft, + child: HeadingText( + AppLocalizations.of( + context)! + .discount_type, + ), + ), + ), + PortraitContainer( + width: + double.infinity, + child: Align( + alignment: Alignment + .centerLeft, + child: HeadingText( + AppLocalizations.of( + context)! + .discount, + ), + ), + ), + PortraitContainer( + width: + double.infinity, + child: Align( + alignment: Alignment + .centerLeft, + child: HeadingText( + AppLocalizations.of( + context)! + .select_tax, + ), + ), + ), + PortraitContainer( + width: + double.infinity, + child: Align( + alignment: Alignment + .centerLeft, + child: HeadingText( + AppLocalizations.of( + context)! + .measurement, + ), + ), + ), + PortraitContainer( + width: + double.infinity, + child: Align( + alignment: Alignment + .centerLeft, + child: HeadingText( + 'Tax %', + ), + ), + ), + PortraitContainer( + width: + double.infinity, + child: Align( + alignment: Alignment + .centerLeft, + child: HeadingText( + AppLocalizations.of( + context)! + .amount, + ), + ), + ), + ], + )), + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment + .start, + mainAxisAlignment: + MainAxisAlignment + .start, + children: [ + PortraitContainer( + width: + double.infinity, + child: getItemsWidget( + position), + ), + PortraitContainer( + width: + double.infinity, + child: Center( + child: + getProductDescription( + position), + ), + ), + PortraitContainer( + width: + double.infinity, + child: Center( + child: + getProductQuantity( + position), + ), + ), + PortraitContainer( + width: + double.infinity, + child: Center( + child: + getProductPrice( + position), + ), + ), + PortraitContainer( + width: + double.infinity, + child: + getDiscountsTypes( + position), + ), + PortraitContainer( + width: + double.infinity, + child: getDiscounts( + position), + ), + PortraitContainer( + width: + double.infinity, + child: getTaxWidget( + position), + ), + PortraitContainer( + width: + double.infinity, + child: + getMeasurementWidget( + position), + ), + PortraitContainer( + width: + double.infinity, + child: Align( + alignment: Alignment + .centerRight, + child: + getSingleItemTaxWidget( + position), + ), + ), + PortraitContainer( + width: + double.infinity, + child: Align( + alignment: Alignment + .centerRight, + child: + getSingleItemAmountWidget( + position), + ), + ), + ], + )), + ], + ), + )), + ], + ), + ); + } else { + return WrapHeightContainer( + child: Row( + children: [ + ChildContainer( + width: 150, + child: getItemsWidget(position), + ), + ChildContainer( + width: 100, + child: Center( + child: getProductDescription( + position), + ), + ), + ChildContainer( + width: 60, + child: Center( + child: + getProductQuantity(position), + ), + ), + ChildContainer( + width: 80, + child: Center( + child: getProductPrice(position), + ), + ), + Expanded( + child: ChildContainer( + child: getDiscountsTypes(position), + )), + Expanded( + child: ChildContainer( + child: getDiscounts(position), + )), + Expanded( + child: ChildContainer( + child: getTaxWidget(position), + )), + Expanded( + child: ChildContainer( + child: + getMeasurementWidget(position), + )), + ChildContainer( + width: 44, + child: getSingleItemTaxWidget( + position), + ), + ChildContainer( + width: 54, + child: getSingleItemAmountWidget( + position), + ), + getRemoveProductButton(position) + ], + ), + ); + } + }, + itemCount: viewModel.addInvoice.products.length, + ), + viewModel.isPortrait + ? BorderContainer( + backgroundColor: MyColors.white, + child: Row( + children: [ + Container( + decoration: const BoxDecoration( + border: Border( + right: BorderSide( + width: 1.0, + color: MyColors + .fillColorGray2), + ), + ), + child: getAddItemButtonWidget(), + ), + Expanded( + child: ChildContainer( + height: 48, + child: Center( + child: Text( + '', + style: + MyColors.textStyleValue(), + ), + ), + )), + Expanded( + child: ChildContainer( + height: 48, + child: Align( + alignment: Alignment.centerRight, + child: CustomTextAddProduct( + viewModel + .getTotalProductsPrice(), + ), + ), + )), + ], + ), + ) + : BorderContainer( + backgroundColor: MyColors.white, + child: Row( + children: [ + HeadingContainer( + width: 150, + heading: '', + ), + HeadingContainer( + width: 100, + heading: '', + ), + HeadingContainer( + width: 60, + heading: '', + ), + HeadingContainer( + width: 80, + heading: '', + ), + Expanded( + child: HeadingContainer( + heading: '', + )), + Expanded( + child: HeadingContainer( + heading: '', + )), + Expanded( + child: HeadingContainer( + heading: '', + )), + Expanded( + child: HeadingContainer( + heading: '', + )), + HeadingContainer( + width: 44, + heading: '', + ), + HeadingContainer( + width: 54, + heading: '', + ), + getAddItemButtonWidget() + ], + ), + ), + AppSpaces.verticalLarge, + Row( + children: [ + viewModel.isPortrait + ? Container() + : const Expanded(child: Text('')), + Expanded( + child: Row( + children: [ + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: Text( + AppLocalizations.of(context)! + .discount, + style: + ThemeText.textStyleAmountHeading, + ), + )), + AppSpaces.horizontalMedium, + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: Text( + viewModel.getTotalDiscount(), + style: ThemeText.textStyleAmountValue, + ), + )), + ], + )), + ], + ), + AppSpaces.verticalSmall, + Row( + children: [ + viewModel.isPortrait + ? Container() + : const Expanded(child: Text('')), + Expanded( + child: Row( + children: [ + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: Text( + '${AppLocalizations.of(context)!.tax} (VAT ${viewModel.getTotalVatPercentage()}%)', + style: + ThemeText.textStyleAmountHeading, + ), + )), + AppSpaces.horizontalMedium, + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: Text( + viewModel.getTotalVatDiscount(), + style: ThemeText.textStyleAmountValue, + ), + )), + ], + )), + ], + ), + AppSpaces.verticalSmall, + Row( + children: [ + viewModel.isPortrait + ? Container() + : const Expanded(child: Text('')), + Expanded( + child: Row( + children: [ + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: Text( + AppLocalizations.of(context)! + .total_amount, + style: ThemeText + .textStyleAmountHeadingBlack, + ), + )), + AppSpaces.horizontalMedium, + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: Text( + viewModel.addInvoice.totalAmount + ?.toStringAsFixed(2) ?? + '0.0', + style: ThemeText + .textStyleAmountValueBlack, + ), + )), + ], + )), + ], + ) + ], + ), + ), + ), + AppSpaces.verticalLarge, + viewModel.isLoadingData + ? Row( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + AppLoader(), + ], + ) + : viewModel.isPortrait + ? Column( + children: [ + Row( + crossAxisAlignment: + CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Flexible(child: getAddServiceButton()), + AppSpaces.horizontalMedium, + Flexible(child: getAddInvoiceButton()), + ], + ), + getPrintButton() + ], + ) + : Row( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + SizedBox( + width: 110, + child: getAddServiceButton()), + AppSpaces.horizontalMedium, + SizedBox( + width: 110, + child: getAddInvoiceButton()), + AppSpaces.horizontalMedium, + SizedBox( + width: 160, child: getPrintButton()), + ], + ) + ], + ), + ), + ); + }), + ); + } + + void checkState() { + if (viewModel.crudOperation == CRUDOperationState.view) { + Navigator.pop(context, true); + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => AddInvoiceAndPrintVC( + id: viewModel.invoiceId, + )), + ); + } else if (viewModel.crudOperation == CRUDOperationState.add) { + Navigator.pop(context, true); + } + } + + Widget getMeasurementWidget(int position) { + return DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name ?? ''); + }, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + selectedItem: viewModel.selectedMeasurement[position], + items: viewModel.measurements, + itemAsString: (Measurement u) => u.name!, + onChanged: (Measurement? data) { + viewModel.setMeasurement(data, position); + }, + dropdownDecoratorProps: MyColors.dropDownStyleAddProduct(hint: 'Choose'), + ); + } + + Widget getTaxWidget(int position) { + return DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name ?? ''); + }, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + selectedItem: viewModel.selectedTax[position], + items: viewModel.taxes, + itemAsString: (VAT u) { + return u.value!; + }, + onChanged: (VAT? data) { + viewModel.setVat(data, position); + }, + dropdownDecoratorProps: MyColors.dropDownStyleAddProduct(hint: 'Choose'), + ); + } + + Widget getCompanyWidget() { + return DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name ?? ''); + }, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + selectedItem: viewModel.selectedCustomerCompany, + items: viewModel.companies, + itemAsString: (StoreCustomer u) { + return u.name!; + }, + onChanged: (StoreCustomer? data) { + viewModel.changeCustomer(data); + }, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), + ); + } + + Widget getDiscountsTypes(int position) { + return DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item); + }, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + selectedItem: + viewModel.addInvoice.products[position].discountType ?? 'Choose', + items: Constants.discountTypes, + itemAsString: (String u) => u, + onChanged: (String? data) { + viewModel.setDiscountType(position, data); + }, + dropdownDecoratorProps: MyColors.dropDownStyleAddProduct(hint: 'Choose'), + ); + } + + Widget getDiscounts(int position) { + if (viewModel.addInvoice.products[position].discountType == null) { + return Container( + height: 42, + ); + } else if (viewModel.addInvoice.products[position].discountType! == + Constants.discountTypes[0]) { + return autoDiscount(position); + } else if (viewModel.addInvoice.products[position].discountType! == + Constants.discountTypes[1]) { + return manualDiscount(position); + } else { + return Container( + height: 42, + ); + } + } + + Widget manualDiscount(int position) { + return CustomTextFieldForm( + keyboardType: TextInputType.number, + initialValue: viewModel.addInvoice.products[position].discountPercentage + ?.toString() ?? + '', + onChanged: (String value) { + viewModel.onChangeManualDiscount(value, position); + }, + hintText: '', + ); + } + + Widget autoDiscount(int position) { + return DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name ?? ''); + }, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + selectedItem: viewModel.selectedDiscount[position], + items: viewModel.storeDiscounts, + itemAsString: (StoreDiscount u) => u.name ?? '', + onChanged: (StoreDiscount? data) { + viewModel.onChangeAutoDiscount(data, position); + // calculateDiscount(data, position); + }, + dropdownDecoratorProps: MyColors.dropDownStyleAddProduct(hint: 'Choose'), + ); + } + + Widget getDefaultStatus() { + return Column( + children: [ + MandatoryTitleText( + hint: AppLocalizations.of(context)!.default_status, + ), + AppSpaces.verticalSmall, + DropdownSearch( + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + selectedItem: viewModel.addInvoice.status ?? 'Choose', + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item); + }, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: Constants.statusTypes, + itemAsString: (String u) => u, + onChanged: (String? data) { + viewModel.addInvoice.status = data!; + }, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), + ) + ], + ); + } + + Widget getInvoiceDate() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.invoice_date, + ), + AppSpaces.verticalSmall, + getEndDateButton() + ], + ); + } + + Widget getEndDateButton() { + return CustomTextButtonIcon( + height: 48, + backgroundColor: MyColors.backFillColor, + icon: Icons.calendar_month, + heading: viewModel.addInvoice.invoiceDate == null + ? 'dd/mm/yyyy' + : (viewModel.addInvoice.invoiceDate!.contains("T") + ? DataTimeFormat.getFormatDateString( + viewModel.addInvoice.invoiceDate!) + : 'dd/mm/yyyy'), + onPressed: () { + viewModel.presentDatePicker(context, true); + }, + ); + } + + Widget getInvoiceDueDate() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.invoice_due_Date, + ), + AppSpaces.verticalSmall, + getStartDateButton() + ], + ); + } + + Widget getStartDateButton() { + return CustomTextButtonIcon( + height: 48, + backgroundColor: MyColors.backFillColor, + icon: Icons.calendar_month, + heading: viewModel.addInvoice.invoiceDueDate == null + ? 'dd/mm/yyyy' + : (viewModel.addInvoice.invoiceDueDate!.contains("T") + ? DataTimeFormat.getFormatDateString( + viewModel.addInvoice.invoiceDueDate!) + : 'dd/mm/yyyy'), + onPressed: () { + viewModel.presentDatePicker(context, false); + }, + ); + } + + Widget getInvoiceReferNo() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.invoice_reference, + ), + AppSpaces.verticalSmall, + CustomTextFieldForm( + readOnly: true, + key: Key(viewModel.addInvoice.invoiceReference.toString()), + initialValue: viewModel.addInvoice.invoiceReference.toString(), + onChanged: (value) { + viewModel.addInvoice.invoiceReference = value; + }, + hintText: 'Enter Invoice Reference') + ], + ); + } + + getChooseInvoiceFor() { + return Column( + children: [ + const MandatoryTitleText( + hint: 'Choose Invoice For', + ), + AppSpaces.verticalSmall, + DropdownSearch( + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + selectedItem: viewModel.selectedInvoiceFor ?? "Choose", + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item); + }, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: Constants.chooseInvoiceForTypes, + itemAsString: (String u) => u, + onChanged: (String? data) { + viewModel.onChangeInvoiceFor(data); + }, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), + ) + ], + ); + } + + getInvoiceFor() { + return Column( + children: [ + MandatoryTitleText( + hint: 'Choose ${viewModel.selectedInvoiceFor}', + ), + AppSpaces.verticalSmall, + getCompanyWidget() + ], + ); + } + + getSelectedCurrencyDropdown() { + return DropdownSearch( + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + selectedItem: viewModel.selectedCurrency, + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name ?? ''); + }, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: viewModel.currencies, + itemAsString: (Currency u) => u.name!, + onChanged: (Currency? data) { + viewModel.addInvoice.currencyId = data!; + }, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose Currency'), + ); + } + + getInvoiceNumber() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.invoice_number, + ), + AppSpaces.verticalSmall, + CustomTextFieldForm( + readOnly: true, + key: Key((viewModel.addInvoice.invoiceNumber ?? 0).toString()), + initialValue: (viewModel.addInvoice.invoiceNumber ?? 0).toString(), + onChanged: (String value) {}, + hintText: 'Enter Invoice Number', + ), + ], + ); + } + + getVatNumber() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.vat_number, + ), + AppSpaces.verticalSmall, + CustomTextFieldForm( + initialValue: (viewModel.addInvoice.vatNumber ?? ""), + onChanged: (String value) { + viewModel.addInvoice.vatNumber = value; + }, + hintText: 'Enter VAT Number', + ), + ], + ); + } + + getProductDescription(int position) { + return CustomTextFieldForm( + key: Key(viewModel.addInvoice.products[position].description ?? ''), + initialValue: viewModel.addInvoice.products[position].description ?? '', + onChanged: (String value) { + viewModel.addInvoice.products[position].description = value; + }, + hintText: '', + ); + } + + getProductQuantity(int position) { + return CustomTextFieldForm( + keyboardType: TextInputType.number, + key: Key((viewModel.addInvoice.products[position].totalQuantity ?? '0') + .toString()), + initialValue: + (viewModel.addInvoice.products[position].totalQuantity ?? '0') + .toString(), + onChanged: (String value) { + viewModel.onChangeQuantity(position, value); + }, + hintText: '', + ); + } + + getProductPrice(int position) { + return CustomTextFieldForm( + key: Key( + (viewModel.addInvoice.products[position].price ?? '0').toString()), + keyboardType: TextInputType.number, + initialValue: + (viewModel.addInvoice.products[position].price ?? '0').toString(), + onChanged: (String value) { + viewModel.onChangeItemPrice(value, position); + }, + hintText: '', + ); + } + + getRemoveProductButton(int position) { + return CustomRemoveItemButton(onPressed: () { + viewModel.onRemoveItem(position); + }); + } + + getSelectedCurrencyWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle(hint: AppLocalizations.of(context)!.currency), + AppSpaces.verticalSmall, + getSelectedCurrencyDropdown() + ], + ); + } + + getStockUpdateOptionWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + CustomSwitch( + value: viewModel.addInvoice.productStock ?? false, + onToggle: (value) { + viewModel.updateStockProduct(value); + }, + ), + AppSpaces.horizontalSmall, + HeadingText( + AppLocalizations.of(context)!.update_product_stock, + ), + ], + ), + AppSpaces.verticalMedium, + HeadingText( + AppLocalizations.of(context)!.option_enable_product_invoice, + ), + ], + ); + } + + getAddItemButtonWidget() { + return CustomAddButton(onPressed: () { + viewModel.onAddService(); + }); + } + + getItemsWidget(int position) { + return TransparentBorderContainer( + backgroundColor: MyColors.backFillColor, + child: DropdownSearch( + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + searchFieldProps: ThemeDropDown.textFieldProps, + searchDelay: Duration.zero, + interceptCallBacks: false, + showSearchBox: true, + isFilterOnline: false, + menuProps: ThemeDropDown.menuProps, + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name ?? ''); + }, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 200), + ), + items: viewModel.filteredProductItems, + itemAsString: (ProductItem u) => u.name ?? '', + onChanged: (ProductItem? data) { + viewModel.updateProduct(data, position); + }, + dropdownDecoratorProps: + MyColors.dropDownStyleAddProduct(hint: 'Choose'), + ), + ); + } + + getSingleItemTaxWidget(int position) { + return CustomTextAddProduct( + viewModel.addInvoice.products[position].tax!.toStringAsFixed(2) ?? + 0.toString(), + ); + } + + getSingleItemAmountWidget(int position) { + return CustomTextAddProduct( + viewModel.addInvoice.products[position].amount!.toStringAsFixed(2)); + } + + getAddServiceButton() { + return CustomSimpleButton( + backGroundColor: MyColors.blueThemeColor, + textColor: MyColors.white, + height: 38, + heading: 'Add Service', + onPressed: () { + viewModel.onAddService(); + }, + ); + } + + getAddInvoiceButton() { + return CustomSimpleButton( + backGroundColor: MyColors.blueThemeColor, + textColor: MyColors.white, + height: 38, + heading: widget.isEdit + ? AppLocalizations.of(context)!.edit_invoice + : AppLocalizations.of(context)!.add_invoice, + onPressed: () async { + await viewModel.isValidate(false); + checkState(); + }, + ); + } + + getPrintButton() { + return CustomSimpleButton( + backGroundColor: MyColors.blueThemeColor, + textColor: MyColors.white, + height: 38, + heading: AppLocalizations.of(context)!.add_invoice_and_print, + onPressed: () async { + await viewModel.isValidate(true); + checkState(); + }, + ); + } +} diff --git a/lib/application/views/salesandordermodule/views/invoiceModule/widgets/AmountWidget.dart b/lib/application/views/salesandordermodule/views/invoiceModule/widgets/AmountWidget.dart new file mode 100644 index 0000000..aa4a6ca --- /dev/null +++ b/lib/application/views/salesandordermodule/views/invoiceModule/widgets/AmountWidget.dart @@ -0,0 +1,36 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeText.dart'; + +class AmountWidget extends StatelessWidget { + String title; + String amount; + + AmountWidget({super.key, required this.title, required this.amount}); + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(8), + color: MyColors.backFillColor, + ), + padding: const EdgeInsets.all(8), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + amount, + style: ThemeText.textStyleAmountHeadingBlack, + ), + AppSpaces.verticalMedium, + Text( + title, + style: ThemeText.textStyleAmountValueBlack, + ), + ], + ), + ); + } +} diff --git a/lib/application/views/salesandordermodule/views/invoiceModule/widgets/InvoiceItemListView.dart b/lib/application/views/salesandordermodule/views/invoiceModule/widgets/InvoiceItemListView.dart index 1886084..314c6b5 100644 --- a/lib/application/views/salesandordermodule/views/invoiceModule/widgets/InvoiceItemListView.dart +++ b/lib/application/views/salesandordermodule/views/invoiceModule/widgets/InvoiceItemListView.dart @@ -3,62 +3,84 @@ import 'package:wosull/application/model/store/StoreInvoicesModel.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/helpers/ThemeText.dart'; import 'package:wosull/helpers/Utils.dart'; +import 'package:wosull/widgets/BorderContainer.dart'; +import 'package:wosull/widgets/ChildContainer.dart'; class InvoiceItemListView extends StatelessWidget { List products; + bool isPortrait = false; - InvoiceItemListView(this.products, {super.key}); + InvoiceItemListView( + this.products, { + super.key, + required this.isPortrait, + }); @override Widget build(BuildContext context) { return Column( children: [ Container( - padding: const EdgeInsets.only(left: 8, right: 8), height: 32, color: MyColors.blueThemeColor, child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Expanded( - child: Text( - lang(context).item_name, - style: ThemeText.headingTextWhite, + child: ChildContainer( + child: Text( + lang(context).item_name, + style: ThemeText.headingTextWhite, + ), )), Expanded( - child: Text( - lang(context).unit_price, - style: ThemeText.headingTextWhite, + child: ChildContainer( + child: Text( + lang(context).unit_price, + style: ThemeText.headingTextWhite, + ), )), Expanded( - child: Text( - lang(context).quantity, - style: ThemeText.headingTextWhite, + child: ChildContainer( + child: Text( + lang(context).quantity, + style: ThemeText.headingTextWhite, + ), )), Expanded( - child: Text( - lang(context).taxable_amount, - style: ThemeText.headingTextWhite, + child: ChildContainer( + child: Text( + lang(context).taxable_amount, + style: ThemeText.headingTextWhite, + ), )), Expanded( - child: Text( - lang(context).discount, - style: ThemeText.headingTextWhite, + child: ChildContainer( + child: Text( + lang(context).discount, + style: ThemeText.headingTextWhite, + ), )), Expanded( - child: Text( - lang(context).tax_rate, - style: ThemeText.headingTextWhite, + child: ChildContainer( + child: Text( + lang(context).tax_rate, + style: ThemeText.headingTextWhite, + ), )), Expanded( - child: Text( - lang(context).tax_amount, - style: ThemeText.headingTextWhite, + child: ChildContainer( + child: Text( + lang(context).tax_amount, + style: ThemeText.headingTextWhite, + ), )), Expanded( - child: Text( - lang(context).item_subtotal, - style: ThemeText.headingTextWhite, + child: ChildContainer( + child: Text( + lang(context).item_subtotal, + style: ThemeText.headingTextWhite, + ), )), ], ), @@ -70,55 +92,68 @@ class InvoiceItemListView extends StatelessWidget { shrinkWrap: true, itemBuilder: (c, position) { var product = products[position]; - return Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - child: Container( - padding: const EdgeInsets.only(left: 8, right: 8), + + return BorderContainer( + backgroundColor: MyColors.white, + child: SizedBox( height: 32, - color: MyColors.white, child: Row( children: [ Expanded( - child: Text( - product.name ?? '', - style: ThemeText.robotoMediumSmall, + child: ChildContainer( + child: Text( + product.name ?? '', + style: ThemeText.robotoMediumSmall, + ), )), Expanded( - child: Text( - product.price?.toStringAsFixed(2) ?? '', - style: ThemeText.robotoMediumSmall, + child: ChildContainer( + child: Text( + product.price?.toStringAsFixed(2) ?? '', + style: ThemeText.robotoMediumSmall, + ), )), Expanded( - child: Text( - product.totalQuantity?.toString() ?? '', - style: ThemeText.robotoMediumSmall, + child: ChildContainer( + child: Text( + product.totalQuantity?.toString() ?? '', + style: ThemeText.robotoMediumSmall, + ), )), Expanded( - child: Text( - product.taxableAmount?.toString() ?? '', - style: ThemeText.robotoMediumSmall, + child: ChildContainer( + child: Text( + product.taxableAmount?.toString() ?? '', + style: ThemeText.robotoMediumSmall, + ), )), Expanded( - child: Text( - product.discountPercentage?.toString() ?? '', - style: ThemeText.robotoMediumSmall, + child: ChildContainer( + child: Text( + product.discountPercentage?.toString() ?? '', + style: ThemeText.robotoMediumSmall, + ), )), Expanded( - child: Text( - product.vat?.toString() ?? '', - style: ThemeText.robotoMediumSmall, + child: ChildContainer( + child: Text( + product.vat?.toString() ?? '', + style: ThemeText.robotoMediumSmall, + ), )), Expanded( - child: Text( - product.tax?.toStringAsFixed(2) ?? '', - style: ThemeText.robotoMediumSmall, + child: ChildContainer( + child: Text( + product.tax?.toStringAsFixed(2) ?? '', + style: ThemeText.robotoMediumSmall, + ), )), Expanded( - child: Text( - product.itemSubTotal?.toStringAsFixed(2) ?? '', - style: ThemeText.robotoMediumSmall, + child: ChildContainer( + child: Text( + product.itemSubTotal?.toStringAsFixed(2) ?? '', + style: ThemeText.robotoMediumSmall, + ), )), ], ), diff --git a/lib/application/views/salesandordermodule/views/invoiceModule/widgets/InvoiceListView.dart b/lib/application/views/salesandordermodule/views/invoiceModule/widgets/InvoiceListView.dart new file mode 100644 index 0000000..79e20bd --- /dev/null +++ b/lib/application/views/salesandordermodule/views/invoiceModule/widgets/InvoiceListView.dart @@ -0,0 +1,548 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/application/model/invoice/StoreInvoice.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/helpers/Utils.dart'; +import 'package:wosull/widgets/ActionPopUpContainer.dart'; +import 'package:wosull/widgets/CustomPopuoMenuButton.dart'; +import 'package:wosull/widgets/EmptyDataWidget.dart'; +import 'package:wosull/widgets/ListHeadingContainer.dart'; +import 'package:wosull/widgets/ValueText.dart'; + +class InvoiceListView extends StatelessWidget { + List data; + + bool isPortrait = false; + final void Function(StoreInvoice invoice) onEdit; + final void Function(StoreInvoice invoice, String? value) onUpdate; + final void Function(StoreInvoice invoice) onReturn; + final void Function(StoreInvoice invoice) onDamage; + final void Function(StoreInvoice invoice) onPrintDownload; + final void Function(StoreInvoice invoice) onDelete; + + InvoiceListView({ + super.key, + required this.isPortrait, + required this.data, + required this.onEdit, + required this.onReturn, + required this.onDamage, + required this.onUpdate, + required this.onPrintDownload, + required this.onDelete, + }); + + @override + Widget build(BuildContext context) { + return data.isEmpty + ? const EmptyDataWidget() + : Column( + children: [ + isPortrait + ? Container() + : ListHeadingContainer( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + child: Text( + lang(context).number, + style: ThemeText.textStyleHeadingSmall, + )), + Expanded( + child: Text( + lang(context).reference_no, + style: ThemeText.textStyleHeadingSmall, + )), + Expanded( + child: Text( + lang(context).bill_to, + style: ThemeText.textStyleHeadingSmall, + )), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: Text( + lang(context).invoice_date, + style: ThemeText.textStyleHeadingSmall, + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: Text( + lang(context).invoice_due_Date, + style: ThemeText.textStyleHeadingSmall, + ), + )), + Expanded( + child: Align( + alignment: Alignment.center, + child: Text( + lang(context).amount, + style: ThemeText.textStyleHeadingSmall, + ), + )), + // SizedBox( + // width: 120, + // child: Align( + // alignment: Alignment.centerLeft, + // child: Text( + // lang(context).switch_status, + // style: ThemeText.textStyleHeadingSmall, + // ), + // )), + // AppSpaces.horizontalMedium, + Expanded( + child: Align( + alignment: Alignment.center, + child: Text( + lang(context).status, + style: ThemeText.textStyleHeadingSmall, + ), + )), + AppSpaces.horizontalMedium, + SizedBox( + width: 46, + child: Text( + lang(context).action, + style: ThemeText.textStyleHeadingSmall, + ), + ), + ], + ), + ), + ListView.builder( + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (c, position) { + final invoice = data[position]; + if (isPortrait) { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: Container( + padding: const EdgeInsets.fromLTRB(16, 0, 0, 16), + color: MyColors.containerBackColor, + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + flex: 2, + child: Container( + padding: const EdgeInsets.only(top: 16), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Row( + children: [ + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: Text( + lang(context).number, + style: + MyColors.textStyleHeading(), + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: ValueText( + invoice.invoiceNumber!.toString(), + ), + )) + ], + ), + AppSpaces.verticalMedium, + Row( + children: [ + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: Text( + lang(context).reference_no, + style: + MyColors.textStyleHeading(), + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: ValueText( + invoice.invoiceReference!), + )) + ], + ), + AppSpaces.verticalMedium, + Row( + children: [ + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: Text( + lang(context).bill_to, + style: + MyColors.textStyleHeading(), + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: ValueText( + invoice.invoiceFor?.first == + "Company" + ? invoice.supplier!.name ?? "" + : invoice.customer!.name ?? + '', + ), + )) + ], + ), + AppSpaces.verticalMedium, + Row( + children: [ + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: Text( + lang(context).invoice_date, + style: + MyColors.textStyleHeading(), + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: ValueText( + DataTimeFormat.getFormatDate( + invoice.invoiceDate!)), + )) + ], + ), + AppSpaces.verticalMedium, + Row( + children: [ + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: Text( + lang(context).invoice_due_Date, + style: + MyColors.textStyleHeading(), + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: ValueText( + DataTimeFormat.getFormatDate( + invoice.invoiceDueDate!), + ), + )) + ], + ), + AppSpaces.verticalMedium, + Row( + children: [ + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: Text( + lang(context).amount, + style: + MyColors.textStyleHeading(), + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: ValueText(invoice + .totalAmount! + .toStringAsFixed(2)), + )) + ], + ), + AppSpaces.verticalMedium, + Row( + children: [ + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: Text( + lang(context).status, + style: + MyColors.textStyleHeading(), + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: Text( + invoice.status!.toString(), + style: + ThemeText.textStyleValueGreen, + ), + )) + ], + ), + // Row( + // children: [ + // Expanded( + // child: Align( + // alignment: Alignment.centerLeft, + // child: ValueText( + // lang(context).switch_status, + // ), + // )), + // Expanded( + // child: Align( + // alignment: Alignment.centerRight, + // child: Container( + // decoration: BoxDecoration( + // color: MyColors.fillColor, + // borderRadius: + // BorderRadius.circular(8), + // ), + // height: 38, + // padding: const EdgeInsets.only( + // left: 8, right: 8), + // width: SizerUtil.deviceType == + // DeviceType.mobile + // ? 120 + // : 100, + // child: DropdownButton( + // hint: const Text('Select'), + // style: + // MyColors.textStyleValue(), + // isExpanded: true, + // underline: + // DropdownButtonHideUnderline( + // child: Container()), + // items: Constants + // .invoiceStatusType + // .map((String items) { + // return DropdownMenuItem( + // value: items, + // child: ValueText(items), + // ); + // }).toList(), + // onChanged: (String? value) { + // onUpdate(invoice, value); + // }, + // ), + // ), + // )) + // ], + // ), + ], + ), + )), + getPopUpMenuButton(context, invoice) + ], + ), + ), + ); + } else { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: ListHeadingContainer( + child: Row( + children: [ + Expanded( + child: ValueText( + invoice.invoiceNumber.toString())), + Expanded( + child: ValueText( + invoice.invoiceReference.toString(), + )), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: ValueText( + invoice.invoiceFor!.first == "Company" + ? invoice.supplier!.name ?? "" + : invoice.customer!.name ?? '', + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: ValueText( + DataTimeFormat.getFormatDate( + invoice.invoiceDate!), + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: ValueText( + DataTimeFormat.getFormatDate( + invoice.invoiceDueDate!), + ), + ), + ), + Expanded( + child: Align( + alignment: Alignment.center, + child: ValueText( + invoice.totalAmount!.toStringAsFixed(2), + ), + )), + // SizedBox( + // width: 120, + // child: Align( + // alignment: Alignment.centerLeft, + // child: Container( + // decoration: BoxDecoration( + // color: MyColors.fillColor, + // borderRadius: BorderRadius.circular(8), + // ), + // height: 38, + // padding: const EdgeInsets.only( + // left: 8, right: 8), + // width: 120, + // child: DropdownButton( + // hint: ValueText('Select'), + // style: MyColors.textStyleValue(), + // isExpanded: true, + // underline: DropdownButtonHideUnderline( + // child: Container()), + // items: Constants.invoiceStatusType + // .map((String items) { + // return DropdownMenuItem( + // value: items, + // child: ValueText(items), + // ); + // }).toList(), + // onChanged: (String? value) { + // onUpdate(invoice, value); + // }, + // ), + // ), + // )), + // AppSpaces.horizontalLarge, + Expanded( + child: Padding( + padding: + const EdgeInsets.fromLTRB(16, 0, 32, 0), + child: Container( + height: 38, + decoration: const BoxDecoration( + color: MyColors.greenColor10, + borderRadius: BorderRadius.all( + Radius.circular(10.0))), + child: Padding( + padding: const EdgeInsets.all(10.0), + child: Center( + child: Text( + invoice.status!, + style: + ThemeText.textStyleValueGreen, + ), + ))), + ), + ), + Padding( + padding: const EdgeInsets.all(4), + child: Align( + alignment: Alignment.centerRight, + child: ActionPopUpContainer( + child: getPopUpMenuButton(context, invoice), + ), + ), + ) + ], + ), + ), + ); + } + }, + itemCount: data.length, + ), + ], + ); + } + + Future actionPopUpItemSelected( + String value, StoreInvoice invoice) async { + if (value == 'edit') { + onEdit(invoice); + } else if (value == 'return') { + onReturn(invoice); + } else if (value == 'damage') { + onDamage(invoice); + } else if (value == 'delete') { + onDelete(invoice); + } else { + onPrintDownload(invoice); + } + } + + Widget getPopUpMenuButton(BuildContext context, StoreInvoice invoice) { + return CustomPopupMenuButton( + onSelected: (String value) => actionPopUpItemSelected(value, invoice), + items: invoice.status!.toLowerCase() == Constants.statusReturn || + invoice.status!.toLowerCase() == Constants.statusDamage + ? getViewOption(context) + : getAllMenuOptions(context), + ); + } + + getViewOption(BuildContext context) { + return [ + PopupMenuItem( + value: 'view', + child: ValueText( + lang(context).view, + ), + ), + ]; + } + + getAllMenuOptions(BuildContext context) { + return [ + // PopupMenuItem( + // value: 'edit', + // child: ValueText( + // lang(context).edit, + // ), + // ), + PopupMenuItem( + value: 'return', + child: ValueText( + lang(context).return_txt, + ), + ), + PopupMenuItem( + value: 'damage', + child: ValueText( + "Damage", + ), + ), + PopupMenuItem( + value: 'view', + child: ValueText( + lang(context).view, + ), + ), + // PopupMenuItem( + // value: 'delete', + // child: ValueText( + // lang(context).delete, + // ), + // ) + ]; + } +} diff --git a/lib/application/views/salesandordermodule/views/ordersModule/OrderVC.dart b/lib/application/views/salesandordermodule/views/ordersModule/OrderVC.dart index 5520b98..915550b 100644 --- a/lib/application/views/salesandordermodule/views/ordersModule/OrderVC.dart +++ b/lib/application/views/salesandordermodule/views/ordersModule/OrderVC.dart @@ -1,18 +1,27 @@ import 'package:dropdown_search/dropdown_search.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:provider/provider.dart'; +import 'package:sizer/sizer.dart'; +import 'package:wosull/application/enum/DataState.dart'; import 'package:wosull/application/interfaces/DrawerWidgetSelect.dart'; import 'package:wosull/application/model/cart/GetHoldOrderModel.dart'; import 'package:wosull/application/model/invoice/StoreInvoice.dart'; -import 'package:wosull/application/model/reports/CashierOrderHistory.dart'; +import 'package:wosull/application/model/reports/CashierOrder.dart'; import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/AppError.dart'; +import 'package:wosull/application/utils/AppLoader.dart'; import 'package:wosull/application/utils/Constants.dart'; import 'package:wosull/application/views/salesandordermodule/views/ordersModule/viewModel/OrderViewModel.dart'; -import 'package:wosull/application/views/transactions/CashierTransactionsVC.dart'; -import 'package:wosull/application/views/transactions/EditOrderVC.dart'; import 'package:wosull/application/views/transactions/return/ReturnPOS.dart'; +import 'package:wosull/application/views/transactions/views/EditOrderVC.dart'; +import 'package:wosull/application/views/transactions/widgets/CashierOrderListView.dart'; import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeDropDown.dart'; import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/widgets/DropdownItemBuilder.dart'; +import 'package:wosull/widgets/PageLimitDropDown.dart'; +import 'package:wosull/widgets/SearchBox.dart'; class OrderVC extends StatefulWidget { const OrderVC({super.key}); @@ -23,11 +32,12 @@ class OrderVC extends StatefulWidget { class _OrderVCState extends State implements TransactionCVS { bool isPortrait = false; + var viewModel = OrderViewModel(); @override Widget build(BuildContext context) { - viewModel = context.watch(); + //viewModel = context.watch(); return Scaffold( backgroundColor: MyColors.fillColor, body: OrientationBuilder(builder: (c, orientation) { @@ -40,57 +50,98 @@ class _OrderVCState extends State implements TransactionCVS { Row( mainAxisAlignment: MainAxisAlignment.start, children: [ - const Text( + Text( 'Order', style: ThemeText.textStylePageHeading, ), - const SizedBox( - width: 4, - ), - SizedBox( - width: 160, - child: Material( - color: MyColors.white, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: 42, - width: double.infinity, - child: DropdownSearch( - popupProps: const PopupProps.menu( - constraints: BoxConstraints(maxHeight: 170)), - clearButtonProps: const ClearButtonProps( - alignment: Alignment.centerRight, - padding: EdgeInsets.zero, - icon: Icon(Icons.clear, size: 12), - color: MyColors.black, - isVisible: true, - ), - items: Constants.orderStatus, - itemAsString: (String u) => u, - onChanged: (String? data) { - if (data != null) { - viewModel.setSelectedFilter(data); - } else { - viewModel.setSelectedFilter('All'); - } + AppSpaces.horizontalSmall, + isPortrait + ? Flexible( + child: SizedBox( + height: 38, + child: getOrderTypeDropdown(), + )) + : SizedBox( + height: 38, + width: 140, + child: getOrderTypeDropdown(), + ), + AppSpaces.horizontalSmall, + isPortrait + ? Container() + : SizedBox( + width: SizerUtil.deviceType == DeviceType.mobile + ? 200 + : 240, + height: 48, + child: SearchBox( + onEditingDone: (text) { + filterSearchResults(text); }, - dropdownDecoratorProps: MyColors.dropDownStyle( - hint: Constants.orderStatus[0]), + onChanged: (text) { + filterSearchResults(text); + }, + hint: AppLocalizations.of(context)!.search, ), ), - ), - ), - ), + Flexible( + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + PageLimitDropdown(onChange: (value) { + viewModel.setLimit(int.parse(value!)); + viewModel.fetch( + isRefresh: true, + limit: viewModel.limit, + filter: viewModel.selectedFilter); + }) + ], + )) ], ), + isPortrait ? AppSpaces.verticalMedium : Container(), + isPortrait + ? SizedBox( + height: 48, + child: SearchBox( + onEditingDone: (text) { + filterSearchResults(text); + }, + onChanged: (text) { + filterSearchResults(text); + }, + hint: AppLocalizations.of(context)!.search, + ), + ) + : Container(), AppSpaces.verticalLarge, - CashierTransactionsVC( - context: context, - delegate: this, - isOrder: true, - filter: viewModel.selectedFilter.toLowerCase(), + ChangeNotifierProvider( + create: (context) => viewModel, + child: Consumer( + builder: (BuildContext context, OrderViewModel controller, + Widget? _) { + switch (controller.dataState) { + case DataState.uninitialized: + Future(() { + controller.fetch( + limit: viewModel.limit, + filter: viewModel.filterValue ?? 'all'); + }); + return showData(controller.filteredList); + case DataState.initialFetching: + return AppLoader(); + case DataState.moreFetching: + case DataState.refreshing: + return showData(controller.filteredList); + case DataState.error: + return AppError(); + case DataState.searching: + case DataState.fetched: + case DataState.noMoreData: + return showData(controller.filteredList); + } + }, + ), ) ], ), @@ -100,11 +151,53 @@ class _OrderVCState extends State implements TransactionCVS { ); } + Widget showData(List data) { + return Column( + children: [ + CashierOrderListView( + posOrders: data, + isPortrait: isPortrait, + isOrder: true, + onReturn: (CashierOrder order) { + returnPOS(order, true); + }, + onDamage: (CashierOrder order) { + returnPOS(order, false); + }, + onView: (CashierOrder order) { + editCashier(order); + }, + onEdit: (CashierOrder order) {}, + onDelete: (CashierOrder order) { + viewModel.deleteOrder(order.id); + }, + ), + if (viewModel.dataState == DataState.moreFetching) AppLoader(), + ], + ); + } + + Future filterSearchResults(String query) async { + if (query.isNotEmpty) { + viewModel.search(searchValue: query); + } else { + //doing duration so if there is any call of api in stack + //will not effect on empty + Future.delayed(const Duration(milliseconds: 700), () { + viewModel.search(searchValue: ""); + }); + } + } + @override Future editCashier(CashierOrder data) async { final result = await Navigator.push( context, - MaterialPageRoute(builder: (context) => EditOrderVC(cashierOrder: data)), + MaterialPageRoute( + builder: (context) => EditOrderVC( + cashierOrder: data, + isView: true, + )), ); if (!mounted) return; @@ -114,9 +207,7 @@ class _OrderVCState extends State implements TransactionCVS { } @override - void editOnNewInvoice(StoreInvoice invoice) { - // TODO: implement editOnNewInvoice - } + void editOnNewInvoice(StoreInvoice invoice) {} @override void printDownloadInvoice(StoreInvoice data) { @@ -151,7 +242,34 @@ class _OrderVCState extends State implements TransactionCVS { if (!mounted) return; if (result != null) { - setState(() {}); + viewModel.fetch(isRefresh: true, limit: viewModel.limit); } } + + getOrderTypeDropdown() { + return DropdownSearch( + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item); + }, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 170)), + clearButtonProps: ThemeDropDown.clearButton, + items: Constants.orderStatus, + itemAsString: (String u) => u, + onChanged: (String? data) { + if (data != null) { + viewModel.setSelectedFilter(data); + viewModel.fetch(isRefresh: true, filter: data.toLowerCase()); + } else { + viewModel.setSelectedFilter('All'); + viewModel.fetch(isRefresh: true, filter: 'All'.toLowerCase()); + } + }, + dropdownDecoratorProps: MyColors.dropDownStyle( + hint: Constants.orderStatus[0], fillColor: MyColors.white), + ); + } } diff --git a/lib/application/views/salesandordermodule/views/ordersModule/repo/OrderRepository.dart b/lib/application/views/salesandordermodule/views/ordersModule/repo/OrderRepository.dart new file mode 100644 index 0000000..2798236 --- /dev/null +++ b/lib/application/views/salesandordermodule/views/ordersModule/repo/OrderRepository.dart @@ -0,0 +1,39 @@ +import 'package:wosull/application/model/SimpleResponsModel.dart'; +import 'package:wosull/application/model/reports/CashierOrder.dart'; +import 'package:wosull/application/model/reports/CashierOrderHistory.dart'; +import 'package:wosull/application/model/reports/SearchCashierOrderHistory.dart'; +import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/utils/Constants.dart'; + +class OrderRepository { + Future> fetch(Map data) async { + var items = []; + await APIManager() + .fetchData(Constants.GET_CASHIER_ORDER_HISTORY, data) + .then((result) { + final value = CashierOrderHistory.fromJson(result); + if (value.success) { + items.addAll(value.topOrders); + } + }).onError((error, stackTrace) {}); + return items; + } + + Future> search(Map data) async { + var orders = []; + await APIManager().fetchData(Constants.searchCashier, data).then((result) { + final value = SearchCashierOrderHistory.fromJson(result); + if (value.success!) { + orders.addAll(value.topOrders!); + } + }).onError((error, stackTrace) {}); + return orders; + } + + Future deleteOrder(String? id) async { + Map data = { + 'orderId': id!, + }; + return await APIManager().getResponsePatch(Constants.DELETE_ORDER, data); + } +} diff --git a/lib/application/views/salesandordermodule/views/ordersModule/viewModel/OrderViewModel.dart b/lib/application/views/salesandordermodule/views/ordersModule/viewModel/OrderViewModel.dart index f716d73..2505e5e 100644 --- a/lib/application/views/salesandordermodule/views/ordersModule/viewModel/OrderViewModel.dart +++ b/lib/application/views/salesandordermodule/views/ordersModule/viewModel/OrderViewModel.dart @@ -1,10 +1,137 @@ import 'package:flutter/cupertino.dart'; +import 'package:wosull/application/enum/DataState.dart'; +import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/application/model/reports/CashierOrder.dart'; +import 'package:wosull/application/views/salesandordermodule/views/ordersModule/repo/OrderRepository.dart'; class OrderViewModel with ChangeNotifier { String selectedFilter = 'All'; + int limit = 10; void setSelectedFilter(String filter) { selectedFilter = filter; + } + + void setLimit(int parse) { + limit = parse; + } + + int _currentPageNumber = 1; + String filterValue = 'all'; + DataState _dataState = DataState.uninitialized; + + bool _didLastLoad = false; + bool _isLoading = false; + + bool get isLoading => _isLoading; + + DataState get dataState => _dataState; + List _dataList = []; + List _filteredList = []; + + List get dataList => _dataList; + + List get filteredList => _filteredList; + + final repository = OrderRepository(); + + void setDataState(DataState state) { + _dataState = state; + } + + fetch({bool isRefresh = false, String filter = 'all', int limit = 10}) async { + this.limit = limit; + _isLoading = true; + selectedFilter = filter; + if (!isRefresh) { + _dataState = (_dataState == DataState.uninitialized) + ? DataState.initialFetching + : DataState.moreFetching; + } else { + _didLastLoad = false; + _currentPageNumber = 1; + _dataState = DataState.refreshing; + } notifyListeners(); + Map data = { + 'store_id': sharedPrefs.storeId, + 'page': _currentPageNumber, + 'limit': limit, + 'order_status': selectedFilter.toLowerCase() + }; + try { + if (_didLastLoad) { + _dataState = DataState.noMoreData; + } else { + await repository.fetch(data).then((orders) { + if (_dataState == DataState.refreshing) { + _filteredList.clear(); + _dataList.clear(); + } + if (orders.isNotEmpty) { + _filteredList.addAll(orders); + _dataList.addAll(orders); + if (orders.length < this.limit) { + _didLastLoad = true; + } else { + _didLastLoad = false; + } + } + _dataState = DataState.fetched; + _currentPageNumber += 1; + }).onError((error, stackTrace) { + _dataState = DataState.error; + }); + } + _isLoading = false; + notifyListeners(); + } catch (e) { + _isLoading = false; + _dataState = DataState.error; + notifyListeners(); + } + } + + search({String searchValue = ""}) async { + if (searchValue.isEmpty) { + _dataState = DataState.fetched; + _filteredList.clear(); + _filteredList.addAll(_dataList); + notifyListeners(); + } else { + List status = ['completed']; + Map data = { + 'store_id': sharedPrefs.storeId, + 'searchTerm': searchValue, + 'status': status + }; + _dataState = DataState.searching; + notifyListeners(); + try { + await repository.search(data).then((orders) { + _filteredList.clear(); + if (orders.isNotEmpty) { + _filteredList.addAll(orders); + } + _dataState = DataState.fetched; + }).onError((error, stackTrace) { + _dataState = DataState.error; + }); + notifyListeners(); + } catch (e) { + _dataState = DataState.error; + notifyListeners(); + } + } + } + + Future deleteOrder(String? id) async { + await repository.deleteOrder(id).then((value) { + if (value.success) { + _filteredList.removeWhere((element) => element.id == id); + _dataList.removeWhere((element) => element.id == id); + notifyListeners(); + } + }).onError((error, stackTrace) {}); } } diff --git a/lib/application/views/salesandordermodule/views/ordersModule/views/OrderCashierVC.dart b/lib/application/views/salesandordermodule/views/ordersModule/views/OrderCashierVC.dart new file mode 100644 index 0000000..b48f2b1 --- /dev/null +++ b/lib/application/views/salesandordermodule/views/ordersModule/views/OrderCashierVC.dart @@ -0,0 +1,124 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:wosull/application/enum/DataState.dart'; +import 'package:wosull/application/interfaces/DrawerWidgetSelect.dart'; +import 'package:wosull/application/model/reports/CashierOrder.dart'; +import 'package:wosull/application/utils/AppError.dart'; +import 'package:wosull/application/utils/AppLoader.dart'; +import 'package:wosull/application/views/transactions/viewmodels/CashierTransactionViewModel.dart'; +import 'package:wosull/application/views/transactions/views/ViewPOSReturnVC.dart'; +import 'package:wosull/application/views/transactions/widgets/CashierOrderListView.dart'; +import 'package:wosull/base/BaseStatefulState.dart'; + +class OrderCashierVC extends StatefulWidget { + TransactionCVS delegate; + BuildContext context; + bool? isOrder = false; + String? filter; + int limit = 10; + bool isPortrait = false; + + OrderCashierVC( + {super.key, + required this.delegate, + required this.context, + required this.isPortrait, + this.filter, + this.limit = 10, + this.isOrder}); + + @override + State createState() => _OrderCashierVCState(); +} + +class _OrderCashierVCState extends BaseStatefulState { + late ScrollController _controller; + final viewModel = CashierTransactionViewModel(); + + @override + void initState() { + _controller = ScrollController()..addListener(_scrollNotification); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return SingleChildScrollView( + controller: _controller, + child: ChangeNotifierProvider( + create: (context) => viewModel, + child: Consumer( + builder: (BuildContext context, + CashierTransactionViewModel controller, Widget? _) { + switch (controller.dataState) { + case DataState.uninitialized: + Future(() { + controller.fetch( + limit: widget.limit, filter: widget.filter ?? 'all'); + }); + return showData(controller.filteredList); + case DataState.initialFetching: + return AppLoader(); + case DataState.moreFetching: + case DataState.refreshing: + return showData(controller.filteredList); + case DataState.error: + return AppError(); + case DataState.searching: + case DataState.fetched: + case DataState.noMoreData: + return showData(controller.filteredList); + } + }, + ), + ), + ); + } + + Widget showData(List data) { + return Column( + children: [ + CashierOrderListView( + posOrders: data, + isPortrait: widget.isPortrait, + isOrder: widget.isOrder, + onReturn: (CashierOrder order) { + widget.delegate.returnPOS(order, true); + }, + onDamage: (CashierOrder order) { + widget.delegate.returnPOS(order, false); + }, + onView: (CashierOrder order) { + viewOrder(order); + }, + onEdit: (CashierOrder order) { + widget.delegate.editCashier(order); + }, + onDelete: (CashierOrder order) { + viewModel.deleteOrder(order.id); + }, + ), + if (viewModel.dataState == DataState.moreFetching) AppLoader(), + ], + ); + } + + bool _scrollNotification() { + if (!viewModel.isLoading && _controller.position.extentAfter < 300) { + viewModel.fetch(limit: viewModel.limit, filter: widget.filter ?? 'all'); + } + return true; + } + + void viewOrder(CashierOrder order) { + showDialog( + barrierColor: Colors.black26, + context: context, + builder: (context) { + return ViewPOSReturnVC( + orderDetails: order.cart!.orderDetails!, + ); + }, + ); + } +} diff --git a/lib/application/views/salesandordermodule/views/quotataionModule/NewQuotationsVC.dart b/lib/application/views/salesandordermodule/views/quotataionModule/NewQuotationsVC.dart index 54e9176..ee57799 100644 --- a/lib/application/views/salesandordermodule/views/quotataionModule/NewQuotationsVC.dart +++ b/lib/application/views/salesandordermodule/views/quotataionModule/NewQuotationsVC.dart @@ -1,36 +1,43 @@ -import 'dart:convert'; -import 'dart:math'; - import 'package:dropdown_search/dropdown_search.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:wosull/application/ViewModel/InventoryViewModel.dart'; -import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:provider/provider.dart'; +import 'package:wosull/application/model/Measurement/InventoryMeasurementModel.dart'; +import 'package:wosull/application/model/StockTransfer/ProductItemCategoryModel.dart'; import 'package:wosull/application/model/converters/DataTimeFormat.dart'; import 'package:wosull/application/model/invoice/QuotationInvioceModel.dart'; import 'package:wosull/application/model/store/GetStoreCurrency.dart'; -import 'package:wosull/application/model/store/StoreInvoicesModel.dart'; -import 'package:wosull/application/network/APIManager.dart'; import 'package:wosull/application/theme/MyColors.dart'; -import 'package:wosull/application/theme/MyFonts.dart'; import 'package:wosull/application/utils/AppLoader.dart'; +import 'package:wosull/application/utils/CRUDOperatoinState.dart'; import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/salesandordermodule/views/quotataionModule/viewModels/NewQuotationViewModel.dart'; import 'package:wosull/base/BaseStatefulState.dart'; import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/ThemeDropDown.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/widgets/BorderContainer.dart'; +import 'package:wosull/widgets/ChildContainer.dart'; +import 'package:wosull/widgets/CustomAddButton.dart'; +import 'package:wosull/widgets/CustomAppBar.dart'; import 'package:wosull/widgets/CustomOptionalTitle.dart'; +import 'package:wosull/widgets/CustomRemoveItemButton.dart'; +import 'package:wosull/widgets/CustomSimpleButton.dart'; +import 'package:wosull/widgets/CustomTextAddProduct.dart'; import 'package:wosull/widgets/CustomTextButtonIcon.dart'; import 'package:wosull/widgets/CustomTextFieldForm.dart'; +import 'package:wosull/widgets/DropdownItemBuilder.dart'; import 'package:wosull/widgets/HeadingContainer.dart'; +import 'package:wosull/widgets/HeadingText.dart'; import 'package:wosull/widgets/MandatoryTitleText.dart'; +import 'package:wosull/widgets/PortraitContainer.dart'; +import 'package:wosull/widgets/TransprentBorderContainer.dart'; +import 'package:wosull/widgets/ValueText.dart'; +import 'package:wosull/widgets/WrapHeightContainer.dart'; -import '../../../../model/SimpleResponsModel.dart'; -import '../../../../model/StockTransfer/ProductItemCategoryModel.dart'; import '../../../../model/WosulSettings.dart'; import '../../../../model/customers/GetStoreCustomer.dart'; import '../../../../model/discount/StoreDiscountModel.dart'; -import '../../../../model/inventory/InventoryMeasurementModel.dart'; -import '../../../inventorymodule/productviews/SearchProductVC.dart'; class NewQuotationsVC extends StatefulWidget { QuotationInvoice storeQuotation; @@ -45,158 +52,46 @@ class NewQuotationsVC extends StatefulWidget { } class _NewQuotationsVCState extends BaseStatefulState { - bool isPortrait = true; - - final viewModel = InventoryViewModel(); - late QuotationInvoice addQuotation = QuotationInvoice(products: []); - - // var selectedSupplier; - var selectedStatus; - - List selectedProduct = []; - - var isLoadingFirst = false; - var isLoadingData = false; - - List selectedDiscount = []; - List selectedMeasurement = []; - List selectedTax = []; - - var selectedCurrency; - - var statusTypes = [ - 'Open', - 'Accepted', - 'Rejected', - ]; - var selectedCustomerCompany; + var viewModel = NewQuotationViewModel(); - var selectedQuotationFor = "Customer"; - var chooseQuotationForTypes = [ - 'Customer', - 'Company', - ]; + @override + void dispose() { + viewModel.disposeData(); + super.dispose(); + } @override void initState() { - // TODO: implement initState + context + .read() + .initData(widget.isEdit, widget.storeQuotation); super.initState(); - if (widget.isEdit) { - setState(() { - isLoadingFirst = true; - }); - addQuotation = widget.storeQuotation; - - if (widget.storeQuotation.supplier != null) { - selectedCustomerCompany = StoreCustomer( - id: widget.storeQuotation.supplier!.id ?? "", - name: widget.storeQuotation.supplier!.name ?? "Choose"); - addQuotation.customerId = widget.storeQuotation.supplier!.id ?? ""; - } else if (widget.storeQuotation.customer != null) { - selectedCustomerCompany = StoreCustomer( - id: widget.storeQuotation.customer!.id ?? "", - name: widget.storeQuotation.customer!.name ?? "Choose"); - addQuotation.customerId = widget.storeQuotation.customer!.id ?? ""; - } - - if (widget.storeQuotation.quotationFor!.isNotEmpty) { - selectedQuotationFor = widget.storeQuotation.quotationFor!.first; - } - - for (var product in addQuotation.products) { - selectedProduct.add(widget.isEdit ? product.name ?? '' : ''); - selectedDiscount.add(StoreDiscount( - categories: [], - products: [], - discountPercentage: widget.isEdit - ? product.discountPercentage?.toString() ?? '' - : "0.0")); - - selectedTax.add(VAT( - name: 'VAT', - value: widget.isEdit ? product.vat?.toString() ?? '' : "0.0")); - - selectedMeasurement.add(Measurement( - name: widget.isEdit ? product.measurement ?? '' : "Choose")); - } - - setState(() { - isLoadingFirst = false; - }); - } else { - addQuotation.products.add(StoreInvoiceProduct( - totalQuantity: 0, - price: 0.0, - vat: 0, - discountPercentage: 0.0, - tax: 0.0, - amount: 0.0, - )); - selectedProduct.add(''); - selectedDiscount.add(StoreDiscount( - categories: [], products: [], discountPercentage: "0.0")); - - selectedTax.add(VAT(name: 'VAT', value: "0.0")); - - selectedMeasurement.add(Measurement(name: "Choose")); - getRandomNumber(); - getRandomQuotationRef(); - } - } - - void getRandomNumber() { - setState(() { - var rng = Random(); - var code = rng.nextInt(900000) + 100000; - addQuotation.quotationNumber = code; - }); - } - - void getRandomQuotationRef() { - setState(() { - var rng = Random(); - var code = rng.nextInt(900000) + 100000; - addQuotation.quotationReference = code.toString(); - }); } @override Widget build(BuildContext context) { + viewModel = context.watch(); return Scaffold( + backgroundColor: MyColors.fillColor, resizeToAvoidBottomInset: true, - appBar: AppBar( - leading: BackButton( - color: Colors.black, - onPressed: () { - Navigator.pop(context); - }, // <-- SEE HERE - ), - centerTitle: true, - title: Text( - widget.isEdit - ? AppLocalizations.of(context)!.edit_quotation - : AppLocalizations.of(context)!.add_quotation, - style: const TextStyle( - color: MyColors.textColorBlack, - fontFamily: MyFonts.Bold, - fontSize: 22), - ), - backgroundColor: MyColors.white, - elevation: 5, + appBar: CustomAppBar( + heading: widget.isEdit + ? AppLocalizations.of(context)!.edit_quotation + : AppLocalizations.of(context)!.add_quotation, ), body: OrientationBuilder(builder: (c, orientation) { - isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; + viewModel.isPortrait = + MediaQuery.of(context).orientation == Orientation.portrait; return SingleChildScrollView( child: Container( - color: MyColors.white, padding: const EdgeInsets.all(8), - child: isLoadingFirst - ? const Center( - child: CircularProgressIndicator(), - ) + child: viewModel.isLoadingFirst + ? AppLoader() : Column( children: [ + AppSpaces.verticalLarge, Card( + elevation: 5, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.0), ), @@ -221,8 +116,8 @@ class _NewQuotationsVCState extends BaseStatefulState { AppSpaces.verticalLarge, getQuotationDate(), AppSpaces.verticalLarge, - getDefaultStatus(), - isPortrait + getCurrencyWidget(), + viewModel.isPortrait ? Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -237,18 +132,18 @@ class _NewQuotationsVCState extends BaseStatefulState { getQuotationDueDate(), AppSpaces.verticalLarge, getQuotationReferNo(), - AppSpaces.verticalLarge, - getDefaultStatus(), + // AppSpaces.verticalLarge, + // getDefaultStatus(), ], ) : Container() ], ), ), - isPortrait + viewModel.isPortrait ? Container() : AppSpaces.horizontalMedium, - isPortrait + viewModel.isPortrait ? Container() : Expanded( flex: 2, @@ -272,13 +167,8 @@ class _NewQuotationsVCState extends BaseStatefulState { getQuotationFor(), AppSpaces.verticalLarge, getQuotationDueDate(), - AppSpaces.verticalLarge, - CustomOptionalTitle( - hint: AppLocalizations - .of(context)! - .currency), - AppSpaces.verticalSmall, - getSelectedCurrencyDropdown() + // AppSpaces.verticalLarge, + // getCurrencyWidget() ], )), AppSpaces.horizontalMedium, @@ -305,6 +195,7 @@ class _NewQuotationsVCState extends BaseStatefulState { ), AppSpaces.verticalLarge, Card( + elevation: 5, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.0), ), @@ -320,7 +211,8 @@ class _NewQuotationsVCState extends BaseStatefulState { CustomTextFieldForm( height: 100, maxLines: 5, - initialValue: addQuotation.terms ?? '', + initialValue: + viewModel.addQuotation.terms ?? '', onChanged: (value) {}, hintText: AppLocalizations.of(context)!.terms) ], @@ -329,11 +221,12 @@ class _NewQuotationsVCState extends BaseStatefulState { ), AppSpaces.verticalLarge, Card( + elevation: 5, shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(4.0), + borderRadius: BorderRadius.circular(8.0), ), child: Container( - padding: const EdgeInsets.all(3), + padding: const EdgeInsets.fromLTRB(8, 16, 8, 16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, @@ -341,27 +234,12 @@ class _NewQuotationsVCState extends BaseStatefulState { Text( AppLocalizations.of(context)! .search_and_add_products, - style: const TextStyle( - color: MyColors.textColorBlack, - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.bold, - fontSize: 14), + style: ThemeText.textStyleHeadingCart, ), - AppSpaces.verticalMedium, - isPortrait + AppSpaces.verticalLarge, + viewModel.isPortrait ? Container() - : Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all( - width: 1, - color: MyColors.fillColorGray2), - color: MyColors.backFillColor, - ), - height: 48, + : BorderContainer( child: Row( children: [ HeadingContainer( @@ -369,7 +247,7 @@ class _NewQuotationsVCState extends BaseStatefulState { AppLocalizations.of(context)! .name_or_barcode, height: 48, - width: 110, + width: 150, ), HeadingContainer( heading: @@ -444,22 +322,38 @@ class _NewQuotationsVCState extends BaseStatefulState { physics: const NeverScrollableScrollPhysics(), shrinkWrap: true, itemBuilder: (c, position) { - if (isPortrait) { - return Container( - padding: - const EdgeInsets.fromLTRB(8, 0, 0, 8), - color: MyColors.containerBackColor, + if (viewModel.isPortrait) { + return WrapHeightContainer( child: Row( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ + Container( + height: 59, + decoration: const BoxDecoration( + border: Border( + bottom: BorderSide( + width: 1.0, + color: MyColors + .fillColorGray2), + ), + ), + child: getRemoveProductButton( + position), + ), Expanded( flex: 2, child: Container( - padding: const EdgeInsets.only( - top: 8), + decoration: const BoxDecoration( + border: Border( + left: BorderSide( + width: 1.0, + color: MyColors + .fillColorGray2), + ), + ), child: Row( crossAxisAlignment: CrossAxisAlignment.start, @@ -475,429 +369,130 @@ class _NewQuotationsVCState extends BaseStatefulState { MainAxisAlignment .start, children: [ - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - left: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), + PortraitContainer( + width: + double.infinity, child: Align( alignment: Alignment .centerLeft, - child: Text( + child: HeadingText( AppLocalizations.of( context)! .name_or_barcode, - style: const TextStyle( - fontFamily: - MyFonts - .Bold, - fontWeight: - FontWeight - .bold, - fontSize: 11, - color: MyColors - .textColorBlack20), ), ), ), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - left: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - bottom: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), + PortraitContainer( + width: + double.infinity, child: Align( alignment: Alignment .centerLeft, - child: Text( - AppLocalizations.of( - context)! - .description, - style: const TextStyle( - fontFamily: - MyFonts - .Bold, - fontWeight: - FontWeight - .bold, - fontSize: 11, - color: MyColors - .textColorBlack20), - ), + child: HeadingText( + AppLocalizations.of( + context)! + .description), ), ), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - left: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), + PortraitContainer( + width: + double.infinity, child: Align( alignment: Alignment .centerLeft, - child: Text( + child: HeadingText( AppLocalizations.of( context)! .quantity, - style: const TextStyle( - fontFamily: - MyFonts - .Bold, - fontWeight: - FontWeight - .bold, - fontSize: 11, - color: MyColors - .textColorBlack20), ), ), ), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - left: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), + PortraitContainer( + width: + double.infinity, child: Align( alignment: Alignment .centerLeft, - child: Text( + child: HeadingText( AppLocalizations.of( context)! .unit_price, - style: const TextStyle( - fontFamily: - MyFonts - .Bold, - fontWeight: - FontWeight - .bold, - fontSize: 11, - color: MyColors - .textColorBlack20), ), ), ), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - left: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), + PortraitContainer( + width: + double.infinity, child: Align( alignment: Alignment .centerLeft, - child: Text( + child: HeadingText( AppLocalizations.of( context)! .discount_type, - style: const TextStyle( - fontFamily: - MyFonts - .Bold, - fontWeight: - FontWeight - .bold, - fontSize: 11, - color: MyColors - .textColorBlack20), ), ), ), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - left: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), + PortraitContainer( + width: + double.infinity, child: Align( alignment: Alignment .centerLeft, - child: Text( + child: HeadingText( AppLocalizations.of( context)! .discount, - style: const TextStyle( - fontFamily: - MyFonts - .Bold, - fontWeight: - FontWeight - .bold, - fontSize: 11, - color: MyColors - .textColorBlack20), ), ), ), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - left: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), + PortraitContainer( + width: + double.infinity, child: Align( alignment: Alignment .centerLeft, - child: Text( + child: HeadingText( AppLocalizations.of( context)! .select_tax, - style: const TextStyle( - fontFamily: - MyFonts - .Bold, - fontWeight: - FontWeight - .bold, - fontSize: 11, - color: MyColors - .textColorBlack20), ), ), ), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - left: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), + PortraitContainer( + width: + double.infinity, child: Align( alignment: Alignment .centerLeft, - child: Text( + child: HeadingText( AppLocalizations.of( context)! .measurement, - style: const TextStyle( - fontFamily: - MyFonts - .Bold, - fontWeight: - FontWeight - .bold, - fontSize: 11, - color: MyColors - .textColorBlack20), ), ), ), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - left: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: const Align( + PortraitContainer( + width: + double.infinity, + child: Align( alignment: Alignment .centerLeft, - child: Text( + child: HeadingText( 'Tax %', - style: TextStyle( - fontFamily: - MyFonts - .Bold, - fontWeight: - FontWeight - .bold, - fontSize: 11, - color: MyColors - .textColorBlack20), ), ), ), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - left: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - bottom: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), + PortraitContainer( + width: + double.infinity, child: Align( alignment: Alignment .centerLeft, - child: Text( + child: HeadingText( AppLocalizations.of( context)! .amount, - style: const TextStyle( - fontFamily: - MyFonts - .Bold, - fontWeight: - FontWeight - .bold, - fontSize: 11, - color: MyColors - .textColorBlack20), ), ), ), @@ -912,208 +507,102 @@ class _NewQuotationsVCState extends BaseStatefulState { MainAxisAlignment .start, children: [ - Container( - height: 48, - padding: - const EdgeInsets - .only( - right: 8), - decoration: - BoxDecoration( - border: Border.all( - color: Colors - .transparent, - width: 1, - ), - color: MyColors - .backFillColor, - borderRadius: - BorderRadius - .circular( - 8.0), - ), - child: - CustomTextButtonIcon( - onPressed: - () { - showSheet( - position); - }, - heading: selectedProduct[ - position] - .isEmpty - ? 'Choose' - : selectedProduct[ - position], - icon: Icons - .arrow_drop_down), + PortraitContainer( + width: + double.infinity, + child: getItemsWidget( + position), ), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), + PortraitContainer( + width: + double.infinity, child: Center( child: getProductDescription( position), ), ), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), + PortraitContainer( + width: + double.infinity, child: Center( child: getProductQuantity( position), ), ), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), + PortraitContainer( + width: + double.infinity, child: Center( child: getProductPrice( position), ), ), - getDiscountsTypes( - context, position), - getDiscounts( - context, position), - getTaxWidget( - context, position), - getMeasurementWidget( - context, position), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - bottom: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), + PortraitContainer( + width: + double.infinity, child: Center( - child: Text( - addQuotation - .products[ - position] - .tax! - .toStringAsFixed( - 2) ?? - 0.toString(), - style: const TextStyle( - fontFamily: - MyFonts - .Bold, - fontWeight: - FontWeight - .bold, - fontSize: 11, - color: MyColors - .textColorBlack20), - ), + child: + getDiscountsTypes( + position), ), ), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - bottom: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), + PortraitContainer( + width: + double.infinity, child: Center( - child: Text( - addQuotation - .products[ - position] - .amount! - .toStringAsFixed( - 2) ?? - 0.toString(), - style: const TextStyle( - fontFamily: - MyFonts - .Bold, - fontWeight: - FontWeight - .bold, - fontSize: 11, - color: MyColors - .textColorBlack20), - ), + child: + getDiscounts( + position)), + ), + PortraitContainer( + width: + double.infinity, + child: Center( + child: + getTaxWidget( + position)), + ), + PortraitContainer( + width: + double.infinity, + child: Center( + child: + getMeasurementWidget( + position)), + ), + PortraitContainer( + width: + double.infinity, + child: Align( + alignment: Alignment + .centerRight, + child: CustomTextAddProduct( + viewModel + .addQuotation + .products[ + position] + .tax! + .toStringAsFixed( + 2)), + ), + ), + PortraitContainer( + width: + double.infinity, + child: Align( + alignment: Alignment + .centerRight, + child: CustomTextAddProduct( + viewModel + .addQuotation + .products[ + position] + .amount! + .toStringAsFixed( + 2)), ), ), ], @@ -1121,163 +610,78 @@ class _NewQuotationsVCState extends BaseStatefulState { ], ), )), - getRemoveProductButton(position) ], ), ); } else { - return Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all( - width: 1, - color: MyColors.fillColorGray2), - color: MyColors.white, - ), + return BorderContainer( + backgroundColor: MyColors.white, child: Row( children: [ - Container( - width: 110, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - padding: const EdgeInsets.all(4), - child: Container( - decoration: BoxDecoration( - border: Border.all( - color: Colors.transparent, - width: 1, - ), - color: MyColors.backFillColor, - borderRadius: - BorderRadius.circular(8.0), - ), - child: CustomTextButtonIcon( - iconSize: 18, - backgroundColor: MyColors - .backFillColor, - onPressed: () { - showSheet(position); - }, - heading: - selectedProduct[position] - .isEmpty - ? 'Choose' - : selectedProduct[ - position], - icon: Icons.arrow_drop_down), - ), + ChildContainer( + width: 150, + child: getItemsWidget(position), ), - Container( - padding: const EdgeInsets.all(4), + ChildContainer( width: 100, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), child: Center( child: getProductDescription( position), ), ), - Container( - padding: const EdgeInsets.all(4), + ChildContainer( width: 60, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), child: Center( child: getProductQuantity(position), ), ), - Container( - padding: const EdgeInsets.all(4), + ChildContainer( width: 80, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), child: Center( child: getProductPrice(position), ), ), Expanded( - child: getDiscountsTypes( - context, position)), + child: ChildContainer( + child: getDiscountsTypes(position), + )), Expanded( - child: getDiscounts( - context, position)), + child: ChildContainer( + child: getDiscounts(position), + )), Expanded( - child: getTaxWidget( - context, position)), + child: ChildContainer( + child: getTaxWidget(position), + )), Expanded( - child: getMeasurementWidget( - context, position)), - Container( + child: ChildContainer( + child: + getMeasurementWidget(position), + )), + ChildContainer( width: 44, height: 54, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), child: Center( - child: Text( - addQuotation.products[position] - .tax == - null - ? "0.0" - : addQuotation - .products[position].tax! - .toStringAsFixed(2), - style: - MyColors.textStyleHeading(), - ), + child: ValueText(viewModel + .addQuotation + .products[position] + .tax == + null + ? "0.0" + : viewModel.addQuotation + .products[position].tax! + .toStringAsFixed(2)), ), ), - Container( + ChildContainer( width: 54, height: 54, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), child: Center( - child: Text( - addQuotation + child: ValueText( + viewModel.addQuotation .products[position].amount! .toStringAsFixed(2), - style: - MyColors.textStyleHeading(), ), ), ), @@ -1287,28 +691,15 @@ class _NewQuotationsVCState extends BaseStatefulState { ); } }, - itemCount: addQuotation.products.length, + itemCount: + viewModel.addQuotation.products.length, ), - isPortrait - ? Container( - margin: - const EdgeInsets.fromLTRB(8, 0, 0, 8), - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all( - width: 1, - color: MyColors.fillColorGray2), - color: Colors.white, - ), - height: 48, + viewModel.isPortrait + ? BorderContainer( + backgroundColor: MyColors.white, child: Row( children: [ - Expanded( - child: Container( - height: 48, + Container( decoration: const BoxDecoration( border: Border( right: BorderSide( @@ -1317,6 +708,10 @@ class _NewQuotationsVCState extends BaseStatefulState { .fillColorGray2), ), ), + child: getItemAddButton(), + ), + Expanded( + child: PortraitContainer( child: Center( child: Text( '', @@ -1326,269 +721,75 @@ class _NewQuotationsVCState extends BaseStatefulState { ), )), Expanded( - child: Container( - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: Text( - getTotalProductsPrice(), - style: - MyColors.textStyleValue(), + child: PortraitContainer( + child: Align( + alignment: Alignment.centerRight, + child: CustomTextAddProduct( + viewModel + .getTotalProductsPrice(), ), ), )), - Center( - child: Container( - margin: const EdgeInsets.all(5), - width: 32, - height: 32, - decoration: const BoxDecoration( - borderRadius: - BorderRadius.all( - Radius.circular(4)), - color: - MyColors.fillColorGray2), - child: IconButton( - icon: const Icon( - size: 14, - Icons.add, - color: - MyColors.textColorBlack, - ), - onPressed: () { - onAddService(); - }), - ), - ), ], ), ) - : Container( - margin: - const EdgeInsets.fromLTRB(0, 0, 0, 8), - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all( - width: 1, - color: MyColors.fillColorGray2), - color: Colors.white, - ), - height: 48, + : BorderContainer( + backgroundColor: MyColors.white, child: Row( children: [ Expanded( - child: Container( - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: Text( - '', - style: - MyColors.textStyleValue(), - ), - ), + child: HeadingContainer( + width: 150, + heading: '', )), Expanded( - child: Container( - padding: - const EdgeInsets.only(left: 8), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: Text( - '', - style: - MyColors.textStyleValue(), - ), - ), + child: HeadingContainer( + width: 100, + heading: '', )), Expanded( - child: Container( - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: Text( - '', - style: - MyColors.textStyleValue(), - ), - ), + child: HeadingContainer( + width: 60, + heading: '', )), Expanded( - child: Container( - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: Text( - '', - style: - MyColors.textStyleValue(), - ), - ), + child: HeadingContainer( + width: 80, + heading: '', )), Expanded( - child: Container( - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: Text( - '', - style: - MyColors.textStyleValue(), - ), - ), + child: HeadingContainer( + heading: '', )), Expanded( - child: Container( - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: Text( - '', - style: - MyColors.textStyleValue(), - ), - ), + child: HeadingContainer( + heading: '', )), Expanded( - child: Container( - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: Text( - '', - style: - MyColors.textStyleValue(), - ), - ), + child: HeadingContainer( + heading: '', )), - Container( + HeadingContainer( width: 44, height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: Text( - '', - style: - MyColors.textStyleHeading(), - ), - ), + heading: '', ), - Container( + HeadingContainer( width: 54, height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: Text( - getTotalProductsPrice(), - style: - MyColors.textStyleHeading(), - ), - ), - ), - Center( - child: Container( - margin: const EdgeInsets.all(5), - width: 34, - height: 32, - decoration: const BoxDecoration( - borderRadius: - BorderRadius.all( - Radius.circular(4)), - color: - MyColors.fillColorGray2), - child: IconButton( - icon: const Icon( - size: 14, - Icons.add, - color: - MyColors.textColorBlack, - ), - onPressed: () { - onAddService(); - }), - ), + heading: viewModel + .getTotalProductsPrice(), ), + getItemAddButton(), ], ), ), AppSpaces.verticalLarge, Row( children: [ - const Expanded(child: Text('')), + viewModel.isPortrait + ? Container() + : const Expanded(child: Text('')), Expanded( child: Row( children: [ @@ -1598,26 +799,17 @@ class _NewQuotationsVCState extends BaseStatefulState { child: Text( AppLocalizations.of(context)! .discount, - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.w500, - fontSize: MyFonts.normal, - color: MyColors.textColorBlack20), + style: + ThemeText.textStyleAmountHeading, ), )), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, Expanded( child: Align( alignment: Alignment.centerRight, child: Text( - getTotalDiscount(), - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.w500, - fontSize: MyFonts.normal, - color: MyColors.textColorBlack20), + viewModel.getTotalDiscount(), + style: ThemeText.textStyleAmountValue, ), )), ], @@ -1627,7 +819,9 @@ class _NewQuotationsVCState extends BaseStatefulState { AppSpaces.verticalSmall, Row( children: [ - const Expanded(child: Text('')), + viewModel.isPortrait + ? Container() + : const Expanded(child: Text('')), Expanded( child: Row( children: [ @@ -1635,27 +829,18 @@ class _NewQuotationsVCState extends BaseStatefulState { child: Align( alignment: Alignment.centerRight, child: Text( - '${AppLocalizations.of(context)!.tax} (VAT ${getTotalVatPercentage()}%)', - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.w500, - fontSize: MyFonts.normal, - color: MyColors.textColorBlack20), + '${AppLocalizations.of(context)!.tax} (VAT ${viewModel.getTotalVatPercentage()}%)', + style: + ThemeText.textStyleAmountHeading, ), )), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, Expanded( child: Align( alignment: Alignment.centerRight, child: Text( - getTotalVatDiscount(), - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.w500, - fontSize: MyFonts.normal, - color: MyColors.textColorBlack20), + viewModel.getTotalVatDiscount(), + style: ThemeText.textStyleAmountValue, ), )), ], @@ -1665,7 +850,9 @@ class _NewQuotationsVCState extends BaseStatefulState { AppSpaces.verticalSmall, Row( children: [ - const Expanded(child: Text('')), + viewModel.isPortrait + ? Container() + : const Expanded(child: Text('')), Expanded( child: Row( children: [ @@ -1675,27 +862,19 @@ class _NewQuotationsVCState extends BaseStatefulState { child: Text( AppLocalizations.of(context)! .total_amount, - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.bold, - fontSize: 13, - color: MyColors.black), + style: ThemeText + .textStyleAmountHeadingBlack, ), )), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, Expanded( child: Align( alignment: Alignment.centerRight, child: Text( - addQuotation.totalAmount! + viewModel.addQuotation.totalAmount! .toStringAsFixed(2), - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.bold, - fontSize: 13, - color: MyColors.black), + style: ThemeText + .textStyleAmountHeadingBlack, ), )), ], @@ -1707,74 +886,37 @@ class _NewQuotationsVCState extends BaseStatefulState { ), ), AppSpaces.verticalLarge, - isLoadingData - ? const Row( - crossAxisAlignment: CrossAxisAlignment.end, - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Center( - child: CircularProgressIndicator(), - ) - ], - ) + viewModel.isLoadingData + ? AppLoader() : Row( crossAxisAlignment: CrossAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end, children: [ SizedBox( width: 120, - child: ElevatedButton( - style: ElevatedButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.circular(6.0), - ), - backgroundColor: - MyColors.blueThemeColor, - minimumSize: - const Size.fromHeight(38), // NEW - ), + child: CustomSimpleButton( + backGroundColor: MyColors.blueThemeColor, + textColor: MyColors.white, onPressed: () { - onAddService(); + viewModel.onAddService(); }, - child: const Text( - 'Add Service', - style: TextStyle( - fontSize: MyFonts.normalButton, - color: MyColors.white, - fontFamily: MyFonts.Bold), - ), + heading: 'Add Service', )), - const SizedBox( - width: 12, - ), + AppSpaces.horizontalMedium, SizedBox( width: 140, - child: ElevatedButton( - style: ElevatedButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.circular(6.0), - ), - backgroundColor: - MyColors.blueThemeColor, - minimumSize: - const Size.fromHeight(38), // NEW - ), - onPressed: () { - isValidate(false); + child: CustomSimpleButton( + backGroundColor: MyColors.blueThemeColor, + textColor: MyColors.white, + onPressed: () async { + await viewModel.isValidate(false); + checkState(); }, - child: Text( - widget.isEdit - ? AppLocalizations.of(context)! - .edit_quotation - : AppLocalizations.of(context)! - .add_quotation, - style: const TextStyle( - fontSize: MyFonts.normalButton, - color: MyColors.white, - fontFamily: MyFonts.Bold), - ), + heading: widget.isEdit + ? AppLocalizations.of(context)! + .edit_quotation + : AppLocalizations.of(context)! + .add_quotation, )), ], ) @@ -1786,70 +928,66 @@ class _NewQuotationsVCState extends BaseStatefulState { ); } - void isValidate(bool isPrint) { - addQuotation.quotationFor = []; - addQuotation.quotationFor!.add(selectedQuotationFor); - if (addQuotation.quotationFor!.isEmpty) { - showMessage('Select Quotation for'); - } else if (addQuotation.customerId!.isEmpty) { - showMessage('Select $selectedQuotationFor'); - } else if (addQuotation.status == null) { - showMessage('Select Status'); - } else if (addQuotation.products.isEmpty) { - showMessage('Add At least One Product'); - } else if (selectedProduct[0].isEmpty) { - showMessage('Add At least One Product'); - } else { - addUpdateQuotation(isPrint); - } - } - - Widget getDiscountsTypes(BuildContext context, int position) { - return Container( - padding: const EdgeInsets.all(4), - decoration: const BoxDecoration( - border: Border( - right: BorderSide(width: 1.0, color: MyColors.fillColorGray2), + getItemsWidget(int position) { + return TransparentBorderContainer( + backgroundColor: MyColors.backFillColor, + child: DropdownSearch( + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + searchFieldProps: ThemeDropDown.textFieldProps, + searchDelay: Duration.zero, + interceptCallBacks: false, + showSearchBox: true, + isFilterOnline: false, + menuProps: ThemeDropDown.menuProps, + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name ?? ''); + }, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 200), ), + items: viewModel.filteredProductItems, + itemAsString: (ProductItem u) => u.name ?? '', + onChanged: (ProductItem? data) { + viewModel.updateProduct(data, position); + }, + dropdownDecoratorProps: + MyColors.dropDownStyleAddProduct(hint: 'Choose'), ), - child: Material( - color: MyColors.backFillColor, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: 48, - width: double.infinity, - child: DropdownSearch( - dropdownButtonProps: const DropdownButtonProps( - iconSize: 14, padding: EdgeInsets.zero), - // selectedItem: selectedDiscount[position], - popupProps: const PopupProps.menu( - fit: FlexFit.tight, - constraints: BoxConstraints(maxHeight: 110)), - clearButtonProps: ThemeDropDown.clearButton, - items: Constants.discountTypes, - itemAsString: (String u) => u, - onChanged: (String? data) { - setDiscountType(position, data); - }, - dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), - ), - ), - ), + ); + } + + Widget getDiscountsTypes(int position) { + return DropdownSearch( + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + // selectedItem: selectedDiscount[position], + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item); + }, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 200), ), + clearButtonProps: ThemeDropDown.clearButton, + items: Constants.discountTypes, + itemAsString: (String u) => u, + onChanged: (String? data) { + viewModel.setDiscountType(position, data); + }, + dropdownDecoratorProps: MyColors.dropDownStyleAddProduct(hint: 'Choose'), ); } - Widget getDiscounts(BuildContext context, int position) { - if (addQuotation.products[position].discountType == null) { + Widget getDiscounts(int position) { + if (viewModel.addQuotation.products[position].discountType == null) { return Container( height: 42, ); - } else if (addQuotation.products[position].discountType! == + } else if (viewModel.addQuotation.products[position].discountType! == Constants.discountTypes[0]) { return autoDiscount(position); - } else if (addQuotation.products[position].discountType! == + } else if (viewModel.addQuotation.products[position].discountType! == Constants.discountTypes[1]) { return manualDiscount(position); } else { @@ -1860,363 +998,108 @@ class _NewQuotationsVCState extends BaseStatefulState { } Widget manualDiscount(int position) { - return Container( - padding: const EdgeInsets.all(4), - decoration: const BoxDecoration( - border: Border( - right: BorderSide(width: 1.0, color: MyColors.fillColorGray2), - ), - ), - child: CustomTextFieldForm( - onChanged: (String value) { - if (value.isNotEmpty) { - addDiscount(double.parse(value), position); - } else { - resetDiscount(position); - } - }, - hintText: '', - ), + return CustomTextFieldForm( + keyboardType: TextInputType.number, + initialValue: viewModel.addQuotation.products[position].discountPercentage + ?.toString() ?? + '', + onChanged: (String value) { + viewModel.onChangeDiscount(value, position); + }, + hintText: '', ); } Widget autoDiscount(int position) { - return FutureBuilder( - future: getDiscount(), - builder: (c, s) { - if (s.hasData) { - var itemsList = s.data!; - return Container( - padding: const EdgeInsets.all(4), - decoration: const BoxDecoration( - border: Border( - right: BorderSide(width: 1.0, color: MyColors.fillColorGray2), - ), - ), - child: Material( - color: MyColors.backFillColor, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: isPortrait ? 42 : 48, - width: double.infinity, - child: DropdownSearch( - selectedItem: selectedDiscount[position], - popupProps: const PopupProps.menu(), - clearButtonProps: ThemeDropDown.clearButton, - items: itemsList, - itemAsString: (StoreDiscount u) => u.name ?? '', - onChanged: (StoreDiscount? data) { - if (data != null) { - addDiscount( - double.parse(data.discountPercentage!), position); - } else { - resetDiscount(position); - } - // calculateDiscount(data, position); - }, - dropdownDecoratorProps: - MyColors.dropDownStyle(hint: 'Choose'), - ), - ), - ), - ), - ); - } else { - return AppLoader(); - } - }); - } - - void setDiscountType(int position, String? data) { - setState(() { - resetDiscount(position); - if (data != null) { - addQuotation.products[position].discountType = data; - } else { - addQuotation.products[position].discountType = ''; - } - }); - } - - getTotalVatPercentage() { - var price = 0; - for (var product in addQuotation.products) { - price += product.vat ?? 0; - } - addQuotation.totalVat = price; - return price; - } - - Widget getMeasurementWidget(BuildContext context, int position) { - return FutureBuilder( - future: getMeasurement(), - builder: (c, s) { - if (s.hasData) { - var itemsList = s.data!; - return Container( - padding: const EdgeInsets.all(4), - decoration: const BoxDecoration( - border: Border( - right: BorderSide(width: 1.0, color: MyColors.fillColorGray2), - ), - ), - child: Material( - color: MyColors.backFillColor, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 4, right: 0), - child: SizedBox( - height: 48, - width: double.infinity, - child: DropdownSearch( - selectedItem: selectedMeasurement[position], - popupProps: const PopupProps.menu(), - clearButtonProps: ThemeDropDown.clearButton, - items: itemsList, - itemAsString: (Measurement u) => u.name!, - onChanged: (Measurement? data) { - setState(() {}); - }, - dropdownDecoratorProps: - MyColors.dropDownStyle(hint: 'Choose'), - ), - ), - ), - ), - ); - } else { - return AppLoader(); - } - }); - } - - Future> getMeasurement() async { - var items = []; - Map data = { - 'store_id': sharedPrefs.storeId, - }; - - await viewModel - .getData(Constants.GET_MEASUREMENT, data) - .then((value) { - final response = InvoiceMeasurementModel.fromJson(value); - if (response.success!) { - items.addAll(response.measurements!); - } - }) - .onError((error, stackTrace) {}) - .timeout(const Duration(minutes: 1)); - - return items; - } - - Widget getTaxWidget(BuildContext context, int position) { - return FutureBuilder( - future: getTax(), - builder: (c, s) { - if (s.hasData) { - var itemsList = s.data!; - return Container( - padding: const EdgeInsets.all(4), - decoration: const BoxDecoration( - border: Border( - right: BorderSide(width: 1.0, color: MyColors.fillColorGray2), - ), - ), - child: Material( - color: MyColors.backFillColor, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: 48, - width: double.infinity, - child: DropdownSearch( - selectedItem: selectedTax[position], - popupProps: const PopupProps.menu(), - clearButtonProps: ThemeDropDown.clearButton, - items: itemsList, - itemAsString: (VAT u) { - return u.value!; - }, - onChanged: (VAT? data) { - if (data != null) { - calculateVat(double.parse(data.value!), position); - } else { - calculateVat(0.0, position); - } - }, - dropdownDecoratorProps: - MyColors.dropDownStyle(hint: 'Choose'), - ), - ), - ), - ), - ); - } else { - return AppLoader(); - } - }); - } - - Future> getTax() async { - var items = []; - await viewModel - .getResponse(Constants.GET_WOSUL_SETTINGS) - .then((value) { - final response = WosulSettings.fromJson(value); - if (response.success!) { - items.addAll(response.wosulSettings!.first.vatTaxes!); - } - }) - .onError((error, stackTrace) {}) - .timeout(const Duration(minutes: 1)); - - return items; - } - - Widget getCompanyWidget(BuildContext context) { - return FutureBuilder( - future: getCompany(), - builder: (c, s) { - if (s.hasData) { - var itemsList = s.data!; - return Material( - color: MyColors.backFillColor, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: 48, - width: double.infinity, - child: DropdownSearch( - selectedItem: selectedCustomerCompany, - popupProps: const PopupProps.menu(), - clearButtonProps: ThemeDropDown.clearButton, - items: itemsList, - itemAsString: (StoreCustomer u) { - return u.name!; - }, - onChanged: (StoreCustomer? data) { - setState(() { - if (data != null) { - selectedCustomerCompany = data; - addQuotation.customerId = data.id!; - } - }); - }, - dropdownDecoratorProps: - MyColors.dropDownStyle(hint: 'Choose'), - ), - ), - ), - ); - } else { - return AppLoader(); - } - }); - } - - Future> getCompany() async { - var items = []; - - Map data = { - 'store': sharedPrefs.storeId, - }; - - await viewModel.getData(Constants.GET_STORE_CUSTOMER, data).then((value) { - final response = GetStoreCustomer.fromJson(value); - if (response.success!) { - items.addAll(response.topOrders!); - // if (widget.isEdit) { - // selectedCustomerCompany = - // StoreCustomer(name: addQuotation.supplier!.name, id: addQuotation.supplier!.id); - // addQuotation.customerId = addQuotation.supplier!.id; - // } else { - selectedCustomerCompany ??= StoreCustomer(name: "Choose", id: ""); - // } - } - }).onError((error, stackTrace) {}); - - return items; + return DropdownSearch( + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + selectedItem: viewModel.selectedDiscount[position], + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name ?? ''); + }, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 200), + ), + clearButtonProps: ThemeDropDown.clearButton, + items: viewModel.storeDiscounts, + itemAsString: (StoreDiscount u) => u.name ?? '', + onChanged: (StoreDiscount? data) { + viewModel.onUpdateAutoDiscount(data, position); + }, + dropdownDecoratorProps: MyColors.dropDownStyleAddProduct(hint: 'Choose'), + ); } - Future> getDiscount() async { - var items = []; - await viewModel - .getData(Constants.GET_DISCOUNT, Constants.getStorePayload()) - .then((value) { - final response = StoreDiscountModel.fromJson(value); - if (response.success!) { - items.addAll(response.storeDiscount!); - } - }) - .onError((error, stackTrace) {}) - .timeout(const Duration(minutes: 1)); - - return items; + Widget getMeasurementWidget(int position) { + return DropdownSearch( + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + selectedItem: viewModel.selectedMeasurement[position], + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name ?? ''); + }, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 200), + ), + clearButtonProps: ThemeDropDown.clearButton, + items: viewModel.measurements, + itemAsString: (Measurement u) => u.name!, + onChanged: (Measurement? data) { + setState(() {}); + }, + dropdownDecoratorProps: MyColors.dropDownStyleAddProduct(hint: 'Choose'), + ); } - void showSheet(int index) async { - final result = await showDialog( - barrierColor: Colors.black26, - context: context, - builder: (context) { - return const SearchProductVC(); + Widget getTaxWidget(int position) { + return DropdownSearch( + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + selectedItem: viewModel.selectedTax[position], + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name ?? ''); + }, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 200), + ), + clearButtonProps: ThemeDropDown.clearButton, + items: viewModel.taxes, + itemAsString: (VAT u) { + return u.value!; }, + onChanged: (VAT? data) { + viewModel.onUpdateVat(data, position); + }, + dropdownDecoratorProps: MyColors.dropDownStyleAddProduct(hint: 'Choose'), ); - - if (!mounted) return; - try { - setState(() { - ProductItem response = result; - selectedProduct[index] = response.name!; - final item = addQuotation.products[index]; - item.price = response.price!; - if (response.total_quantity! > 0) { - item.amount = (response.price! * response.total_quantity!).toDouble(); - } else { - item.amount = 0.0; - } - - item.name = response.name; - item.itemId = response.id; - addQuotation.products[index] = item; - - item.totalQuantity = response.total_quantity; - addQuotation.products[index].description = response.details!; - addQuotation.products[index].totalQuantity = response.total_quantity!; - addQuotation.products[index].price = response.price!; - }); - } catch (e) { - print(e); - } } - void _presentDatePicker(bool isStart) { - // showDatePicker is a pre-made funtion of Flutter - showDatePicker( - context: context, - initialDate: DateTime.now(), - firstDate: DateTime(1965), - lastDate: DateTime(2030)) - .then((pickedDate) { - // Check if no date is selected - if (pickedDate == null) { - return; - } - setState(() { - if (isStart) { - addQuotation.quotationDate = - DataTimeFormat.formatDateFromPicketINVOICE(pickedDate); - } else { - addQuotation.quotationDueDate = - DataTimeFormat.formatDateFromPicketINVOICE(pickedDate); - } - }); - }); + Widget getCompanyWidget() { + return DropdownSearch( + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + selectedItem: viewModel.selectedCustomerCompany, + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name ?? ''); + }, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 200), + ), + clearButtonProps: ThemeDropDown.clearButton, + items: viewModel.companies, + itemAsString: (StoreCustomer u) { + return u.name!; + }, + onChanged: (StoreCustomer? data) { + viewModel.updateStoreCustomer(data); + }, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), + ); } getChooseQuotationFor() { @@ -2226,35 +1109,23 @@ class _NewQuotationsVCState extends BaseStatefulState { hint: 'Choose Quotation For', ), AppSpaces.verticalSmall, - Material( - color: MyColors.backFillColor, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: 48, - width: double.infinity, - child: DropdownSearch( - selectedItem: selectedQuotationFor ?? "Choose", - popupProps: const PopupProps.menu( - constraints: BoxConstraints(maxHeight: 100), - ), - items: chooseQuotationForTypes, - itemAsString: (String u) => u, - onChanged: (String? data) { - setState(() { - selectedQuotationFor = data!; - print(selectedQuotationFor); - - addQuotation.quotationFor ??= []; - addQuotation.quotationFor!.clear(); - addQuotation.quotationFor!.add(data); - }); - }, - dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), - ), - ), + DropdownSearch( + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + selectedItem: viewModel.selectedQuotationFor, + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item); + }, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 200), ), + items: Constants.chooseInvoiceForTypes, + itemAsString: (String u) => u, + onChanged: (String? data) { + viewModel.onUpdateQuotationFor(data); + }, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), ), ], ); @@ -2264,50 +1135,33 @@ class _NewQuotationsVCState extends BaseStatefulState { return Column( children: [ MandatoryTitleText( - hint: 'Choose $selectedQuotationFor', + hint: 'Choose ${viewModel.selectedQuotationFor}', ), AppSpaces.verticalSmall, - getCompanyWidget(context) + getCompanyWidget() ], ); } getSelectedCurrencyDropdown() { - return FutureBuilder( - future: getCurrency(), - builder: (c, snapShot) { - if (snapShot.hasData) { - var currency = snapShot.data!; - return Material( - color: MyColors.backFillColor, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: 48, - width: double.infinity, - child: DropdownSearch( - selectedItem: selectedCurrency, - popupProps: const PopupProps.menu( - constraints: BoxConstraints(maxHeight: 200), - ), - items: currency, - itemAsString: (Currency u) => u.name!, - onChanged: (Currency? data) { - setState(() { - addQuotation.currencyId = data; - }); - }, - dropdownDecoratorProps: - MyColors.dropDownStyle(hint: 'Choose Currency'), - ), - ), - ), - ); - } else { - return AppLoader(); - } - }); + return DropdownSearch( + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + selectedItem: viewModel.selectedCurrency, + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name ?? ''); + }, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 200), + ), + items: viewModel.currencies, + itemAsString: (Currency u) => u.name!, + onChanged: (Currency? data) { + viewModel.updateCurrency(data); + }, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose Currency'), + ); } getQuotationNumber() { @@ -2320,8 +1174,9 @@ class _NewQuotationsVCState extends BaseStatefulState { AppSpaces.verticalSmall, CustomTextFieldForm( readOnly: true, - key: Key((addQuotation.quotationNumber ?? 0).toString()), - initialValue: (addQuotation.quotationNumber ?? 0).toString(), + key: Key((viewModel.addQuotation.quotationNumber ?? 0).toString()), + initialValue: + (viewModel.addQuotation.quotationNumber ?? 0).toString(), onChanged: (String value) {}, hintText: 'Enter Quotation Number', ), @@ -2331,10 +1186,10 @@ class _NewQuotationsVCState extends BaseStatefulState { getProductDescription(int position) { return CustomTextFieldForm( - key: Key(addQuotation.products[position].description ?? ''), - initialValue: addQuotation.products[position].description ?? '', + key: Key(viewModel.addQuotation.products[position].description ?? ''), + initialValue: viewModel.addQuotation.products[position].description ?? '', onChanged: (String value) { - addQuotation.products[position].description = value; + viewModel.updateProductDescription(value, position); }, hintText: '', ); @@ -2343,12 +1198,13 @@ class _NewQuotationsVCState extends BaseStatefulState { getProductQuantity(int position) { return CustomTextFieldForm( keyboardType: TextInputType.number, - key: Key( - (addQuotation.products[position].totalQuantity ?? '0').toString()), + key: Key((viewModel.addQuotation.products[position].totalQuantity ?? '0') + .toString()), initialValue: - (addQuotation.products[position].totalQuantity ?? '0').toString(), + (viewModel.addQuotation.products[position].totalQuantity ?? '0') + .toString(), onChanged: (String value) { - onChangeQuantity(position, value); + viewModel.onChangeQuantity(position, value); }, hintText: '', ); @@ -2356,66 +1212,22 @@ class _NewQuotationsVCState extends BaseStatefulState { getProductPrice(int position) { return CustomTextFieldForm( - key: Key((addQuotation.products[position].price ?? '0').toString()), + key: Key( + (viewModel.addQuotation.products[position].price ?? '0').toString()), keyboardType: TextInputType.number, - initialValue: (addQuotation.products[position].price ?? '0').toString(), + initialValue: + (viewModel.addQuotation.products[position].price ?? '0').toString(), onChanged: (String value) { - addQuotation.products[position].price = double.parse(value); - if (addQuotation.products[position].discountPercentage != null) { - addDiscount( - addQuotation.products[position].discountPercentage!, position); - } else { - resetDiscount(position); - } + viewModel.onUpdateProductPrice(position, value); }, hintText: '', ); } getRemoveProductButton(int position) { - return SizedBox( - width: 44, - height: 48, - child: Center( - child: Container( - width: 32, - height: 32, - decoration: const BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(4)), - color: MyColors.fillColorGray2), - child: IconButton( - icon: const Icon( - size: 14, - Icons.close, - color: MyColors.textColorBlack, - ), - onPressed: () { - onRemoveItem(position); - }), - ), - )); - } - - Future> getCurrency() async { - var currencies = []; - await APIManager() - .fetchData(Constants.GET_STORE_CURRENCY, Constants.getStorePayload()) - .then((value) async { - final response = GetStoreCurrency.fromJson(value); - if (response.success) { - currencies.addAll(response.currencies); - - for (var currency in currencies) { - if (currency.id == addQuotation.currencyId!.id!) { - selectedCurrency = Currency(name: currency.name!, id: currency.id!); - } - } - } - }).onError((error, stackTrace) { - print(error.toString()); + return CustomRemoveItemButton(onPressed: () { + viewModel.onRemoveItem(position); }); - - return currencies; } Widget getDefaultStatus() { @@ -2425,31 +1237,24 @@ class _NewQuotationsVCState extends BaseStatefulState { hint: AppLocalizations.of(context)!.default_status, ), AppSpaces.verticalSmall, - Material( - color: MyColors.backFillColor, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: 48, - width: double.infinity, - child: DropdownSearch( - selectedItem: addQuotation.status ?? 'Choose', - popupProps: const PopupProps.menu( - constraints: BoxConstraints(maxHeight: 200), - ), - items: statusTypes, - itemAsString: (String u) => u, - onChanged: (String? data) { - setState(() { - addQuotation.status = data!; - }); - }, - dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), - ), - ), + DropdownSearch( + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + selectedItem: viewModel.addQuotation.status ?? 'Choose', + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item); + }, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 200), ), - ), + items: Constants.quotationStatusTypes, + itemAsString: (String u) => u, + onChanged: (String? data) { + viewModel.updateStatus(data); + }, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), + ) ], ); } @@ -2477,139 +1282,16 @@ class _NewQuotationsVCState extends BaseStatefulState { AppSpaces.verticalSmall, CustomTextFieldForm( readOnly: true, - key: Key(addQuotation.quotationReference.toString()), - initialValue: addQuotation.quotationReference.toString(), + key: Key(viewModel.addQuotation.quotationReference.toString()), + initialValue: viewModel.addQuotation.quotationReference.toString(), onChanged: (value) { - addQuotation.quotationReference = value; + viewModel.updateReferenceNo(value); }, hintText: 'Enter Quotation Reference') ], ); } - String getTotalProductsPrice() { - var price = 0.0; - for (var product in addQuotation.products) { - price += product.amount ?? 0.0; - } - - addQuotation.totalAmount = price; - return price.toStringAsFixed(2); - } - - void onRemoveItem(int position) { - setState(() { - selectedProduct.removeAt(position); - selectedMeasurement.removeAt(position); - selectedDiscount.removeAt(position); - selectedTax.removeAt(position); - addQuotation.products.removeAt(position); - }); - } - - void onChangeQuantity(int position, String value) { - setState(() { - if (value.isNotEmpty) { - addQuotation.products[position].totalQuantity = int.parse(value); - final unitPrice = - addQuotation.products[position].price ?? 0.0; // 1 pece value - final discount = - addQuotation.products[position].discountPercentage ?? 0.0; - if (discount > 0) { - addQuotation.products[position].amount = - addQuotation.products[position].totalQuantity! * unitPrice - - discount; - } else { - addQuotation.products[position].amount = - addQuotation.products[position].totalQuantity! * unitPrice; - } - var tax = getTaxCalu(position); - addQuotation.products[position].tax = tax; - addQuotation.products[position].amount = - addQuotation.products[position].amount! + - addQuotation.products[position].tax!; - } - }); - } - - void clearDiscount(int position) {} - - String getTotalDiscount() { - var price = 0.0; - for (var product in addQuotation.products) { - if (product.discountPercentage != null) { - try { - price += product.discountPercentage!; - } catch (e) { - price += product.discountPercentage!; - } - } - } - - addQuotation.totalDiscount = price; - return price.toStringAsFixed(2); - } - - String getTotalVatDiscount() { - var price = 0.0; - for (var product in addQuotation.products) { - price += product.tax ?? 0.0; - } - - addQuotation.totalTaxExcluding = price; - return price.toStringAsFixed(2); - } - - double getTaxCalu(int position) { - double totalPrice = (addQuotation.products[position].totalQuantity! * - addQuotation.products[position].price!) - - (addQuotation.products[position].discountPercentage ?? 0.0); - var tax = (totalPrice * addQuotation.products[position].vat!); - tax = tax / 100; - return tax; - } - - void addUpdateQuotation(bool isPrint) async { - setState(() { - isLoadingData = true; - }); - - var map = addQuotation.toJson(); - print(jsonEncode(map.toString())); - await viewModel.getData(Constants.ADD_QUOTATION, map).then((value) { - final response = SimpleResponseModel.fromJson(value); - if (response.success) { - showMessage(response.message); - Navigator.pop(context, true); - } - }).onError((error, stackTrace) { - print(stackTrace.toString()); - setState(() { - isLoadingData = false; - }); - }); - } - - void onAddService() { - setState(() { - selectedProduct.add(''); - selectedDiscount.add(StoreDiscount( - categories: [], products: [], discountPercentage: "0.0")); - - selectedTax.add(VAT(name: 'VAT', value: "0.0")); - - selectedMeasurement.add(Measurement(name: "Choose")); - addQuotation.products.add(StoreInvoiceProduct( - totalQuantity: 0, - price: 0.0, - vat: 0, - discountPercentage: 0.0, - tax: 0.0, - amount: 0.0, - )); - }); - } - Widget getQuotationDate() { return Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -2628,13 +1310,14 @@ class _NewQuotationsVCState extends BaseStatefulState { height: 48, backgroundColor: MyColors.backFillColor, icon: Icons.calendar_month, - heading: addQuotation.quotationDate == null + heading: viewModel.addQuotation.quotationDate == null ? 'dd/mm/yyyy' - : (addQuotation.quotationDate!.contains("T") - ? DataTimeFormat.getFormatDateString(addQuotation.quotationDate!) + : (viewModel.addQuotation.quotationDate!.contains("T") + ? DataTimeFormat.getFormatDateString( + viewModel.addQuotation.quotationDate!) : 'dd/mm/yyyy'), onPressed: () { - _presentDatePicker(true); + viewModel.presentDatePicker(context, true); }, ); } @@ -2644,100 +1327,39 @@ class _NewQuotationsVCState extends BaseStatefulState { height: 48, backgroundColor: MyColors.backFillColor, icon: Icons.calendar_month, - heading: addQuotation.quotationDueDate == null + heading: viewModel.addQuotation.quotationDueDate == null ? 'dd/mm/yyyy' - : (addQuotation.quotationDueDate!.contains("T") + : (viewModel.addQuotation.quotationDueDate!.contains("T") ? DataTimeFormat.getFormatDateString( - addQuotation.quotationDueDate!) + viewModel.addQuotation.quotationDueDate!) : 'dd/mm/yyyy'), onPressed: () { - _presentDatePicker(false); + viewModel.presentDatePicker(context, false); }, ); } - void addDiscount(double discount, int position) { - print(discount); - setState(() { - addQuotation.products[position].discountPercentage = discount; - if (addQuotation.products[position].tax != null) { - print('hre'); - calculateVat(addQuotation.products[position].vat!.toDouble(), position); - } else { - print('hress'); - calculateVat(0, position); - // addQuotation.products[position].amount = - // addQuotation.products[position].amount! - - // addQuotation.products[position].discountPercentage!; - } - }); + getCurrencyWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle(hint: AppLocalizations.of(context)!.currency), + AppSpaces.verticalSmall, + getSelectedCurrencyDropdown() + ], + ); } - void resetDiscount(int position) { - setState(() { - addQuotation.products[position].discountPercentage = 0.0; - addQuotation.products[position].amount = - addQuotation.products[position].amount! + - addQuotation.products[position].discountPercentage!; - if (addQuotation.products[position].tax != null) { - print('hre'); - calculateVat(addQuotation.products[position].vat!.toDouble(), position); - } else { - print('hress'); - calculateVat(0, position); - // addQuotation.products[position].amount = - // addQuotation.products[position].amount! - - // addQuotation.products[position].discountPercentage!; - } - // addQuotation.products[position].amount = - // addQuotation.products[position].amount! + - // addQuotation.products[position].discountPercentage!; - // addQuotation.products[position].discountPercentage = 0.0; + getItemAddButton() { + return CustomAddButton(onPressed: () { + viewModel.onAddService(); }); } - void calculateVat(double data, int position) { - print(data); - setState(() { - try { - var totalQuantity = addQuotation.products[position].totalQuantity!; - double totalPrice = - (totalQuantity.toDouble() * addQuotation.products[position].price!); - - print("before" + totalPrice.toString()); - - totalPrice = totalPrice - - (addQuotation.products[position].discountPercentage ?? 0.0); - print("after" + totalPrice.toString()); - print("value tax" + data.toString()); - - addQuotation.products[position].vat = data.toInt(); - var tax = (totalPrice * data); - - tax = tax / 100; //Total tax - print('tax ' + tax.toString()); - addQuotation.products[position].tax = tax; - - addQuotation.products[position].amount = totalPrice + tax; - print('amount ' + addQuotation.products[position].amount.toString()); - // if (addQuotation.products[position].discountPercentage != null) { - // addQuotation.products[position].amount = - // addQuotation.products[position].amount! - - // addQuotation.products[position].discountPercentage!; - // } - } catch (e) { - print(e.toString()); - } - - // if (data > 0) { - // - // } else { - // addQuotation.products[position].vat = 0; - // addQuotation.products[position].amount = - // addQuotation.products[position].amount! - - // addQuotation.products[position].tax!; - // addQuotation.products[position].tax = 0.0; - // } - }); + void checkState() { + print(viewModel.crudOperation); + if (viewModel.crudOperation == CRUDOperationState.add) { + Navigator.pop(context, true); + } } } diff --git a/lib/application/views/salesandordermodule/views/quotataionModule/QuotationsVC.dart b/lib/application/views/salesandordermodule/views/quotataionModule/QuotationsVC.dart index 75c9698..417c5b4 100644 --- a/lib/application/views/salesandordermodule/views/quotataionModule/QuotationsVC.dart +++ b/lib/application/views/salesandordermodule/views/quotataionModule/QuotationsVC.dart @@ -4,23 +4,24 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:provider/provider.dart'; import 'package:sizer/sizer.dart'; import 'package:wosull/application/enum/DataState.dart'; -import 'package:wosull/application/model/converters/DataTimeFormat.dart'; import 'package:wosull/application/model/invoice/QuotationInvioceModel.dart'; import 'package:wosull/application/network/APIManager.dart'; import 'package:wosull/application/theme/MyColors.dart'; -import 'package:wosull/application/theme/MyFonts.dart'; import 'package:wosull/application/utils/AppError.dart'; import 'package:wosull/application/utils/AppLoader.dart'; import 'package:wosull/application/utils/Constants.dart'; import 'package:wosull/application/views/popups/DeleteRecordPopUp.dart'; import 'package:wosull/application/views/salesandordermodule/viewModel/QuotationViewModel.dart'; import 'package:wosull/application/views/salesandordermodule/views/quotataionModule/NewQuotationsVC.dart'; +import 'package:wosull/application/views/salesandordermodule/views/quotataionModule/widgets/QuotationsListView.dart'; import 'package:wosull/base/BaseStatefulState.dart'; import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeDropDown.dart'; import 'package:wosull/helpers/ThemeText.dart'; import 'package:wosull/widgets/CustomSimpleButton.dart'; -import 'package:wosull/widgets/EmptyDataWidget.dart'; -import 'package:wosull/widgets/ValueText.dart'; +import 'package:wosull/widgets/DropdownItemBuilder.dart'; +import 'package:wosull/widgets/PageLimitDropDown.dart'; +import 'package:wosull/widgets/SearchBox.dart'; class QuotationsVC extends StatefulWidget { const QuotationsVC({Key? key}) : super(key: key); @@ -56,61 +57,80 @@ class _QuotationsVCState extends BaseStatefulState { padding: const EdgeInsets.all(12), child: Column( children: [ - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Text( - AppLocalizations.of(context)!.quotations, - style: ThemeText.textStylePageHeading, - ), - const SizedBox( - width: 8, - ), - Container( - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - ), - height: 42, - padding: const EdgeInsets.only(left: 8, right: 0), - width: SizerUtil.deviceType == DeviceType.mobile - ? 120 - : 100, - child: DropdownSearch( - popupProps: const PopupProps.menu( - constraints: BoxConstraints(maxHeight: 200), - ), - items: Constants.quotationStatus, - itemAsString: (String u) => u, - onChanged: (String? data) { - viewModel.fetch(isRefresh: true, filter: data!); - }, - dropdownDecoratorProps: const DropDownDecoratorProps( - baseStyle: TextStyle( - fontFamily: MyFonts.Bold, - fontSize: 11, - color: MyColors.textColorBlack), - dropdownSearchDecoration: InputDecoration( - border: InputBorder.none, hintText: 'All'), - ), - ), - ), - const SizedBox( - width: 8, - ), - SizedBox( - width: 140, - child: CustomSimpleButton( - textColor: MyColors.blueThemeColor, - backGroundColor: MyColors.backColorBlue50, - heading: AppLocalizations.of(context)!.new_quotations, - onPressed: () { - newInvoice(false, QuotationInvoice(products: [])); - }, + isPortrait + ? Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)!.quotations, + style: ThemeText.textStylePageHeading, + ), + AppSpaces.horizontalSmall, + SizedBox( + height: 38, + width: + SizerUtil.deviceType == DeviceType.mobile + ? 120 + : 100, + child: getDropdownFilter(), + ), + AppSpaces.horizontalSmall, + Flexible( + child: getNewQuotationButton(), + ), + ], + ), + AppSpaces.verticalSmall, + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Flexible( + child: SizedBox( + height: 48, + child: getSearchBox(), + ), + ), + AppSpaces.horizontalSmall, + getPageLimitDropdown() + ], + ), + ], + ) + : Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)!.quotations, + style: ThemeText.textStylePageHeading, + ), + AppSpaces.horizontalSmall, + SizedBox( + height: 38, + width: 160, + child: getDropdownFilter(), + ), + AppSpaces.horizontalSmall, + SizedBox( + width: 140, + child: getNewQuotationButton(), + ), + AppSpaces.horizontalSmall, + SizedBox( + width: SizerUtil.deviceType == DeviceType.mobile + ? 200 + : 240, + height: 48, + child: getSearchBox(), + ), + Flexible( + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [getPageLimitDropdown()], + )) + ], ), - ), - ], - ), AppSpaces.verticalMedium, ChangeNotifierProvider( create: (context) => viewModel, @@ -122,18 +142,18 @@ class _QuotationsVCState extends BaseStatefulState { Future(() { controller.fetch(); }); - return showData(controller.filteredList, true); + return showData(controller.filteredList); case DataState.initialFetching: return AppLoader(); case DataState.moreFetching: case DataState.refreshing: - return showData(controller.filteredList, true); + return showData(controller.filteredList); case DataState.error: return AppError(); case DataState.searching: case DataState.fetched: case DataState.noMoreData: - return showData(controller.filteredList, false); + return showData(controller.filteredList); } }, ), @@ -145,610 +165,25 @@ class _QuotationsVCState extends BaseStatefulState { })); } - Widget showData(List data, bool isLoading) { + Widget showData(List data) { return Column( children: [ - data.isEmpty - ? const EmptyDataWidget() - : Column( - children: [ - isPortrait - ? Container() - : Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 50, - color: MyColors.containerBackColor, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - Expanded( - child: Text( - AppLocalizations.of(context)!.number, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 10, - fontWeight: FontWeight.w300, - color: MyColors.black), - )), - Expanded( - child: Text( - AppLocalizations.of(context)!.reference_no, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 10, - fontWeight: FontWeight.w300, - color: MyColors.black), - )), - Expanded( - child: Text( - AppLocalizations.of(context)!.bill_to, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 10, - fontWeight: FontWeight.w300, - color: MyColors.black), - )), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)!.quotation_date, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 10, - fontWeight: FontWeight.w300, - color: MyColors.black), - ), - )), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .quotations_due_date, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 10, - fontWeight: FontWeight.w300, - color: MyColors.black), - ), - )), - Expanded( - child: Align( - alignment: Alignment.center, - child: Text( - AppLocalizations.of(context)!.amount, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 10, - fontWeight: FontWeight.w300, - color: MyColors.black), - ), - )), - SizedBox( - width: 120, - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .switch_status, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 10, - fontWeight: FontWeight.w300, - color: MyColors.black), - ), - )), - const SizedBox( - width: 10, - ), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)!.status, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 10, - fontWeight: FontWeight.w300, - color: MyColors.black), - ), - )), - const SizedBox( - width: 10, - ), - SizedBox( - width: 46, - child: Text( - AppLocalizations.of(context)!.action, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 10, - fontWeight: FontWeight.w300, - color: MyColors.black), - ), - ), - ], - ), - ), - ListView.builder( - padding: EdgeInsets.zero, - scrollDirection: Axis.vertical, - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - itemBuilder: (c, position) { - final quotation = data[position]; - if (isPortrait) { - return Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - child: Container( - padding: const EdgeInsets.fromLTRB(16, 0, 0, 16), - color: MyColors.containerBackColor, - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Expanded( - flex: 2, - child: Container( - padding: const EdgeInsets.only(top: 16), - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.start, - children: [ - Row( - children: [ - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .number, - style: MyColors - .textStyleHeading(), - ), - )), - Expanded( - child: Align( - alignment: - Alignment.centerRight, - child: Text( - quotation.quotationNumber! - .toString(), - style: - MyColors.textStyleValue(), - ), - )) - ], - ), - Row( - children: [ - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .reference_no, - style: MyColors - .textStyleHeading(), - ), - )), - Expanded( - child: Align( - alignment: - Alignment.centerRight, - child: Text( - quotation.quotationReference! - .toString(), - style: - MyColors.textStyleValue(), - ), - )) - ], - ), - Row( - children: [ - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .bill_to, - style: MyColors - .textStyleHeading(), - ), - )), - Expanded( - child: Align( - alignment: - Alignment.centerRight, - child: Text( - quotation.supplier!.name ?? - '', - style: - MyColors.textStyleValue(), - ), - )) - ], - ), - Row( - children: [ - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .quotation_date, - style: MyColors - .textStyleHeading(), - ), - )), - Expanded( - child: Align( - alignment: - Alignment.centerRight, - child: Text( - DataTimeFormat.getFormatDate( - quotation.quotationDate!), - style: - MyColors.textStyleValue(), - ), - )) - ], - ), - Row( - children: [ - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .quotations_due_date, - style: MyColors - .textStyleHeading(), - ), - )), - Expanded( - child: Align( - alignment: - Alignment.centerRight, - child: Text( - DataTimeFormat.getFormatDate( - quotation - .quotationDueDate!), - style: - MyColors.textStyleValue(), - ), - )) - ], - ), - Row( - children: [ - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .amount, - style: MyColors - .textStyleHeading(), - ), - )), - Expanded( - child: Align( - alignment: - Alignment.centerRight, - child: Text( - quotation.totalAmount! - .toStringAsFixed(2), - style: - MyColors.textStyleValue(), - ), - )) - ], - ), - Row( - children: [ - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .status, - style: MyColors - .textStyleHeading(), - ), - )), - Expanded( - child: Align( - alignment: - Alignment.centerRight, - child: Text( - quotation.status ?? '', - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: - FontWeight.w500, - fontSize: MyFonts.normal, - color: - MyColors.greenColor), - ), - )) - ], - ), - Row( - children: [ - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .switch_status, - style: MyColors - .textStyleHeading(), - ), - )), - Expanded( - child: Align( - alignment: - Alignment.centerRight, - child: Container( - decoration: BoxDecoration( - color: MyColors.fillColor, - borderRadius: - BorderRadius.circular( - 8), - ), - height: 38, - padding: - const EdgeInsets.only( - left: 8, right: 8), - width: SizerUtil.deviceType == - DeviceType.mobile - ? 120 - : 100, - child: DropdownButton( - hint: const Text('Select'), - style: MyColors - .textStyleValue(), - isExpanded: true, - underline: - DropdownButtonHideUnderline( - child: Container()), - items: Constants - .quotationStatus - .map((String items) { - return DropdownMenuItem( - value: items, - child: Text(items), - ); - }).toList(), - onChanged: (Object? value) { - _update(quotation.id!, - value.toString()); - }, - ), - ), - )) - ], - ), - ], - ), - )), - PopupMenuButton( - icon: const Icon(Icons.more_vert), - itemBuilder: (c) { - return [ - PopupMenuItem( - value: 'edit', - child: ValueText( - AppLocalizations.of(context)!.edit, - ), - ), - PopupMenuItem( - value: 'view', - child: ValueText( - AppLocalizations.of(context)!.view, - ), - ), - PopupMenuItem( - value: 'delete', - child: ValueText( - AppLocalizations.of(context)!.delete, - ), - ) - ]; - }, - onSelected: (String value) => - actionPopUpItemSelected(value, quotation), - ) - ], - ), - ), - ); - } else { - return Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - child: Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 56, - color: MyColors.containerBackColor, - child: Row( - children: [ - Expanded( - child: Text( - quotation.quotationNumber.toString(), - style: MyColors.textStyleValue())), - Expanded( - child: Text( - quotation.quotationReference.toString(), - style: MyColors.textStyleValue(), - )), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - quotation.supplier!.name ?? '', - style: MyColors.textStyleValue(), - ), - )), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - DataTimeFormat.getFormatDate( - quotation.quotationDate ?? ""), - style: MyColors.textStyleValue(), - ), - )), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - DataTimeFormat.getFormatDate( - quotation.quotationDueDate ?? ""), - style: MyColors.textStyleValue(), - ), - ), - ), - Expanded( - child: Align( - alignment: Alignment.center, - child: Text( - quotation.totalAmount!.toStringAsFixed(2), - style: MyColors.textStyleValue(), - ), - )), - SizedBox( - width: 120, - child: Align( - alignment: Alignment.centerLeft, - child: Container( - decoration: BoxDecoration( - color: MyColors.fillColor, - borderRadius: - BorderRadius.circular(8), - ), - height: 38, - padding: const EdgeInsets.only( - left: 8, right: 8), - width: 120, - child: DropdownButton( - hint: const Text('Select'), - style: MyColors.textStyleValue(), - isExpanded: true, - underline: - DropdownButtonHideUnderline( - child: Container()), - items: Constants.quotationStatus - .map((String items) { - return DropdownMenuItem( - value: items, - child: Text(items), - ); - }).toList(), - onChanged: (Object? value) { - _update(quotation.id!, - value.toString()); - }, - ), - ), - )), - const SizedBox( - width: 16, - ), - Expanded( - child: Container( - height: 38, - decoration: const BoxDecoration( - color: MyColors.greenColor10, - borderRadius: BorderRadius.all( - Radius.circular(10.0))), - child: Padding( - padding: const EdgeInsets.all(10.0), - child: Center( - child: Text( - quotation.status!, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: MyFonts.normal, - fontWeight: FontWeight.w700, - color: MyColors.greenColor), - ), - ))), - ), - Padding( - padding: const EdgeInsets.all(4), - child: Align( - alignment: Alignment.centerRight, - child: Container( - width: 42, - height: 42, - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular(4)), - color: MyColors.backFillColor), - child: PopupMenuButton( - padding: EdgeInsets.zero, - icon: const Icon(Icons.more_vert), - itemBuilder: (c) { - return [ - PopupMenuItem( - value: 'edit', - child: ValueText( - AppLocalizations.of(context)! - .edit, - ), - ), - PopupMenuItem( - value: 'view', - child: ValueText( - AppLocalizations.of(context)! - .view, - ), - ), - PopupMenuItem( - value: 'delete', - child: ValueText( - AppLocalizations.of(context)! - .delete, - ), - ) - ]; - }, - onSelected: (String value) => - actionPopUpItemSelected( - value, quotation), - ), - ), - ), - ) - ], - ), - ), - ); - } - }, - itemCount: data.length, - ), - ], - ), + QuotationListView( + data: data, + isPortrait: isPortrait, + onEdit: (quotation) { + newInvoice(true, quotation); + }, + onUpdate: (quotation, value) { + _update(quotation.id!, value.toString()); + }, + onView: (quotation) { + newInvoice(true, quotation); + }, + onDelete: (quotation) { + showDeletePopup(quotation); + }, + ), if (viewModel.dataState == DataState.moreFetching) AppLoader(), ], ); @@ -756,7 +191,7 @@ class _QuotationsVCState extends BaseStatefulState { bool _scrollNotification() { if (!viewModel.isLoading && _controller.position.extentAfter < 300) { - viewModel.fetch(); + viewModel.fetch(limit: viewModel.limit); } return true; } @@ -773,7 +208,6 @@ class _QuotationsVCState extends BaseStatefulState { getCurrency(isEdit, response.invoices!); } }).onError((error, stackTrace) { - print(stackTrace.toString()); //hideProgressBar(); }); } else { @@ -809,23 +243,79 @@ class _QuotationsVCState extends BaseStatefulState { hideProgressBar(); } - Future actionPopUpItemSelected( - String value, QuotationInvoice invoice) async { - if (value == 'edit') { - newInvoice(true, invoice); - } else if (value == 'delete') { - final result = await showDialog( - barrierColor: Colors.black26, - context: context, - builder: (context) { - return const DeleteRecordPopUp(); + showDeletePopup(QuotationInvoice quotation) async { + final result = await showDialog( + barrierColor: Colors.black26, + context: context, + builder: (context) { + return const DeleteRecordPopUp(); + }, + ); + + if (!mounted) return; + if (result) { + _delete(quotation.id!); + } + } + + getDropdownFilter() { + return DropdownSearch( + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item); }, - ); + fit: FlexFit.loose, + ), + items: Constants.quotationStatus, + itemAsString: (String u) => u, + onChanged: (String? data) { + viewModel.fetch(isRefresh: true, filter: data!); + }, + dropdownDecoratorProps: + MyColors.dropDownStyle(hint: 'All', fillColor: MyColors.white), + ); + } + + getNewQuotationButton() { + return CustomSimpleButton( + textColor: MyColors.blueThemeColor, + backGroundColor: MyColors.backColorBlue50, + heading: AppLocalizations.of(context)!.new_quotations, + onPressed: () { + newInvoice(false, QuotationInvoice(products: [])); + }, + ); + } + + getSearchBox() { + return SearchBox( + onEditingDone: (text) { + filterSearchResults(text); + }, + onChanged: (text) { + filterSearchResults(text); + }, + hint: AppLocalizations.of(context)!.search, + ); + } + + Future filterSearchResults(String query) async { + if (query.isNotEmpty) { + viewModel.search(searchValue: query); + } else { + //doing duration so if there is any call of api in stack + //will not effect on empty + Future.delayed(const Duration(milliseconds: 700), () { + viewModel.search(searchValue: ""); + }); + } + } - if (!mounted) return; - if (result) { - _delete(invoice.id!); - } - } else {} + getPageLimitDropdown() { + return PageLimitDropdown(onChange: (value) { + viewModel.fetch(isRefresh: true, limit: int.parse(value!)); + }); } } diff --git a/lib/application/views/salesandordermodule/views/quotataionModule/repo/QuotationRepository.dart b/lib/application/views/salesandordermodule/views/quotataionModule/repo/QuotationRepository.dart new file mode 100644 index 0000000..7d17e54 --- /dev/null +++ b/lib/application/views/salesandordermodule/views/quotataionModule/repo/QuotationRepository.dart @@ -0,0 +1,75 @@ +import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/application/model/SimpleResponsModel.dart'; +import 'package:wosull/application/model/invoice/QuotationInvioceModel.dart'; +import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/utils/Constants.dart'; + +class QuotationRepository { + Future getQuotationById(String id) async { + final value = await APIManager() + .getResponseAuth("${Constants.GET_QUOTATION_BY_ID}/$id"); + final response = QuotationInvoiceByID.fromJson(value); + return response.invoices!; + } + + Future> fetchQuotations(data) async { + var quotations = []; + await APIManager().fetchData(Constants.GET_QUOTATION, data).then((result) { + final value = QuotationInvoiceModel.fromJson(result); + if (value.success!) { + quotations.addAll(value.invoices!); + } + }).onError((error, stackTrace) {}); + + return quotations; + } + + Future> search( + String searchValue, String status) async { + var quotations = []; + Map data = { + 'store_id': sharedPrefs.storeId, + 'searchTerm': searchValue, + 'quotation_status': status + }; + await APIManager() + .fetchData(Constants.searchQuotation, data) + .then((result) { + final value = QuotationInvoiceModel.fromJson(result); + if (value.success!) { + quotations.addAll(value.invoices!); + } + }).onError((error, stackTrace) {}); + + return quotations; + } + + Future delete(String id) async { + Map data = {'quotationId': id}; + await APIManager() + .getResponsePatch(Constants.DELETE_QUOTATION, data) + .then((result) { + return true; + }).onError((error, stackTrace) { + return false; + }); + return false; + } + + Future update(String id, String status) async { + Map data = {'quotationId': id, "status": status}; + await APIManager() + .getResponsePatch(Constants.UPDATE_QUOTATION, data) + .then((result) { + return true; + }).onError((error, stackTrace) { + return false; + }); + return false; + } + + Future addUpdateQuotation(map) async { + final result = await APIManager().fetchData(Constants.ADD_QUOTATION, map); + return SimpleResponseModel.fromJson(result); + } +} diff --git a/lib/application/views/salesandordermodule/views/quotataionModule/viewModels/NewQuotationViewModel.dart b/lib/application/views/salesandordermodule/views/quotataionModule/viewModels/NewQuotationViewModel.dart new file mode 100644 index 0000000..0aeb1ab --- /dev/null +++ b/lib/application/views/salesandordermodule/views/quotataionModule/viewModels/NewQuotationViewModel.dart @@ -0,0 +1,487 @@ +import 'dart:math'; + +import 'package:flutter/material.dart'; +import 'package:wosull/application/model/Measurement/InventoryMeasurementModel.dart'; +import 'package:wosull/application/model/StockTransfer/ProductItemCategoryModel.dart'; +import 'package:wosull/application/model/WosulSettings.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/application/model/customers/GetStoreCustomer.dart'; +import 'package:wosull/application/model/discount/StoreDiscountModel.dart'; +import 'package:wosull/application/model/invoice/QuotationInvioceModel.dart'; +import 'package:wosull/application/model/store/GetStoreCurrency.dart'; +import 'package:wosull/application/model/store/StoreInvoicesModel.dart'; +import 'package:wosull/application/repository/WosulRepository.dart'; +import 'package:wosull/application/utils/CRUDOperatoinState.dart'; +import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/salesandordermodule/views/quotataionModule/repo/QuotationRepository.dart'; +import 'package:wosull/helpers/DatePicker.dart'; +import 'package:wosull/helpers/Utils.dart'; + +class NewQuotationViewModel with ChangeNotifier { + bool isPortrait = true; + var isLoadingFirst = false; + var isLoadingData = false; + var isEdit = false; + late QuotationInvoice addQuotation = QuotationInvoice(products: []); + final repository = QuotationRepository(); + var selectedCurrency; + var selectedStatus; + var selectedCustomerCompany; + List selectedProduct = []; + List selectedDiscount = []; + List selectedMeasurement = []; + List selectedTax = []; + var selectedQuotationFor = "Customer"; + + //data lists + List measurements = []; + List taxes = []; + List companies = []; + List storeDiscounts = []; + List currencies = []; + List filteredProductItems = []; + + var _crudOperation = CRUDOperationState.uninitialized; + + CRUDOperationState get crudOperation => _crudOperation; + + void disposeData() { + isLoadingData = false; + measurements.clear(); + taxes.clear(); + companies.clear(); + storeDiscounts.clear(); + currencies.clear(); + filteredProductItems.clear(); + selectedProduct.clear(); + selectedDiscount.clear(); + selectedMeasurement.clear(); + selectedTax.clear(); + addQuotation = QuotationInvoice(products: []); + selectedCurrency = null; + selectedStatus = null; + selectedCustomerCompany = null; + } + + void setState(CRUDOperationState state) { + _crudOperation = state; + } + + Future initData(bool isEdit, QuotationInvoice storeQuotation) async { + isLoadingFirst = true; + this.isEdit = isEdit; + + if (isEdit) { + await getQuotationById(storeQuotation.id ?? ''); + } else { + addQuotation.status = 'Pending'; + addEmptyService(); + getRandomNumber(); + getRandomQuotationRef(); + } + + await getMeasurement(); + await getTax(); + await getCompany(); + await getDiscount(); + await getCurrency(); + await getProducts(); + + isLoadingFirst = false; + + notifyListeners(); + } + + void setLoading(bool value) { + isLoadingData = value; + notifyListeners(); + } + + Future getTax() async { + final response = await WosulRepository().getTax(); + taxes.addAll(response); + } + + Future getMeasurement() async { + final response = await WosulRepository().getMeasurement(); + measurements.addAll(response); + } + + Future getDiscount() async { + final response = await WosulRepository().getDiscount(); + storeDiscounts.addAll(response); + } + + Future getProducts() async { + final response = await WosulRepository().getAllProducts(); + filteredProductItems.addAll(response); + } + + Future getCurrency() async { + final response = await WosulRepository().getCurrency(); + currencies.addAll(response); + if (isEdit) { + for (var currency in currencies) { + if (currency.id == addQuotation.currencyId!.id!) { + selectedCurrency = Currency(name: currency.name!, id: currency.id!); + } + } + } + } + + Future isValidate(bool isPrint) async { + addQuotation.quotationFor = []; + addQuotation.quotationFor!.add(selectedQuotationFor); + if (addQuotation.quotationFor!.isEmpty) { + Utils.showMessage('Select Quotation for'); + } else if (addQuotation.customerId!.isEmpty) { + Utils.showMessage('Select $selectedQuotationFor'); + } else if (addQuotation.products.isEmpty) { + Utils.showMessage('Add At least One Product'); + } else { + await addUpdateQuotation(isPrint); + } + } + + Future addUpdateQuotation(bool isPrint) async { + setLoading(true); + var map = addQuotation.toJson(); + await repository.addUpdateQuotation(map).then((value) { + if (value.success) { + Utils.showMessage(value.message); + setState(CRUDOperationState.add); + } + setLoading(false); + }).onError((error, stackTrace) { + setLoading(false); + }); + } + + void onAddService() { + addEmptyService(); + notifyListeners(); + } + + Future getCompany() async { + final response = await WosulRepository().getCompany(); + companies.addAll(response); + if (isEdit) {} + selectedCustomerCompany ??= StoreCustomer(name: "Choose", id: ""); + } + + void setDiscountType(int position, String? data) { + resetDiscount(position); + if (data != null) { + addQuotation.products[position].discountType = data; + } else { + addQuotation.products[position].discountType = ''; + } + notifyListeners(); + } + + getTotalVatPercentage() { + var price = 0; + for (var product in addQuotation.products) { + price += product.vat ?? 0; + } + addQuotation.totalVat = price; + return price; + } + + void getRandomNumber() { + var rng = Random(); + var code = rng.nextInt(900000) + 100000; + addQuotation.quotationNumber = code; + } + + void getRandomQuotationRef() { + var rng = Random(); + var code = rng.nextInt(900000) + 100000; + addQuotation.quotationReference = code.toString(); + } + + void updateStoreCustomer(StoreCustomer? data) { + if (data != null) { + selectedCustomerCompany = data; + addQuotation.customerId = data.id!; + } + } + + void onUpdateVat(VAT? data, int position) { + if (data != null) { + calculateVat(double.parse(data.value!), position); + } else { + calculateVat(0.0, position); + } + } + + void updateProduct(result, int index) { + ProductItem response = result; + //selectedProduct[index] = response.name!; + final item = addQuotation.products[index]; + item.price = response.price!; + if (response.total_quantity! > 0) { + item.amount = (response.price! * response.total_quantity!).toDouble(); + } else { + item.amount = 0.0; + } + + item.name = response.name; + item.itemId = response.id; + addQuotation.products[index] = item; + + item.totalQuantity = response.total_quantity; + addQuotation.products[index].description = response.details!; + addQuotation.products[index].totalQuantity = response.total_quantity!; + addQuotation.products[index].price = response.price!; + notifyListeners(); + } + + Future presentDatePicker(BuildContext context, bool isStart) async { + final pickedDate = await DatePicker.presentDatePicker(context, isStart); + + if (pickedDate == null) { + return; + } + + if (isStart) { + addQuotation.quotationDate = + DataTimeFormat.formatDateFromPicketINVOICE(pickedDate); + } else { + addQuotation.quotationDueDate = + DataTimeFormat.formatDateFromPicketINVOICE(pickedDate); + } + notifyListeners(); + } + + void onUpdateQuotationFor(String? data) { + if (data != null) { + selectedQuotationFor = data; + addQuotation.quotationFor ??= []; + addQuotation.quotationFor!.clear(); + addQuotation.quotationFor!.add(data); + } + } + + void updateCurrency(Currency? data) { + if (data != null) { + addQuotation.currencyId = data; + } + } + + void updateProductDescription(String value, int position) { + addQuotation.products[position].description = value; + } + + void onUpdateProductPrice(int position, String value) { + addQuotation.products[position].price = double.parse(value); + if (addQuotation.products[position].discountPercentage != null) { + addDiscount( + addQuotation.products[position].discountPercentage!, position); + } else { + resetDiscount(position); + } + } + + void addDiscount(double discount, int position) { + addQuotation.products[position].discountPercentage = discount; + if (addQuotation.products[position].tax != null) { + calculateVat(addQuotation.products[position].vat!.toDouble(), position); + } else { + calculateVat(0, position); + } + notifyListeners(); + } + + void resetDiscount(int position) { + addQuotation.products[position].discountPercentage = 0.0; + addQuotation.products[position].amount = + addQuotation.products[position].amount! + + addQuotation.products[position].discountPercentage!; + if (addQuotation.products[position].tax != null) { + calculateVat(addQuotation.products[position].vat!.toDouble(), position); + } else { + calculateVat(0, position); + } + notifyListeners(); + } + + void calculateVat(double data, int position) { + try { + var totalQuantity = addQuotation.products[position].totalQuantity!; + double totalPrice = + (totalQuantity.toDouble() * addQuotation.products[position].price!); + + totalPrice = totalPrice - + (addQuotation.products[position].discountPercentage ?? 0.0); + + addQuotation.products[position].vat = data.toInt(); + var tax = (totalPrice * data); + + tax = tax / 100; //Total tax + addQuotation.products[position].tax = tax; + + addQuotation.products[position].amount = totalPrice + tax; + // if (addQuotation.products[position].discountPercentage != null) { + // addQuotation.products[position].amount = + // addQuotation.products[position].amount! - + // addQuotation.products[position].discountPercentage!; + // } + } catch (e) {} + notifyListeners(); + } + + String getTotalProductsPrice() { + var price = 0.0; + for (var product in addQuotation.products) { + price += product.amount ?? 0.0; + } + + addQuotation.totalAmount = price; + return price.toStringAsFixed(2); + } + + void onRemoveItem(int position) { + // selectedProduct.removeAt(position); + selectedMeasurement.removeAt(position); + selectedDiscount.removeAt(position); + selectedTax.removeAt(position); + addQuotation.products.removeAt(position); + notifyListeners(); + } + + void onChangeQuantity(int position, String value) { + if (value.isNotEmpty) { + addQuotation.products[position].totalQuantity = int.parse(value); + final unitPrice = + addQuotation.products[position].price ?? 0.0; // 1 pece value + final discount = + addQuotation.products[position].discountPercentage ?? 0.0; + if (discount > 0) { + addQuotation.products[position].amount = + addQuotation.products[position].totalQuantity! * unitPrice - + discount; + } else { + addQuotation.products[position].amount = + addQuotation.products[position].totalQuantity! * unitPrice; + } + var tax = getTaxCalu(position); + addQuotation.products[position].tax = tax; + addQuotation.products[position].amount = + addQuotation.products[position].amount! + + addQuotation.products[position].tax!; + } + + notifyListeners(); + } + + void clearDiscount(int position) {} + + String getTotalDiscount() { + var price = 0.0; + for (var product in addQuotation.products) { + if (product.discountPercentage != null) { + try { + price += product.discountPercentage!; + } catch (e) { + price += product.discountPercentage!; + } + } + } + + addQuotation.totalDiscount = price; + return price.toStringAsFixed(2); + } + + String getTotalVatDiscount() { + var price = 0.0; + for (var product in addQuotation.products) { + price += product.tax ?? 0.0; + } + + addQuotation.totalTaxExcluding = price; + return price.toStringAsFixed(2); + } + + double getTaxCalu(int position) { + double totalPrice = (addQuotation.products[position].totalQuantity! * + addQuotation.products[position].price!) - + (addQuotation.products[position].discountPercentage ?? 0.0); + var tax = (totalPrice * addQuotation.products[position].vat!); + tax = tax / 100; + return tax; + } + + void updateStatus(String? data) { + if (data != null) { + addQuotation.status = data!; + } + } + + void updateReferenceNo(String value) { + addQuotation.quotationReference = value; + } + + void onChangeDiscount(String value, int position) { + if (value.isNotEmpty) { + addDiscount(double.parse(value), position); + } else { + resetDiscount(position); + } + } + + void onUpdateAutoDiscount(StoreDiscount? data, int position) { + if (data != null) { + addDiscount(double.parse(data.discountPercentage!), position); + } else { + resetDiscount(position); + } + } + + void addEmptyService() { + addQuotation.products.add(StoreInvoiceProduct( + totalQuantity: 0, + price: 0.0, + vat: 0, + discountPercentage: 0.0, + tax: 0.0, + amount: 0.0, + )); + // selectedProduct.add(''); + selectedDiscount.add( + StoreDiscount(categories: [], products: [], discountPercentage: "0.0")); + selectedTax.add(VAT(name: 'VAT', value: "0.0")); + selectedMeasurement.add(Measurement(name: "Choose")); + } + + Future getQuotationById(String id) async { + addQuotation = await repository.getQuotationById(id); + if (addQuotation.quotationFor!.first == + Constants.chooseInvoiceForTypes[1]) { + selectedCustomerCompany = StoreCustomer( + id: addQuotation.supplier!.id ?? "", + name: addQuotation.supplier!.name ?? "Choose"); + } else if (addQuotation.quotationFor!.first == + Constants.chooseInvoiceForTypes[0]) { + selectedCustomerCompany = StoreCustomer( + id: addQuotation.customer!.id ?? "", + name: addQuotation.customer!.name ?? "Choose"); + } + selectedQuotationFor = addQuotation.quotationFor!.first; + + for (var product in addQuotation.products) { + // selectedProduct.add(isEdit ? product.name ?? '' : ''); + selectedDiscount.add(StoreDiscount( + categories: [], + products: [], + discountPercentage: + isEdit ? product.discountPercentage?.toString() ?? '' : "0.0")); + + selectedTax.add(VAT( + name: 'VAT', value: isEdit ? product.vat?.toString() ?? '' : "0.0")); + + selectedMeasurement.add( + Measurement(name: isEdit ? product.measurement ?? '' : "Choose")); + } + } +} diff --git a/lib/application/views/salesandordermodule/views/quotataionModule/widgets/QuotationsListView.dart b/lib/application/views/salesandordermodule/views/quotataionModule/widgets/QuotationsListView.dart new file mode 100644 index 0000000..c693ba9 --- /dev/null +++ b/lib/application/views/salesandordermodule/views/quotataionModule/widgets/QuotationsListView.dart @@ -0,0 +1,494 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/application/model/invoice/QuotationInvioceModel.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/helpers/Utils.dart'; +import 'package:wosull/widgets/ActionPopUpContainer.dart'; +import 'package:wosull/widgets/CustomPopuoMenuButton.dart'; +import 'package:wosull/widgets/EmptyDataWidget.dart'; +import 'package:wosull/widgets/HeadingText.dart'; +import 'package:wosull/widgets/ListHeadingContainer.dart'; +import 'package:wosull/widgets/ValueText.dart'; + +class QuotationListView extends StatelessWidget { + List data; + bool isPortrait; + final void Function(QuotationInvoice invoice) onEdit; + final void Function(QuotationInvoice invoice, String? value) onUpdate; + final void Function(QuotationInvoice invoice) onView; + final void Function(QuotationInvoice invoice) onDelete; + + QuotationListView( + {super.key, + required this.data, + required this.isPortrait, + required this.onEdit, + required this.onUpdate, + required this.onView, + required this.onDelete}); + + @override + Widget build(BuildContext context) { + return data.isEmpty + ? const EmptyDataWidget() + : Column( + children: [ + isPortrait + ? Container() + : ListHeadingContainer( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + child: Text( + lang(context).number, + style: ThemeText.textStyleHeadingSmall, + )), + Expanded( + child: Text( + lang(context).reference_no, + style: ThemeText.textStyleHeadingSmall, + )), + Expanded( + child: Text( + lang(context).bill_to, + style: ThemeText.textStyleHeadingSmall, + )), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: Text( + lang(context).quotation_date, + style: ThemeText.textStyleHeadingSmall, + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: Text( + lang(context).quotations_due_date, + style: ThemeText.textStyleHeadingSmall, + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: Text( + lang(context).amount, + style: ThemeText.textStyleHeadingSmall, + ), + )), + // SizedBox( + // width: 120, + // child: Align( + // alignment: Alignment.centerLeft, + // child: Text( + // lang(context).switch_status, + // style: ThemeText.textStyleHeadingSmall, + // ), + // )), + // const SizedBox( + // width: 10, + // ), + Expanded( + child: Align( + alignment: Alignment.center, + child: Text( + lang(context).status, + style: ThemeText.textStyleHeadingSmall, + ), + )), + const SizedBox( + width: 10, + ), + SizedBox( + width: 46, + child: Text( + lang(context).action, + style: ThemeText.textStyleHeadingSmall, + ), + ), + ], + ), + ), + ListView.builder( + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (c, position) { + final quotation = data[position]; + if (isPortrait) { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: Container( + padding: const EdgeInsets.fromLTRB(16, 0, 0, 16), + color: MyColors.containerBackColor, + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + flex: 2, + child: Container( + padding: const EdgeInsets.only(top: 16), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Row( + children: [ + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + lang(context).number, + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: ValueText( + quotation.quotationNumber! + .toString(), + ), + )) + ], + ), + AppSpaces.verticalMedium, + Row( + children: [ + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + lang(context).reference_no, + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: ValueText( + quotation.quotationReference! + .toString(), + ), + )) + ], + ), + AppSpaces.verticalMedium, + Row( + children: [ + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + lang(context).bill_to, + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: ValueText( + quotation.quotationFor!.first == + "Company" + ? quotation.supplier!.name ?? + "" + : quotation.customer!.name ?? + '', + ), + )) + ], + ), + AppSpaces.verticalMedium, + Row( + children: [ + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + lang(context).quotation_date, + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: ValueText( + DataTimeFormat.getFormatDate( + quotation.quotationDate!), + ), + )) + ], + ), + AppSpaces.verticalMedium, + Row( + children: [ + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + lang(context).quotations_due_date, + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: ValueText( + DataTimeFormat.getFormatDate( + quotation.quotationDueDate!), + ), + )) + ], + ), + AppSpaces.verticalMedium, + Row( + children: [ + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + lang(context).amount, + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: ValueText( + quotation.totalAmount! + .toStringAsFixed(2), + ), + )) + ], + ), + AppSpaces.verticalMedium, + Row( + children: [ + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + lang(context).status, + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: Text( + quotation.status ?? '', + style: + ThemeText.textStyleValueGreen, + ), + )) + ], + ), + AppSpaces.verticalMedium, + // Row( + // children: [ + // Expanded( + // child: Align( + // alignment: Alignment.centerLeft, + // child: HeadingText( + // lang(context).switch_status, + // ), + // )), + // Expanded( + // child: Align( + // alignment: Alignment.centerRight, + // child: Container( + // decoration: BoxDecoration( + // color: MyColors.fillColor, + // borderRadius: + // BorderRadius.circular(8), + // ), + // height: 38, + // padding: const EdgeInsets.only( + // left: 8, right: 8), + // width: SizerUtil.deviceType == + // DeviceType.mobile + // ? 120 + // : 100, + // child: + // getDropdownButton(quotation), + // ), + // )) + // ], + // ), + ], + ), + )), + getMenuPopupButton(context, quotation) + ], + ), + ), + ); + } else { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: ListHeadingContainer( + child: Row( + children: [ + Expanded( + child: ValueText( + quotation.quotationNumber.toString(), + )), + Expanded( + child: ValueText( + quotation.quotationReference.toString(), + )), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: ValueText( + quotation.quotationFor!.first == "Company" + ? quotation.supplier!.name ?? "" + : quotation.customer!.name ?? '', + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: ValueText( + DataTimeFormat.getFormatDate( + quotation.quotationDate ?? ""), + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: ValueText( + DataTimeFormat.getFormatDate( + quotation.quotationDueDate ?? ""), + ), + ), + ), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: ValueText( + quotation.totalAmount!.toStringAsFixed(2), + ), + )), + // SizedBox( + // width: 120, + // child: Align( + // alignment: Alignment.centerLeft, + // child: Container( + // decoration: BoxDecoration( + // color: MyColors.fillColor, + // borderRadius: BorderRadius.circular(8), + // ), + // height: 38, + // padding: const EdgeInsets.only( + // left: 8, right: 8), + // width: 120, + // child: getDropdownButton(quotation), + // ), + // )), + // const SizedBox( + // width: 16, + // ), + Expanded( + child: Padding( + padding: + const EdgeInsets.fromLTRB(16, 0, 32, 0), + child: Container( + width: 100, + height: 38, + decoration: const BoxDecoration( + color: MyColors.greenColor10, + borderRadius: BorderRadius.all( + Radius.circular(10.0))), + child: Padding( + padding: const EdgeInsets.all(10.0), + child: Center( + child: Text( + quotation.status!, + style: + ThemeText.textStyleValueGreen, + ), + ))), + ), + ), + Padding( + padding: const EdgeInsets.all(4), + child: Align( + alignment: Alignment.centerRight, + child: ActionPopUpContainer( + child: getMenuPopupButton(context, quotation), + ), + ), + ) + ], + ), + ), + ); + } + }, + itemCount: data.length, + ), + ], + ); + } + + getMenuPopupButton(BuildContext context, QuotationInvoice quotation) { + return CustomPopupMenuButton( + onSelected: (String value) => actionPopUpItemSelected(value, quotation), + items: [ + PopupMenuItem( + value: 'edit', + child: ValueText( + lang(context).edit, + ), + ), + PopupMenuItem( + value: 'view', + child: ValueText( + lang(context).view, + ), + ), + PopupMenuItem( + value: 'delete', + child: ValueText( + lang(context).delete, + ), + ) + ], + ); + } + + Future actionPopUpItemSelected( + String value, QuotationInvoice invoice) async { + if (value == 'edit') { + onEdit(invoice); + } else if (value == 'delete') { + onDelete(invoice); + } else { + onView(invoice); + } + } + + getDropdownButton(QuotationInvoice quotation) { + return DropdownButton( + hint: ValueText('Select'), + style: ThemeText.textStyleValue, + isExpanded: true, + underline: DropdownButtonHideUnderline(child: Container()), + items: Constants.quotationStatus.map((String items) { + return DropdownMenuItem( + value: items, + child: ValueText(items), + ); + }).toList(), + onChanged: (Object? value) { + onUpdate(quotation, value.toString()); + }, + ); + } +} diff --git a/lib/application/views/settings/ReportsVC.dart b/lib/application/views/settings/ReportsVC.dart deleted file mode 100644 index d994533..0000000 --- a/lib/application/views/settings/ReportsVC.dart +++ /dev/null @@ -1,456 +0,0 @@ -import 'dart:io'; - -import 'package:csv/csv.dart'; -import 'package:dropdown_search/dropdown_search.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:path_provider/path_provider.dart'; -import 'package:wosull/application/ViewModel/InventoryViewModel.dart'; -import 'package:wosull/application/interfaces/DrawerWidgetSelect.dart'; -import 'package:wosull/application/model/cart/GetHoldOrderModel.dart'; -import 'package:wosull/application/model/customers/GetStoreCustomer.dart'; -import 'package:wosull/application/model/reports/CashierOrderHistory.dart'; -import 'package:wosull/application/model/reports/TopOrderItemsModel.dart'; -import 'package:wosull/application/model/suppliers/GetStoreSupplierModel.dart'; -import 'package:wosull/application/theme/MyColors.dart'; -import 'package:wosull/application/theme/MyFonts.dart'; -import 'package:wosull/application/views/settings/reportsViews/BestSuppliersVC.dart'; -import 'package:wosull/application/views/settings/reportsViews/POSReturnOrderVC.dart'; -import 'package:wosull/application/views/settings/reportsViews/ReportsCategoryVC.dart'; -import 'package:wosull/application/views/settings/reportsViews/ReportsInvoiceVC.dart'; -import 'package:wosull/application/views/settings/reportsViews/ReportsQuotationVC.dart'; -import 'package:wosull/base/BaseStatefulState.dart'; -import 'package:wosull/helpers/AppSpaces.dart'; -import 'package:wosull/helpers/ThemeText.dart'; - -import 'reportsViews/POSCompleteVC.dart'; -import 'reportsViews/ReportsProductsVC.dart'; - -class ReportsVC extends StatefulWidget { - const ReportsVC({super.key}); - - @override - State createState() => _ReportsVCState(); -} - -class _ReportsVCState extends BaseStatefulState - implements ReportsCVS { - final viewModel = InventoryViewModel(); - bool isPortrait = true; - bool isLoading = true; - bool _isLoadMoreRunning = false; - List cvsData = []; - List completedOrders = []; - List returnOrder = []; - List customerData = []; - List suppliers = []; - - var items = [ - 'Best Seller', - 'POS Complete', - 'POS Return', - 'Invoices', - 'Quotations', - 'Categories', - 'Products' - ]; - String selectedReport = ""; - - @override - void initState() { - // TODO: implement initState - super.initState(); - selectedReport = items[0]; - } - - @override - Widget build(BuildContext context) { - return MaterialApp( - debugShowCheckedModeBanner: false, - home: Scaffold( - resizeToAvoidBottomInset: true, - body: OrientationBuilder(builder: (c, orientation) { - isPortrait = - MediaQuery.of(context).orientation == Orientation.portrait; - return Container( - padding: const EdgeInsets.all(12), - color: MyColors.fillColor, - child: Column( - children: [ - isPortrait - ? Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Text( - AppLocalizations.of(context)!.pos_sales, - style: ThemeText.textStylePageHeading, - ), - const SizedBox( - width: 4, - ), - Flexible( - child: getReportsTypeButton(), - ) - ], - ), - const SizedBox( - height: 4, - ), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Flexible( - child: SizedBox( - height: 48, - child: Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - child: TextField( - style: TextStyle( - fontSize: MyFonts.normalButton, - fontFamily: MyFonts.DMREGULAR, - color: MyColors.textColorBlack), - decoration: InputDecoration( - contentPadding: - const EdgeInsets.symmetric( - vertical: 0), - hintText: - AppLocalizations.of(context)! - .search, - prefixIcon: Icon(Icons.search), - focusedBorder: OutlineInputBorder( - borderSide: const BorderSide( - color: Colors.transparent, - width: 1.0), - borderRadius: - BorderRadius.circular(8.0), - ), - enabledBorder: OutlineInputBorder( - borderSide: const BorderSide( - width: 1, //<-- SEE HERE - color: Colors.transparent, - ), - borderRadius: - BorderRadius.circular(8.0), - ), - )), - ), - )), - const SizedBox(), - SizedBox( - width: 100, - child: ElevatedButton.icon( - style: ElevatedButton.styleFrom( - elevation: 0, - shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.circular(8.0), - ), - backgroundColor: MyColors.backColorBlue50, - minimumSize: - const Size.fromHeight(38), // NEW - ), - onPressed: () { - generateCsv(selectedReport); - }, - label: Text( - AppLocalizations.of(context)!.excel, - style: MyColors.textStyleButton(), - ), - icon: Icon( - size: 14, - Icons.file_download_outlined, - color: MyColors.blueThemeColor, - ), - ), - ) - ], - ), - ], - ) - : Row( - children: [ - Expanded( - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Text( - AppLocalizations.of(context)!.pos_sales, - style: ThemeText.textStylePageHeading, - ), - const SizedBox( - width: 8, - ), - SizedBox( - width: 150, - child: Material( - color: MyColors.white, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only( - left: 6, right: 0), - child: SizedBox( - height: 42, - width: double.infinity, - child: DropdownSearch( - selectedItem: - selectedReport ?? 'Choose', - popupProps: const PopupProps.menu( - constraints: - BoxConstraints(maxHeight: 200), - ), - items: items, - itemAsString: (String u) => u, - onChanged: (String? data) { - setState(() { - selectedReport = data!; - }); - }, - dropdownDecoratorProps: - const DropDownDecoratorProps( - baseStyle: TextStyle( - fontFamily: MyFonts.Medium, - fontSize: 11, - color: MyColors.textColorBlack), - dropdownSearchDecoration: - InputDecoration( - border: InputBorder.none, - hintText: 'Choose'), - ), - ), - ), - ), - ), - ), - ], - )), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - SizedBox( - width: 100, - child: ElevatedButton.icon( - style: ElevatedButton.styleFrom( - elevation: 0, - shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.circular(8.0), - ), - backgroundColor: MyColors.backColorBlue50, - minimumSize: - const Size.fromHeight(38), // NEW - ), - onPressed: () { - generateCsv(selectedReport); - }, - label: Text( - AppLocalizations.of(context)!.excel, - style: MyColors.textStyleButton(), - ), - icon: Icon( - size: 14, - Icons.file_download_outlined, - color: MyColors.blueThemeColor, - ), - ), - ), - const SizedBox(), - SizedBox( - width: 240, - height: 48, - child: Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - child: TextField( - style: TextStyle( - fontSize: MyFonts.normalButton, - fontFamily: MyFonts.DMREGULAR, - color: MyColors.textColorBlack), - decoration: InputDecoration( - contentPadding: - const EdgeInsets.symmetric( - vertical: 0), - hintText: - AppLocalizations.of(context)! - .search, - prefixIcon: Icon(Icons.search), - focusedBorder: OutlineInputBorder( - borderSide: const BorderSide( - color: Colors.transparent, - width: 1.0), - borderRadius: - BorderRadius.circular(8.0), - ), - enabledBorder: OutlineInputBorder( - borderSide: const BorderSide( - width: 1, //<-- SEE HERE - color: Colors.transparent, - ), - borderRadius: - BorderRadius.circular(8.0), - ), - )), - ), - ), - ], - ), - ], - ), - AppSpaces.verticalMedium, - Expanded( - child: getReportsType(), - ) - ], - ), - ); - })), - ); - } - - generateCsv(String name) async { - List> data = [[]]; - if (selectedReport == items[0]) { - data.clear(); - data.add(cvsData); - } else if (selectedReport == items[1]) { - data.clear(); - data.add(completedOrders); - } else if (selectedReport == items[2]) { - data.clear(); - data.add(returnOrder); - } else if (selectedReport == items[3]) { - data.clear(); - data.add(customerData); - } else if (selectedReport == items[4]) { - data.clear(); - data.add(suppliers); - } - String csvData = const ListToCsvConverter().convert(data); - final String directory = (await getApplicationDocumentsDirectory()).path; - final path = "$directory/${name.trim()}${DateTime.now()}.csv"; - print(path); - final File file = File(path); - await file.writeAsString("csvData"); - // FileStorage.writeCounter( - // csvData, '$name${DateTime.now()}.csv'); - - // String csv = const ListToCsvConverter().convert(data); - // String dir = await ExtStorage.getExternalStoragePublicDirectory( - // ExtStorage.DIRECTORY_DOWNLOADS); - // print("dir $dir"); - // String file = "$dir"; - // File f = File(file + "/filename.csv"); - // f.writeAsString(csv); - // showMessage('$name File downloaded'); - } - - Widget getReportsType() { - if (selectedReport == items[0]) { - return BestSupplierVC( - context: context, - delegate: this, - ); - } else if (selectedReport == items[1]) { - return POSComplete( - context: context, - delegate: this, - ); - } else if (selectedReport == items[2]) { - return POSReturnOrderVC( - context: context, - delegate: this, - ); - } else if (selectedReport == items[3]) { - return ReportsInvoiceVC( - context: context, - delegate: this, - ); - } else if (selectedReport == items[4]) { - return ReportsQuotationVC( - context: context, - delegate: this, - ); - } else if (selectedReport == items[5]) { - return ReportsCategoryVC( - context: context, - delegate: this, - ); - } else if (selectedReport == items[6]) { - return ReportsProductsVC( - context: context, - delegate: this, - ); - } else { - return Container(); - } - } - - @override - void updateData(List data) { - cvsData.clear(); - cvsData.addAll(data); - } - - Widget getReportsTypeButton() { - return Material( - color: MyColors.white, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: 42, - width: double.infinity, - child: DropdownSearch( - selectedItem: selectedReport ?? 'Choose', - popupProps: const PopupProps.menu( - constraints: BoxConstraints(maxHeight: 200), - ), - items: items, - itemAsString: (String u) => u, - onChanged: (String? data) { - setState(() { - selectedReport = data!; - }); - }, - dropdownDecoratorProps: const DropDownDecoratorProps( - baseStyle: TextStyle( - fontFamily: MyFonts.Medium, - fontSize: 11, - color: MyColors.textColorBlack), - dropdownSearchDecoration: - InputDecoration(border: InputBorder.none, hintText: 'Choose'), - ), - ), - ), - ), - ); - } - - @override - void customerCVS(List data) { - customerData.clear(); - customerData.addAll(data); - } - - @override - void posCompleteCVS(List data) { - completedOrders.clear(); - completedOrders.addAll(data); - } - - @override - void posReturnCVS(List data) { - returnOrder.clear(); - returnOrder.addAll(data); - } - - @override - void suppliersCVS(List data) { - suppliers.clear(); - suppliers.addAll(data); - } -} diff --git a/lib/application/views/settings/SettingsMainVC.dart b/lib/application/views/settings/SettingsMainVC.dart index 1359a84..fa41e78 100644 --- a/lib/application/views/settings/SettingsMainVC.dart +++ b/lib/application/views/settings/SettingsMainVC.dart @@ -3,11 +3,14 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:wosull/application/interfaces/DrawerWidgetSelect.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/theme/MyFonts.dart'; +import 'package:wosull/application/views/settings/views/paymentMethods/views/PaymentMethodVC.dart'; +import 'package:wosull/helpers/ThemeText.dart'; -import 'ReportsVC.dart'; +import 'views/reports/ReportsVC.dart'; class SettingsMainVC extends StatefulWidget { final DrawerWidgetSelect delegateDrawer; + const SettingsMainVC({super.key, required this.delegateDrawer}); @override @@ -18,7 +21,7 @@ class _SettingsMainVCState extends State { @override Widget build(BuildContext context) { return DefaultTabController( - length: 1, + length: 2, child: Scaffold( body: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -84,23 +87,18 @@ class _SettingsMainVCState extends State { ), TabBar( indicatorColor: Colors.white, - labelStyle: TextStyle( - fontSize: MyFonts.normalButton, - fontWeight: FontWeight.w500, - fontFamily: MyFonts.Bold, - color: MyColors.blueThemeColor), + labelStyle: ThemeText.tabLabelStyle, isScrollable: true, - unselectedLabelStyle: const TextStyle( - fontSize: MyFonts.normalButton, - fontWeight: FontWeight.w500, - fontFamily: MyFonts.Medium, - color: MyColors.textColorBlack), + unselectedLabelStyle: ThemeText.unSelectedTabLabelStyle, unselectedLabelColor: MyColors.textColorBlack, labelColor: MyColors.blueThemeColor, tabs: [ Tab( text: AppLocalizations.of(context)!.reports, ), + const Tab( + text: 'Payment Methods', + ), ], ) ], @@ -108,7 +106,7 @@ class _SettingsMainVCState extends State { ), const Expanded( child: TabBarView( - children: [ReportsVC()], + children: [ReportsVC(), PaymentMethodVC()], )) ], ), diff --git a/lib/application/views/settings/repo/ReportsRepository.dart b/lib/application/views/settings/repo/ReportsRepository.dart new file mode 100644 index 0000000..c26f538 --- /dev/null +++ b/lib/application/views/settings/repo/ReportsRepository.dart @@ -0,0 +1,67 @@ +import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/application/model/cart/GetHoldOrderModel.dart'; +import 'package:wosull/application/model/inventory/Item.dart'; +import 'package:wosull/application/model/reports/CashierOrder.dart'; +import 'package:wosull/application/model/reports/CashierOrderHistory.dart'; +import 'package:wosull/application/model/reports/TopOrderItemsModel.dart'; +import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/utils/Constants.dart'; + +class ReportsRepository { + Future> fetchReportsProduct(Map map) async { + var products = []; + await APIManager() + .getResponseAuth(Constants.GET_ITEMS_WITH_CATEGORY, map) + .then((result) { + final value = ReportProductModel.fromJson(result); + if (value.success) { + products.addAll(value.storeItems); + } + }).onError((error, stackTrace) {}); + return products; + } + + Future> fetchBestSupplier( + Map data) async { + var suppliers = []; + + await APIManager() + .getResponseAuth(Constants.GET_BEST_SELLER + sharedPrefs.storeId, data) + .then((result) { + final value = TopOrderItemsModel.fromJson(result); + if (value.success) { + suppliers.addAll(value.topOrders); + } + }).onError((error, stackTrace) {}); + + return suppliers; + } + + Future> fetchCompletePOS(Map data) async { + var orders = []; + await APIManager() + .fetchData(Constants.GET_CASHIER_ORDER_HISTORY, data) + .then((result) { + final value = CashierOrderHistory.fromJson(result); + if (value.success) { + orders.addAll(value.topOrders); + } + }).onError((error, stackTrace) {}); + return orders; + } + + Future> fetchReturnedOrder( + Map data) async { + var orders = []; + await APIManager() + .fetchData(Constants.GET_RETURN_ORDER_HISTORY, data) + .then((result) { + final value = GetReturnAndDamageModel.fromJson(result); + if (value.success!) { + orders.addAll(value.orderModel!); + } + }).onError((error, stackTrace) {}); + + return orders; + } +} diff --git a/lib/application/views/settings/reportsViews/BestSuppliersVC.dart b/lib/application/views/settings/reportsViews/BestSuppliersVC.dart deleted file mode 100644 index 9fc5f99..0000000 --- a/lib/application/views/settings/reportsViews/BestSuppliersVC.dart +++ /dev/null @@ -1,230 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:wosull/application/enum/DataState.dart'; -import 'package:wosull/application/interfaces/DrawerWidgetSelect.dart'; -import 'package:wosull/application/model/reports/TopOrderItemsModel.dart'; -import 'package:wosull/application/theme/MyColors.dart'; -import 'package:wosull/application/utils/AppError.dart'; -import 'package:wosull/application/utils/AppLoader.dart'; -import 'package:wosull/application/views/settings/viewModels/BestSupplierViewModel.dart'; -import 'package:wosull/helpers/Utils.dart'; -import 'package:wosull/widgets/EmptyDataWidget.dart'; -import 'package:wosull/widgets/HeadingText.dart'; -import 'package:wosull/widgets/ValueText.dart'; - -class BestSupplierVC extends StatelessWidget { - final ReportsCVS delegate; - BuildContext context; - - BestSupplierVC({super.key, required this.delegate, required this.context}); - - late ScrollController _controller; - final viewModel = BestSupplierViewModel(); - bool isPortrait = true; //changing the view accrodingly - - @override - Widget build(BuildContext context) { - return OrientationBuilder(builder: (c, orientation) { - isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; - _controller = ScrollController()..addListener(_scrollNotification); - return SingleChildScrollView( - controller: _controller, - child: ChangeNotifierProvider( - create: (context) => viewModel, - child: Consumer( - builder: (BuildContext context, BestSupplierViewModel controller, - Widget? _) { - switch (controller.dataState) { - case DataState.uninitialized: - Future(() { - controller.fetch(); - }); - return showData(controller.data, true); - case DataState.initialFetching: - return AppLoader(); - case DataState.moreFetching: - case DataState.refreshing: - return showData(controller.data, true); - case DataState.error: - return AppError(error: viewModel.wosulError.message); - case DataState.searching: - case DataState.fetched: - case DataState.noMoreData: - return showData(controller.data, false); - } - }, - ), - )); - }); - } - - Widget showData(List data, bool isLoading) { - return Column( - children: [ - data.isEmpty - ? const EmptyDataWidget() // for empty - : Column( - children: [ - isPortrait - ? Container() - : Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 50, - color: MyColors.containerBackColor, - child: Row( - children: [ - Expanded( - child: HeadingText( - lang(context).rank, - )), - Expanded( - child: HeadingText( - lang(context).id_txt, - )), - Expanded( - child: HeadingText( - lang(context).name, - )), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: HeadingText( - lang(context).no_of_order, - ), - )), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: HeadingText( - lang(context).overall_quantity, - ))), - ], - ), - ), - ListView.builder( - padding: EdgeInsets.zero, - scrollDirection: Axis.vertical, - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - itemBuilder: (c, position) { - final topOrders = data[position]; - if (isPortrait) { - return Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - elevation: 2, - color: MyColors.white, - child: Container( - padding: const EdgeInsets.fromLTRB(8, 8, 8, 8), - child: Row( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - HeadingText( - lang(context).rank, - ), - const SizedBox( - height: 8, - ), - HeadingText( - lang(context).id_txt, - ), - const SizedBox( - height: 8, - ), - HeadingText( - lang(context).item_name, - ), - const SizedBox( - height: 8, - ), - HeadingText(lang(context).no_of_order), - const SizedBox( - height: 8, - ), - HeadingText(lang(context).overall_quantity), - ], - )), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.end, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - ValueText('$position'), - const SizedBox( - height: 4, - ), - ValueText(topOrders.uniqueId!.toString()), - const SizedBox( - height: 8, - ), - ValueText(topOrders.itemName!), - const SizedBox( - height: 8, - ), - ValueText(topOrders.totalOrderQuantity! - .toString()), - const SizedBox( - height: 8, - ), - ValueText(topOrders.count!.toString()), - ], - )), - ], - ), - ), - ); - } else { - return Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - child: Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 56, - color: MyColors.containerBackColor, - child: Row( - children: [ - Expanded(child: ValueText('$position')), - Expanded( - child: ValueText( - topOrders.uniqueId!.toString())), - Expanded( - child: Text( - topOrders.itemName ?? "", - style: MyColors.textStyleValue(), - )), - Expanded( - child: ValueText(topOrders - .totalOrderQuantity! - .toString())), - Expanded( - child: ValueText( - topOrders.count!.toString() ?? "0")), - ], - ), - ), - ); - } - }, - itemCount: data.length, - ) - ], - ), - if (viewModel.dataState == DataState.moreFetching) AppLoader(), - ], - ); - } - - bool _scrollNotification() { - if (!viewModel.isLoading && _controller.position.extentAfter < 300) { - viewModel.fetch(); - } - return true; - } -} diff --git a/lib/application/views/settings/reportsViews/POSCompleteVC.dart b/lib/application/views/settings/reportsViews/POSCompleteVC.dart deleted file mode 100644 index a9faf95..0000000 --- a/lib/application/views/settings/reportsViews/POSCompleteVC.dart +++ /dev/null @@ -1,232 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:provider/provider.dart'; -import 'package:wosull/application/enum/DataState.dart'; -import 'package:wosull/application/interfaces/DrawerWidgetSelect.dart'; -import 'package:wosull/application/model/converters/DataTimeFormat.dart'; -import 'package:wosull/application/model/reports/CashierOrderHistory.dart'; -import 'package:wosull/application/theme/MyColors.dart'; -import 'package:wosull/application/utils/AppError.dart'; -import 'package:wosull/application/utils/AppLoader.dart'; -import 'package:wosull/application/views/settings/viewModels/POSCompleteViewModel.dart'; -import 'package:wosull/widgets/HeadingText.dart'; -import 'package:wosull/widgets/ValueText.dart'; - -import '../../../../widgets/EmptyDataWidget.dart'; - -class POSComplete extends StatelessWidget { - late ScrollController _controller; - final viewModel = POSCompleteViewModel(); - bool isPortrait = true; - - final ReportsCVS delegate; - BuildContext context; - - POSComplete({super.key, required this.delegate, required this.context}); - - @override - Widget build(BuildContext context) { - return OrientationBuilder(builder: (c, orientation) { - _controller = ScrollController()..addListener(_scrollNotification); - isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; - return SingleChildScrollView( - controller: _controller, - child: ChangeNotifierProvider( - create: (context) => viewModel, - child: Consumer( - builder: (BuildContext context, POSCompleteViewModel controller, - Widget? _) { - switch (controller.dataState) { - case DataState.uninitialized: - Future(() { - controller.fetch(); - }); - return showData(controller.data); - case DataState.initialFetching: - return AppLoader(); - case DataState.moreFetching: - case DataState.refreshing: - return showData(controller.data); - case DataState.error: - return AppError(); - case DataState.searching: - case DataState.fetched: - case DataState.noMoreData: - return showData(controller.data); - } - }, - ), - ), - ); - }); - } - - Widget showData(List data) { - return Column( - children: [ - data.isEmpty - ? const EmptyDataWidget() - : Column( - children: [ - isPortrait - ? Container() - : Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 50, - color: MyColors.containerBackColor, - child: Row( - children: [ - Expanded( - child: HeadingText( - AppLocalizations.of(context)! - .order_number)), - Expanded( - child: HeadingText( - AppLocalizations.of(context)! - .store_name)), - Expanded( - child: HeadingText( - AppLocalizations.of(context)!.status)), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: HeadingText( - AppLocalizations.of(context)!.created_on), - )), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: HeadingText( - AppLocalizations.of(context)! - .updated_on))), - ], - ), - ), - ListView.builder( - padding: EdgeInsets.zero, - scrollDirection: Axis.vertical, - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - itemBuilder: (c, position) { - final completePOS = data[position]; - if (isPortrait) { - return Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - elevation: 2, - color: MyColors.white, - child: Container( - padding: const EdgeInsets.all(12), - child: Row( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - HeadingText(AppLocalizations.of(context)! - .order_number), - const SizedBox( - height: 8, - ), - HeadingText(AppLocalizations.of(context)! - .store_name), - const SizedBox( - height: 8, - ), - HeadingText( - AppLocalizations.of(context)!.status), - const SizedBox( - height: 8, - ), - HeadingText(AppLocalizations.of(context)! - .created_on), - const SizedBox( - height: 8, - ), - HeadingText(AppLocalizations.of(context)! - .updated_on), - ], - )), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.end, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - ValueText( - completePOS.uniqueId!.toString(), - ), - const SizedBox( - height: 12, - ), - ValueText(completePOS.storeId!.name ?? ''), - const SizedBox( - height: 12, - ), - ValueText(completePOS.status ?? ''), - const SizedBox( - height: 12, - ), - ValueText(DataTimeFormat.getFormatDate( - completePOS.createdAt ?? '')), - const SizedBox( - height: 12, - ), - ValueText(DataTimeFormat.getFormatDate( - completePOS.updatedAt ?? '')), - ], - )), - ], - ), - ), - ); - } else { - return Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - child: Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 56, - color: MyColors.containerBackColor, - child: Row( - children: [ - Expanded( - child: ValueText( - completePOS.uniqueId!.toString())), - Expanded( - child: - ValueText(completePOS.storeId!.name!)), - Expanded(child: ValueText(completePOS.status!)), - Expanded( - child: ValueText( - DataTimeFormat.getFormatDate( - completePOS.createdAt!))), - Expanded( - child: ValueText( - DataTimeFormat.getFormatDate( - completePOS.updatedAt!))), - ], - ), - ), - ); - } - }, - itemCount: data.length, - ) - ], - ), - if (viewModel.dataState == DataState.moreFetching) AppLoader(), - ], - ); - } - - bool _scrollNotification() { - if (!viewModel.isLoading && _controller.position.extentAfter < 300) { - viewModel.fetch(); - } - return true; - } -} diff --git a/lib/application/views/settings/reportsViews/POSReturnOrderVC.dart b/lib/application/views/settings/reportsViews/POSReturnOrderVC.dart deleted file mode 100644 index 455c2c1..0000000 --- a/lib/application/views/settings/reportsViews/POSReturnOrderVC.dart +++ /dev/null @@ -1,229 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:provider/provider.dart'; -import 'package:wosull/application/enum/DataState.dart'; -import 'package:wosull/application/interfaces/DrawerWidgetSelect.dart'; -import 'package:wosull/application/model/cart/GetHoldOrderModel.dart'; -import 'package:wosull/application/model/converters/DataTimeFormat.dart'; -import 'package:wosull/application/theme/MyColors.dart'; -import 'package:wosull/application/utils/AppError.dart'; -import 'package:wosull/application/utils/AppLoader.dart'; -import 'package:wosull/application/views/settings/viewModels/POSReturnOrderViewModel.dart'; -import 'package:wosull/widgets/EmptyDataWidget.dart'; -import 'package:wosull/widgets/HeadingText.dart'; -import 'package:wosull/widgets/ValueText.dart'; - -class POSReturnOrderVC extends StatelessWidget { - late ScrollController _controller; - final viewModel = POSReturnOrderViewModel(); - bool isPortrait = true; - - final ReportsCVS delegate; - BuildContext context; - - POSReturnOrderVC({super.key, required this.delegate, required this.context}); - - @override - Widget build(BuildContext context) { - return OrientationBuilder(builder: (c, orientation) { - isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; - _controller = ScrollController()..addListener(_scrollNotification); - return SingleChildScrollView( - controller: _controller, - child: ChangeNotifierProvider( - create: (context) => viewModel, - child: Consumer( - builder: (BuildContext context, POSReturnOrderViewModel controller, - Widget? _) { - switch (controller.dataState) { - case DataState.uninitialized: - Future(() { - controller.fetch(); - }); - return showData(controller.data); - case DataState.initialFetching: - return AppLoader(); - case DataState.moreFetching: - case DataState.refreshing: - return showData(controller.data); - case DataState.error: - return AppError(); - case DataState.searching: - case DataState.fetched: - case DataState.noMoreData: - return showData(controller.data); - } - }, - ), - ), - ); - }); - } - - Widget showData(List data) { - return Column( - children: [ - data.isEmpty - ? const EmptyDataWidget() - : Column( - children: [ - isPortrait - ? Container() - : Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 50, - color: MyColors.containerBackColor, - child: Row( - children: [ - Expanded( - child: HeadingText( - AppLocalizations.of(context)! - .order_number)), - Expanded( - child: HeadingText( - AppLocalizations.of(context)! - .store_name)), - Expanded( - child: HeadingText( - AppLocalizations.of(context)!.status)), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: HeadingText( - AppLocalizations.of(context)!.created_on), - )), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: HeadingText( - AppLocalizations.of(context)! - .updated_on))), - ], - ), - ), - ListView.builder( - padding: EdgeInsets.zero, - scrollDirection: Axis.vertical, - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - itemBuilder: (c, position) { - final returnOrder = data[position]; - if (isPortrait) { - return Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - elevation: 2, - color: MyColors.white, - child: Container( - padding: const EdgeInsets.all(12), - child: Row( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - HeadingText(AppLocalizations.of(context)! - .order_number), - const SizedBox( - height: 8, - ), - HeadingText(AppLocalizations.of(context)! - .store_name), - const SizedBox( - height: 8, - ), - HeadingText( - AppLocalizations.of(context)!.status), - const SizedBox( - height: 8, - ), - HeadingText(AppLocalizations.of(context)! - .created_on), - const SizedBox( - height: 8, - ), - HeadingText(AppLocalizations.of(context)! - .updated_on), - ], - )), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.end, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - ValueText(returnOrder.uniqueId!.toString()), - const SizedBox( - height: 12, - ), - ValueText(returnOrder.storeId!.name ?? ''), - const SizedBox( - height: 12, - ), - ValueText(returnOrder.status ?? ''), - const SizedBox( - height: 12, - ), - ValueText(DataTimeFormat.getFormatDate( - returnOrder.createdAt ?? '')), - const SizedBox( - height: 12, - ), - ValueText(DataTimeFormat.getFormatDate( - returnOrder.updatedAt ?? '')), - ], - )), - ], - ), - ), - ); - } else { - return Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - child: Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 56, - color: MyColors.containerBackColor, - child: Row( - children: [ - Expanded( - child: ValueText( - returnOrder.uniqueId!.toString())), - Expanded( - child: - ValueText(returnOrder.storeId!.name!)), - Expanded(child: ValueText(returnOrder.status!)), - Expanded( - child: ValueText( - DataTimeFormat.getFormatDate( - returnOrder.createdAt!))), - Expanded( - child: ValueText( - DataTimeFormat.getFormatDate( - returnOrder.updatedAt!))), - ], - ), - ), - ); - } - }, - itemCount: data.length, - ) - ], - ), - if (viewModel.dataState == DataState.moreFetching) AppLoader(), - ], - ); - } - - bool _scrollNotification() { - if (!viewModel.isLoading && _controller.position.extentAfter < 300) { - viewModel.fetch(); - } - return true; - } -} diff --git a/lib/application/views/settings/reportsViews/ReportsCategoryVC.dart b/lib/application/views/settings/reportsViews/ReportsCategoryVC.dart deleted file mode 100644 index 3a258ee..0000000 --- a/lib/application/views/settings/reportsViews/ReportsCategoryVC.dart +++ /dev/null @@ -1,299 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:provider/provider.dart'; -import 'package:wosull/application/enum/DataState.dart'; -import 'package:wosull/application/interfaces/DrawerWidgetSelect.dart'; -import 'package:wosull/application/model/inventory/category/ItemCategory.dart'; -import 'package:wosull/application/theme/MyColors.dart'; -import 'package:wosull/application/theme/MyFonts.dart'; -import 'package:wosull/application/views/inventorymodule/categoryviews/viewModels/CategoryViewModel.dart'; - -import '../../../../widgets/EmptyDataWidget.dart'; - -class ReportsCategoryVC extends StatefulWidget { - final ReportsCVS delegate; - BuildContext context; - - ReportsCategoryVC({super.key, required this.delegate, required this.context}); - - @override - State createState() => _ReportsCategoryVCState(); -} - -class _ReportsCategoryVCState extends State { - bool isPortrait = true; - bool _isLoading = false; - late ScrollController _controller; - late DataState _dataState; - final categoryViewModel = CategoryViewModel(); - - @override - void initState() { - super.initState(); - _controller = ScrollController()..addListener(_scrollNotification); - } - - @override - Widget build(BuildContext context) { - return OrientationBuilder(builder: (c, orientation) { - isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; - - return SingleChildScrollView( - controller: _controller, - child: Column( - children: [ - ChangeNotifierProvider( - create: (context) => categoryViewModel, - child: Consumer( - builder: (BuildContext context, CategoryViewModel controller, - Widget? _) { - _dataState = - Provider.of(context, listen: false) - .dataState; - switch (controller.dataState) { - case DataState.uninitialized: - Future(() { - controller.fetchCategories(); - }); - return categoryListViewWidget(controller.dataList, true); - case DataState.initialFetching: - return const Center( - child: CircularProgressIndicator(), - ); - case DataState.moreFetching: - case DataState.refreshing: - return categoryListViewWidget(controller.dataList, true); - case DataState.error: - return const Center( - child: Text("Error"), - ); - case DataState.searching: - case DataState.fetched: - case DataState.noMoreData: - return categoryListViewWidget(controller.dataList, false); - } - }, - ), - ), - ], - ), - ); - }); - } - - Widget categoryListViewWidget(List _data, bool isLoading) { - _isLoading = isLoading; - return Column( - children: [ - _data.isEmpty - ? const EmptyDataWidget() - : Column( - children: [ - isPortrait - ? Container() - : Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 50, - color: MyColors.containerBackColor, - child: Row( - children: [ - Expanded( - child: Text( - AppLocalizations.of(widget.context)!.name, - style: MyColors.textStyleHeading(), - )), - Expanded( - child: Text( - AppLocalizations.of(widget.context)!.status, - style: MyColors.textStyleHeading(), - )), - Expanded( - child: Text( - AppLocalizations.of(widget.context)! - .description, - style: MyColors.textStyleHeading(), - )), - Expanded( - child: Text( - AppLocalizations.of(widget.context)!.status, - style: MyColors.textStyleHeading(), - )), - ], - ), - ), - ListView.builder( - physics: const NeverScrollableScrollPhysics(), - padding: EdgeInsets.zero, - scrollDirection: Axis.vertical, - shrinkWrap: true, - itemBuilder: (c, position) { - if (isPortrait) { - return Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - elevation: 2, - color: MyColors.white, - child: Container( - padding: const EdgeInsets.fromLTRB(8, 0, 0, 8), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Expanded( - child: Container( - padding: const EdgeInsets.only(top: 16), - child: Row( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.start, - children: [ - Text( - AppLocalizations.of(widget.context)! - .category_name, - style: MyColors.textStyleHeading(), - ), - const SizedBox( - height: 8, - ), - Text( - AppLocalizations.of(widget.context)! - .arabic_name, - style: MyColors.textStyleHeading(), - ), - const SizedBox( - height: 8, - ), - Text( - AppLocalizations.of(widget.context)! - .description, - style: MyColors.textStyleHeading(), - ), - const SizedBox( - height: 8, - ), - Text( - AppLocalizations.of( - widget.context)! - .status, - style: - MyColors.textStyleHeading()), - ], - )), - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.end, - mainAxisAlignment: - MainAxisAlignment.start, - children: [ - Text( - _data[position].name ?? '', - style: MyColors.textStyleValue(), - ), - const SizedBox( - height: 8, - ), - Text( - _data[position].arabicName ?? '', - style: MyColors.textStyleValue(), - ), - const SizedBox( - height: 8, - ), - Text( - _data[position].description ?? '', - style: MyColors.textStyleValue(), - ), - const SizedBox( - height: 8, - ), - Text( - _data[position].isActive() ?? '', - style: MyColors.textStyleValue(), - ), - ], - )), - ], - ), - )), - ], - ), - ), - ); - } else { - return Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - child: Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 56, - color: MyColors.containerBackColor, - child: Row( - children: [ - Expanded( - child: Text( - _data[position].name ?? '', - style: MyColors.textStyleValue(), - )), - Expanded( - child: Text( - _data[position].arabicName ?? '', - style: MyColors.textStyleValue(), - )), - Expanded( - child: Text( - _data[position].description ?? '', - style: MyColors.textStyleValue(), - )), - Expanded( - child: Container( - height: 38, - decoration: BoxDecoration( - color: MyColors.greenColor10, - borderRadius: BorderRadius.all( - Radius.circular(10.0))), - child: Padding( - padding: EdgeInsets.all(10.0), - child: Center( - child: Text( - _data[position].isActive()!, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: MyFonts.normal, - fontWeight: FontWeight.w700, - color: MyColors.greenColor), - ), - ))), - ), - ], - ), - ), - ); - } - }, - itemCount: _data.length, - ) - ], - ), - if (_dataState == DataState.moreFetching) - const Center(child: CircularProgressIndicator()), - ], - ); - } - - bool _scrollNotification() { - if (!_isLoading && _controller.position.extentAfter < 300) { - _isLoading = true; - categoryViewModel.fetchCategories(); - } - return true; - } -} diff --git a/lib/application/views/settings/reportsViews/ReportsInvoiceVC.dart b/lib/application/views/settings/reportsViews/ReportsInvoiceVC.dart deleted file mode 100644 index 3de8d8f..0000000 --- a/lib/application/views/settings/reportsViews/ReportsInvoiceVC.dart +++ /dev/null @@ -1,461 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:provider/provider.dart'; -import 'package:wosull/application/enum/DataState.dart'; -import 'package:wosull/application/interfaces/DrawerWidgetSelect.dart'; -import 'package:wosull/application/model/converters/DataTimeFormat.dart'; -import 'package:wosull/application/model/invoice/StoreInvoice.dart'; -import 'package:wosull/application/theme/MyColors.dart'; -import 'package:wosull/application/theme/MyFonts.dart'; -import 'package:wosull/application/views/settings/viewModels/ReportsInvoiceViewModel.dart'; - -class ReportsInvoiceVC extends StatelessWidget { - bool isPortrait = true; - - late ScrollController _controller; - - final viewModel = ReportsInvoiceViewModel(); - - final ReportsCVS delegate; - BuildContext context; - - ReportsInvoiceVC({super.key, required this.delegate, required this.context}); - - @override - Widget build(BuildContext context) { - return OrientationBuilder(builder: (c, orientation) { - isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; - _controller = ScrollController()..addListener(_scrollNotification); - return SingleChildScrollView( - controller: _controller, - child: ChangeNotifierProvider( - create: (context) => viewModel, - child: Consumer( - builder: (BuildContext context, ReportsInvoiceViewModel controller, - Widget? _) { - switch (controller.dataState) { - case DataState.uninitialized: - Future(() { - controller.fetchInvoices(); - }); - return showList(controller.invoiceList); - case DataState.initialFetching: - return const Center( - child: CircularProgressIndicator(), - ); - case DataState.moreFetching: - case DataState.refreshing: - return showList(controller.invoiceList); - case DataState.error: - return const Center( - child: Text("Error"), - ); - case DataState.fetched: - case DataState.searching: - case DataState.noMoreData: - return showList(controller.invoiceList); - } - }, - ), - ), - ); - }); - } - - Widget showList(List data) { - return Column( - children: [ - isPortrait - ? Container() - : Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 50, - color: MyColors.containerBackColor, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - const Expanded( - child: Text( - "Supplier name", - style: TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 10, - fontWeight: FontWeight.w300, - color: MyColors.black), - )), - Expanded( - child: Text( - AppLocalizations.of(context)!.invoice_number, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 10, - fontWeight: FontWeight.w300, - color: MyColors.black), - )), - Expanded( - child: Text( - AppLocalizations.of(context)!.invoice_date, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 10, - fontWeight: FontWeight.w300, - color: MyColors.black), - )), - Expanded( - child: Text( - AppLocalizations.of(context)!.invoice_due_date, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 10, - fontWeight: FontWeight.w300, - color: MyColors.black), - )), - Expanded( - child: Text( - AppLocalizations.of(context)!.amount, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 10, - fontWeight: FontWeight.w300, - color: MyColors.black), - )), - Expanded( - child: Text( - AppLocalizations.of(context)!.currency, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 10, - fontWeight: FontWeight.w300, - color: MyColors.black), - )), - Expanded( - child: Text( - AppLocalizations.of(context)!.vat_number, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 10, - fontWeight: FontWeight.w300, - color: MyColors.black), - )), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)!.default_status, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 10, - fontWeight: FontWeight.w300, - color: MyColors.black), - ), - )), - ], - ), - ), - ListView.builder( - padding: EdgeInsets.zero, - scrollDirection: Axis.vertical, - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - itemBuilder: (c, position) { - final storeInvoice = data[position]; - if (isPortrait) { - return Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - child: Container( - padding: const EdgeInsets.fromLTRB(16, 0, 0, 16), - color: MyColors.containerBackColor, - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Expanded( - flex: 2, - child: Container( - padding: const EdgeInsets.only(top: 16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Row( - children: [ - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - 'Supplier name', - style: MyColors.textStyleHeading(), - ), - )), - Expanded( - child: Align( - alignment: Alignment.centerRight, - child: Text( - storeInvoice.supplier?.name ?? "", - style: MyColors.textStyleValue(), - ), - )) - ], - ), - Row( - children: [ - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .invoice_number, - style: MyColors.textStyleHeading(), - ), - )), - Expanded( - child: Align( - alignment: Alignment.centerRight, - child: Text( - storeInvoice.invoiceNumber!.toString(), - style: MyColors.textStyleValue(), - ), - )) - ], - ), - Row( - children: [ - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .invoice_date, - style: MyColors.textStyleHeading(), - ), - )), - Expanded( - child: Align( - alignment: Alignment.centerRight, - child: Text( - DataTimeFormat.getFormatDate( - storeInvoice.invoiceDate!), - style: MyColors.textStyleValue(), - ), - )) - ], - ), - Row( - children: [ - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .invoice_due_date, - style: MyColors.textStyleHeading(), - ), - )), - Expanded( - child: Align( - alignment: Alignment.centerRight, - child: Text( - DataTimeFormat.getFormatDate( - storeInvoice.invoiceDueDate!), - style: MyColors.textStyleValue(), - ), - )) - ], - ), - Row( - children: [ - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)!.amount, - style: MyColors.textStyleHeading(), - ), - )), - Expanded( - child: Align( - alignment: Alignment.centerRight, - child: Text( - storeInvoice.totalAmount! - .toStringAsFixed(2), - style: MyColors.textStyleValue(), - ), - )) - ], - ), - Row( - children: [ - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)!.currency, - style: MyColors.textStyleHeading(), - ), - )), - Expanded( - child: Align( - alignment: Alignment.centerRight, - child: Text( - "", - style: MyColors.textStyleValue(), - ), - )) - ], - ), - Row( - children: [ - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .vat_number, - style: MyColors.textStyleHeading(), - ), - )), - Expanded( - child: Align( - alignment: Alignment.centerRight, - child: Text( - storeInvoice.vatNumber!, - style: MyColors.textStyleValue(), - ), - )) - ], - ), - Row( - children: [ - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)!.status, - style: MyColors.textStyleHeading(), - ), - )), - Expanded( - child: Align( - alignment: Alignment.centerRight, - child: Text( - storeInvoice.status!.toString(), - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.w500, - fontSize: MyFonts.normal, - color: MyColors.greenColor), - ), - )) - ], - ), - ], - ), - )), - ], - ), - ), - ); - } else { - return Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - child: Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 56, - color: MyColors.containerBackColor, - child: Row( - children: [ - Expanded( - child: Text(storeInvoice.supplier?.name ?? "", - style: MyColors.textStyleValue())), - Expanded( - child: Text( - storeInvoice.invoiceNumber.toString(), - style: MyColors.textStyleValue(), - )), - Expanded( - child: Text( - DataTimeFormat.getFormatDate(storeInvoice.invoiceDate!), - style: MyColors.textStyleValue(), - )), - Expanded( - child: Text( - DataTimeFormat.getFormatDate( - storeInvoice.invoiceDueDate!), - style: MyColors.textStyleValue(), - ), - ), - Expanded( - child: Text( - (storeInvoice.totalAmount ?? 0.0).toStringAsFixed(2), - style: MyColors.textStyleValue(), - )), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - storeInvoice.currencyId?.name ?? "", - style: MyColors.textStyleValue(), - ), - )), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - storeInvoice.vatNumber!, - style: MyColors.textStyleValue(), - ), - )), - Expanded( - child: Container( - height: 38, - decoration: const BoxDecoration( - color: MyColors.greenColor10, - borderRadius: - BorderRadius.all(Radius.circular(10.0))), - child: Padding( - padding: const EdgeInsets.all(10.0), - child: Center( - child: Text( - storeInvoice.status!, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: MyFonts.normal, - fontWeight: FontWeight.w700, - color: MyColors.greenColor), - ), - ))), - ), - ], - ), - ), - ); - } - }, - itemCount: data.length, - ), - if (viewModel.dataState == DataState.moreFetching) - const Center(child: CircularProgressIndicator()), - ], - ); - } - - bool _scrollNotification() { - if (!viewModel.isLoading && _controller.position.extentAfter < 300) { - viewModel.fetchInvoices(); - } - return true; - } -} diff --git a/lib/application/views/settings/reportsViews/ReportsProductsVC.dart b/lib/application/views/settings/reportsViews/ReportsProductsVC.dart deleted file mode 100644 index 870486e..0000000 --- a/lib/application/views/settings/reportsViews/ReportsProductsVC.dart +++ /dev/null @@ -1,307 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:provider/provider.dart'; -import 'package:wosull/application/enum/DataState.dart'; -import 'package:wosull/application/interfaces/DrawerWidgetSelect.dart'; -import 'package:wosull/application/model/inventory/Item.dart'; -import 'package:wosull/application/theme/MyColors.dart'; -import 'package:wosull/application/views/inventorymodule/viewmodel/ProductViewModel.dart'; -import 'package:wosull/widgets/EmptyDataWidget.dart'; - -class ReportsProductsVC extends StatefulWidget { - final ReportsCVS delegate; - BuildContext context; - - ReportsProductsVC({super.key, required this.delegate, required this.context}); - - @override - State createState() => _ReportsProductsVCState(); -} - -class _ReportsProductsVCState extends State { - final viewModel = ProductViewModel(); - bool isPortrait = true; - bool _isLoading = false; - late ScrollController _controller; - late DataState _dataState; - - @override - void initState() { - super.initState(); - _controller = ScrollController()..addListener(_scrollNotification); - } - - @override - Widget build(BuildContext context) { - return OrientationBuilder(builder: (c, orientation) { - isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; - - return SingleChildScrollView( - controller: _controller, - child: Column( - children: [ - ChangeNotifierProvider( - create: (context) => viewModel, - child: Consumer( - builder: (BuildContext context, ProductViewModel controller, - Widget? _) { - _dataState = - Provider.of(context, listen: false) - .dataState; - switch (controller.dataState) { - case DataState.uninitialized: - Future(() { - controller.fetchReportsProducts(); - }); - return showList(controller.dataList, true); - case DataState.initialFetching: - return const Center( - child: CircularProgressIndicator(), - ); - case DataState.moreFetching: - case DataState.refreshing: - return showList(controller.dataList, true); - case DataState.error: - return const Center( - child: Text("Error"), - ); - case DataState.searching: - case DataState.fetched: - case DataState.noMoreData: - return showList(controller.dataList, false); - } - }, - ), - ), - ], - ), - ); - }); - } - - Widget showList(List _data, bool isLoading) { - _isLoading = isLoading; - return Column( - children: [ - _data.isEmpty - ? const EmptyDataWidget() - : Column( - children: [ - isPortrait - ? Container() - : Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 50, - color: MyColors.containerBackColor, - child: Row( - children: [ - Expanded( - child: Text( - AppLocalizations.of(widget.context)!.item_name, - style: MyColors.textStyleHeading(), - )), - Expanded( - child: Text( - AppLocalizations.of(widget.context)!.category, - style: MyColors.textStyleHeading(), - )), - Expanded( - child: Text( - AppLocalizations.of(widget.context)!.price, - style: MyColors.textStyleHeading(), - )), - Expanded( - child: Text( - AppLocalizations.of(widget.context)! - .description, - style: MyColors.textStyleHeading(), - )), - Expanded( - child: Text( - 'Quantity Available', - style: MyColors.textStyleHeading(), - )), - ], - ), - ), - ListView.builder( - physics: const NeverScrollableScrollPhysics(), - padding: EdgeInsets.zero, - scrollDirection: Axis.vertical, - shrinkWrap: true, - itemBuilder: (c, position) { - if (isPortrait) { - return Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - elevation: 2, - color: MyColors.white, - child: Container( - padding: const EdgeInsets.fromLTRB(8, 0, 0, 8), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Expanded( - child: Container( - padding: const EdgeInsets.only(top: 16), - child: Row( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.start, - children: [ - Text( - AppLocalizations.of(widget.context)! - .category_name, - style: MyColors.textStyleHeading(), - ), - const SizedBox( - height: 8, - ), - Text( - AppLocalizations.of(widget.context)! - .category, - style: MyColors.textStyleHeading(), - ), - const SizedBox( - height: 8, - ), - Text( - AppLocalizations.of(widget.context)! - .price, - style: MyColors.textStyleHeading(), - ), - const SizedBox( - height: 8, - ), - Text( - AppLocalizations.of( - widget.context)! - .description, - style: - MyColors.textStyleHeading()), - const SizedBox( - height: 8, - ), - Text('Quantity Available', - style: - MyColors.textStyleHeading()), - ], - )), - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.end, - mainAxisAlignment: - MainAxisAlignment.start, - children: [ - Text( - _data[position].name ?? '', - style: MyColors.textStyleValue(), - ), - const SizedBox( - height: 8, - ), - Text( - _data[position] - .productId - ?.categoryId - ?.name ?? - '', - style: MyColors.textStyleValue(), - ), - const SizedBox( - height: 8, - ), - Text( - _data[position].details ?? '', - style: MyColors.textStyleValue(), - ), - const SizedBox( - height: 8, - ), - Text( - _data[position] - .totalQuantity - ?.toString() ?? - '', - style: MyColors.textStyleValue(), - ), - ], - )), - ], - ), - )), - ], - ), - ), - ); - } else { - return Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - child: Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 56, - color: MyColors.containerBackColor, - child: Row( - children: [ - Expanded( - child: Text( - _data[position].name ?? '', - style: MyColors.textStyleValue(), - )), - Expanded( - child: Text( - _data[position].productId?.categoryId?.name ?? - '', - style: MyColors.textStyleValue(), - )), - Expanded( - child: Text( - _data[position].price?.toStringAsFixed(2) ?? - '0.0', - style: MyColors.textStyleValue(), - )), - Expanded( - child: Text( - _data[position].details ?? '0.0', - style: MyColors.textStyleValue(), - )), - Expanded( - child: Text( - _data[position].totalQuantity?.toString() ?? - '0.0', - style: MyColors.textStyleValue(), - )), - ], - ), - ), - ); - } - }, - itemCount: _data.length, - ) - ], - ), - if (_dataState == DataState.moreFetching) - const Center(child: CircularProgressIndicator()), - ], - ); - } - - bool _scrollNotification() { - if (!_isLoading && _controller.position.extentAfter < 300) { - _isLoading = true; - viewModel.fetchReportsProducts(); - } - return true; - } -} diff --git a/lib/application/views/settings/reportsViews/ReportsQuotationVC.dart b/lib/application/views/settings/reportsViews/ReportsQuotationVC.dart deleted file mode 100644 index e715444..0000000 --- a/lib/application/views/settings/reportsViews/ReportsQuotationVC.dart +++ /dev/null @@ -1,514 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:provider/provider.dart'; -import 'package:wosull/application/enum/DataState.dart'; -import 'package:wosull/application/interfaces/DrawerWidgetSelect.dart'; -import 'package:wosull/application/model/converters/DataTimeFormat.dart'; -import 'package:wosull/application/model/invoice/QuotationInvioceModel.dart'; -import 'package:wosull/application/theme/MyColors.dart'; -import 'package:wosull/application/theme/MyFonts.dart'; -import 'package:wosull/application/views/settings/viewModels/ReportsViewModel.dart'; -import 'package:wosull/widgets/EmptyDataWidget.dart'; - -class ReportsQuotationVC extends StatefulWidget { - final ReportsCVS delegate; - BuildContext context; - - ReportsQuotationVC( - {super.key, required this.delegate, required this.context}); - - @override - State createState() => _ReportsQuotationVCState(); -} - -class _ReportsQuotationVCState extends State { - bool isPortrait = true; - bool _isLoading = false; - late ScrollController _controller; - late DataState _dataState; - final viewModel = ReportsViewModel(); - @override - void initState() { - _controller = ScrollController()..addListener(_scrollNotification); - super.initState(); - } - - @override - Widget build(BuildContext context) { - return OrientationBuilder(builder: (c, orientation) { - isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; - - return SingleChildScrollView( - controller: _controller, - child: Column( - children: [ - ChangeNotifierProvider( - create: (context) => viewModel, - child: Consumer( - builder: (BuildContext context, ReportsViewModel controller, - Widget? _) { - _dataState = - Provider.of(context, listen: false) - .dataState; - switch (controller.dataState) { - case DataState.uninitialized: - Future(() { - controller.fetchQuotations(); - }); - return showList(controller.quotationList, true); - case DataState.initialFetching: - return const Center( - child: CircularProgressIndicator(), - ); - case DataState.moreFetching: - case DataState.refreshing: - return showList(controller.quotationList, true); - case DataState.error: - return const Center( - child: Text("Error"), - ); - case DataState.searching: - case DataState.fetched: - case DataState.noMoreData: - return showList(controller.quotationList, false); - } - }, - ), - ), - ], - ), - ); - }); - } - - Widget showList(List _data, bool isLoading) { - return Column( - children: [ - _data.isEmpty - ? const EmptyDataWidget() - : Column( - children: [ - isPortrait - ? Container() - : Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 50, - color: MyColors.containerBackColor, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - Expanded( - child: Text( - AppLocalizations.of(widget.context)!.number, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 10, - fontWeight: FontWeight.w300, - color: MyColors.black), - )), - Expanded( - child: Text( - AppLocalizations.of(widget.context)! - .reference_no, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 10, - fontWeight: FontWeight.w300, - color: MyColors.black), - )), - Expanded( - child: Text( - AppLocalizations.of(widget.context)!.bill_to, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 10, - fontWeight: FontWeight.w300, - color: MyColors.black), - )), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(widget.context)! - .quotation_date, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 10, - fontWeight: FontWeight.w300, - color: MyColors.black), - ), - )), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(widget.context)! - .quotations_due_date, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 10, - fontWeight: FontWeight.w300, - color: MyColors.black), - ), - )), - Expanded( - child: Align( - alignment: Alignment.center, - child: Text( - AppLocalizations.of(widget.context)!.amount, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 10, - fontWeight: FontWeight.w300, - color: MyColors.black), - ), - )), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(widget.context)!.status, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 10, - fontWeight: FontWeight.w300, - color: MyColors.black), - ), - )), - ], - ), - ), - ListView.builder( - padding: EdgeInsets.zero, - scrollDirection: Axis.vertical, - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - itemBuilder: (c, position) { - if (isPortrait) { - return Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - child: Container( - padding: const EdgeInsets.fromLTRB(16, 0, 0, 16), - color: MyColors.containerBackColor, - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Expanded( - flex: 2, - child: Container( - padding: const EdgeInsets.only(top: 16), - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.start, - children: [ - Row( - children: [ - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .number, - style: MyColors - .textStyleHeading(), - ), - )), - Expanded( - child: Align( - alignment: - Alignment.centerRight, - child: Text( - _data[position] - .quotationNumber! - .toString(), - style: - MyColors.textStyleValue(), - ), - )) - ], - ), - Row( - children: [ - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .reference_no, - style: MyColors - .textStyleHeading(), - ), - )), - Expanded( - child: Align( - alignment: - Alignment.centerRight, - child: Text( - _data[position] - .quotationReference! - .toString(), - style: - MyColors.textStyleValue(), - ), - )) - ], - ), - Row( - children: [ - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .bill_to, - style: MyColors - .textStyleHeading(), - ), - )), - Expanded( - child: Align( - alignment: - Alignment.centerRight, - child: Text( - _data[position] - .supplier! - .name! - .toString(), - style: - MyColors.textStyleValue(), - ), - )) - ], - ), - Row( - children: [ - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .quotation_date, - style: MyColors - .textStyleHeading(), - ), - )), - Expanded( - child: Align( - alignment: - Alignment.centerRight, - child: Text( - DataTimeFormat.getFormatDate( - _data[position] - .quotationDate!), - style: - MyColors.textStyleValue(), - ), - )) - ], - ), - Row( - children: [ - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .quotations_due_date, - style: MyColors - .textStyleHeading(), - ), - )), - Expanded( - child: Align( - alignment: - Alignment.centerRight, - child: Text( - DataTimeFormat.getFormatDate( - _data[position] - .quotationDueDate!), - style: - MyColors.textStyleValue(), - ), - )) - ], - ), - Row( - children: [ - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .amount, - style: MyColors - .textStyleHeading(), - ), - )), - Expanded( - child: Align( - alignment: - Alignment.centerRight, - child: Text( - _data[position] - .totalAmount! - .toStringAsFixed(2), - style: - MyColors.textStyleValue(), - ), - )) - ], - ), - Row( - children: [ - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .status, - style: MyColors - .textStyleHeading(), - ), - )), - Expanded( - child: Align( - alignment: - Alignment.centerRight, - child: Text( - _data[position] - .status! - .toString(), - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: - FontWeight.w500, - fontSize: MyFonts.normal, - color: - MyColors.greenColor), - ), - )) - ], - ), - ], - ), - )), - ], - ), - ), - ); - } else { - return Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - child: Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 56, - color: MyColors.containerBackColor, - child: Row( - children: [ - Expanded( - child: Text( - _data[position] - .quotationNumber - .toString(), - style: MyColors.textStyleValue())), - Expanded( - child: Text( - _data[position].quotationReference.toString(), - style: MyColors.textStyleValue(), - )), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - _data[position].supplier?.name ?? "", - style: MyColors.textStyleValue(), - ), - )), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - DataTimeFormat.getFormatDate( - _data[position].quotationDate!), - style: MyColors.textStyleValue(), - ), - )), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - DataTimeFormat.getFormatDate( - _data[position].quotationDueDate!), - style: MyColors.textStyleValue(), - ), - ), - ), - Expanded( - child: Align( - alignment: Alignment.center, - child: Text( - _data[position] - .totalAmount! - .toStringAsFixed(2), - style: MyColors.textStyleValue(), - ), - )), - Expanded( - child: Container( - height: 38, - decoration: const BoxDecoration( - color: MyColors.greenColor10, - borderRadius: BorderRadius.all( - Radius.circular(10.0))), - child: Padding( - padding: const EdgeInsets.all(10.0), - child: Center( - child: Text( - _data[position].status!, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: MyFonts.normal, - fontWeight: FontWeight.w700, - color: MyColors.greenColor), - ), - ))), - ), - ], - ), - ), - ); - } - }, - itemCount: _data.length, - ), - ], - ), - if (_dataState == DataState.moreFetching) - const Center(child: CircularProgressIndicator()), - ], - ); - } - - bool _scrollNotification() { - if (!_isLoading && _controller.position.extentAfter < 300) { - _isLoading = true; - viewModel.fetchQuotations(); - } - return true; - } -} diff --git a/lib/application/views/settings/viewModels/BestSupplierViewModel.dart b/lib/application/views/settings/viewModels/BestSupplierViewModel.dart index 0a150ac..832674d 100644 --- a/lib/application/views/settings/viewModels/BestSupplierViewModel.dart +++ b/lib/application/views/settings/viewModels/BestSupplierViewModel.dart @@ -1,17 +1,16 @@ import 'package:flutter/cupertino.dart'; import 'package:wosull/application/enum/DataState.dart'; -import 'package:wosull/application/localdb/SharedPrefs.dart'; import 'package:wosull/application/model/reports/TopOrderItemsModel.dart'; -import 'package:wosull/application/network/APIManager.dart'; import 'package:wosull/application/network/WosulError.dart'; -import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/settings/repo/ReportsRepository.dart'; class BestSupplierViewModel with ChangeNotifier { + final repository = ReportsRepository(); int _currentPageNumber = 1; DataState _dataState = DataState.uninitialized; bool _didLastLoad = false; bool _isLoading = false; - + int limit = 10; bool get isLoading => _isLoading; DataState get dataState => _dataState; @@ -28,7 +27,8 @@ class BestSupplierViewModel with ChangeNotifier { notifyListeners(); } - fetch({bool isRefresh = false}) async { + fetch({bool isRefresh = false, int limit = 50}) async { + this.limit = limit; _isLoading = true; if (!isRefresh) { _dataState = (_dataState == DataState.uninitialized) @@ -40,7 +40,7 @@ class BestSupplierViewModel with ChangeNotifier { } notifyListeners(); Map data = { - 'limit': 50, + 'limit': this.limit, 'page': _currentPageNumber, }; @@ -49,17 +49,13 @@ class BestSupplierViewModel with ChangeNotifier { _dataState = DataState.noMoreData; notifyListeners(); } else { - await APIManager() - .getResponseAuth( - Constants.GET_BEST_SELLER + sharedPrefs.storeId, data) - .then((result) { - final value = TopOrderItemsModel.fromJson(result); + await repository.fetchBestSupplier(data).then((result) { if (_dataState == DataState.refreshing) { _data.clear(); } - if (value.success!) { - _data.addAll(value.topOrders!); - if (value.topOrders!.length < 50) { + if (result.isNotEmpty) { + _data.addAll(result); + if (result.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; @@ -72,16 +68,18 @@ class BestSupplierViewModel with ChangeNotifier { notifyListeners(); }).onError((error, stackTrace) { _dataState = DataState.error; - WosulError wosulError = WosulError( + + setUserError(WosulError( message: error.toString(), - ); - setUserError(wosulError); + )); }); } } catch (e) { _isLoading = true; _dataState = DataState.error; - notifyListeners(); + setUserError(WosulError( + message: e.toString(), + )); } } } diff --git a/lib/application/views/settings/viewModels/POSCompleteViewModel.dart b/lib/application/views/settings/viewModels/POSCompleteViewModel.dart index 1aeffb5..781ecef 100644 --- a/lib/application/views/settings/viewModels/POSCompleteViewModel.dart +++ b/lib/application/views/settings/viewModels/POSCompleteViewModel.dart @@ -1,16 +1,18 @@ import 'package:flutter/cupertino.dart'; import 'package:wosull/application/enum/DataState.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; -import 'package:wosull/application/model/reports/CashierOrderHistory.dart'; -import 'package:wosull/application/network/APIManager.dart'; -import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/application/model/reports/CashierOrder.dart'; +import 'package:wosull/application/views/settings/repo/ReportsRepository.dart'; +import 'package:wosull/helpers/DatePicker.dart'; class POSCompleteViewModel with ChangeNotifier { + final repository = ReportsRepository(); int _currentPageNumber = 1; DataState _dataState = DataState.uninitialized; bool _didLastLoad = false; bool _isLoading = false; - + int limit = 10; bool get isLoading => _isLoading; DataState get dataState => _dataState; @@ -18,7 +20,28 @@ class POSCompleteViewModel with ChangeNotifier { List get data => _data; - fetch({bool isRefresh = false}) async { + var stareDate = 'dd/mm/yyyy'; + var endDate = 'dd/mm/yyyy'; + + Future presentDatePicker(BuildContext context, bool isStart) async { + // showDatePicker is a pre-made funtion of Flutter + + final pickedDate = await DatePicker.presentDatePicker(context, isStart); + + if (pickedDate == null) { + return; + } + if (isStart) { + stareDate = DataTimeFormat.formatDateFromPicket(pickedDate); + } else { + endDate = DataTimeFormat.formatDateFromPicket(pickedDate); + } + + notifyListeners(); + } + + fetch({bool isRefresh = false, int limit = 10}) async { + this.limit = limit; _isLoading = true; if (!isRefresh) { _dataState = (_dataState == DataState.uninitialized) @@ -33,22 +56,20 @@ class POSCompleteViewModel with ChangeNotifier { Map data = { 'store_id': sharedPrefs.storeId, 'page': _currentPageNumber, + 'limit': this.limit }; try { if (_didLastLoad) { _dataState = DataState.noMoreData; } else { - await APIManager() - .fetchData(Constants.GET_CASHIER_ORDER_HISTORY, data) - .then((result) { - final value = CashierOrderHistory.fromJson(result); + await repository.fetchCompletePOS(data).then((result) { if (_dataState == DataState.refreshing) { _data.clear(); } - if (value.success!) { - _data.addAll(value.topOrders!); - if (value.topOrders!.length < 10) { + if (result.isNotEmpty) { + _data.addAll(result); + if (result.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; diff --git a/lib/application/views/settings/viewModels/POSReturnOrderViewModel.dart b/lib/application/views/settings/viewModels/POSReturnOrderViewModel.dart index 8ecace5..a0dc7bf 100644 --- a/lib/application/views/settings/viewModels/POSReturnOrderViewModel.dart +++ b/lib/application/views/settings/viewModels/POSReturnOrderViewModel.dart @@ -2,22 +2,26 @@ import 'package:flutter/cupertino.dart'; import 'package:wosull/application/enum/DataState.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; import 'package:wosull/application/model/cart/GetHoldOrderModel.dart'; -import 'package:wosull/application/network/APIManager.dart'; -import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/settings/repo/ReportsRepository.dart'; class POSReturnOrderViewModel with ChangeNotifier { + final repository = ReportsRepository(); + int _currentPageNumber = 1; DataState _dataState = DataState.uninitialized; bool _didLastLoad = false; bool _isLoading = false; + int limit = 10; bool get isLoading => _isLoading; DataState get dataState => _dataState; List _data = []; + List get data => _data; - fetch({bool isRefresh = false}) async { + fetch({bool isRefresh = false, int limit = 10}) async { + this.limit = limit; _isLoading = true; if (!isRefresh) { _dataState = (_dataState == DataState.uninitialized) @@ -32,37 +36,36 @@ class POSReturnOrderViewModel with ChangeNotifier { Map data = { 'store_id': sharedPrefs.storeId, 'page': _currentPageNumber, + 'limit': this.limit }; try { if (_didLastLoad) { _dataState = DataState.noMoreData; } else { - await APIManager() - .fetchData(Constants.GET_RETURN_ORDER_HISTORY, data) - .then((result) { - final value = GetReturnOrderModel.fromJson(result); + await repository.fetchReturnedOrder(data).then((result) { if (_dataState == DataState.refreshing) { _data.clear(); } - if (value.success!) { - _data.addAll(value.orderModel!); - if (value.orderModel!.length < 10) { + if (result.isNotEmpty) { + _data.addAll(result); + if (result.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; } } - _isLoading = true; + _isLoading = false; _dataState = DataState.fetched; _currentPageNumber += 1; }).onError((error, stackTrace) { + _isLoading = false; _dataState = DataState.error; }); } notifyListeners(); } catch (e) { - _isLoading = true; + _isLoading = false; _dataState = DataState.error; notifyListeners(); } diff --git a/lib/application/views/settings/viewModels/ReportsViewModel.dart b/lib/application/views/settings/viewModels/ReportsViewModel.dart index b29603c..111b8fa 100644 --- a/lib/application/views/settings/viewModels/ReportsViewModel.dart +++ b/lib/application/views/settings/viewModels/ReportsViewModel.dart @@ -10,10 +10,13 @@ import 'package:wosull/application/network/APIManager.dart'; import 'package:wosull/application/utils/Constants.dart'; class ReportsViewModel with ChangeNotifier { + bool _isLoading = false; + bool get isLoading => _isLoading; + int _currentPageNumber = 1; DataState _dataState = DataState.uninitialized; bool _didLastLoad = false; - + int limit = 10; DataState get dataState => _dataState; List _invoiceList = []; List get invoiceList => _invoiceList; @@ -21,7 +24,9 @@ class ReportsViewModel with ChangeNotifier { List _quotationList = []; List get quotationList => _quotationList; - fetchInvoices({bool isRefresh = false}) async { + fetchInvoices({bool isRefresh = false, int limit = 10}) async { + this.limit = limit; + _isLoading = true; if (!isRefresh) { _dataState = (_dataState == DataState.uninitialized) ? DataState.initialFetching @@ -34,6 +39,7 @@ class ReportsViewModel with ChangeNotifier { Map data = { 'store_id': sharedPrefs.storeId, 'page': _currentPageNumber, + 'limit': this.limit }; try { if (_didLastLoad) { @@ -48,26 +54,30 @@ class ReportsViewModel with ChangeNotifier { } if (value.success!) { _invoiceList.addAll(value.invoices!); - if (value.invoices!.length < 10) { + if (value.invoices!.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; } } + _isLoading = false; _dataState = DataState.fetched; _currentPageNumber += 1; }).onError((error, stackTrace) { + _isLoading = false; _dataState = DataState.error; }); } notifyListeners(); } catch (e) { + _isLoading = false; _dataState = DataState.error; notifyListeners(); } } - fetchQuotations({bool isRefresh = false}) async { + fetchQuotations({bool isRefresh = false, int limit = 10}) async { + this.limit = limit; if (!isRefresh) { _dataState = (_dataState == DataState.uninitialized) ? DataState.initialFetching @@ -81,6 +91,7 @@ class ReportsViewModel with ChangeNotifier { 'store_id': sharedPrefs.storeId, 'page': _currentPageNumber, 'quotation_status': 'All', + 'limit': this.limit }; try { if (_didLastLoad) { @@ -96,7 +107,7 @@ class ReportsViewModel with ChangeNotifier { } if (value.success!) { _quotationList.addAll(value.invoices!); - if (value.invoices!.length < 10) { + if (value.invoices!.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; diff --git a/lib/application/views/settings/views/paymentMethods/repo/PaymentMethodRepository.dart b/lib/application/views/settings/views/paymentMethods/repo/PaymentMethodRepository.dart new file mode 100644 index 0000000..0551c78 --- /dev/null +++ b/lib/application/views/settings/views/paymentMethods/repo/PaymentMethodRepository.dart @@ -0,0 +1,26 @@ +import 'package:wosull/application/model/SimpleResponsModel.dart'; +import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/utils/Constants.dart'; + +class PaymentMethodRepository { + Future addPaymentMethod( + Map data) async { + final result = + await APIManager().fetchData(Constants.addPaymentMethod, data); + + return SimpleResponseModel.fromJson(result); + } + + Future deletePaymentMethod(String id) async { + final data = {'payment_id': id}; + return await APIManager() + .getResponsePatch(Constants.deletePaymentMethod, data); + } + + Future updatePaymentMethod( + String id, bool status) async { + final data = {'payment_id': id, 'status': status}; + return await APIManager() + .getResponsePatch(Constants.updatePaymentMethodStatus, data); + } +} diff --git a/lib/application/views/settings/views/paymentMethods/viewModel/NewPaymentMethodViewModel.dart b/lib/application/views/settings/views/paymentMethods/viewModel/NewPaymentMethodViewModel.dart new file mode 100644 index 0000000..1f591a5 --- /dev/null +++ b/lib/application/views/settings/views/paymentMethods/viewModel/NewPaymentMethodViewModel.dart @@ -0,0 +1,80 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/model/invoice/PaymentMethod.dart'; +import 'package:wosull/application/utils/CRUDOperatoinState.dart'; +import 'package:wosull/application/views/settings/views/paymentMethods/repo/PaymentMethodRepository.dart'; +import 'package:wosull/helpers/Utils.dart'; + +class NewPaymentMethodViewModel with ChangeNotifier { + final repository = PaymentMethodRepository(); + var paymentMethod = PaymentMethod( + paymentMethod: '', + ); + + bool isPortrait = false; + + bool _isLoading = false; + + bool get isLoading => _isLoading; + var _crudOperation = CRUDOperationState.uninitialized; + + CRUDOperationState get crudOperation => _crudOperation; + + void disposeData() { + setOperation(CRUDOperationState.uninitialized); + setLoading(false); + paymentMethod = PaymentMethod( + paymentMethod: '', + ); + } + + void initData(bool isEdit, PaymentMethod paymentMethod) { + if (isEdit) { + this.paymentMethod = paymentMethod; + } + } + + void setLoading(bool value) { + _isLoading = value; + notifyListeners(); + } + + void setOperation(CRUDOperationState state) { + _crudOperation = state; + } + + void setActiveStatus(bool value) { + paymentMethod.status = value; + notifyListeners(); + } + + Future isValidate() async { + if (paymentMethod.paymentMethod!.isEmpty) { + Utils.showMessage('Please Fill Payment Method Name!'); + } else { + await addPaymentMethod(); + } + } + + Future addPaymentMethod() async { + setLoading(true); + await repository.addPaymentMethod(paymentMethod.toJson()).then((value) { + if (value.success) { + setOperation(CRUDOperationState.add); + } else { + setOperation(CRUDOperationState.error); + } + setLoading(false); + }).onError((error, stackTrace) { + setOperation(CRUDOperationState.error); + setLoading(false); + }); + } + + void updateMethodName(String value) { + paymentMethod.paymentMethod = value; + } + + void updateDescription(String value) { + paymentMethod.description = value; + } +} diff --git a/lib/application/views/settings/views/paymentMethods/viewModel/PaymentMethodViewModel.dart b/lib/application/views/settings/views/paymentMethods/viewModel/PaymentMethodViewModel.dart new file mode 100644 index 0000000..c9878d9 --- /dev/null +++ b/lib/application/views/settings/views/paymentMethods/viewModel/PaymentMethodViewModel.dart @@ -0,0 +1,124 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/enum/DataState.dart'; +import 'package:wosull/application/model/invoice/PaymentMethod.dart'; +import 'package:wosull/application/repository/WosulRepository.dart'; +import 'package:wosull/application/utils/CRUDOperatoinState.dart'; +import 'package:wosull/application/views/settings/views/paymentMethods/repo/PaymentMethodRepository.dart'; + +class PaymentMethodViewModel with ChangeNotifier { + final repository = PaymentMethodRepository(); + int _currentPageNumber = 1; + int limit = 10; + + //using this state to handle for get data and pagination + DataState _dataState = DataState.uninitialized; + + DataState get dataState => _dataState; + + bool _didLastLoad = false; + bool _isLoading = false; + + bool get isLoading => _isLoading; + + final List _dataList = []; + final List _filteredList = []; + + List get dataList => _dataList; + + List get filteredList => _filteredList; + + var _crudOperation = CRUDOperationState.uninitialized; + + CRUDOperationState get crudOperation => _crudOperation; + + void setOperation(CRUDOperationState state) { + _crudOperation = state; + } + + fetchPaymentMethod({bool isRefresh = false, int limit = 10}) async { + this.limit = limit; + _isLoading = true; + if (!isRefresh) { + _dataState = (_dataState == DataState.uninitialized) + ? DataState.initialFetching + : DataState.moreFetching; + } else { + _didLastLoad = false; + _currentPageNumber = 1; + _dataState = DataState.refreshing; + } + notifyListeners(); + var map = { + 'page': _currentPageNumber, + 'is_pagination_included': true, + 'limit': limit + }; + try { + if (_didLastLoad) { + _dataState = DataState.noMoreData; + } else { + await WosulRepository().getPaymentMethods(map: map).then((result) { + if (_dataState == DataState.refreshing) { + _filteredList.clear(); + _dataList.clear(); + } + if (result.isNotEmpty) { + _filteredList.addAll(result); + _dataList.addAll(result); + if (result.length < this.limit) { + _didLastLoad = true; + } else { + _didLastLoad = false; + } + } + _dataState = DataState.fetched; + _currentPageNumber += 1; + _isLoading = false; + notifyListeners(); + }).onError((error, stackTrace) { + _dataState = DataState.error; + _isLoading = false; + notifyListeners(); + }); + } + } catch (e) { + _isLoading = false; + _dataState = DataState.error; + notifyListeners(); + } + } + + Future delete(String id) async { + await repository.deletePaymentMethod(id).then((result) { + if (result.success) { + _filteredList.removeWhere((element) => element.id == id); + _dataList.removeWhere((element) => element.id == id); + setOperation(CRUDOperationState.delete); + } else { + setOperation(CRUDOperationState.error); + } + notifyListeners(); + }).onError((error, stackTrace) { + setOperation(CRUDOperationState.error); + notifyListeners(); + }); + } + + Future update(String id, bool value) async { + await repository.updatePaymentMethod(id, value).then((result) { + print(result.success); + if (result.success) { + int index = _filteredList.indexWhere((element) => element.id == id); + _filteredList[index].status = value; + int dataIndex = _dataList.indexWhere((element) => element.id == id); + _dataList[dataIndex].status = value; + } else {} + + notifyListeners(); + }).onError((error, stackTrace) { + print(stackTrace.toString()); + setOperation(CRUDOperationState.error); + notifyListeners(); + }); + } +} diff --git a/lib/application/views/settings/views/paymentMethods/views/NewPaymentMethodVC.dart b/lib/application/views/settings/views/paymentMethods/views/NewPaymentMethodVC.dart new file mode 100644 index 0000000..7481337 --- /dev/null +++ b/lib/application/views/settings/views/paymentMethods/views/NewPaymentMethodVC.dart @@ -0,0 +1,208 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:provider/provider.dart'; +import 'package:wosull/application/model/invoice/PaymentMethod.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/CRUDOperatoinState.dart'; +import 'package:wosull/application/views/settings/views/paymentMethods/viewModel/NewPaymentMethodViewModel.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/widgets/CustomOptionalTitle.dart'; +import 'package:wosull/widgets/CustomSimpleButton.dart'; +import 'package:wosull/widgets/CustomSwitch.dart'; +import 'package:wosull/widgets/CustomTextFieldForm.dart'; +import 'package:wosull/widgets/DialogHeader.dart'; +import 'package:wosull/widgets/MandatoryTitleText.dart'; + +class NewPaymentMethodVC extends StatefulWidget { + bool isEdit = false; + bool isView = false; + PaymentMethod paymentMethod; + + NewPaymentMethodVC( + {super.key, + required this.isEdit, + required this.isView, + required this.paymentMethod}); + + @override + State createState() => _NewPaymentMethodVCState(); +} + +class _NewPaymentMethodVCState extends State { + var viewModel = NewPaymentMethodViewModel(); + + @override + void initState() { + context + .read() + .initData(widget.isEdit, widget.paymentMethod); + super.initState(); + } + + @override + void dispose() { + viewModel.disposeData(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + viewModel = context.watch(); + return Directionality( + textDirection: TextDirection.ltr, + child: Dialog( + elevation: 0, + backgroundColor: const Color(0xffffffff), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: OrientationBuilder(builder: (c, orientation) { + viewModel.isPortrait = + MediaQuery.of(c).orientation == Orientation.portrait; + + return SingleChildScrollView( + child: Container( + width: !viewModel.isPortrait + ? MediaQuery.of(context).size.width / 1.2 + : double.infinity, + padding: const EdgeInsets.only(bottom: 8), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + DialogHeader(title: 'Add Payment Method'), + Padding( + padding: const EdgeInsets.all(12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Flexible( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + getMethodName(), + AppSpaces.verticalMedium, + viewModel.isPortrait + ? getStatusWidget() + : Container() + ], + ), + ), + AppSpaces.horizontalMedium, + viewModel.isPortrait + ? Container() + : Flexible( + flex: 1, + child: getStatusWidget(), + ), + ], + ), + AppSpaces.verticalMedium, + getDescriptionWidget() + ], + ), + ), + Visibility( + visible: !widget.isView, + child: SizedBox( + width: 120, + child: Padding( + padding: const EdgeInsets.only(right: 12), + child: CustomSimpleButton( + textColor: MyColors.white, + isLoading: viewModel.isLoading, + backGroundColor: MyColors.blueThemeColor, + onPressed: () async { + await viewModel.isValidate(); + checkState(); + }, + heading: AppLocalizations.of(context)!.save, + ), + ), + ), + ) + ], + ), + ), + ); + }), + )); + } + + getDescriptionWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.description, + ), + AppSpaces.verticalSmall, + CustomTextFieldForm( + height: 100, + initialValue: viewModel.paymentMethod.description ?? '', + readOnly: widget.isView, + hintText: AppLocalizations.of(context)!.description, + maxLines: 5, + keyboardType: TextInputType.multiline, + onChanged: (String value) { + viewModel.updateDescription(value); + }, + ), + ], + ); + } + + getMethodName() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const MandatoryTitleText(hint: 'Method Name'), + AppSpaces.verticalSmall, + CustomTextFieldForm( + readOnly: widget.isView, + initialValue: viewModel.paymentMethod.paymentMethod ?? '', + onChanged: (value) { + viewModel.updateMethodName(value); + }, + hintText: 'Enter method name') + ], + ); + } + + getStatusWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle(hint: AppLocalizations.of(context)!.status), + AppSpaces.verticalLarge, + Row( + children: [ + CustomOptionalTitle(hint: AppLocalizations.of(context)!.inactive), + AppSpaces.horizontalMedium, + CustomSwitch( + value: viewModel.paymentMethod.status ?? true, + onToggle: (value) { + if (!widget.isView) { + viewModel.setActiveStatus(value); + } + }, + ), + AppSpaces.horizontalMedium, + CustomOptionalTitle(hint: AppLocalizations.of(context)!.active) + ], + ), + ], + ); + } + + void checkState() { + if (viewModel.crudOperation == CRUDOperationState.add) { + Navigator.pop(context, true); + } + } +} diff --git a/lib/application/views/settings/views/paymentMethods/views/PaymentMethodVC.dart b/lib/application/views/settings/views/paymentMethods/views/PaymentMethodVC.dart new file mode 100644 index 0000000..fc217fb --- /dev/null +++ b/lib/application/views/settings/views/paymentMethods/views/PaymentMethodVC.dart @@ -0,0 +1,224 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:wosull/application/enum/DataState.dart'; +import 'package:wosull/application/model/invoice/PaymentMethod.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/AppError.dart'; +import 'package:wosull/application/utils/AppLoader.dart'; +import 'package:wosull/application/utils/CRUDOperatoinState.dart'; +import 'package:wosull/application/views/popups/DeleteRecordPopUp.dart'; +import 'package:wosull/application/views/settings/views/paymentMethods/viewModel/PaymentMethodViewModel.dart'; +import 'package:wosull/application/views/settings/views/paymentMethods/views/NewPaymentMethodVC.dart'; +import 'package:wosull/application/views/settings/views/paymentMethods/widgets/PaymentMethodListView.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/helpers/Utils.dart'; +import 'package:wosull/widgets/CustomSimpleButton.dart'; +import 'package:wosull/widgets/PageLimitDropDown.dart'; + +class PaymentMethodVC extends StatefulWidget { + const PaymentMethodVC({super.key}); + + @override + State createState() => _PaymentMethodVCState(); +} + +class _PaymentMethodVCState extends State { + var viewModel = PaymentMethodViewModel(); + bool isPortrait = true; + late ScrollController _controller; + + @override + Widget build(BuildContext context) { + _controller = ScrollController()..addListener(_scrollNotification); + return Scaffold( + backgroundColor: MyColors.fillColor, + resizeToAvoidBottomInset: true, + body: OrientationBuilder(builder: (c, orientation) { + isPortrait = + MediaQuery.of(context).orientation == Orientation.portrait; + return SingleChildScrollView( + controller: _controller, + child: Container( + padding: const EdgeInsets.all(12), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + isPortrait + ? Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + 'Payment Methods', + style: ThemeText.textStylePageHeading, + ), + AppSpaces.horizontalSmall, + Flexible( + child: SizedBox( + height: 38, + child: newPaymentMethod(), + )), + ], + ), + AppSpaces.verticalSmall, + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + PageLimitDropdown(onChange: (value) {}) + ], + ), + ], + ) + : Row( + children: [ + Text( + 'Payment Methods', + style: ThemeText.textStylePageHeading, + ), + AppSpaces.horizontalSmall, + SizedBox( + height: 38, + width: 170, + child: newPaymentMethod()), + AppSpaces.horizontalSmall, + Flexible( + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + PageLimitDropdown(onChange: (value) {}) + ], + )) + ], + ), + AppSpaces.verticalMedium, + ChangeNotifierProvider( + create: (context) => viewModel, + child: Consumer( + builder: (BuildContext context, + PaymentMethodViewModel controller, Widget? _) { + switch (controller.dataState) { + case DataState.uninitialized: + Future(() { + controller.fetchPaymentMethod(); + }); + return showList(controller.filteredList); + case DataState.initialFetching: + return AppLoader(); + case DataState.moreFetching: + case DataState.refreshing: + return showList(controller.filteredList); + case DataState.error: + return AppError(); + case DataState.searching: + case DataState.fetched: + case DataState.noMoreData: + return showList(controller.filteredList); + } + }, + ), + ) + ], + ), + ), + ); + })); + } + + Widget showList(List data) { + return Column( + children: [ + PaymentMethodListView( + data: data, + isPortrait: isPortrait, + onUpdate: (method, value) { + update(method.id!, value); + }, + onDelete: (method) { + showDeletePopUp(method); + }, + onView: (method) { + addUpdatePaymentMethod(true, true, method); + }, + onEdit: (method) { + addUpdatePaymentMethod(true, false, method); + }), + if (viewModel.dataState == DataState.moreFetching) AppLoader(), + ], + ); + } + + bool _scrollNotification() { + if (!viewModel.isLoading && _controller.position.extentAfter < 300) { + viewModel.fetchPaymentMethod(limit: viewModel.limit); + } + return true; + } + + Future update(String id, bool value) async { + Utils.progressDialogue(context); + await viewModel.update(id, value); + checkState(); + } + + Future showDeletePopUp(PaymentMethod method) async { + final result = await showDialog( + barrierColor: Colors.black26, + context: context, + builder: (context) { + return const DeleteRecordPopUp(); + }, + ); + + if (result) { + delete(method.id!); + } + } + + Future delete(String id) async { + Utils.progressDialogue(context); + await viewModel.delete(id); + checkState(); + } + + newPaymentMethod() { + return CustomSimpleButton( + textColor: MyColors.blueThemeColor, + backGroundColor: MyColors.backColorBlue50, + heading: '+ New Payment Methods', + onPressed: () { + addUpdatePaymentMethod(false, false, PaymentMethod()); + }, + ); + } + + Future addUpdatePaymentMethod( + bool isEdit, bool isView, PaymentMethod method) async { + final result = await showDialog( + barrierColor: Colors.black26, + context: context, + builder: (context) { + return NewPaymentMethodVC( + isEdit: isEdit, + isView: isView, + paymentMethod: method, + ); + }, + ); + + if (result != null) { + viewModel.fetchPaymentMethod(isRefresh: true); + } + } + + void checkState() { + Utils.hideProgressBar(context); + if (viewModel.crudOperation == CRUDOperationState.view) { + // showCategoryPopUp(); + return; + } + } +} diff --git a/lib/application/views/settings/views/paymentMethods/widgets/PaymentMethodListView.dart b/lib/application/views/settings/views/paymentMethods/widgets/PaymentMethodListView.dart new file mode 100644 index 0000000..4b5ec8c --- /dev/null +++ b/lib/application/views/settings/views/paymentMethods/widgets/PaymentMethodListView.dart @@ -0,0 +1,242 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/application/model/invoice/PaymentMethod.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/Utils.dart'; +import 'package:wosull/widgets/ActionPopUpContainer.dart'; +import 'package:wosull/widgets/CustomPopuoMenuButton.dart'; +import 'package:wosull/widgets/CustomSwitch.dart'; +import 'package:wosull/widgets/EmptyDataWidget.dart'; +import 'package:wosull/widgets/HeadingText.dart'; +import 'package:wosull/widgets/ListHeadingContainer.dart'; +import 'package:wosull/widgets/ValueText.dart'; + +class PaymentMethodListView extends StatelessWidget { + List data; + bool isPortrait; + final void Function(PaymentMethod itemCategory, bool status) onUpdate; + final void Function(PaymentMethod itemCategory) onDelete; + final void Function(PaymentMethod itemCategory) onView; + final void Function(PaymentMethod itemCategory) onEdit; + + PaymentMethodListView( + {super.key, + required this.data, + required this.isPortrait, + required this.onUpdate, + required this.onDelete, + required this.onView, + required this.onEdit}); + + @override + Widget build(BuildContext context) { + return data.isEmpty + ? const EmptyDataWidget() + : Column( + children: [ + data.isEmpty + ? const EmptyDataWidget() + : Column( + children: [ + isPortrait + ? Container() + : ListHeadingContainer( + child: Row( + children: [ + Expanded( + child: HeadingText(lang(context).name)), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + lang(context).status, + ), + )), + Expanded( + child: HeadingText( + lang(context).updated_on, + )), + Expanded( + child: Padding( + padding: const EdgeInsets.only(right: 16), + child: Align( + alignment: Alignment.centerRight, + child: HeadingText( + lang(context).action, + ), + ), + )), + ], + ), + ), + ListView.builder( + physics: const NeverScrollableScrollPhysics(), + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, + shrinkWrap: true, + itemBuilder: (c, position) { + if (isPortrait) { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + elevation: 2, + color: MyColors.white, + child: Container( + padding: + const EdgeInsets.fromLTRB(8, 0, 0, 8), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + child: Container( + padding: const EdgeInsets.only(top: 16), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.end, + children: [ + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + HeadingText( + lang(context).name, + ), + AppSpaces.verticalMedium, + HeadingText( + lang(context).updated_on), + AppSpaces.verticalMedium, + HeadingText( + lang(context).status), + ], + )), + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.end, + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + ValueText(data[position] + .paymentMethod!), + AppSpaces.verticalMedium, + ValueText(DataTimeFormat + .getFormatDate( + data[position] + .updatedAt!)), + AppSpaces.verticalSmall, + Row( + mainAxisAlignment: + MainAxisAlignment.end, + crossAxisAlignment: + CrossAxisAlignment.end, + children: [ + CustomSwitch( + value: data[position] + .status!, + onToggle: (value) { + onUpdate(data[position], + value); + }, + ) + ], + ), + ], + )), + ], + ), + )), + getPopupMenu(context, position) + ], + ), + ), + ); + } else { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: ListHeadingContainer( + child: Row( + children: [ + Expanded( + child: ValueText( + data[position].paymentMethod!, + )), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: CustomSwitch( + value: data[position].status!, + onToggle: (value) { + onUpdate(data[position], value); + }), + )), + Expanded( + child: ValueText( + DataTimeFormat.getFormatDate( + data[position].updatedAt!), + )), + Expanded( + child: Padding( + padding: const EdgeInsets.all(4), + child: Align( + alignment: Alignment.centerRight, + child: ActionPopUpContainer( + child: + getPopupMenu(context, position), + ), + ), + )) + ], + ), + ), + ); + } + }, + itemCount: data.length, + ) + ], + ) + ], + ); + } + + Future actionPopUpItemSelected( + String value, PaymentMethod paymentMethod, int position) async { + if (value == 'edit') { + onEdit(paymentMethod); + } else if (value == 'delete') { + onDelete(paymentMethod); + } else { + onView(paymentMethod); + } + } + + getPopupMenu(BuildContext context, int position) { + return CustomPopupMenuButton( + onSelected: (String value) => + actionPopUpItemSelected(value, data[position], position), + items: [ + PopupMenuItem( + value: 'edit', + child: ValueText(lang(context).edit), + ), + PopupMenuItem( + value: 'view', + child: ValueText(lang(context).view), + ), + PopupMenuItem( + value: 'delete', + child: ValueText(lang(context).delete), + ) + ], + ); + } +} diff --git a/lib/application/views/settings/views/reports/ReportsVC.dart b/lib/application/views/settings/views/reports/ReportsVC.dart new file mode 100644 index 0000000..61ea125 --- /dev/null +++ b/lib/application/views/settings/views/reports/ReportsVC.dart @@ -0,0 +1,263 @@ +import 'dart:io'; + +import 'package:csv/csv.dart'; +import 'package:dropdown_search/dropdown_search.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:wosull/application/interfaces/DrawerWidgetSelect.dart'; +import 'package:wosull/application/model/cart/GetHoldOrderModel.dart'; +import 'package:wosull/application/model/customers/GetStoreCustomer.dart'; +import 'package:wosull/application/model/reports/CashierOrder.dart'; +import 'package:wosull/application/model/reports/TopOrderItemsModel.dart'; +import 'package:wosull/application/model/suppliers/GetStoreSupplierModel.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/settings/views/reportsViews/BestSuppliersVC.dart'; +import 'package:wosull/application/views/settings/views/reportsViews/POSCompleteVC.dart'; +import 'package:wosull/application/views/settings/views/reportsViews/POSReturnOrderVC.dart'; +import 'package:wosull/application/views/settings/views/reportsViews/ReportsCategoryVC.dart'; +import 'package:wosull/application/views/settings/views/reportsViews/ReportsInvoiceVC.dart'; +import 'package:wosull/application/views/settings/views/reportsViews/ReportsProductsVC.dart'; +import 'package:wosull/application/views/settings/views/reportsViews/ReportsQuotationVC.dart'; +import 'package:wosull/base/BaseStatefulState.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeDropDown.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/widgets/DropdownItemBuilder.dart'; +import 'package:wosull/widgets/PageLimitDropDown.dart'; + +class ReportsVC extends StatefulWidget { + const ReportsVC({super.key}); + + @override + State createState() => _ReportsVCState(); +} + +class _ReportsVCState extends BaseStatefulState + implements ReportsCVS { + bool isPortrait = true; + bool isLoading = true; + + int limit = 10; + + List cvsData = []; + List completedOrders = []; + List returnOrder = []; + List customerData = []; + List suppliers = []; + + String selectedReport = ""; + + @override + void initState() { + super.initState(); + selectedReport = Constants.reportsTypes[0]; + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: MyColors.fillColor, + resizeToAvoidBottomInset: true, + body: OrientationBuilder(builder: (c, orientation) { + isPortrait = + MediaQuery.of(context).orientation == Orientation.portrait; + return Container( + padding: const EdgeInsets.all(12), + color: MyColors.fillColor, + child: Column( + children: [ + isPortrait + ? Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)!.pos_sales, + style: ThemeText.textStylePageHeading, + ), + AppSpaces.horizontalSmall, + Flexible( + child: SizedBox( + height: 38, + child: getReportsTypeButton(), + ), + ), + AppSpaces.horizontalSmall, + PageLimitDropdown(onChange: (value) { + limit = int.parse(value!); + }) + ], + ) + : Row( + children: [ + Text( + AppLocalizations.of(context)!.pos_sales, + style: ThemeText.textStylePageHeading, + ), + AppSpaces.horizontalSmall, + SizedBox( + width: 150, + child: getReportsTypeButton(), + ), + Flexible( + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + PageLimitDropdown(onChange: (value) { + limit = int.parse(value!); + }) + ], + )) + ], + ), + AppSpaces.verticalMedium, + Expanded( + child: getReportsType(), + ) + ], + ), + ); + })); + } + + generateCsv(String name) async { + List> data = [[]]; + if (selectedReport == Constants.reportsTypes[0]) { + data.clear(); + data.add(cvsData); + } else if (selectedReport == Constants.reportsTypes[1]) { + data.clear(); + data.add(completedOrders); + } else if (selectedReport == Constants.reportsTypes[2]) { + data.clear(); + data.add(returnOrder); + } else if (selectedReport == Constants.reportsTypes[3]) { + data.clear(); + data.add(customerData); + } else if (selectedReport == Constants.reportsTypes[4]) { + data.clear(); + data.add(suppliers); + } + String csvData = const ListToCsvConverter().convert(data); + final String directory = (await getApplicationDocumentsDirectory()).path; + final path = "$directory/${name.trim()}${DateTime.now()}.csv"; + print(path); + final File file = File(path); + await file.writeAsString(csvData); + + // FileStorage.writeCounter( + // csvData, '$name${DateTime.now()}.csv'); + + // String csv = const ListToCsvConverter().convert(data); + // String dir = await ExtStorage.getExternalStoragePublicDirectory( + // ExtStorage.DIRECTORY_DOWNLOADS); + // print("dir $dir"); + // String file = "$dir"; + // File f = File(file + "/filename.csv"); + // f.writeAsString(csv); + // showMessage('$name File downloaded'); + } + + Widget getReportsType() { + if (selectedReport == Constants.reportsTypes[0]) { + return BestSupplierVC( + limit: limit, + context: context, + delegate: this, + ); + } else if (selectedReport == Constants.reportsTypes[1]) { + return POSComplete( + limit: limit, + context: context, + delegate: this, + ); + } else if (selectedReport == Constants.reportsTypes[2]) { + return POSReturnOrderVC( + limit: limit, + context: context, + delegate: this, + ); + } else if (selectedReport == Constants.reportsTypes[3]) { + return ReportsInvoiceVC( + limit: limit, + context: context, + delegate: this, + ); + } else if (selectedReport == Constants.reportsTypes[4]) { + return ReportsQuotationVC( + limit: limit, + context: context, + delegate: this, + ); + } else if (selectedReport == Constants.reportsTypes[5]) { + return ReportsCategoryVC( + limit: limit, + context: context, + delegate: this, + ); + } else if (selectedReport == Constants.reportsTypes[6]) { + return ReportsProductsVC( + limit: limit, + context: context, + delegate: this, + ); + } else { + return Container(); + } + } + + @override + void updateData(List data) { + cvsData.clear(); + cvsData.addAll(data); + } + + Widget getReportsTypeButton() { + return DropdownSearch( + selectedItem: selectedReport, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 200), + ), + items: Constants.reportsTypes, + itemAsString: (String u) => u, + onChanged: (String? data) { + setState(() { + selectedReport = data!; + }); + }, + dropdownDecoratorProps: + MyColors.dropDownStyle(hint: 'Choose', fillColor: MyColors.white), + ); + } + + @override + void customerCVS(List data) { + customerData.clear(); + customerData.addAll(data); + } + + @override + void posCompleteCVS(List data) { + completedOrders.clear(); + completedOrders.addAll(data); + } + + @override + void posReturnCVS(List data) { + returnOrder.clear(); + returnOrder.addAll(data); + } + + @override + void suppliersCVS(List data) { + suppliers.clear(); + suppliers.addAll(data); + } +} diff --git a/lib/application/views/settings/views/reportsViews/BestSuppliersVC.dart b/lib/application/views/settings/views/reportsViews/BestSuppliersVC.dart new file mode 100644 index 0000000..44a27c7 --- /dev/null +++ b/lib/application/views/settings/views/reportsViews/BestSuppliersVC.dart @@ -0,0 +1,78 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:wosull/application/enum/DataState.dart'; +import 'package:wosull/application/interfaces/DrawerWidgetSelect.dart'; +import 'package:wosull/application/model/reports/TopOrderItemsModel.dart'; +import 'package:wosull/application/utils/AppError.dart'; +import 'package:wosull/application/utils/AppLoader.dart'; +import 'package:wosull/application/views/settings/viewModels/BestSupplierViewModel.dart'; +import 'package:wosull/application/views/settings/widgets/BestSupplierListView.dart'; + +class BestSupplierVC extends StatelessWidget { + final ReportsCVS delegate; + BuildContext context; + int limit = 10; + + BestSupplierVC( + {super.key, + required this.delegate, + required this.context, + this.limit = 10}); + + late ScrollController _controller; + final viewModel = BestSupplierViewModel(); + bool isPortrait = true; //changing the view accrodingly + + @override + Widget build(BuildContext context) { + _controller = ScrollController()..addListener(_scrollNotification); + return OrientationBuilder(builder: (c, orientation) { + isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; + + return SingleChildScrollView( + controller: _controller, + child: ChangeNotifierProvider( + create: (context) => viewModel, + child: Consumer( + builder: (BuildContext context, BestSupplierViewModel controller, + Widget? _) { + switch (controller.dataState) { + case DataState.uninitialized: + Future(() { + controller.fetch(limit: limit); + }); + return showData(controller.data); + case DataState.initialFetching: + return AppLoader(); + case DataState.moreFetching: + case DataState.refreshing: + return showData(controller.data); + case DataState.error: + return AppError(error: viewModel.wosulError.message); + case DataState.searching: + case DataState.fetched: + case DataState.noMoreData: + return showData(controller.data); + } + }, + ), + )); + }); + } + + Widget showData(List data) { + return Column( + children: [ + BestSupplierListView(isPortrait: isPortrait, data: data), + if (viewModel.dataState == DataState.moreFetching) AppLoader(), + ], + ); + } + + bool _scrollNotification() { + if (!viewModel.isLoading && _controller.position.extentAfter < 300) { + viewModel.fetch(limit: limit); + } + return true; + } +} diff --git a/lib/application/views/settings/views/reportsViews/POSCompleteVC.dart b/lib/application/views/settings/views/reportsViews/POSCompleteVC.dart new file mode 100644 index 0000000..6aea41e --- /dev/null +++ b/lib/application/views/settings/views/reportsViews/POSCompleteVC.dart @@ -0,0 +1,78 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:wosull/application/enum/DataState.dart'; +import 'package:wosull/application/interfaces/DrawerWidgetSelect.dart'; +import 'package:wosull/application/model/reports/CashierOrder.dart'; +import 'package:wosull/application/utils/AppError.dart'; +import 'package:wosull/application/utils/AppLoader.dart'; +import 'package:wosull/application/views/settings/viewModels/POSCompleteViewModel.dart'; +import 'package:wosull/application/views/settings/widgets/POSCompleteListView.dart'; + +class POSComplete extends StatelessWidget { + late ScrollController _controller; + final viewModel = POSCompleteViewModel(); + bool isPortrait = true; + int limit = 10; + + final ReportsCVS delegate; + BuildContext context; + + POSComplete( + {super.key, + required this.delegate, + required this.context, + this.limit = 10}); + + @override + Widget build(BuildContext context) { + return OrientationBuilder(builder: (c, orientation) { + _controller = ScrollController()..addListener(_scrollNotification); + isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; + return SingleChildScrollView( + controller: _controller, + child: ChangeNotifierProvider( + create: (context) => viewModel, + child: Consumer( + builder: (BuildContext context, POSCompleteViewModel controller, + Widget? _) { + switch (controller.dataState) { + case DataState.uninitialized: + Future(() { + controller.fetch(limit: limit); + }); + return showData(controller.data); + case DataState.initialFetching: + return AppLoader(); + case DataState.moreFetching: + case DataState.refreshing: + return showData(controller.data); + case DataState.error: + return AppError(); + case DataState.searching: + case DataState.fetched: + case DataState.noMoreData: + return showData(controller.data); + } + }, + ), + ), + ); + }); + } + + Widget showData(List data) { + return Column( + children: [ + POSCompleteListView(isPortrait: isPortrait, data: data), + if (viewModel.dataState == DataState.moreFetching) AppLoader(), + ], + ); + } + + bool _scrollNotification() { + if (!viewModel.isLoading && _controller.position.extentAfter < 300) { + viewModel.fetch(limit: limit); + } + return true; + } +} diff --git a/lib/application/views/settings/views/reportsViews/POSReturnOrderVC.dart b/lib/application/views/settings/views/reportsViews/POSReturnOrderVC.dart new file mode 100644 index 0000000..ac83e6a --- /dev/null +++ b/lib/application/views/settings/views/reportsViews/POSReturnOrderVC.dart @@ -0,0 +1,77 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:wosull/application/enum/DataState.dart'; +import 'package:wosull/application/interfaces/DrawerWidgetSelect.dart'; +import 'package:wosull/application/model/cart/GetHoldOrderModel.dart'; +import 'package:wosull/application/utils/AppError.dart'; +import 'package:wosull/application/utils/AppLoader.dart'; +import 'package:wosull/application/views/settings/viewModels/POSReturnOrderViewModel.dart'; +import 'package:wosull/application/views/settings/widgets/POSReturnOrderListView.dart'; + +class POSReturnOrderVC extends StatelessWidget { + late ScrollController _controller; + final viewModel = POSReturnOrderViewModel(); + bool isPortrait = true; + int limit = 10; + final ReportsCVS delegate; + BuildContext context; + + POSReturnOrderVC( + {super.key, + required this.delegate, + required this.context, + this.limit = 10}); + + @override + Widget build(BuildContext context) { + return OrientationBuilder(builder: (c, orientation) { + isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; + _controller = ScrollController()..addListener(_scrollNotification); + return SingleChildScrollView( + controller: _controller, + child: ChangeNotifierProvider( + create: (context) => viewModel, + child: Consumer( + builder: (BuildContext context, POSReturnOrderViewModel controller, + Widget? _) { + switch (controller.dataState) { + case DataState.uninitialized: + Future(() { + controller.fetch(limit: limit); + }); + return showData(controller.data); + case DataState.initialFetching: + return AppLoader(); + case DataState.moreFetching: + case DataState.refreshing: + return showData(controller.data); + case DataState.error: + return AppError(); + case DataState.searching: + case DataState.fetched: + case DataState.noMoreData: + return showData(controller.data); + } + }, + ), + ), + ); + }); + } + + Widget showData(List data) { + return Column( + children: [ + POSReturnOrderListView(data: data, isPortrait: isPortrait), + if (viewModel.dataState == DataState.moreFetching) AppLoader(), + ], + ); + } + + bool _scrollNotification() { + if (!viewModel.isLoading && _controller.position.extentAfter < 300) { + viewModel.fetch(limit: viewModel.limit); + } + return true; + } +} diff --git a/lib/application/views/settings/views/reportsViews/ReportsCategoryVC.dart b/lib/application/views/settings/views/reportsViews/ReportsCategoryVC.dart new file mode 100644 index 0000000..c5cb291 --- /dev/null +++ b/lib/application/views/settings/views/reportsViews/ReportsCategoryVC.dart @@ -0,0 +1,100 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:wosull/application/enum/DataState.dart'; +import 'package:wosull/application/interfaces/DrawerWidgetSelect.dart'; +import 'package:wosull/application/model/inventory/category/ItemCategory.dart'; +import 'package:wosull/application/utils/AppLoader.dart'; +import 'package:wosull/application/views/inventorymodule/categoryviews/viewModels/CategoryViewModel.dart'; +import 'package:wosull/application/views/settings/widgets/ReportsCategoryListView.dart'; + +class ReportsCategoryVC extends StatefulWidget { + final ReportsCVS delegate; + BuildContext context; + int limit = 10; + + ReportsCategoryVC( + {super.key, + required this.delegate, + required this.context, + this.limit = 10}); + + @override + State createState() => _ReportsCategoryVCState(); +} + +class _ReportsCategoryVCState extends State { + bool isPortrait = true; + + late ScrollController _controller; + + // late DataState _dataState; + final categoryViewModel = CategoryViewModel(); + + @override + void initState() { + super.initState(); + _controller = ScrollController()..addListener(_scrollNotification); + } + + @override + Widget build(BuildContext context) { + return OrientationBuilder(builder: (c, orientation) { + isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; + + return SingleChildScrollView( + controller: _controller, + child: ChangeNotifierProvider( + create: (context) => categoryViewModel, + child: Consumer( + builder: (BuildContext context, CategoryViewModel controller, + Widget? _) { + // _dataState = + // Provider.of(context, listen: false) + // .dataState; + switch (controller.dataState) { + case DataState.uninitialized: + Future(() { + controller.fetchCategories(limit: widget.limit); + }); + return categoryListViewWidget(controller.dataList); + case DataState.initialFetching: + return AppLoader(); + case DataState.moreFetching: + case DataState.refreshing: + return categoryListViewWidget(controller.dataList); + case DataState.error: + return const Center( + child: Text("Error"), + ); + case DataState.searching: + case DataState.fetched: + case DataState.noMoreData: + return categoryListViewWidget(controller.dataList); + } + }, + ), + ), + ); + }); + } + + Widget categoryListViewWidget(List data) { + return Column( + children: [ + ReportsCategoryListView( + isPortrait: isPortrait, + data: data, + ), + if (categoryViewModel.dataState == DataState.moreFetching) AppLoader(), + ], + ); + } + + bool _scrollNotification() { + if (!categoryViewModel.isLoading && + _controller.position.extentAfter < 300) { + categoryViewModel.fetchCategories(limit: categoryViewModel.limit); + } + return true; + } +} diff --git a/lib/application/views/settings/reportsViews/ReportsCustomerVC.dart b/lib/application/views/settings/views/reportsViews/ReportsCustomerVC.dart similarity index 98% rename from lib/application/views/settings/reportsViews/ReportsCustomerVC.dart rename to lib/application/views/settings/views/reportsViews/ReportsCustomerVC.dart index 49b0dc3..0ed9ac0 100644 --- a/lib/application/views/settings/reportsViews/ReportsCustomerVC.dart +++ b/lib/application/views/settings/views/reportsViews/ReportsCustomerVC.dart @@ -1,15 +1,15 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:wosull/application/ViewModel/InventoryViewModel.dart'; import 'package:wosull/application/interfaces/DrawerWidgetSelect.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; import 'package:wosull/application/model/converters/DataTimeFormat.dart'; import 'package:wosull/application/model/customers/GetStoreCustomer.dart'; +import 'package:wosull/application/repository/WosulRepository.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/theme/MyFonts.dart'; +import 'package:wosull/application/utils/AppLoader.dart'; import 'package:wosull/application/utils/Constants.dart'; - -import '../../../../widgets/EmptyDataWidget.dart'; +import 'package:wosull/widgets/EmptyDataWidget.dart'; class ReportsCustomerVC extends StatefulWidget { final ReportsCVS delegate; @@ -23,7 +23,7 @@ class ReportsCustomerVC extends StatefulWidget { class _ReportsCustomerVCState extends State { late ScrollController _controller; - final viewModel = InventoryViewModel(); + final viewModel = WosulRepository(); bool isPortrait = true; bool isLoading = true; bool _isLoadMoreRunning = false; @@ -50,9 +50,7 @@ class _ReportsCustomerVCState extends State { child: Column( children: [ isLoading - ? const Center( - child: CircularProgressIndicator(), - ) + ? AppLoader() : customers.isEmpty ? const EmptyDataWidget() : Column( @@ -349,7 +347,7 @@ class _ReportsCustomerVCState extends State { const EdgeInsets.all(10.0), child: Text( customers[position].status!, - style: const TextStyle( + style: TextStyle( fontStyle: FontStyle.normal, fontFamily: MyFonts.Bold, diff --git a/lib/application/views/settings/views/reportsViews/ReportsInvoiceVC.dart b/lib/application/views/settings/views/reportsViews/ReportsInvoiceVC.dart new file mode 100644 index 0000000..6b8fdc6 --- /dev/null +++ b/lib/application/views/settings/views/reportsViews/ReportsInvoiceVC.dart @@ -0,0 +1,81 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:wosull/application/enum/DataState.dart'; +import 'package:wosull/application/interfaces/DrawerWidgetSelect.dart'; +import 'package:wosull/application/model/invoice/StoreInvoice.dart'; +import 'package:wosull/application/utils/AppLoader.dart'; +import 'package:wosull/application/views/salesandordermodule/views/invoiceModule/viewModels/InvoiceViewModel.dart'; +import 'package:wosull/application/views/settings/widgets/ReportsInvoiceListView.dart'; + +class ReportsInvoiceVC extends StatelessWidget { + bool isPortrait = true; + + late ScrollController _controller; + + final viewModel = InvoiceViewModel(); + + final ReportsCVS delegate; + BuildContext context; + int limit = 10; + + ReportsInvoiceVC( + {super.key, + required this.delegate, + required this.context, + this.limit = 10}); + + @override + Widget build(BuildContext context) { + _controller = ScrollController()..addListener(_scrollNotification); + return OrientationBuilder(builder: (c, orientation) { + isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; + return SingleChildScrollView( + controller: _controller, + child: ChangeNotifierProvider( + create: (context) => viewModel, + child: Consumer( + builder: + (BuildContext context, InvoiceViewModel controller, Widget? _) { + switch (controller.dataState) { + case DataState.uninitialized: + Future(() { + controller.fetch(limit: limit); + }); + return showList(controller.filteredList); + case DataState.initialFetching: + return AppLoader(); + case DataState.moreFetching: + case DataState.refreshing: + return showList(controller.filteredList); + case DataState.error: + return const Center( + child: Text("Error"), + ); + case DataState.fetched: + case DataState.searching: + case DataState.noMoreData: + return showList(controller.filteredList); + } + }, + ), + ), + ); + }); + } + + Widget showList(List data) { + return Column( + children: [ + ReportsInvoiceListView(data: data, isPortrait: isPortrait), + if (viewModel.dataState == DataState.moreFetching) AppLoader(), + ], + ); + } + + bool _scrollNotification() { + if (!viewModel.isLoading && _controller.position.extentAfter < 300) { + viewModel.fetch(limit: viewModel.limit); + } + return true; + } +} diff --git a/lib/application/views/settings/views/reportsViews/ReportsProductsVC.dart b/lib/application/views/settings/views/reportsViews/ReportsProductsVC.dart new file mode 100644 index 0000000..724cf83 --- /dev/null +++ b/lib/application/views/settings/views/reportsViews/ReportsProductsVC.dart @@ -0,0 +1,99 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:wosull/application/enum/DataState.dart'; +import 'package:wosull/application/interfaces/DrawerWidgetSelect.dart'; +import 'package:wosull/application/model/inventory/Item.dart'; +import 'package:wosull/application/utils/AppLoader.dart'; +import 'package:wosull/application/views/inventorymodule/viewmodel/ProductViewModel.dart'; +import 'package:wosull/application/views/settings/widgets/ReportsProductListView.dart'; + +class ReportsProductsVC extends StatefulWidget { + final ReportsCVS delegate; + BuildContext context; + + int limit = 10; + + ReportsProductsVC( + {super.key, + required this.delegate, + required this.context, + this.limit = 10}); + + @override + State createState() => _ReportsProductsVCState(); +} + +class _ReportsProductsVCState extends State { + final viewModel = ProductViewModel(); + bool isPortrait = true; + + //bool _isLoading = false; + late ScrollController _controller; + + //late DataState _dataState; + + @override + void initState() { + super.initState(); + _controller = ScrollController()..addListener(_scrollNotification); + } + + @override + Widget build(BuildContext context) { + return OrientationBuilder(builder: (c, orientation) { + isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; + + return SingleChildScrollView( + controller: _controller, + child: ChangeNotifierProvider( + create: (context) => viewModel, + child: Consumer( + builder: + (BuildContext context, ProductViewModel controller, Widget? _) { + // _dataState = + // Provider.of(context, listen: false) + // .dataState; + switch (controller.dataState) { + case DataState.uninitialized: + Future(() { + controller.fetchReportsProducts(limit: widget.limit); + }); + return showList(controller.dataList); + case DataState.initialFetching: + return AppLoader(); + case DataState.moreFetching: + case DataState.refreshing: + return showList(controller.dataList); + case DataState.error: + return const Center( + child: Text("Error"), + ); + case DataState.searching: + case DataState.fetched: + case DataState.noMoreData: + return showList(controller.dataList); + } + }, + ), + ), + ); + }); + } + + Widget showList(List data) { + //_isLoading = isLoading; + return Column( + children: [ + ReportsProductListView(data: data, isPortrait: isPortrait), + if (viewModel.dataState == DataState.moreFetching) AppLoader(), + ], + ); + } + + bool _scrollNotification() { + if (!viewModel.isLoading && _controller.position.extentAfter < 300) { + viewModel.fetchReportsProducts(limit: viewModel.limit); + } + return true; + } +} diff --git a/lib/application/views/settings/views/reportsViews/ReportsQuotationVC.dart b/lib/application/views/settings/views/reportsViews/ReportsQuotationVC.dart new file mode 100644 index 0000000..977767f --- /dev/null +++ b/lib/application/views/settings/views/reportsViews/ReportsQuotationVC.dart @@ -0,0 +1,100 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:wosull/application/enum/DataState.dart'; +import 'package:wosull/application/interfaces/DrawerWidgetSelect.dart'; +import 'package:wosull/application/model/invoice/QuotationInvioceModel.dart'; +import 'package:wosull/application/utils/AppLoader.dart'; +import 'package:wosull/application/views/settings/viewModels/ReportsViewModel.dart'; +import 'package:wosull/application/views/settings/widgets/ReportsQuotationListView.dart'; + +class ReportsQuotationVC extends StatefulWidget { + final ReportsCVS delegate; + BuildContext context; + int limit = 10; + + ReportsQuotationVC( + {super.key, + required this.delegate, + required this.context, + this.limit = 10}); + + @override + State createState() => _ReportsQuotationVCState(); +} + +class _ReportsQuotationVCState extends State { + bool isPortrait = true; + + // bool _isLoading = false; + late ScrollController _controller; + + // late DataState _dataState; + final viewModel = ReportsViewModel(); + + @override + void initState() { + _controller = ScrollController()..addListener(_scrollNotification); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return OrientationBuilder(builder: (c, orientation) { + isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; + + return SingleChildScrollView( + controller: _controller, + child: ChangeNotifierProvider( + create: (context) => viewModel, + child: Consumer( + builder: + (BuildContext context, ReportsViewModel controller, Widget? _) { + // _dataState = + // Provider.of(context, listen: false) + // .dataState; + switch (controller.dataState) { + case DataState.uninitialized: + Future(() { + controller.fetchQuotations(limit: widget.limit); + }); + return showList(controller.quotationList); + case DataState.initialFetching: + return AppLoader(); + case DataState.moreFetching: + case DataState.refreshing: + return showList(controller.quotationList); + case DataState.error: + return const Center( + child: Text("Error"), + ); + case DataState.searching: + case DataState.fetched: + case DataState.noMoreData: + return showList(controller.quotationList); + } + }, + ), + ), + ); + }); + } + + Widget showList(List data) { + return Column( + children: [ + ReportsQuotationListView( + data: data, + isPortrait: isPortrait, + ), + if (viewModel.dataState == DataState.moreFetching) AppLoader(), + ], + ); + } + + bool _scrollNotification() { + if (!viewModel.isLoading && _controller.position.extentAfter < 300) { + viewModel.fetchQuotations(limit: viewModel.limit); + } + return true; + } +} diff --git a/lib/application/views/settings/reportsViews/ReportsSupplierVC.dart b/lib/application/views/settings/views/reportsViews/ReportsSupplierVC.dart similarity index 100% rename from lib/application/views/settings/reportsViews/ReportsSupplierVC.dart rename to lib/application/views/settings/views/reportsViews/ReportsSupplierVC.dart diff --git a/lib/application/views/settings/widgets/BestSupplierListView.dart b/lib/application/views/settings/widgets/BestSupplierListView.dart new file mode 100644 index 0000000..db8ce66 --- /dev/null +++ b/lib/application/views/settings/widgets/BestSupplierListView.dart @@ -0,0 +1,152 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/model/reports/TopOrderItemsModel.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/Utils.dart'; +import 'package:wosull/widgets/EmptyDataWidget.dart'; +import 'package:wosull/widgets/HeadingText.dart'; +import 'package:wosull/widgets/ListHeadingContainer.dart'; +import 'package:wosull/widgets/ValueText.dart'; + +class BestSupplierListView extends StatelessWidget { + List data; + bool isPortrait; + + BestSupplierListView( + {super.key, required this.isPortrait, required this.data}); + + @override + Widget build(BuildContext context) { + return data.isEmpty + ? const EmptyDataWidget() // for empty + : Column( + children: [ + isPortrait + ? Container() + : ListHeadingContainer( + child: Row( + children: [ + Expanded( + child: HeadingText( + lang(context).rank, + )), + Expanded( + child: HeadingText( + lang(context).id_txt, + )), + Expanded( + child: HeadingText( + lang(context).name, + )), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + lang(context).no_of_order, + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + lang(context).overall_quantity, + ))), + ], + ), + ), + ListView.builder( + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (c, position) { + final topOrders = data[position]; + if (isPortrait) { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + elevation: 2, + color: MyColors.white, + child: Container( + padding: const EdgeInsets.fromLTRB(8, 8, 8, 8), + child: Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + HeadingText( + lang(context).rank, + ), + AppSpaces.verticalMedium, + HeadingText( + lang(context).id_txt, + ), + AppSpaces.verticalMedium, + HeadingText( + lang(context).item_name, + ), + AppSpaces.verticalMedium, + HeadingText(lang(context).no_of_order), + AppSpaces.verticalMedium, + HeadingText(lang(context).overall_quantity), + ], + )), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + ValueText('${position + 1}'), + AppSpaces.verticalMedium, + ValueText(topOrders.uniqueId.toString()), + AppSpaces.verticalMedium, + ValueText(topOrders.itemName), + AppSpaces.verticalMedium, + ValueText( + topOrders.totalOrderQuantity.toString()), + AppSpaces.verticalMedium, + ValueText(topOrders.count.toString()), + ], + )), + ], + ), + ), + ); + } else { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: ListHeadingContainer( + child: Row( + children: [ + Expanded(child: ValueText('${position + 1}')), + Expanded( + child: + ValueText(topOrders.uniqueId.toString())), + Expanded( + child: ValueText( + topOrders.itemName ?? "", + )), + Expanded( + child: ValueText( + topOrders.totalOrderQuantity.toString())), + Expanded( + child: ValueText( + topOrders.count.toString() ?? "0")), + ], + ), + ), + ); + } + }, + itemCount: data.length, + ) + ], + ); + } +} diff --git a/lib/application/views/settings/widgets/POSCompleteListView.dart b/lib/application/views/settings/widgets/POSCompleteListView.dart new file mode 100644 index 0000000..bab8b3b --- /dev/null +++ b/lib/application/views/settings/widgets/POSCompleteListView.dart @@ -0,0 +1,207 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/application/model/reports/CashierOrder.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/helpers/Utils.dart'; +import 'package:wosull/widgets/EmptyDataWidget.dart'; +import 'package:wosull/widgets/HeadingText.dart'; +import 'package:wosull/widgets/ListHeadingContainer.dart'; +import 'package:wosull/widgets/ValueText.dart'; + +class POSCompleteListView extends StatelessWidget { + List data; + bool isPortrait; + + POSCompleteListView( + {super.key, required this.isPortrait, required this.data}); + + @override + Widget build(BuildContext context) { + return data.isEmpty + ? const EmptyDataWidget() + : Column( + children: [ + isPortrait + ? Container() + : ListHeadingContainer( + child: Row( + children: [ + Expanded( + child: HeadingText(lang(context).order_number)), + Expanded( + child: HeadingText(lang(context).store_name)), + Expanded(child: HeadingText('Delivery Type')), + Expanded( + child: HeadingText(lang(context).payment_mode)), + Expanded(child: HeadingText(lang(context).table)), + Expanded(child: HeadingText(lang(context).total)), + Expanded(child: HeadingText(lang(context).discount)), + Expanded(child: HeadingText(lang(context).status)), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText(lang(context).created_on), + )), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: + HeadingText(lang(context).updated_on))), + ], + ), + ), + ListView.builder( + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (c, position) { + final completePOS = data[position]; + if (isPortrait) { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + elevation: 2, + color: MyColors.white, + child: Container( + padding: const EdgeInsets.all(12), + child: Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + HeadingText(lang(context).order_number), + AppSpaces.verticalMedium, + HeadingText(lang(context).store_name), + AppSpaces.verticalMedium, + HeadingText('Delivery Type'), + AppSpaces.verticalMedium, + HeadingText(lang(context).payment_mode), + AppSpaces.verticalMedium, + HeadingText(lang(context).table), + AppSpaces.verticalMedium, + HeadingText(lang(context).total), + AppSpaces.verticalMedium, + HeadingText(lang(context).discount), + AppSpaces.verticalMedium, + HeadingText(lang(context).status), + AppSpaces.verticalMedium, + HeadingText(lang(context).created_on), + AppSpaces.verticalMedium, + HeadingText(lang(context).updated_on), + ], + )), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + ValueText( + completePOS.uniqueId!.toString(), + ), + AppSpaces.verticalMedium, + ValueText(completePOS.storeId!.name ?? ''), + AppSpaces.verticalMedium, + Text( + completePOS.orderType ?? '', + style: getStyle(completePOS.orderType! + .replaceAll(' ', '') + .toLowerCase()), + ), + AppSpaces.verticalMedium, + ValueText(completePOS.paymentMode ?? ''), + AppSpaces.verticalMedium, + ValueText(completePOS.table ?? ''), + AppSpaces.verticalMedium, + ValueText(completePOS.totalAmount + ?.toStringAsFixed(2) ?? + ''), + AppSpaces.verticalMedium, + ValueText(completePOS.totalDiscount + ?.toStringAsFixed(2) ?? + ''), + AppSpaces.verticalMedium, + ValueText( + completePOS.status!.toCapitalized() ?? ''), + AppSpaces.verticalMedium, + ValueText(DataTimeFormat.getFormatDate( + completePOS.createdAt ?? '')), + AppSpaces.verticalMedium, + ValueText(DataTimeFormat.getFormatDate( + completePOS.updatedAt ?? '')), + ], + )), + ], + ), + ), + ); + } else { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: ListHeadingContainer( + child: Row( + children: [ + Expanded( + child: ValueText( + completePOS.uniqueId!.toString())), + Expanded( + child: ValueText(completePOS.storeId!.name)), + Expanded( + child: Text(completePOS.orderType!, + style: getStyle( + completePOS.orderType! + .replaceAll(' ', '') + .toLowerCase(), + ))), + Expanded( + child: ValueText(completePOS.paymentMode!)), + Expanded( + child: ValueText(completePOS.table ?? 'N/A')), + Expanded( + child: ValueText(completePOS.totalAmount + ?.toStringAsFixed(2) ?? + '')), + Expanded( + child: ValueText(completePOS.totalDiscount + ?.toStringAsFixed(2) ?? + '')), + Expanded( + child: ValueText( + completePOS.status!.toCapitalized())), + Expanded( + child: ValueText(DataTimeFormat.getFormatDate( + completePOS.createdAt!))), + Expanded( + child: ValueText(DataTimeFormat.getFormatDate( + completePOS.updatedAt!))), + ], + ), + ), + ); + } + }, + itemCount: data.length, + ) + ], + ); + } + + getStyle(String status) { + if (status == Constants.dineIn) { + return ThemeText.textStyleValueGreen; + } else if (status == Constants.takeAway) { + return ThemeText.textStyleValueRed; + } else { + return ThemeText.textStyleValueOrange; + } + } +} diff --git a/lib/application/views/settings/widgets/POSReturnOrderListView.dart b/lib/application/views/settings/widgets/POSReturnOrderListView.dart new file mode 100644 index 0000000..aae952a --- /dev/null +++ b/lib/application/views/settings/widgets/POSReturnOrderListView.dart @@ -0,0 +1,144 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/model/cart/GetHoldOrderModel.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/helpers/Utils.dart'; +import 'package:wosull/widgets/EmptyDataWidget.dart'; +import 'package:wosull/widgets/HeadingText.dart'; +import 'package:wosull/widgets/ListHeadingContainer.dart'; +import 'package:wosull/widgets/ValueText.dart'; + +class POSReturnOrderListView extends StatelessWidget { + List data; + bool isPortrait; + + POSReturnOrderListView( + {super.key, required this.data, required this.isPortrait}); + + @override + Widget build(BuildContext context) { + return data.isEmpty + ? const EmptyDataWidget() + : Column( + children: [ + isPortrait + ? Container() + : ListHeadingContainer( + child: Row( + children: [ + Expanded( + child: HeadingText(lang(context).order_number)), + Expanded( + child: HeadingText(lang(context).store_name)), + Expanded(child: HeadingText(lang(context).status)), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText(lang(context).created_on), + )), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: + HeadingText(lang(context).updated_on))), + ], + ), + ), + ListView.builder( + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (c, position) { + final returnOrder = data[position]; + if (isPortrait) { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + elevation: 2, + color: MyColors.white, + child: Container( + padding: const EdgeInsets.all(12), + child: Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + HeadingText(lang(context).order_number), + AppSpaces.verticalMedium, + HeadingText(lang(context).store_name), + AppSpaces.verticalMedium, + HeadingText(lang(context).status), + AppSpaces.verticalMedium, + HeadingText(lang(context).created_on), + AppSpaces.verticalMedium, + HeadingText(lang(context).updated_on), + ], + )), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + ValueText(returnOrder.uniqueId!.toString()), + AppSpaces.verticalMedium, + ValueText(returnOrder.storeId!.name ?? ''), + AppSpaces.verticalMedium, + Text( + returnOrder.status?.toCapitalized() ?? '', + style: ThemeText.textStyleValueRed, + ), + AppSpaces.verticalMedium, + ValueText(DataTimeFormat.getFormatDate( + returnOrder.createdAt ?? '')), + AppSpaces.verticalMedium, + ValueText(DataTimeFormat.getFormatDate( + returnOrder.updatedAt ?? '')), + ], + )), + ], + ), + ), + ); + } else { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: ListHeadingContainer( + child: Row( + children: [ + Expanded( + child: ValueText( + returnOrder.uniqueId!.toString())), + Expanded( + child: ValueText(returnOrder.storeId!.name)), + Expanded( + child: Text( + returnOrder.status?.toCapitalized() ?? '', + style: ThemeText.textStyleValueRed, + )), + Expanded( + child: ValueText(DataTimeFormat.getFormatDate( + returnOrder.createdAt!))), + Expanded( + child: ValueText(DataTimeFormat.getFormatDate( + returnOrder.updatedAt!))), + ], + ), + ), + ); + } + }, + itemCount: data.length, + ) + ], + ); + } +} diff --git a/lib/application/views/settings/widgets/ReportsCategoryListView.dart b/lib/application/views/settings/widgets/ReportsCategoryListView.dart new file mode 100644 index 0000000..1208da0 --- /dev/null +++ b/lib/application/views/settings/widgets/ReportsCategoryListView.dart @@ -0,0 +1,171 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/model/inventory/category/ItemCategory.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/theme/MyFonts.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/Utils.dart'; +import 'package:wosull/widgets/EmptyDataWidget.dart'; +import 'package:wosull/widgets/HeadingText.dart'; +import 'package:wosull/widgets/ListHeadingContainer.dart'; +import 'package:wosull/widgets/ValueText.dart'; + +class ReportsCategoryListView extends StatelessWidget { + List data; + bool isPortrait; + + ReportsCategoryListView( + {super.key, required this.isPortrait, required this.data}); + + @override + Widget build(BuildContext context) { + return data.isEmpty + ? const EmptyDataWidget() + : Column( + children: [ + isPortrait + ? Container() + : ListHeadingContainer( + child: Row( + children: [ + Expanded( + child: HeadingText( + lang(context).name, + )), + Expanded( + child: HeadingText( + lang(context).status, + )), + Expanded( + child: HeadingText( + lang(context).description, + )), + Expanded( + child: HeadingText( + lang(context).status, + )), + ], + ), + ), + ListView.builder( + physics: const NeverScrollableScrollPhysics(), + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, + shrinkWrap: true, + itemBuilder: (c, position) { + if (isPortrait) { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + elevation: 2, + color: MyColors.white, + child: Container( + padding: const EdgeInsets.all(8), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + child: Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + HeadingText( + lang(context).category_name, + ), + AppSpaces.verticalMedium, + HeadingText(lang(context).arabic_name), + AppSpaces.verticalMedium, + HeadingText(lang(context).description), + AppSpaces.verticalMedium, + HeadingText(lang(context).status), + ], + )), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + ValueText( + data[position].name, + ), + AppSpaces.verticalMedium, + ValueText( + data[position].arabicName, + ), + AppSpaces.verticalMedium, + ValueText( + data[position].description, + ), + AppSpaces.verticalMedium, + ValueText( + data[position].isActive(), + ), + ], + )), + ], + )), + ], + ), + ), + ); + } else { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: Container( + padding: const EdgeInsets.only(left: 8, right: 8), + height: 56, + color: MyColors.containerBackColor, + child: Row( + children: [ + Expanded( + child: ValueText( + data[position].name, + )), + Expanded( + child: ValueText( + data[position].arabicName, + )), + Expanded( + child: ValueText( + data[position].description, + )), + Expanded( + child: Container( + height: 38, + decoration: const BoxDecoration( + color: MyColors.greenColor10, + borderRadius: BorderRadius.all( + Radius.circular(10.0))), + child: Padding( + padding: const EdgeInsets.all(10.0), + child: Center( + child: Text( + data[position].isActive(), + style: TextStyle( + fontStyle: FontStyle.normal, + fontFamily: MyFonts.Bold, + fontSize: MyFonts.normal, + fontWeight: FontWeight.w700, + color: MyColors.greenColor), + ), + ))), + ), + ], + ), + ), + ); + } + }, + itemCount: data.length, + ) + ], + ); + } +} diff --git a/lib/application/views/settings/widgets/ReportsInvoiceListView.dart b/lib/application/views/settings/widgets/ReportsInvoiceListView.dart new file mode 100644 index 0000000..aa14c7a --- /dev/null +++ b/lib/application/views/settings/widgets/ReportsInvoiceListView.dart @@ -0,0 +1,336 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/application/model/invoice/StoreInvoice.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/theme/MyFonts.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/Utils.dart'; +import 'package:wosull/widgets/HeadingText.dart'; +import 'package:wosull/widgets/ListHeadingContainer.dart'; +import 'package:wosull/widgets/ValueText.dart'; + +class ReportsInvoiceListView extends StatelessWidget { + List data; + bool isPortrait; + + ReportsInvoiceListView( + {super.key, required this.data, required this.isPortrait}); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + isPortrait + ? Container() + : ListHeadingContainer( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + child: HeadingText( + "Supplier name", + )), + Expanded( + child: HeadingText( + lang(context).invoice_number, + )), + Expanded( + child: HeadingText( + lang(context).invoice_date, + )), + Expanded( + child: HeadingText( + lang(context).invoice_due_date, + )), + Expanded( + child: HeadingText( + lang(context).amount, + )), + Expanded( + child: HeadingText( + lang(context).currency, + )), + Expanded( + child: HeadingText( + lang(context).vat_number, + )), + Expanded( + child: HeadingText( + lang(context).default_status, + )), + ], + ), + ), + ListView.builder( + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (c, position) { + final storeInvoice = data[position]; + if (isPortrait) { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: Container( + padding: const EdgeInsets.all(8), + color: MyColors.containerBackColor, + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + flex: 2, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Row( + children: [ + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + 'Supplier name', + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: ValueText( + storeInvoice.invoiceFor!.first == + 'Company' + ? storeInvoice.supplier?.name ?? "" + : storeInvoice.customer?.name ?? '', + ), + )) + ], + ), + AppSpaces.verticalMedium, + Row( + children: [ + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + lang(context).invoice_number, + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: ValueText( + storeInvoice.invoiceNumber!.toString(), + ), + )) + ], + ), + AppSpaces.verticalMedium, + Row( + children: [ + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + lang(context).invoice_date, + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: ValueText( + DataTimeFormat.getFormatDate( + storeInvoice.invoiceDate!), + ), + )) + ], + ), + AppSpaces.verticalMedium, + Row( + children: [ + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + lang(context).invoice_due_date, + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: ValueText( + DataTimeFormat.getFormatDate( + storeInvoice.invoiceDueDate!), + ), + )) + ], + ), + AppSpaces.verticalMedium, + Row( + children: [ + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + lang(context).amount, + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: ValueText( + storeInvoice.totalAmount! + .toStringAsFixed(2), + ), + )) + ], + ), + AppSpaces.verticalMedium, + Row( + children: [ + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + lang(context).currency, + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: ValueText( + "", + ), + )) + ], + ), + AppSpaces.verticalMedium, + Row( + children: [ + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + lang(context).vat_number, + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: ValueText( + storeInvoice.vatNumber!, + ), + )) + ], + ), + AppSpaces.verticalMedium, + Row( + children: [ + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + lang(context).status, + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: Text( + storeInvoice.status!.toString(), + style: TextStyle( + fontFamily: MyFonts.Bold, + fontWeight: FontWeight.w500, + fontSize: MyFonts.normal, + color: MyColors.greenColor), + ), + )) + ], + ), + ], + )), + ], + ), + ), + ); + } else { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: Container( + padding: const EdgeInsets.only(left: 8, right: 8), + height: 56, + color: MyColors.containerBackColor, + child: Row( + children: [ + Expanded( + child: ValueText( + storeInvoice.supplier?.name ?? "", + )), + Expanded( + child: ValueText( + storeInvoice.invoiceNumber.toString(), + )), + Expanded( + child: ValueText( + DataTimeFormat.getFormatDate(storeInvoice.invoiceDate!), + )), + Expanded( + child: ValueText( + DataTimeFormat.getFormatDate( + storeInvoice.invoiceDueDate!), + ), + ), + Expanded( + child: ValueText( + (storeInvoice.totalAmount ?? 0.0).toStringAsFixed(2), + )), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: ValueText( + storeInvoice.currencyId?.name ?? "", + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: ValueText( + storeInvoice.vatNumber!, + ), + )), + Expanded( + child: Container( + height: 38, + decoration: const BoxDecoration( + color: MyColors.greenColor10, + borderRadius: + BorderRadius.all(Radius.circular(10.0))), + child: Padding( + padding: const EdgeInsets.all(10.0), + child: Center( + child: Text( + storeInvoice.status!, + style: TextStyle( + fontStyle: FontStyle.normal, + fontFamily: MyFonts.Bold, + fontSize: MyFonts.normal, + fontWeight: FontWeight.w700, + color: MyColors.greenColor), + ), + ))), + ), + ], + ), + ), + ); + } + }, + itemCount: data.length, + ) + ], + ); + } +} diff --git a/lib/application/views/settings/widgets/ReportsProductListView.dart b/lib/application/views/settings/widgets/ReportsProductListView.dart new file mode 100644 index 0000000..173bae9 --- /dev/null +++ b/lib/application/views/settings/widgets/ReportsProductListView.dart @@ -0,0 +1,172 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/model/inventory/Item.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/Utils.dart'; +import 'package:wosull/widgets/EmptyDataWidget.dart'; +import 'package:wosull/widgets/HeadingText.dart'; +import 'package:wosull/widgets/ListHeadingContainer.dart'; +import 'package:wosull/widgets/ValueText.dart'; + +class ReportsProductListView extends StatelessWidget { + List data; + bool isPortrait; + + ReportsProductListView( + {super.key, required this.data, required this.isPortrait}); + + @override + Widget build(BuildContext context) { + return data.isEmpty + ? const EmptyDataWidget() + : Column( + children: [ + isPortrait + ? Container() + : ListHeadingContainer( + child: Row( + children: [ + Expanded( + child: HeadingText( + lang(context).item_name, + )), + Expanded(child: HeadingText(lang(context).category)), + Expanded( + child: HeadingText( + lang(context).price, + )), + Expanded( + child: HeadingText( + lang(context).description, + )), + Expanded( + child: HeadingText( + 'Quantity Available', + )), + ], + ), + ), + ListView.builder( + physics: const NeverScrollableScrollPhysics(), + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, + shrinkWrap: true, + itemBuilder: (c, position) { + if (isPortrait) { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + elevation: 2, + color: MyColors.white, + child: Container( + padding: const EdgeInsets.all(8), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + child: Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + HeadingText( + lang(context).item_name, + ), + AppSpaces.verticalMedium, + HeadingText( + lang(context).category, + ), + AppSpaces.verticalMedium, + HeadingText( + lang(context).price, + ), + AppSpaces.verticalMedium, + HeadingText( + lang(context).description, + ), + AppSpaces.verticalMedium, + HeadingText( + 'Quantity Available', + ), + ], + )), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + ValueText( + data[position].name ?? '', + ), + AppSpaces.verticalMedium, + ValueText(data[position] + .productId + ?.categoryId + ?.name ?? + ''), + AppSpaces.verticalMedium, + ValueText(data[position] + .price + ?.toStringAsFixed(2) ?? + ''), + AppSpaces.verticalMedium, + ValueText(data[position].details ?? ''), + AppSpaces.verticalMedium, + ValueText(data[position] + .totalQuantity + ?.toString() ?? + ''), + ], + )), + ], + )), + ], + ), + ), + ); + } else { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: Container( + padding: const EdgeInsets.only(left: 8, right: 8), + height: 56, + color: MyColors.containerBackColor, + child: Row( + children: [ + Expanded( + child: ValueText(data[position].name ?? '')), + Expanded( + child: ValueText( + data[position].productId?.categoryId?.name ?? '', + )), + Expanded( + child: ValueText( + data[position].price?.toStringAsFixed(2) ?? '0.0', + )), + Expanded( + child: ValueText( + data[position].details ?? '0.0', + )), + Expanded( + child: ValueText( + data[position].totalQuantity?.toString() ?? '0.0', + )), + ], + ), + ), + ); + } + }, + itemCount: data.length, + ) + ], + ); + } +} diff --git a/lib/application/views/settings/widgets/ReportsQuotationListView.dart b/lib/application/views/settings/widgets/ReportsQuotationListView.dart new file mode 100644 index 0000000..7620fff --- /dev/null +++ b/lib/application/views/settings/widgets/ReportsQuotationListView.dart @@ -0,0 +1,330 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/application/model/invoice/QuotationInvioceModel.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/theme/MyFonts.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/Utils.dart'; +import 'package:wosull/widgets/EmptyDataWidget.dart'; +import 'package:wosull/widgets/HeadingText.dart'; +import 'package:wosull/widgets/ListHeadingContainer.dart'; +import 'package:wosull/widgets/ValueText.dart'; + +class ReportsQuotationListView extends StatelessWidget { + List data; + bool isPortrait; + + ReportsQuotationListView( + {super.key, required this.data, required this.isPortrait}); + + @override + Widget build(BuildContext context) { + return data.isEmpty + ? const EmptyDataWidget() + : Column( + children: [ + isPortrait + ? Container() + : ListHeadingContainer( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + child: HeadingText( + lang(context).number, + )), + Expanded( + child: HeadingText( + lang(context).reference_no, + )), + Expanded( + child: HeadingText( + lang(context).bill_to, + )), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + lang(context).quotation_date, + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + lang(context).quotations_due_date, + ), + )), + Expanded( + child: Align( + alignment: Alignment.center, + child: HeadingText( + lang(context).amount, + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + lang(context).status, + ), + )), + ], + ), + ), + ListView.builder( + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (c, position) { + if (isPortrait) { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: Container( + padding: const EdgeInsets.all(8), + color: MyColors.containerBackColor, + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + flex: 2, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Row( + children: [ + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + lang(context).number, + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: ValueText(data[position] + .quotationNumber! + .toString()), + )) + ], + ), + AppSpaces.verticalMedium, + Row( + children: [ + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + lang(context).reference_no, + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: ValueText( + data[position] + .quotationReference! + .toString(), + ), + )) + ], + ), + AppSpaces.verticalMedium, + Row( + children: [ + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + lang(context).bill_to, + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: ValueText( + data[position] + .supplier! + .name! + .toString(), + ), + )) + ], + ), + AppSpaces.verticalMedium, + Row( + children: [ + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + lang(context).quotation_date, + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: ValueText( + DataTimeFormat.getFormatDate( + data[position].quotationDate!), + ), + )) + ], + ), + AppSpaces.verticalMedium, + Row( + children: [ + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + lang(context).quotations_due_date, + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: ValueText( + DataTimeFormat.getFormatDate( + data[position] + .quotationDueDate!), + ), + )) + ], + ), + AppSpaces.verticalMedium, + Row( + children: [ + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + lang(context).amount, + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: ValueText( + data[position] + .totalAmount! + .toStringAsFixed(2), + ), + )) + ], + ), + AppSpaces.verticalMedium, + Row( + children: [ + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + lang(context).status, + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: Text( + data[position].status!.toString(), + style: TextStyle( + fontFamily: MyFonts.Bold, + fontWeight: FontWeight.w500, + fontSize: MyFonts.normal, + color: MyColors.greenColor), + ), + )) + ], + ), + ], + )), + ], + ), + ), + ); + } else { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: ListHeadingContainer( + child: Row( + children: [ + Expanded( + child: ValueText( + data[position].quotationNumber.toString())), + Expanded( + child: ValueText( + data[position].quotationReference.toString(), + )), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: ValueText( + data[position].supplier?.name ?? "", + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: ValueText( + DataTimeFormat.getFormatDate( + data[position].quotationDate!), + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: ValueText( + DataTimeFormat.getFormatDate( + data[position].quotationDueDate!), + ), + ), + ), + Expanded( + child: Align( + alignment: Alignment.center, + child: ValueText( + data[position].totalAmount!.toStringAsFixed(2), + ), + )), + Expanded( + child: Container( + height: 38, + decoration: const BoxDecoration( + color: MyColors.greenColor10, + borderRadius: BorderRadius.all( + Radius.circular(10.0))), + child: Padding( + padding: const EdgeInsets.all(10.0), + child: Center( + child: Text( + data[position].status!, + style: TextStyle( + fontStyle: FontStyle.normal, + fontFamily: MyFonts.Bold, + fontSize: MyFonts.normal, + fontWeight: FontWeight.w700, + color: MyColors.greenColor), + ), + ))), + ), + ], + ), + ), + ); + } + }, + itemCount: data.length, + ), + ], + ); + } +} diff --git a/lib/application/views/transactions/CashierTransactionsVC.dart b/lib/application/views/transactions/CashierTransactionsVC.dart deleted file mode 100644 index 3daf49d..0000000 --- a/lib/application/views/transactions/CashierTransactionsVC.dart +++ /dev/null @@ -1,491 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:wosull/application/ViewModel/InventoryViewModel.dart'; -import 'package:wosull/application/interfaces/DrawerWidgetSelect.dart'; -import 'package:wosull/application/localdb/SharedPrefs.dart'; -import 'package:wosull/application/model/converters/DataTimeFormat.dart'; -import 'package:wosull/application/model/reports/CashierOrderHistory.dart'; -import 'package:wosull/application/network/APIManager.dart'; -import 'package:wosull/application/theme/MyColors.dart'; -import 'package:wosull/application/utils/AppLoader.dart'; -import 'package:wosull/application/utils/Constants.dart'; -import 'package:wosull/application/views/transactions/ViewPOSReturnVC.dart'; -import 'package:wosull/base/BaseStatefulState.dart'; -import 'package:wosull/helpers/ThemeText.dart'; -import 'package:wosull/helpers/Utils.dart'; -import 'package:wosull/widgets/ValueText.dart'; - -class CashierTransactionsVC extends StatefulWidget { - TransactionCVS delegate; - BuildContext context; - bool? isOrder = false; - String? filter; - - CashierTransactionsVC( - {super.key, - required this.delegate, - required this.context, - this.filter, - this.isOrder}); - - @override - State createState() => _CashierTransactionsVCState(); -} - -class _CashierTransactionsVCState - extends BaseStatefulState { - late ScrollController _controller; - final viewModel = InventoryViewModel(); - bool isPortrait = false; - bool isLoading = true; - bool _isLoadMoreRunning = false; - List posOrders = []; - - int _pageForPOS = 1; - bool __hasNextPageForPOS = true; - - @override - void initState() { - super.initState(); - _controller = ScrollController()..addListener(loadMore); - } - - @override - Widget build(BuildContext context) { - return FutureBuilder( - future: _firstLoad(), - builder: (c, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return AppLoader(); - } - return SingleChildScrollView( - controller: _controller, - child: Column( - children: [ - isPortrait - ? Container() - : Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 50, - color: MyColors.containerBackColor, - child: Row( - children: [ - Expanded( - child: Text( - AppLocalizations.of(widget.context)!.order_number, - style: MyColors.textStyleHeading(), - )), - Expanded( - child: Text( - AppLocalizations.of(widget.context)!.store_name, - style: MyColors.textStyleHeading(), - )), - Expanded( - child: Text( - AppLocalizations.of(widget.context)!.status, - style: MyColors.textStyleHeading(), - )), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(widget.context)! - .created_on, - style: MyColors.textStyleHeading(), - ))), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(widget.context)! - .updated_on, - style: MyColors.textStyleHeading(), - ))), - Container( - width: 56, - child: Text( - AppLocalizations.of(widget.context)!.action, - style: MyColors.textStyleHeading(), - ), - ), - ], - ), - ), - ListView.builder( - padding: EdgeInsets.zero, - scrollDirection: Axis.vertical, - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - itemBuilder: (c, position) { - if (isPortrait) { - return Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - color: MyColors.white, - child: Container( - padding: const EdgeInsets.fromLTRB(8, 0, 0, 8), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Expanded( - child: Container( - padding: const EdgeInsets.only(top: 16), - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.start, - children: [ - const SizedBox( - height: 8, - ), - Text( - AppLocalizations.of(widget.context)! - .order_number, - style: MyColors.textStyleHeading(), - ), - const SizedBox( - height: 8, - ), - Text( - AppLocalizations.of(widget.context)! - .store_name, - style: MyColors.textStyleHeading(), - ), - const SizedBox( - height: 8, - ), - Text( - AppLocalizations.of(widget.context)! - .status, - style: MyColors.textStyleHeading(), - ), - const SizedBox( - height: 8, - ), - Text( - AppLocalizations.of(widget.context)! - .created_on, - style: MyColors.textStyleHeading(), - ), - const SizedBox( - height: 8, - ), - Text( - AppLocalizations.of(widget.context)! - .updated_on, - style: MyColors.textStyleHeading(), - ), - ], - )), - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.end, - mainAxisAlignment: - MainAxisAlignment.start, - children: [ - Text( - posOrders[position] - .uniqueId! - .toString(), - style: MyColors.textStyleValue(), - ), - const SizedBox( - height: 12, - ), - Text( - posOrders[position].storeId!.name ?? - '', - style: MyColors.textStyleValue(), - ), - const SizedBox( - height: 12, - ), - Text( - posOrders[position].status ?? '', - style: MyColors.textStyleValue(), - ), - const SizedBox( - height: 12, - ), - Text( - DataTimeFormat.getFormatDate( - posOrders[position].createdAt ?? - ''), - style: MyColors.textStyleValue()), - const SizedBox( - height: 12, - ), - Text( - DataTimeFormat.getFormatDate( - posOrders[position].updatedAt ?? - ''), - style: MyColors.textStyleValue()), - ], - )), - ], - ), - )), - PopupMenuButton( - icon: const Icon(Icons.more_vert), - itemBuilder: (c) { - return getPopUpMenuButton(); - }, - onSelected: (String value) => - actionPopUpItemSelected( - value, posOrders[position]), - ) - ], - ), - ), - ); - } else { - return Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - child: Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 56, - color: MyColors.containerBackColor, - child: Row( - children: [ - Expanded( - child: Text( - posOrders[position].uniqueId!.toString(), - style: MyColors.textStyleValue(), - )), - Expanded( - child: Text( - posOrders[position].storeId!.name, - style: MyColors.textStyleValue(), - )), - Expanded( - child: Text( - posOrders[position].status!.toCapitalized(), - style: posOrders[position].status == 'completed' - ? ThemeText.textStyleValueGreen - : ThemeText.textStyleValueRed, - )), - Expanded( - child: Text( - DataTimeFormat.getFormatDate( - posOrders[position].createdAt!), - style: MyColors.textStyleValue(), - )), - Expanded( - child: Text( - DataTimeFormat.getFormatDate( - posOrders[position].updatedAt!), - style: MyColors.textStyleValue(), - )), - Padding( - padding: const EdgeInsets.all(4), - child: Align( - alignment: Alignment.centerRight, - child: Container( - width: 42, - height: 42, - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular(4)), - color: MyColors.backFillColor), - child: PopupMenuButton( - icon: const Icon(Icons.more_vert), - itemBuilder: (c) { - return getPopUpMenuButton(); - }, - onSelected: (String value) => - actionPopUpItemSelected( - value, posOrders[position]), - ), - ), - ), - ) - ], - ), - ), - ); - } - }, - itemCount: posOrders.length, - ), - _isLoadMoreRunning == true - ? const Padding( - padding: EdgeInsets.only(top: 10, bottom: 10), - child: Center( - child: CircularProgressIndicator(), - ), - ) - : Container(), - ], - ), - ); - }); - } - - void actionPopUpItemSelected(String value, CashierOrder order) { - if (value == 'delete') { - deleteOrder(order.id); - } else if (value == 'edit') { - widget.delegate.editCashier(order); - // Utils.showMessage('Already done but need to test'); - } else if (value == 'return') { - widget.delegate.returnPOS(order, true); - } else if (value == 'damage') { - widget.delegate.returnPOS(order, false); - } else if (value == 'view') { - showDialog( - barrierColor: Colors.black26, - context: context, - builder: (context) { - return ViewPOSReturnVC( - orderDetails: order.cart!.orderDetails!, - ); - }, - ); - } - } - - Future _firstLoad() async { - _pageForPOS = 1; - - Map data = { - 'store_id': sharedPrefs.storeId, - 'page': _pageForPOS, - 'order_status': widget.filter ?? 'all' - }; - - await viewModel - .getData(Constants.GET_CASHIER_ORDER_HISTORY, data) - .then((value) { - final response = CashierOrderHistory.fromJson(value); - posOrders.clear(); - if (response.success!) { - posOrders.addAll(response.topOrders!); - widget.delegate.updateCashier(posOrders); - } - - if (response.topOrders!.length < 10) { - __hasNextPageForPOS = false; - } - // setState(() { - // isLoading = false; - // }); - }).onError((error, stackTrace) { - print(stackTrace.toString()); - }); - - return true; - } - - void loadMore() async { - if (__hasNextPageForPOS == true && - isLoading == false && - _isLoadMoreRunning == false && - _controller.position.extentAfter < 300) { - setState(() { - _isLoadMoreRunning = true; // Display a progress indicator at the bottom - }); - - _pageForPOS += 1; // Increase _page by 1 - - Map data = { - 'store_id': sharedPrefs.storeId, - 'page': _pageForPOS, - }; - - await viewModel - .getData(Constants.GET_CASHIER_ORDER_HISTORY, data) - .then((response) { - final value = CashierOrderHistory.fromJson(response); - if (value.success!) { - if (value.topOrders!.isNotEmpty) { - if (value.topOrders!.length < 10) { - __hasNextPageForPOS = false; - } - setState(() { - posOrders.addAll(value.topOrders!); - // widget.delegate.posCompleteCVS(posOrders); - _isLoadMoreRunning = false; - }); - } else { - setState(() { - __hasNextPageForPOS = false; - }); - } - } - }).onError((error, stackTrace) { - setState(() { - __hasNextPageForPOS = false; - }); - }).timeout(const Duration(seconds: 60)); - } else {} - } - - List> getPopUpMenuButton() { - if (widget.isOrder!) { - return [ - PopupMenuItem( - value: 'edit', - child: ValueText('Edit'), - ), - PopupMenuItem( - value: 'return', - child: ValueText('Return'), - ), - PopupMenuItem( - value: 'damage', - child: ValueText('Damage'), - ), - PopupMenuItem( - value: 'delete', - child: ValueText('Delete'), - ), - PopupMenuItem( - value: 'view', - child: ValueText('View'), - ), - ]; - } else { - return [ - PopupMenuItem( - value: 'return', - child: ValueText('Return'), - ), - PopupMenuItem( - value: 'damage', - child: ValueText('Damage'), - ), - PopupMenuItem( - value: 'view', - child: ValueText('View'), - ), - ]; - } - } - - Future deleteOrder(String? id) async { - Map data = { - 'orderId': id!, - }; - - await APIManager() - .getResponsePatch(Constants.DELETE_ORDER, data) - .then((value) { - if (value.success) { - setState(() { - posOrders.removeWhere((element) => element.id == id); - }); - } - }).onError((error, stackTrace) {}); - } -} diff --git a/lib/application/views/transactions/EditOrderVC.dart b/lib/application/views/transactions/EditOrderVC.dart deleted file mode 100644 index ebe11ce..0000000 --- a/lib/application/views/transactions/EditOrderVC.dart +++ /dev/null @@ -1,2767 +0,0 @@ -import 'package:async/async.dart'; -import 'package:dropdown_search/dropdown_search.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:objectbox/objectbox.dart'; -import 'package:wosull/application/ViewModel/InventoryViewModel.dart'; -import 'package:wosull/application/localdb/SharedPrefs.dart'; -import 'package:wosull/application/model/SimpleResponsModel.dart'; -import 'package:wosull/application/model/StockTransfer/ProductItemCategoryModel.dart'; -import 'package:wosull/application/model/converters/DataTimeFormat.dart'; -import 'package:wosull/application/model/createOrder/CashierCart.dart'; -import 'package:wosull/application/model/reports/CashierOrderHistory.dart'; -import 'package:wosull/application/model/store/GetSpecificStores.dart'; -import 'package:wosull/application/model/store/StoreItemsResponse.dart'; -import 'package:wosull/application/model/store/StoreServiceModel.dart'; -import 'package:wosull/application/model/store/StoreServiceResponse.dart'; -import 'package:wosull/application/model/store/WosulStore.dart'; -import 'package:wosull/application/model/tables/GetStoreTable.dart'; -import 'package:wosull/application/theme/MyColors.dart'; -import 'package:wosull/application/theme/MyFonts.dart'; -import 'package:wosull/application/utils/Constants.dart'; -import 'package:wosull/application/views/inventorymodule/productviews/SearchProductVC.dart'; -import 'package:wosull/helpers/Utils.dart'; -import 'package:wosull/objectbox.g.dart'; - -class EditOrderVC extends StatefulWidget { - CashierOrder cashierOrder; - - EditOrderVC({super.key, required this.cashierOrder}); - - @override - State createState() => _EditOrderVCState(); -} - -class _EditOrderVCState extends State { - var items = [ - 'Cash', - 'Card Machine', - ]; - var statusItems = [ - 'Completed', - 'Cancelled', - 'Return', - ]; - - var storeItems = []; - List tables = []; - List stores = []; - bool isPortrait = true; - late AsyncMemoizer _memoizer; - final viewModel = InventoryViewModel(); - - final amountController = TextEditingController(); - final balanceChangeController = TextEditingController(); - final createdAtController = TextEditingController(); - final deliveryNoteController = TextEditingController(); - - List> itemNotesController = [[]]; - List> itemQuantityController = [[]]; - List> itemCostPriceController = [[]]; - - dynamic selectedStatus; - dynamic selectedStore; - dynamic selectedOrderType; - dynamic selectedPaymentMode; - dynamic selectedTable; - - bool isLoading = false; - - @override - void initState() { - super.initState(); - selectedStatus = widget.cashierOrder.status!.toCapitalized(); - selectedPaymentMode = widget.cashierOrder.paymentMode!.toCapitalized(); - amountController.text = widget.cashierOrder.amount!.toString(); - // balanceChangeController.text = - // (widget.cashierOrder.amount! - widget.cashierOrder.totalAmount!) - // .toStringAsFixed(2); - createdAtController.text = - DataTimeFormat.getFormatDate(widget.cashierOrder.createdAt!); - deliveryNoteController.text = widget.cashierOrder.deliveryNotes!; - - fillControllersData(); - - _memoizer = AsyncMemoizer(); - } - - @override - Widget build(BuildContext context) { - return MaterialApp( - debugShowCheckedModeBanner: false, - home: Scaffold( - resizeToAvoidBottomInset: true, - appBar: AppBar( - leading: BackButton( - color: Colors.black, - onPressed: () { - Navigator.pop(context); - }, // <-- SEE HERE - ), - centerTitle: true, - title: Text( - AppLocalizations.of(context)!.edit_order, - style: const TextStyle( - color: MyColors.textColorBlack, - fontFamily: MyFonts.Bold, - fontSize: 22), - ), - backgroundColor: MyColors.white, - elevation: 5, - ), - body: OrientationBuilder(builder: (c, orientation) { - isPortrait = - MediaQuery.of(context).orientation == Orientation.portrait; - return SingleChildScrollView( - child: Container( - color: MyColors.white, - padding: const EdgeInsets.all(8), - child: Column( - children: [ - Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - child: Padding( - padding: const EdgeInsets.all(15), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - Expanded( - flex: 1, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - AppLocalizations.of(context)!.status, - style: const TextStyle( - fontSize: MyFonts.normalButton, - fontFamily: MyFonts.Medium, - color: MyColors.black), - ), - const SizedBox( - height: 4, - ), - Material( - color: MyColors.fillColor2, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only( - left: 6, right: 0), - child: SizedBox( - height: 42, - width: double.infinity, - child: DropdownSearch( - selectedItem: - selectedStatus ?? "Choose", - popupProps: const PopupProps.menu( - constraints: BoxConstraints( - maxHeight: 200), - ), - items: statusItems, - itemAsString: (String u) => u, - onChanged: (String? data) {}, - dropdownDecoratorProps: - const DropDownDecoratorProps( - baseStyle: TextStyle( - fontFamily: MyFonts.Medium, - fontSize: 11, - color: - MyColors.textColorBlack), - dropdownSearchDecoration: - InputDecoration( - border: InputBorder.none, - hintText: 'Choose'), - ), - ), - ), - ), - ), - const SizedBox( - height: 8, - ), - Text( - AppLocalizations.of(context)!.store, - style: const TextStyle( - fontSize: MyFonts.normalButton, - fontFamily: MyFonts.Medium, - color: MyColors.black), - ), - const SizedBox( - height: 4, - ), - getSubStoresWidget(), - const SizedBox( - height: 8, - ), - Text( - AppLocalizations.of(context)!.order_type, - style: const TextStyle( - fontSize: MyFonts.normalButton, - fontFamily: MyFonts.Medium, - color: MyColors.black), - ), - const SizedBox( - height: 4, - ), - getOrderTypeWidget(), - isPortrait - ? Column( - crossAxisAlignment: - CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.start, - children: [ - const SizedBox( - height: 8, - ), - Text( - AppLocalizations.of(context)! - .payment_mode, - style: const TextStyle( - fontSize: - MyFonts.normalButton, - fontFamily: MyFonts.Medium, - color: MyColors.black), - ), - const SizedBox( - height: 4, - ), - getSelectedPaymentMode(), - const SizedBox( - height: 8, - ), - Text( - AppLocalizations.of(context)! - .table, - style: const TextStyle( - fontSize: - MyFonts.normalButton, - fontFamily: MyFonts.Medium, - color: MyColors.black), - ), - const SizedBox( - height: 4, - ), - getStoreTables(), - const SizedBox( - height: 8, - ), - Text( - AppLocalizations.of(context)! - .amount, - style: const TextStyle( - fontSize: - MyFonts.normalButton, - fontFamily: MyFonts.Medium, - color: MyColors.black), - ), - const SizedBox( - height: 4, - ), - SizedBox( - height: 42, - child: TextField( - keyboardType: - TextInputType.number, - controller: amountController, - onChanged: (value) {}, - style: const TextStyle( - fontFamily: - MyFonts.DMREGULAR, - fontSize: - MyFonts.normalButton, - color: MyColors.black), - decoration: InputDecoration( - contentPadding: - const EdgeInsets - .fromLTRB( - 8, 0, 8, 0), - hintText: 'Enter Amount', - fillColor: - MyColors.fillColor2, - filled: true, - focusedBorder: - OutlineInputBorder( - borderSide: - const BorderSide( - color: Colors - .transparent, - width: 1.0), - borderRadius: - BorderRadius.circular( - 8.0), - ), - enabledBorder: - OutlineInputBorder( - borderSide: - const BorderSide( - width: 1, //<-- SEE HERE - color: - Colors.transparent, - ), - borderRadius: - BorderRadius.circular( - 8.0), - ), - ), - ), - ), - const SizedBox( - height: 8, - ), - Text( - AppLocalizations.of(context)! - .balance_change, - style: const TextStyle( - fontSize: - MyFonts.normalButton, - fontFamily: MyFonts.Medium, - color: MyColors.black), - ), - const SizedBox( - height: 4, - ), - SizedBox( - height: 42, - child: TextField( - readOnly: true, - controller: - balanceChangeController, - style: const TextStyle( - fontFamily: - MyFonts.DMREGULAR, - fontSize: - MyFonts.normalButton, - color: MyColors.black), - decoration: InputDecoration( - contentPadding: - const EdgeInsets - .fromLTRB( - 8, 0, 8, 0), - hintText: 'Enter Amount', - fillColor: - MyColors.fillColor2, - filled: true, - focusedBorder: - OutlineInputBorder( - borderSide: - const BorderSide( - color: Colors - .transparent, - width: 1.0), - borderRadius: - BorderRadius.circular( - 8.0), - ), - enabledBorder: - OutlineInputBorder( - borderSide: - const BorderSide( - width: 1, //<-- SEE HERE - color: - Colors.transparent, - ), - borderRadius: - BorderRadius.circular( - 8.0), - ), - ), - ), - ), - const SizedBox( - height: 8, - ), - Text( - AppLocalizations.of(context)! - .created_at, - style: const TextStyle( - fontSize: - MyFonts.normalButton, - fontFamily: MyFonts.Medium, - color: MyColors.black), - ), - const SizedBox( - height: 4, - ), - SizedBox( - height: 42, - child: TextField( - readOnly: true, - controller: - createdAtController, - style: const TextStyle( - fontFamily: - MyFonts.DMREGULAR, - fontSize: - MyFonts.normalButton, - color: MyColors.black), - decoration: InputDecoration( - contentPadding: - const EdgeInsets - .fromLTRB( - 8, 0, 8, 0), - hintText: 'Enter Amount', - fillColor: - MyColors.fillColor2, - filled: true, - focusedBorder: - OutlineInputBorder( - borderSide: - const BorderSide( - color: Colors - .transparent, - width: 1.0), - borderRadius: - BorderRadius.circular( - 8.0), - ), - enabledBorder: - OutlineInputBorder( - borderSide: - const BorderSide( - width: 1, //<-- SEE HERE - color: - Colors.transparent, - ), - borderRadius: - BorderRadius.circular( - 8.0), - ), - ), - ), - ), - const SizedBox( - height: 8, - ), - Text( - AppLocalizations.of(context)! - .delivery_note, - style: const TextStyle( - fontSize: - MyFonts.normalButton, - fontFamily: MyFonts.Medium, - color: MyColors.black), - ), - const SizedBox( - height: 4, - ), - SizedBox( - height: 42, - child: TextField( - controller: - deliveryNoteController, - style: const TextStyle( - fontFamily: - MyFonts.DMREGULAR, - fontSize: - MyFonts.normalButton, - color: MyColors.black), - decoration: InputDecoration( - contentPadding: - const EdgeInsets - .fromLTRB( - 8, 0, 8, 0), - hintText: - 'Enter Delivery Note', - fillColor: - MyColors.fillColor2, - filled: true, - focusedBorder: - OutlineInputBorder( - borderSide: - const BorderSide( - color: Colors - .transparent, - width: 1.0), - borderRadius: - BorderRadius.circular( - 8.0), - ), - enabledBorder: - OutlineInputBorder( - borderSide: - const BorderSide( - width: 1, //<-- SEE HERE - color: - Colors.transparent, - ), - borderRadius: - BorderRadius.circular( - 8.0), - ), - ), - ), - ), - ], - ) - : Container() - ], - ), - ), - isPortrait - ? Container() - : const SizedBox( - width: 8, - ), - isPortrait - ? Container() - : Expanded( - flex: 2, - child: Column( - mainAxisAlignment: - MainAxisAlignment.start, - children: [ - Row( - crossAxisAlignment: - CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - AppLocalizations.of( - context)! - .payment_mode, - style: const TextStyle( - fontSize: MyFonts - .normalButton, - fontFamily: - MyFonts.Medium, - color: MyColors.black), - ), - const SizedBox( - height: 4, - ), - getSelectedPaymentMode(), - const SizedBox( - height: 8, - ), - Text( - AppLocalizations.of( - context)! - .amount, - style: const TextStyle( - fontSize: MyFonts - .normalButton, - fontFamily: - MyFonts.Medium, - color: MyColors.black), - ), - const SizedBox( - height: 4, - ), - SizedBox( - height: 42, - child: TextField( - controller: - amountController, - style: const TextStyle( - fontFamily: - MyFonts.DMREGULAR, - fontSize: MyFonts - .normalButton, - color: - MyColors.black), - decoration: - InputDecoration( - contentPadding: - const EdgeInsets - .fromLTRB( - 8, 0, 8, 0), - hintText: - 'Enter Amount', - fillColor: - MyColors.fillColor2, - filled: true, - focusedBorder: - OutlineInputBorder( - borderSide: - const BorderSide( - color: Colors - .transparent, - width: 1.0), - borderRadius: - BorderRadius - .circular( - 8.0), - ), - enabledBorder: - OutlineInputBorder( - borderSide: - const BorderSide( - width: 1, - //<-- SEE HERE - color: Colors - .transparent, - ), - borderRadius: - BorderRadius - .circular( - 8.0), - ), - ), - ), - ), - const SizedBox( - height: 8, - ), - Text( - AppLocalizations.of( - context)! - .balance_change, - style: const TextStyle( - fontSize: MyFonts - .normalButton, - fontFamily: - MyFonts.Medium, - color: MyColors.black), - ), - const SizedBox( - height: 4, - ), - SizedBox( - height: 42, - child: TextField( - readOnly: true, - controller: - balanceChangeController, - style: const TextStyle( - fontFamily: - MyFonts.DMREGULAR, - fontSize: MyFonts - .normalButton, - color: - MyColors.black), - decoration: - InputDecoration( - contentPadding: - const EdgeInsets - .fromLTRB( - 8, 0, 8, 0), - hintText: - 'Enter Amount', - fillColor: - MyColors.fillColor2, - filled: true, - focusedBorder: - OutlineInputBorder( - borderSide: - const BorderSide( - color: Colors - .transparent, - width: 1.0), - borderRadius: - BorderRadius - .circular( - 8.0), - ), - enabledBorder: - OutlineInputBorder( - borderSide: - const BorderSide( - width: 1, - //<-- SEE HERE - color: Colors - .transparent, - ), - borderRadius: - BorderRadius - .circular( - 8.0), - ), - ), - ), - ), - ], - )), - const SizedBox( - width: 12, - ), - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - AppLocalizations.of( - context)! - .table, - style: const TextStyle( - fontSize: MyFonts - .normalButton, - fontFamily: - MyFonts.Medium, - color: MyColors.black), - ), - const SizedBox( - height: 4, - ), - getStoreTables(), - const SizedBox( - height: 8, - ), - Text( - AppLocalizations.of( - context)! - .created_at, - style: const TextStyle( - fontSize: MyFonts - .normalButton, - fontFamily: - MyFonts.Medium, - color: MyColors.black), - ), - const SizedBox( - height: 4, - ), - SizedBox( - height: 42, - child: TextField( - readOnly: true, - controller: - createdAtController, - style: const TextStyle( - fontFamily: - MyFonts.DMREGULAR, - fontSize: MyFonts - .normalButton, - color: - MyColors.black), - decoration: - InputDecoration( - contentPadding: - const EdgeInsets - .fromLTRB( - 8, 0, 8, 0), - hintText: - 'Enter Amount', - fillColor: - MyColors.fillColor2, - filled: true, - focusedBorder: - OutlineInputBorder( - borderSide: - const BorderSide( - color: Colors - .transparent, - width: 1.0), - borderRadius: - BorderRadius - .circular( - 8.0), - ), - enabledBorder: - OutlineInputBorder( - borderSide: - const BorderSide( - width: 1, - //<-- SEE HERE - color: Colors - .transparent, - ), - borderRadius: - BorderRadius - .circular( - 8.0), - ), - ), - ), - ), - const SizedBox( - height: 8, - ), - Text( - AppLocalizations.of( - context)! - .delivery_note, - style: const TextStyle( - fontSize: MyFonts - .normalButton, - fontFamily: - MyFonts.Medium, - color: MyColors.black), - ), - const SizedBox( - height: 4, - ), - SizedBox( - height: 42, - child: TextField( - controller: - deliveryNoteController, - style: const TextStyle( - fontFamily: - MyFonts.DMREGULAR, - fontSize: MyFonts - .normalButton, - color: - MyColors.black), - decoration: - InputDecoration( - contentPadding: - const EdgeInsets - .fromLTRB( - 8, 0, 8, 0), - hintText: - 'Enter Delivery Note', - fillColor: - MyColors.fillColor2, - filled: true, - focusedBorder: - OutlineInputBorder( - borderSide: - const BorderSide( - color: Colors - .transparent, - width: 1.0), - borderRadius: - BorderRadius - .circular( - 8.0), - ), - enabledBorder: - OutlineInputBorder( - borderSide: - const BorderSide( - width: 1, - //<-- SEE HERE - color: Colors - .transparent, - ), - borderRadius: - BorderRadius - .circular( - 8.0), - ), - ), - ), - ), - ], - )), - ], - ), - ], - )), - ], - ), - ], - ), - ), - ), - const SizedBox( - height: 12, - ), - Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(4.0), - ), - child: Container( - padding: const EdgeInsets.all(8), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Text( - AppLocalizations.of(context)! - .search_and_add_products, - style: const TextStyle( - color: MyColors.textColorBlack, - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.bold, - fontSize: 14), - ), - const SizedBox( - height: 12, - ), - isPortrait - ? Container() - : Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all( - width: 1, - color: MyColors.fillColorGray2), - color: MyColors.containerBackColor, - ), - height: 48, - child: Row( - children: [ - Expanded( - child: Container( - padding: const EdgeInsets.only( - left: 4, right: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .name_or_barcode, - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.bold, - fontSize: MyFonts.normal, - color: - MyColors.textColorBlack20), - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.only(left: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .item_note, - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.bold, - fontSize: MyFonts.normal, - color: - MyColors.textColorBlack20), - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.only(left: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .quantity, - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.bold, - fontSize: MyFonts.normal, - color: - MyColors.textColorBlack20), - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.only(left: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .total_cost_price, - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.bold, - fontSize: MyFonts.normal, - color: - MyColors.textColorBlack20), - ), - ), - )), - Container( - padding: const EdgeInsets.only(left: 4), - width: 84, - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .total_price, - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.bold, - fontSize: MyFonts.normal, - color: - MyColors.textColorBlack20), - ), - ), - ), - Container( - padding: const EdgeInsets.only(left: 4), - width: 84, - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)! - .total_amount, - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.bold, - fontSize: MyFonts.normal, - color: - MyColors.textColorBlack20), - ), - ), - ), - Container( - width: 44, - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: const Center( - child: Text( - '', - style: TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.bold, - fontSize: MyFonts.normal, - color: - MyColors.textColorBlack20), - ), - ), - ) - ], - ), - ), - ListView.builder( - padding: EdgeInsets.zero, - scrollDirection: Axis.vertical, - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - itemBuilder: (c, position) { - return ListView.builder( - padding: EdgeInsets.zero, - scrollDirection: Axis.vertical, - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - itemBuilder: (c, i) { - var item = widget.cashierOrder.cart! - .orderDetails![position].items![i]; - if (isPortrait) { - return Container( - padding: - const EdgeInsets.fromLTRB(8, 0, 0, 8), - color: MyColors.containerBackColor, - child: Row( - crossAxisAlignment: - CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.start, - children: [ - Expanded( - flex: 2, - child: Container( - padding: const EdgeInsets.only( - top: 8), - child: Row( - crossAxisAlignment: - CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.start, - children: [ - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment - .start, - mainAxisAlignment: - MainAxisAlignment - .start, - children: [ - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - left: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: Alignment - .centerLeft, - child: Text( - AppLocalizations.of( - context)! - .name_or_barcode, - style: const TextStyle( - fontFamily: - MyFonts - .Bold, - fontWeight: - FontWeight - .bold, - fontSize: 11, - color: MyColors - .textColorBlack20), - ), - ), - ), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - left: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: Alignment - .centerLeft, - child: Text( - AppLocalizations.of( - context)! - .item_note, - style: const TextStyle( - fontFamily: - MyFonts - .Bold, - fontWeight: - FontWeight - .bold, - fontSize: 11, - color: MyColors - .textColorBlack20), - ), - ), - ), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - left: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: Alignment - .centerLeft, - child: Text( - AppLocalizations.of( - context)! - .quantity, - style: const TextStyle( - fontFamily: - MyFonts - .Bold, - fontWeight: - FontWeight - .bold, - fontSize: 11, - color: MyColors - .textColorBlack20), - ), - ), - ), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - left: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: Alignment - .centerLeft, - child: Text( - AppLocalizations.of( - context)! - .total_cost_price, - style: const TextStyle( - fontFamily: - MyFonts - .Bold, - fontWeight: - FontWeight - .bold, - fontSize: 11, - color: MyColors - .textColorBlack20), - ), - ), - ), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - left: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: Alignment - .centerLeft, - child: Text( - AppLocalizations.of( - context)! - .total_price, - style: const TextStyle( - fontFamily: - MyFonts - .Bold, - fontWeight: - FontWeight - .bold, - fontSize: 11, - color: MyColors - .textColorBlack20), - ), - ), - ), - ], - )), - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment - .start, - mainAxisAlignment: - MainAxisAlignment - .start, - children: [ - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Container( - decoration: - BoxDecoration( - border: - Border.all( - color: Colors - .transparent, - width: 1, - ), - color: MyColors - .fillColor2, - borderRadius: - BorderRadius - .circular( - 8.0), - ), - child: Row( - children: [ - Expanded( - child: - TextButton( - onPressed: - () { - showSheet( - position, - i); - }, - child: Align( - alignment: - Alignment - .centerLeft, - child: Text( - item.name - .isEmpty - ? 'Choose' - : item - .name, - textAlign: - TextAlign - .left, - style: const TextStyle( - fontFamily: MyFonts - .Bold, - fontSize: - 10, - color: - MyColors.textColorBlack), - ), - ), - )), - const Icon( - // <-- Icon - Icons - .arrow_drop_down, - size: 24.0, - color: MyColors - .black, - ) - ], - ), - ), - ), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: TextField( - controller: - itemNotesController[ - position][i], - onChanged: - (value) { - setState(() { - widget - .cashierOrder - .cart! - .orderDetails![ - position] - .items![i] - .noteForItem! - .add( - value); - }); - }, - style: const TextStyle( - fontFamily: - MyFonts - .DMREGULAR, - fontSize: - MyFonts - .normal, - color: MyColors - .black), - decoration: - InputDecoration( - contentPadding: - const EdgeInsets - .fromLTRB( - 4, - 0, - 4, - 0), - hintText: - 'Enter item note', - fillColor: MyColors - .fillColor2, - filled: true, - focusedBorder: - OutlineInputBorder( - borderSide: const BorderSide( - color: Colors - .transparent, - width: - 1.0), - borderRadius: - BorderRadius - .circular( - 8.0), - ), - enabledBorder: - OutlineInputBorder( - borderSide: - const BorderSide( - width: 1, - //<-- SEE HERE - color: Colors - .transparent, - ), - borderRadius: - BorderRadius - .circular( - 4.0), - ), - ), - ), - ), - ), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: TextField( - keyboardType: - TextInputType - .number, - controller: - itemQuantityController[ - position][i], - onChanged: - (value) { - setState(() { - widget - .cashierOrder - .cart! - .orderDetails![ - position] - .items![i] - .quantity = int.parse(value); - }); - }, - style: const TextStyle( - fontFamily: - MyFonts - .DMREGULAR, - fontSize: - MyFonts - .normal, - color: MyColors - .black), - decoration: - InputDecoration( - contentPadding: - const EdgeInsets - .fromLTRB( - 4, - 0, - 4, - 0), - hintText: - 'Enter item quantity', - fillColor: MyColors - .fillColor2, - filled: true, - focusedBorder: - OutlineInputBorder( - borderSide: const BorderSide( - color: Colors - .transparent, - width: - 1.0), - borderRadius: - BorderRadius - .circular( - 8.0), - ), - enabledBorder: - OutlineInputBorder( - borderSide: - const BorderSide( - width: 1, - //<-- SEE HERE - color: Colors - .transparent, - ), - borderRadius: - BorderRadius - .circular( - 4.0), - ), - ), - ), - ), - ), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: TextField( - keyboardType: - TextInputType - .number, - controller: - itemCostPriceController[ - position][i], - onChanged: - (value) { - setState(() { - widget - .cashierOrder - .cart! - .orderDetails![ - position] - .items![i] - .price = double.parse(value); - }); - }, - style: const TextStyle( - fontFamily: - MyFonts - .DMREGULAR, - fontSize: - MyFonts - .normal, - color: MyColors - .black), - decoration: - InputDecoration( - contentPadding: - const EdgeInsets - .fromLTRB( - 4, - 0, - 4, - 0), - hintText: - 'Enter item price', - fillColor: MyColors - .fillColor2, - filled: true, - focusedBorder: - OutlineInputBorder( - borderSide: const BorderSide( - color: Colors - .transparent, - width: - 1.0), - borderRadius: - BorderRadius - .circular( - 8.0), - ), - enabledBorder: - OutlineInputBorder( - borderSide: - const BorderSide( - width: 1, - //<-- SEE HERE - color: Colors - .transparent, - ), - borderRadius: - BorderRadius - .circular( - 4.0), - ), - ), - ), - ), - ), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - bottom: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: Text( - (item.price * - item - .quantity) - .toStringAsFixed( - 2), - style: MyColors - .textStyleHeading(), - ), - ), - ), - ], - )), - ], - ), - )), - SizedBox( - width: 44, - height: 48, - child: Center( - child: Container( - width: 32, - height: 32, - decoration: - const BoxDecoration( - borderRadius: - BorderRadius.all( - Radius - .circular( - 4)), - color: MyColors - .fillColorGray2), - child: IconButton( - icon: const Icon( - size: 18, - Icons.close, - color: MyColors - .textColorBlack, - ), - onPressed: () { - removeItemFromCart( - position, i); - }), - ), - )) - ], - ), - ); - } else { - return Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all( - width: 1, - color: MyColors.fillColorGray2), - color: MyColors.white, - ), - height: 48, - child: Row( - children: [ - Expanded( - child: Container( - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - height: 48, - padding: const EdgeInsets.all(4), - child: Container( - decoration: BoxDecoration( - border: Border.all( - color: Colors.transparent, - width: 1, - ), - color: MyColors.fillColor2, - borderRadius: - BorderRadius.circular( - 8.0), - ), - child: Row( - children: [ - Expanded( - child: TextButton( - onPressed: () { - showSheet(position, i); - }, - child: Align( - alignment: Alignment - .centerLeft, - child: Text( - item.name.isEmpty - ? 'Choose' - : item.name, - textAlign: - TextAlign.left, - style: const TextStyle( - fontFamily: - MyFonts.Bold, - fontSize: 10, - color: MyColors - .textColorBlack), - ), - ), - )), - const Icon( - // <-- Icon - Icons.arrow_drop_down, - size: 24.0, - color: MyColors.black, - ) - ], - ), - ), - ), - ), - Expanded( - child: Container( - padding: const EdgeInsets.all(4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: TextField( - controller: itemNotesController[ - position][i], - onChanged: (value) { - setState(() { - widget - .cashierOrder - .cart! - .orderDetails![position] - .items![i] - .noteForItem! - .add(value); - }); - }, - style: const TextStyle( - fontFamily: - MyFonts.DMREGULAR, - fontSize: MyFonts.normal, - color: MyColors.black), - decoration: InputDecoration( - contentPadding: - const EdgeInsets.fromLTRB( - 4, 0, 4, 0), - hintText: 'Enter item note', - fillColor: - MyColors.fillColor2, - filled: true, - focusedBorder: - OutlineInputBorder( - borderSide: - const BorderSide( - color: Colors - .transparent, - width: 1.0), - borderRadius: - BorderRadius.circular( - 8.0), - ), - enabledBorder: - OutlineInputBorder( - borderSide: - const BorderSide( - width: 1, - //<-- SEE HERE - color: Colors.transparent, - ), - borderRadius: - BorderRadius.circular( - 4.0), - ), - ), - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.all(4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: TextField( - keyboardType: - TextInputType.number, - controller: - itemQuantityController[ - position][i], - onChanged: (value) { - setState(() { - widget - .cashierOrder - .cart! - .orderDetails![position] - .items![i] - .quantity = - int.parse(value); - }); - }, - style: const TextStyle( - fontFamily: - MyFonts.DMREGULAR, - fontSize: MyFonts.normal, - color: MyColors.black), - decoration: InputDecoration( - contentPadding: - const EdgeInsets.fromLTRB( - 4, 0, 4, 0), - hintText: - 'Enter item quantity', - fillColor: - MyColors.fillColor2, - filled: true, - focusedBorder: - OutlineInputBorder( - borderSide: - const BorderSide( - color: Colors - .transparent, - width: 1.0), - borderRadius: - BorderRadius.circular( - 8.0), - ), - enabledBorder: - OutlineInputBorder( - borderSide: - const BorderSide( - width: 1, - //<-- SEE HERE - color: Colors.transparent, - ), - borderRadius: - BorderRadius.circular( - 4.0), - ), - ), - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.all(4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: TextField( - keyboardType: - TextInputType.number, - controller: - itemCostPriceController[ - position][i], - onChanged: (value) { - setState(() { - widget - .cashierOrder - .cart! - .orderDetails![position] - .items![i] - .price = - double.parse(value); - }); - }, - style: const TextStyle( - fontFamily: - MyFonts.DMREGULAR, - fontSize: MyFonts.normal, - color: MyColors.black), - decoration: InputDecoration( - contentPadding: - const EdgeInsets.fromLTRB( - 4, 0, 4, 0), - hintText: 'Enter item price', - fillColor: - MyColors.fillColor2, - filled: true, - focusedBorder: - OutlineInputBorder( - borderSide: - const BorderSide( - color: Colors - .transparent, - width: 1.0), - borderRadius: - BorderRadius.circular( - 8.0), - ), - enabledBorder: - OutlineInputBorder( - borderSide: - const BorderSide( - width: 1, - //<-- SEE HERE - color: Colors.transparent, - ), - borderRadius: - BorderRadius.circular( - 4.0), - ), - ), - ), - ), - )), - Container( - width: 84, - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: Text( - (item.price * item.quantity) - .toStringAsFixed(2), - style: - MyColors.textStyleHeading(), - ), - ), - ), - Container( - width: 84, - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: Text( - '', - style: - MyColors.textStyleHeading(), - ), - ), - ), - SizedBox( - width: 44, - height: 48, - child: Center( - child: Container( - width: 32, - height: 32, - decoration: - const BoxDecoration( - borderRadius: - BorderRadius.all( - Radius - .circular( - 4)), - color: MyColors - .fillColorGray2), - child: IconButton( - icon: const Icon( - size: 14, - Icons.close, - color: MyColors - .textColorBlack, - ), - onPressed: () { - removeItemFromCart( - position, i); - }), - ), - )), - ], - ), - ); - } - }, - itemCount: widget.cashierOrder.cart! - .orderDetails![position].items!.length, - ); - }, - itemCount: - widget.cashierOrder.cart!.orderDetails!.length, - ), - isPortrait - ? Container( - margin: const EdgeInsets.fromLTRB(8, 0, 0, 8), - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all( - width: 1, - color: MyColors.fillColorGray2), - color: Colors.white, - ), - height: 48, - child: Row( - children: [ - Expanded( - child: Container( - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: Text( - AppLocalizations.of(context)! - .total_amount, - style: MyColors.textStyleHeading(), - ), - ), - )), - Expanded( - child: Container( - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: Text( - getItemsPriceWithModifier(), - style: MyColors.textStyleHeading(), - ), - ), - )), - Center( - child: Container( - margin: const EdgeInsets.all(5), - width: 32, - height: 32, - decoration: const BoxDecoration( - borderRadius: BorderRadius.all( - Radius.circular(4)), - color: MyColors.fillColorGray2), - child: IconButton( - icon: const Icon( - size: 14, - Icons.add, - color: MyColors.textColorBlack, - ), - onPressed: () { - addNewItem(); - }), - ), - ), - ], - ), - ) - : Container( - margin: const EdgeInsets.fromLTRB(0, 0, 0, 8), - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all( - width: 1, - color: MyColors.fillColorGray2), - color: Colors.white, - ), - height: 48, - child: Row( - children: [ - Expanded( - child: Container( - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: Text( - '', - style: MyColors.textStyleValue(), - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.only(left: 8), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: Text( - '', - style: MyColors.textStyleValue(), - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.only(left: 8), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: Text( - '', - style: MyColors.textStyleValue(), - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.only(left: 8), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: Text( - '', - style: MyColors.textStyleValue(), - ), - ), - )), - Container( - width: 84, - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: Text( - getItemsPriceOnly(), - style: MyColors.textStyleHeading(), - ), - ), - ), - Container( - width: 84, - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: Text( - getItemsPriceWithModifier(), - style: MyColors.textStyleHeading(), - ), - ), - ), - Center( - child: Container( - margin: const EdgeInsets.all(5), - width: 34, - height: 32, - decoration: const BoxDecoration( - borderRadius: BorderRadius.all( - Radius.circular(4)), - color: MyColors.fillColorGray2), - child: IconButton( - icon: const Icon( - size: 14, - Icons.add, - color: MyColors.textColorBlack, - ), - onPressed: () { - addNewItem(); - }), - ), - ), - ], - ), - ), - const SizedBox( - height: 20, - ), - ], - ), - ), - ), - const SizedBox( - height: 12, - ), - Row( - crossAxisAlignment: CrossAxisAlignment.end, - mainAxisAlignment: MainAxisAlignment.end, - children: [ - SizedBox( - width: 120, - child: isLoading - ? const Center( - child: CircularProgressIndicator(), - ) - : ElevatedButton( - style: ElevatedButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(6.0), - ), - backgroundColor: MyColors.blueThemeColor, - minimumSize: - const Size.fromHeight(38), // NEW - ), - onPressed: () { - updateOrder(); - }, - child: Text( - AppLocalizations.of(context)!.save, - style: const TextStyle( - fontSize: MyFonts.normalButton, - color: MyColors.white, - fontFamily: MyFonts.Bold), - ), - )), - ], - ) - ], - ), - ), - ); - }), - ), - ); - } - - Future updateOrder() async { - setState(() { - isLoading = true; - }); - - final map = widget.cashierOrder.toJson(); - - await viewModel.getData(Constants.UPDATE_CASHIER_ORDER, map).then((value) { - final response = SimpleResponseModel.fromJson(value); - setState(() { - isLoading = false; - }); - if (response.success) { - Navigator.pop(context, true); - } - }).onError((error, stackTrace) { - setState(() { - isLoading = false; - }); - }); - } - - void showSheet(int parent, int child) async { - final result = await showDialog( - barrierColor: Colors.black26, - context: context, - builder: (context) { - return const SearchProductVC(); - }, - ); - - if (!mounted) return; - - setState(() { - if (result != null) { - ProductItem item = result; - final orderDetails = CashierOrderDetails(); - orderDetails.productId = item.productId; - orderDetails.items = []; - final storeItem = StoreItems( - deliveryPartners: ToMany(items: []), - modifiers: ToMany(items: item.modifiers!), - comboProduct: ToMany(items: item.comboProduct!), - ingredients: ToMany(items: item.ingredients!), - selectedModifiers: ToMany(items: []), - name: item.name!, - price: item.price!, - quantity: item.total_quantity!, - uniqueIdForStoreData: item.uniqueIdForStoreData!, - productId: item.productId!, - selectedCombos: ToMany(items: []), - ); - orderDetails.items!.add(storeItem); - - widget.cashierOrder.cart!.orderDetails![parent] = orderDetails; - fillControllersData(); - } - }); - } - - void addNewItem() { - setState(() { - final orderDetails = CashierOrderDetails(); - orderDetails.productId = ""; - orderDetails.items = []; - final storeItem = StoreItems( - name: 'Choose', - price: 0.0, - quantity: 1, - modifiers: ToMany(items: []), - deliveryPartners: ToMany(items: []), - comboProduct: ToMany(items: []), - ingredients: ToMany(items: []), - selectedModifiers: ToMany(items: []), - selectedCombos: ToMany(items: [])); - orderDetails.items!.add(storeItem); - - widget.cashierOrder.cart!.orderDetails!.add(orderDetails); - fillControllersData(); - }); - } - - Widget getOrderTypeWidget() { - return FutureBuilder( - future: getService(), - builder: (c, s) { - if (s.hasData) { - var itemsList = s.data!; - return Material( - color: MyColors.fillColor2, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: 42, - width: double.infinity, - child: DropdownSearch( - selectedItem: selectedOrderType, - popupProps: const PopupProps.menu( - constraints: BoxConstraints(maxHeight: 200), - ), - items: itemsList, - itemAsString: (StoreServiceModel u) => u.name!, - onChanged: (StoreServiceModel? data) {}, - dropdownDecoratorProps: const DropDownDecoratorProps( - baseStyle: TextStyle( - fontFamily: MyFonts.Medium, - fontSize: 11, - color: MyColors.textColorBlack), - dropdownSearchDecoration: InputDecoration( - border: InputBorder.none, hintText: 'Choose'), - ), - ), - ), - ), - ); - } else { - return const Center(child: CircularProgressIndicator()); - } - }); - } - - Future> getService() async { - _memoizer.runOnce(() async { - // This below code will call only ones. This will return the same data directly without performing any Future task. - Map data = { - 'store_id': sharedPrefs.storeId, - }; - await viewModel.getData(Constants.Store_services_URL, data).then((value) { - final response = StoreServiceResponse.fromJson(value); - if (response.success) { - storeItems.addAll(response.services); - - setState(() { - selectedOrderType = storeItems.singleWhere( - (element) => element.name == widget.cashierOrder.orderType); - selectedOrderType ??= StoreServiceModel(name: 'N/A'); - }); - } - }).onError((error, stackTrace) {}); - }); - - return storeItems; - } - - Widget getStoreTables() { - return FutureBuilder( - future: getTablesList(), - builder: (c, s) { - if (s.hasData) { - var itemsList = s.data!; - return Material( - color: MyColors.fillColor2, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: 42, - width: double.infinity, - child: DropdownSearch( - selectedItem: selectedTable ?? - StoreTable(id: '', tableName: 'N/A', noOfOccupants: 0), - popupProps: const PopupProps.menu( - constraints: BoxConstraints(maxHeight: 200), - ), - items: itemsList, - itemAsString: (StoreTable u) => - u.tableName + " | " + u.noOfOccupants.toString(), - onChanged: (StoreTable? data) {}, - dropdownDecoratorProps: const DropDownDecoratorProps( - baseStyle: TextStyle( - fontFamily: MyFonts.Medium, - fontSize: 11, - color: MyColors.textColorBlack), - dropdownSearchDecoration: InputDecoration( - border: InputBorder.none, hintText: 'Choose'), - ), - ), - ), - ), - ); - } else { - return const Center(child: CircularProgressIndicator()); - } - }); - } - - Future> getTablesList() async { - if (widget.cashierOrder.orderType!.toLowerCase().compareTo('dinein') == 0) { - await viewModel - .getData(Constants.GET_STORE_TABLES, Constants.getStorePayload()) - .then((value) { - final response = GetStoreTable.fromJson(value); - if (response.success) { - tables.clear(); - tables.addAll(response.storeTables); - - // selectedTable = tables.singleWhere((element) => element.id! == widget.cashierOrder.storeId!.id!); - } - }).onError((error, stackTrace) {}); - } - selectedTable ??= StoreTable(id: '', tableName: 'N/A', noOfOccupants: 0); - return tables; - } - - Widget getSubStoresWidget() { - return FutureBuilder( - future: getSubStores(), - builder: (c, s) { - if (s.hasData) { - var itemsList = s.data!; - return Material( - color: MyColors.fillColor2, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: 42, - width: double.infinity, - child: DropdownSearch( - selectedItem: selectedStore, - popupProps: const PopupProps.menu( - constraints: BoxConstraints(maxHeight: 200), - ), - items: itemsList, - itemAsString: (WosulStore u) => u.name, - onChanged: (WosulStore? data) {}, - dropdownDecoratorProps: const DropDownDecoratorProps( - baseStyle: TextStyle( - fontFamily: MyFonts.Medium, - fontSize: 11, - color: MyColors.textColorBlack), - dropdownSearchDecoration: InputDecoration( - border: InputBorder.none, hintText: 'Choose'), - ), - ), - ), - ), - ); - } else { - return const Center(child: CircularProgressIndicator()); - } - }); - } - - Future> getSubStores() async { - await viewModel - .getData(Constants.GET_STORE_SUB_STORES, Constants.getStorePayload()) - .then((value) { - final response = GetSpecificStores.fromJson(value); - if (response.success) { - stores.clear(); - stores.addAll(response.stores); - selectedStore = stores.singleWhere( - (element) => element.id == widget.cashierOrder.storeId!.id); - } - selectedStore ??= WosulStore(id: '', name: 'Choose'); - }).onError((error, stackTrace) {}); - return stores; - } - - Widget getSelectedPaymentMode() { - return Material( - color: MyColors.fillColor2, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: 42, - width: double.infinity, - child: DropdownSearch( - selectedItem: selectedPaymentMode ?? "Choose", - popupProps: const PopupProps.menu( - constraints: BoxConstraints(maxHeight: 200), - ), - items: items, - itemAsString: (String u) => u, - onChanged: (String? data) {}, - dropdownDecoratorProps: const DropDownDecoratorProps( - baseStyle: TextStyle( - fontFamily: MyFonts.Medium, - fontSize: 11, - color: MyColors.textColorBlack), - dropdownSearchDecoration: - InputDecoration(border: InputBorder.none, hintText: 'Choose'), - ), - ), - ), - ), - ); - } - - String getItemsPriceWithModifier() { - double price = 0.0; - for (var order in widget.cashierOrder.cart!.orderDetails!) { - for (var item in order.items!) { - price += (item.quantity * item.price); - if (item.selectedModifiers!.isNotEmpty) { - for (var modi in item.selectedModifiers!) { - price += modi.price; - } - } - } - } - balanceChangeController.text = - (widget.cashierOrder.amount! - price).toString(); - return price.toStringAsFixed(2); - } - - String getItemsPriceOnly() { - double price = 0.0; - for (var order in widget.cashierOrder.cart!.orderDetails!) { - for (var item in order.items!) { - price += (item.quantity * item.price); - } - } - - return price.toStringAsFixed(2); - } - - void removeItemFromCart(int parentPosition, int child) { - setState(() { - //remove specif child - - widget.cashierOrder.returnOrderDetails! - .add(widget.cashierOrder.cart!.orderDetails![parentPosition]); - - widget.cashierOrder.cart!.orderDetails![parentPosition].items! - .removeAt(child); - //check if all items deleted - if (widget - .cashierOrder.cart!.orderDetails![parentPosition].items!.isEmpty) { - widget.cashierOrder.cart!.orderDetails!.removeAt(parentPosition); - } - fillControllersData(); - }); - } - - void fillControllersData() { - itemNotesController.clear(); - itemQuantityController.clear(); - itemCostPriceController.clear(); - for (int i = 0; i < widget.cashierOrder.cart!.orderDetails!.length; i++) { - itemNotesController.add([]); - itemQuantityController.add([]); - itemCostPriceController.add([]); - for (int j = 0; - j < widget.cashierOrder.cart!.orderDetails![i].items!.length; - j++) { - var item = widget.cashierOrder.cart!.orderDetails![i].items![j]; - var text = ""; - item.noteForItem ??= []; - for (var note in item.noteForItem!) { - if (text.isEmpty) { - text = note; - } else { - text = "$text,$note"; - } - } - - itemNotesController[i].add(TextEditingController(text: text)); - itemQuantityController[i] - .add(TextEditingController(text: item.quantity.toString())); - itemCostPriceController[i] - .add(TextEditingController(text: item.price.toString())); - } - } - } -} diff --git a/lib/application/views/transactions/TransactionInvoicesVC.dart b/lib/application/views/transactions/TransactionInvoicesVC.dart deleted file mode 100644 index a7a1f06..0000000 --- a/lib/application/views/transactions/TransactionInvoicesVC.dart +++ /dev/null @@ -1,982 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:sizer/sizer.dart'; -import 'package:wosull/application/ViewModel/InventoryViewModel.dart'; -import 'package:wosull/application/interfaces/DrawerWidgetSelect.dart'; -import 'package:wosull/application/localdb/SharedPrefs.dart'; -import 'package:wosull/application/model/converters/DataTimeFormat.dart'; -import 'package:wosull/application/model/invoice/StoreInvoice.dart'; -import 'package:wosull/application/model/store/StoreInvoicesModel.dart'; -import 'package:wosull/application/theme/MyColors.dart'; -import 'package:wosull/application/theme/MyFonts.dart'; -import 'package:wosull/application/utils/Constants.dart'; -import 'package:wosull/application/views/popups/DeleteRecordPopUp.dart'; -import 'package:wosull/application/views/salesandordermodule/views/ReturnInvoiceVC.dart'; -import 'package:wosull/base/BaseStatefulState.dart'; -import 'package:wosull/widgets/EmptyDataWidget.dart'; - -class TransactionInvoicesVC extends StatefulWidget { - TransactionCVS delegate; - BuildContext context; - String filter = 'All'; - - TransactionInvoicesVC( - {super.key, - required this.filter, - required this.delegate, - required this.context}); - - @override - State createState() => _TransactionInvoicesVCState(); -} - -class _TransactionInvoicesVCState - extends BaseStatefulState { - bool isPortrait = true; - var itemsList = [ - 'Open', - 'Paid Partially', - 'Paid', - 'Cancelled', - 'Return', - 'Damage' - ]; - - InventoryViewModel viewModel = InventoryViewModel(); - - List filteredInvoices = []; - - int _page = 1; - bool _isFirstLoadRunning = false; - bool _hasNextPage = true; - - bool _isLoadMoreRunning = false; - late ScrollController _controller; - - @override - void initState() { - super.initState(); - _firstLoad(); - _controller = ScrollController()..addListener(_loadMore); - } - - @override - Widget build(BuildContext context) { - return OrientationBuilder(builder: (c, orientation) { - isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; - - return SingleChildScrollView( - controller: _controller, - child: Column( - children: [ - _isFirstLoadRunning - ? const Center( - child: CircularProgressIndicator(), - ) - : filteredInvoices.isEmpty - ? const EmptyDataWidget() - : Column( - children: [ - isPortrait - ? Container() - : Container( - padding: - const EdgeInsets.only(left: 8, right: 8), - height: 50, - color: MyColors.containerBackColor, - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceEvenly, - children: [ - Expanded( - child: Text( - AppLocalizations.of(widget.context)! - .number, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 10, - fontWeight: FontWeight.w300, - color: MyColors.black), - )), - Expanded( - child: Text( - AppLocalizations.of(widget.context)! - .reference_no, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 10, - fontWeight: FontWeight.w300, - color: MyColors.black), - )), - Expanded( - child: Text( - AppLocalizations.of(widget.context)! - .bill_to, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 10, - fontWeight: FontWeight.w300, - color: MyColors.black), - )), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(widget.context)! - .invoice_date, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 10, - fontWeight: FontWeight.w300, - color: MyColors.black), - ), - )), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(widget.context)! - .invoice_due_Date, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 10, - fontWeight: FontWeight.w300, - color: MyColors.black), - ), - )), - Expanded( - child: Align( - alignment: Alignment.center, - child: Text( - AppLocalizations.of(widget.context)! - .amount, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 10, - fontWeight: FontWeight.w300, - color: MyColors.black), - ), - )), - Container( - width: 120, - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of( - widget.context)! - .switch_status, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 10, - fontWeight: FontWeight.w300, - color: MyColors.black), - ), - )), - const SizedBox( - width: 10, - ), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(widget.context)! - .status, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 10, - fontWeight: FontWeight.w300, - color: MyColors.black), - ), - )), - const SizedBox( - width: 10, - ), - Container( - width: 46, - child: Text( - AppLocalizations.of(widget.context)! - .action, - style: const TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.Bold, - fontSize: 10, - fontWeight: FontWeight.w300, - color: MyColors.black), - ), - ), - ], - ), - ), - ListView.builder( - padding: EdgeInsets.zero, - scrollDirection: Axis.vertical, - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - itemBuilder: (c, position) { - if (isPortrait) { - return Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - child: Container( - padding: - const EdgeInsets.fromLTRB(16, 0, 0, 16), - color: MyColors.containerBackColor, - child: Row( - crossAxisAlignment: - CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.start, - children: [ - Expanded( - flex: 2, - child: Container( - padding: const EdgeInsets.only( - top: 16), - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.start, - children: [ - Row( - children: [ - Expanded( - child: Align( - alignment: Alignment - .centerLeft, - child: Text( - AppLocalizations.of( - widget - .context)! - .number, - style: MyColors - .textStyleHeading(), - ), - )), - Expanded( - child: Align( - alignment: Alignment - .centerRight, - child: Text( - filteredInvoices[ - position] - .invoiceNumber! - .toString(), - style: MyColors - .textStyleValue(), - ), - )) - ], - ), - Row( - children: [ - Expanded( - child: Align( - alignment: Alignment - .centerLeft, - child: Text( - AppLocalizations.of( - widget - .context)! - .reference_no, - style: MyColors - .textStyleHeading(), - ), - )), - Expanded( - child: Align( - alignment: Alignment - .centerRight, - child: Text( - filteredInvoices[ - position] - .invoiceReference! - .toString(), - style: MyColors - .textStyleValue(), - ), - )) - ], - ), - Row( - children: [ - Expanded( - child: Align( - alignment: Alignment - .centerLeft, - child: Text( - AppLocalizations.of( - widget - .context)! - .bill_to, - style: MyColors - .textStyleHeading(), - ), - )), - Expanded( - child: Align( - alignment: Alignment - .centerRight, - child: Text( - filteredInvoices[ - position] - .supplier! - .name ?? - '', - style: MyColors - .textStyleValue(), - ), - )) - ], - ), - Row( - children: [ - Expanded( - child: Align( - alignment: Alignment - .centerLeft, - child: Text( - AppLocalizations.of( - widget - .context)! - .invoice_date, - style: MyColors - .textStyleHeading(), - ), - )), - Expanded( - child: Align( - alignment: Alignment - .centerRight, - child: Text( - DataTimeFormat.getFormatDate( - filteredInvoices[ - position] - .invoiceDate!), - style: MyColors - .textStyleValue(), - ), - )) - ], - ), - Row( - children: [ - Expanded( - child: Align( - alignment: Alignment - .centerLeft, - child: Text( - AppLocalizations.of( - widget - .context)! - .invoice_due_date, - style: MyColors - .textStyleHeading(), - ), - )), - Expanded( - child: Align( - alignment: Alignment - .centerRight, - child: Text( - DataTimeFormat.getFormatDate( - filteredInvoices[ - position] - .invoiceDueDate!), - style: MyColors - .textStyleValue(), - ), - )) - ], - ), - Row( - children: [ - Expanded( - child: Align( - alignment: Alignment - .centerLeft, - child: Text( - AppLocalizations.of( - widget - .context)! - .amount, - style: MyColors - .textStyleHeading(), - ), - )), - Expanded( - child: Align( - alignment: Alignment - .centerRight, - child: Text( - filteredInvoices[ - position] - .totalAmount! - .toStringAsFixed( - 2), - style: MyColors - .textStyleValue(), - ), - )) - ], - ), - Row( - children: [ - Expanded( - child: Align( - alignment: Alignment - .centerLeft, - child: Text( - AppLocalizations.of( - widget - .context)! - .status, - style: MyColors - .textStyleHeading(), - ), - )), - Expanded( - child: Align( - alignment: Alignment - .centerRight, - child: Text( - filteredInvoices[ - position] - .status! - .toString(), - style: const TextStyle( - fontFamily: - MyFonts.Bold, - fontWeight: - FontWeight - .w500, - fontSize: MyFonts - .normal, - color: MyColors - .greenColor), - ), - )) - ], - ), - Row( - children: [ - Expanded( - child: Align( - alignment: Alignment - .centerLeft, - child: Text( - AppLocalizations.of( - widget - .context)! - .switch_status, - style: MyColors - .textStyleHeading(), - ), - )), - Expanded( - child: Align( - alignment: Alignment - .centerRight, - child: Container( - decoration: - BoxDecoration( - color: MyColors - .fillColor, - borderRadius: - BorderRadius - .circular( - 8), - ), - height: 38, - padding: - const EdgeInsets - .only( - left: 8, - right: 8), - width: SizerUtil - .deviceType == - DeviceType - .mobile - ? 120 - : 100, - child: DropdownButton< - String>( - hint: const Text( - 'Select'), - style: MyColors - .textStyleValue(), - isExpanded: true, - underline: - DropdownButtonHideUnderline( - child: - Container()), - items: itemsList - .map((String - items) { - return DropdownMenuItem( - value: items, - child: - Text(items), - ); - }).toList(), - onChanged: (value) { - filteredInvoices[ - position] - .status = value!; - _update( - filteredInvoices[ - position] - .id!, - value - .toString()); - }, - ), - ), - )) - ], - ), - ], - ), - )), - PopupMenuButton( - icon: const Icon(Icons.more_vert), - itemBuilder: (c) { - return [ - PopupMenuItem( - value: 'edit', - child: Text( - AppLocalizations.of( - widget.context)! - .edit, - ), - ), - PopupMenuItem( - value: 'return', - child: Text( - AppLocalizations.of( - widget.context)! - .return_txt, - ), - ), - const PopupMenuItem( - value: 'damage', - child: Text( - "Damage", - ), - ), - PopupMenuItem( - value: 'view', - child: Text( - AppLocalizations.of( - widget.context)! - .print_or_download, - ), - ), - PopupMenuItem( - value: 'delete', - child: Text( - AppLocalizations.of( - widget.context)! - .delete, - ), - ) - ]; - }, - onSelected: (String value) => - actionPopUpItemSelected(value, - filteredInvoices[position]), - ) - ], - ), - ), - ); - } else { - return Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - child: Container( - padding: const EdgeInsets.only( - left: 8, right: 8), - height: 56, - color: MyColors.containerBackColor, - child: Row( - children: [ - Expanded( - child: Text( - filteredInvoices[position] - .invoiceNumber - .toString(), - style: - MyColors.textStyleValue())), - Expanded( - child: Text( - filteredInvoices[position] - .invoiceReference - .toString(), - style: MyColors.textStyleValue(), - )), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - filteredInvoices[position] - .supplier! - .name ?? - "", - style: MyColors.textStyleValue(), - ), - )), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - DataTimeFormat.getFormatDate( - filteredInvoices[position] - .invoiceDate!), - style: MyColors.textStyleValue(), - ), - )), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - DataTimeFormat.getFormatDate( - filteredInvoices[position] - .invoiceDueDate!), - style: MyColors.textStyleValue(), - ), - ), - ), - Expanded( - child: Align( - alignment: Alignment.center, - child: Text( - filteredInvoices[position] - .totalAmount! - .toStringAsFixed(2), - style: MyColors.textStyleValue(), - ), - )), - Container( - width: 120, - child: Align( - alignment: Alignment.centerLeft, - child: Container( - decoration: BoxDecoration( - color: MyColors.fillColor, - borderRadius: - BorderRadius.circular(8), - ), - height: 38, - padding: const EdgeInsets.only( - left: 8, right: 8), - width: 120, - child: DropdownButton( - hint: const Text('Select'), - style: - MyColors.textStyleValue(), - isExpanded: true, - underline: - DropdownButtonHideUnderline( - child: Container()), - items: itemsList - .map((String items) { - return DropdownMenuItem( - value: items, - child: Text(items), - ); - }).toList(), - onChanged: (value) { - filteredInvoices[position] - .status = value!; - _update( - filteredInvoices[ - position] - .id!, - value.toString()); - }, - ), - ), - )), - const SizedBox( - width: 16, - ), - Expanded( - child: Container( - height: 38, - decoration: const BoxDecoration( - color: MyColors.greenColor10, - borderRadius: - BorderRadius.all( - Radius.circular( - 10.0))), - child: Padding( - padding: const EdgeInsets.all( - 10.0), - child: Center( - child: Text( - filteredInvoices[position] - .status!, - style: const TextStyle( - fontStyle: - FontStyle.normal, - fontFamily: - MyFonts.Bold, - fontSize: - MyFonts.normal, - fontWeight: - FontWeight.w700, - color: MyColors - .greenColor), - ), - ))), - ), - Padding( - padding: const EdgeInsets.all(4), - child: Align( - alignment: Alignment.centerRight, - child: Container( - width: 42, - height: 42, - decoration: BoxDecoration( - borderRadius: - const BorderRadius.all( - Radius.circular(4)), - color: - MyColors.backFillColor), - child: PopupMenuButton( - padding: EdgeInsets.zero, - icon: - const Icon(Icons.more_vert), - itemBuilder: (c) { - return [ - PopupMenuItem( - value: 'edit', - child: Text( - AppLocalizations.of( - widget.context)! - .edit, - ), - ), - PopupMenuItem( - value: 'return', - child: Text( - AppLocalizations.of( - widget.context)! - .return_txt, - ), - ), - const PopupMenuItem( - value: 'damage', - child: Text( - "Damage", - ), - ), - PopupMenuItem( - value: 'view', - child: Text( - AppLocalizations.of( - widget.context)! - .print_or_download, - ), - ), - PopupMenuItem( - value: 'delete', - child: Text( - AppLocalizations.of( - widget.context)! - .delete, - ), - ) - ]; - }, - onSelected: (String value) => - actionPopUpItemSelected( - value, - filteredInvoices[ - position]), - ), - ), - ), - ) - ], - ), - ), - ); - } - }, - itemCount: filteredInvoices.length, - ), - _isLoadMoreRunning == true - ? const Padding( - padding: EdgeInsets.only(top: 10, bottom: 10), - child: Center( - child: CircularProgressIndicator(), - ), - ) - : Container(), - ], - ), - ], - ), - ); - }); - } - - Future _delete(String id) async { - Map data = {'invoiceId': id}; - final response = - await viewModel.getResponsePatch(Constants.DELETE_NVOICE, data); - - if (response.success!) { - setState(() { - filteredInvoices.removeWhere((element) => element.id! == id); - }); - } - } - - Future _update(String id, String value) async { - Map data = {'invoiceId': id, 'status': value}; - final response = - await viewModel.getResponsePatch(Constants.UPDATE_INVOICE, data); - - if (response.success!) { - setState(() {}); - } - } - - void _loadMore() async { - if (_hasNextPage == true && - _isFirstLoadRunning == false && - _isLoadMoreRunning == false && - _controller.position.extentAfter < 300) { - setState(() { - _isLoadMoreRunning = true; // Display a progress indicator at the bottom - }); - - _page += 1; // Increase _page by 1 - - Map data = { - 'store_id': sharedPrefs.storeId, - 'page': _page, - 'invoice_status': widget.filter, - }; - await viewModel.getData(Constants.GET_INVOICE, data).then((response) { - final value = StoreInvoicesModel.fromJson(response); - if (value.success!) { - if (value.invoices!.isNotEmpty) { - if (value.invoices!.length < 10) { - _hasNextPage = false; - } - setState(() { - filteredInvoices.addAll(value.invoices!); - }); - } else { - setState(() { - _hasNextPage = false; - }); - } - } - }).onError((error, stackTrace) { - setState(() { - _hasNextPage = false; - }); - }).timeout(const Duration(seconds: 60)); - - setState(() { - _isLoadMoreRunning = false; - }); - } - } - - void _firstLoad() async { - setState(() { - _isFirstLoadRunning = true; - _hasNextPage = true; - }); - _page = 1; - - Map data = { - 'store_id': sharedPrefs.storeId, - 'page': _page, - 'invoice_status': widget.filter, - }; - - await viewModel.getData(Constants.GET_INVOICE, data).then((response) { - final value = StoreInvoicesModel.fromJson(response); - if (value.success!) { - filteredInvoices.clear(); - filteredInvoices.addAll(value.invoices!); - if (value.invoices!.length < 10) { - _hasNextPage = false; - } - setState(() { - _isFirstLoadRunning = false; - }); - } - }).onError((error, stackTrace) { - print(error.toString()); - setState(() { - _isFirstLoadRunning = false; - }); - }).timeout(const Duration(seconds: 60)); - } - - Future actionPopUpItemSelected( - String value, StoreInvoice invoice) async { - if (value == 'edit') { - widget.delegate.editOnNewInvoice(invoice); - } else if (value == 'return') { - final result = await Navigator.push( - widget.context, - MaterialPageRoute( - builder: (context) => ReturnInvoiceVC( - storeInvoice: invoice, - isReturn: true, - )), - ); - if (!mounted) return; - if (result) { - _firstLoad(); - } - } else if (value == 'damage') { - final result = await Navigator.push( - widget.context, - MaterialPageRoute( - builder: (context) => ReturnInvoiceVC( - storeInvoice: invoice, - isReturn: false, - )), - ); - if (!mounted) return; - if (result) { - _firstLoad(); - } - } else if (value == 'delete') { - final result = await showDialog( - barrierColor: Colors.black26, - context: context, - builder: (context) { - return const DeleteRecordPopUp(); - }, - ); - - if (!mounted) return; - if (result) { - _delete(invoice.id!); - } - } else { - widget.delegate.printDownloadInvoice(invoice); - } - } -} diff --git a/lib/application/views/transactions/TransactionPOSReturnVC.dart b/lib/application/views/transactions/TransactionPOSReturnVC.dart deleted file mode 100644 index d231ed2..0000000 --- a/lib/application/views/transactions/TransactionPOSReturnVC.dart +++ /dev/null @@ -1,467 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:wosull/application/ViewModel/InventoryViewModel.dart'; -import 'package:wosull/application/interfaces/DrawerWidgetSelect.dart'; -import 'package:wosull/application/localdb/SharedPrefs.dart'; -import 'package:wosull/application/model/cart/GetHoldOrderModel.dart'; -import 'package:wosull/application/model/converters/DataTimeFormat.dart'; -import 'package:wosull/application/theme/MyColors.dart'; -import 'package:wosull/application/utils/Constants.dart'; -import 'package:wosull/application/views/transactions/ViewPOSReturnVC.dart'; -import 'package:wosull/base/BaseStatefulState.dart'; -import 'package:wosull/widgets/EmptyDataWidget.dart'; - -class TransactionPOSReturnVC extends StatefulWidget { - TransactionCVS delegate; - BuildContext context; - TransactionPOSReturnVC( - {super.key, required this.delegate, required this.context}); - - @override - State createState() => _TransactionPOSReturnVCState(); -} - -class _TransactionPOSReturnVCState - extends BaseStatefulState { - late ScrollController _controller; - final viewModel = InventoryViewModel(); - bool isPortrait = false; - bool isLoading = true; - bool _isLoadMoreRunning = false; - - int _pageForPOS = 1; - bool __hasNextPageForPOS = true; - - List orders = []; - - @override - void initState() { - // TODO: implement initState - super.initState(); - _controller = ScrollController()..addListener(loadMore); - _firstLoad(); - } - - @override - Widget build(BuildContext context) { - return SingleChildScrollView( - controller: _controller, - child: Column( - children: [ - isLoading - ? const Center( - child: CircularProgressIndicator(), - ) - : orders.isEmpty - ? const EmptyDataWidget() - : Column( - children: [ - isPortrait - ? Container() - : Container( - padding: - const EdgeInsets.only(left: 8, right: 8), - height: 50, - color: MyColors.containerBackColor, - child: Row( - children: [ - Expanded( - child: Text( - AppLocalizations.of(widget.context)! - .order_number, - style: MyColors.textStyleHeading(), - )), - Expanded( - child: Text( - AppLocalizations.of(widget.context)! - .store_name, - style: MyColors.textStyleHeading(), - )), - Expanded( - child: Text( - AppLocalizations.of(widget.context)! - .status, - style: MyColors.textStyleHeading(), - )), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(widget.context)! - .created_on, - style: MyColors.textStyleHeading(), - ), - )), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of( - widget.context)! - .updated_on, - style: - MyColors.textStyleHeading(), - ))), - Container( - width: 56, - child: Text( - AppLocalizations.of(widget.context)! - .action, - style: MyColors.textStyleHeading(), - ), - ), - ], - ), - ), - ListView.builder( - padding: EdgeInsets.zero, - scrollDirection: Axis.vertical, - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - itemBuilder: (c, position) { - if (isPortrait) { - return Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - elevation: 2, - color: MyColors.white, - child: Container( - padding: const EdgeInsets.all(12), - child: Row( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Expanded( - child: Container( - padding: const EdgeInsets.only(top: 16), - child: Row( - mainAxisAlignment: - MainAxisAlignment.start, - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.start, - children: [ - Text( - AppLocalizations.of( - widget.context)! - .order_number, - style: MyColors - .textStyleHeading(), - ), - const SizedBox( - height: 8, - ), - Text( - AppLocalizations.of( - widget.context)! - .store_name, - style: MyColors - .textStyleHeading(), - ), - const SizedBox( - height: 8, - ), - Text( - AppLocalizations.of( - widget.context)! - .status, - style: MyColors - .textStyleHeading(), - ), - const SizedBox( - height: 8, - ), - Text( - AppLocalizations.of( - context)! - .created_on, - style: MyColors - .textStyleHeading()), - const SizedBox( - height: 8, - ), - Text( - AppLocalizations.of( - context)! - .updated_on, - style: MyColors - .textStyleHeading()), - ], - )), - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.end, - mainAxisAlignment: - MainAxisAlignment.start, - children: [ - Text( - orders[position] - .uniqueId! - .toString(), - style: - MyColors.textStyleValue(), - ), - const SizedBox( - height: 12, - ), - Text( - orders[position] - .storeId! - .name ?? - '', - style: - MyColors.textStyleValue(), - ), - const SizedBox( - height: 12, - ), - Text( - orders[position].status ?? '', - style: - MyColors.textStyleValue(), - ), - const SizedBox( - height: 12, - ), - Text( - DataTimeFormat - .getFormatDate(orders[ - position] - .createdAt ?? - ''), - style: MyColors - .textStyleValue()), - const SizedBox( - height: 12, - ), - Text( - DataTimeFormat - .getFormatDate(orders[ - position] - .updatedAt ?? - ''), - style: MyColors - .textStyleValue()), - ], - )), - ], - ), - )), - PopupMenuButton( - icon: const Icon(Icons.more_vert), - itemBuilder: (context) { - return [ - PopupMenuItem( - value: 'view', - child: Text( - AppLocalizations.of( - widget.context)! - .view, - ), - ), - ]; - }, - onSelected: (String value) => - actionPopUpItemSelected( - value, orders[position]), - ) - ], - ), - ), - ); - } else { - return Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - child: Container( - padding: - const EdgeInsets.only(left: 8, right: 8), - height: 56, - color: MyColors.containerBackColor, - child: Row( - children: [ - Expanded( - child: Text( - orders[position].uniqueId!.toString(), - style: MyColors.textStyleValue(), - )), - Expanded( - child: Text( - orders[position].storeId!.name!, - style: MyColors.textStyleValue(), - )), - Expanded( - child: Text( - orders[position].status!, - style: MyColors.textStyleValue(), - )), - Expanded( - child: Text( - DataTimeFormat.getFormatDate( - orders[position].createdAt!), - style: MyColors.textStyleValue(), - )), - Expanded( - child: Text( - DataTimeFormat.getFormatDate( - orders[position].updatedAt!), - style: MyColors.textStyleValue(), - )), - PopupMenuButton( - icon: const Icon(Icons.more_vert), - itemBuilder: (context) { - return [ - PopupMenuItem( - value: 'view', - child: Text( - AppLocalizations.of( - widget.context)! - .view, - ), - ) - ]; - }, - onSelected: (String value) => - actionPopUpItemSelected( - value, orders[position]), - ), - ], - ), - ), - ); - } - }, - itemCount: orders.length, - ) - ], - ), - _isLoadMoreRunning == true - ? const Padding( - padding: EdgeInsets.only(top: 10, bottom: 10), - child: Center( - child: CircularProgressIndicator(), - ), - ) - : Container(), - ], - ), - ); - } - - void actionPopUpItemSelected(String value, ReturnOrderModel order) { - if (value == 'view') { - showDialog( - barrierColor: Colors.black26, - context: context, - builder: (context) { - return ViewPOSReturnVC( - orderDetails: order.cart!.orderDetails!, - ); - }, - ); - } - } - - Future _delete(String id) async { - // { - // "store_id": "63e728cea1ed06ff5850a7d9", - // "order_id": "644b9d33e598f6ae9f99c713", - // "status": "return" - // } - // Map data = {'orderId': id}; - // - // await viewModel - // .getResponsePatch(Constants.DELETE_ORDER, data) - // .then((value) { - // if (value.success!) { - // showMessage('Deleted Successfully'); - // setState(() { - // posOrders.removeWhere((element) => element.id! == id); - // // posOrders.removeWhere((element) => element.id! == id); - // }); - // } - // }).onError((error, stackTrace) {}); - } - - void _firstLoad() async { - _pageForPOS = 1; - - Map data = { - 'store_id': sharedPrefs.storeId, - 'page': _pageForPOS, - }; - - await viewModel - .getData(Constants.GET_RETURN_ORDER_HISTORY, data) - .then((value) { - final response = GetReturnOrderModel.fromJson(value); - if (response.success!) { - orders.addAll(response.orderModel!); - // widget.delegate.posReturnCVS(orders); - } - if (response.orderModel!.length < 10) { - __hasNextPageForPOS = false; - } - - setState(() { - isLoading = false; - }); - }).onError((error, stackTrace) { - setState(() { - isLoading = false; - }); - print('getCashierOrderHistory ' + error.toString()); - }); - } - - void loadMore() async { - if (__hasNextPageForPOS == true && - isLoading == false && - _isLoadMoreRunning == false && - _controller.position.extentAfter < 300) { - setState(() { - _isLoadMoreRunning = true; // Display a progress indicator at the bottom - }); - - _pageForPOS += 1; // Increase _page by 1 - - Map data = { - 'store_id': sharedPrefs.storeId, - 'page': _pageForPOS, - }; - await viewModel - .getData(Constants.GET_CASHIER_ORDER_HISTORY, data) - .then((response) { - final value = GetReturnOrderModel.fromJson(response); - if (value.success!) { - if (value.orderModel!.isNotEmpty) { - if (value.orderModel!.length < 10) { - __hasNextPageForPOS = false; - } - setState(() { - orders.addAll(value.orderModel!); - //widget.delegate.posReturnCVS(orders); - _isLoadMoreRunning = false; - }); - } else { - setState(() { - __hasNextPageForPOS = false; - }); - } - } - }).onError((error, stackTrace) { - setState(() { - __hasNextPageForPOS = false; - }); - }).timeout(const Duration(seconds: 60)); - } - } -} diff --git a/lib/application/views/transactions/TransactionVC.dart b/lib/application/views/transactions/TransactionVC.dart index 5ad7b5f..6f24103 100644 --- a/lib/application/views/transactions/TransactionVC.dart +++ b/lib/application/views/transactions/TransactionVC.dart @@ -1,26 +1,26 @@ import 'package:dropdown_search/dropdown_search.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:wosull/application/ViewModel/InventoryViewModel.dart'; import 'package:wosull/application/interfaces/DrawerWidgetSelect.dart'; import 'package:wosull/application/model/invoice/StoreInvoice.dart'; +import 'package:wosull/application/model/reports/CashierOrder.dart'; +import 'package:wosull/application/repository/WosulRepository.dart'; import 'package:wosull/application/theme/MyColors.dart'; -import 'package:wosull/application/theme/MyFonts.dart'; -import 'package:wosull/application/views/salesandordermodule/views/AddInvoiceAndPrintVC.dart'; -import 'package:wosull/application/views/transactions/CashierTransactionsVC.dart'; -import 'package:wosull/application/views/transactions/EditOrderVC.dart'; -import 'package:wosull/application/views/transactions/ReturnTransactionInvoiceVC.dart'; -import 'package:wosull/application/views/transactions/TransactionDamageInvoiceVC.dart'; -import 'package:wosull/application/views/transactions/TransactionInvoicesVC.dart'; -import 'package:wosull/application/views/transactions/TransactionPOSReturnVC.dart'; -import 'package:wosull/application/views/transactions/TransactionQuotationVC.dart'; +import 'package:wosull/application/views/salesandordermodule/views/invoiceModule/views/AddInvoiceAndPrintVC.dart'; import 'package:wosull/application/views/transactions/return/ReturnPOS.dart'; +import 'package:wosull/application/views/transactions/views/TransactionCashierVC.dart'; +import 'package:wosull/application/views/transactions/views/TransactionInvoicesVC.dart'; +import 'package:wosull/application/views/transactions/views/TransactionQuotationVC.dart'; +import 'package:wosull/application/views/transactions/views/ViewCashierTransactionVC.dart'; import 'package:wosull/base/BaseStatefulState.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeDropDown.dart'; import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/widgets/DropdownItemBuilder.dart'; +import 'package:wosull/widgets/PageLimitDropDown.dart'; import '../../model/cart/GetHoldOrderModel.dart'; -import '../../model/reports/CashierOrderHistory.dart'; -import '../salesandordermodule/views/invoiceModule/NewInvoiceVC.dart'; +import '../salesandordermodule/views/invoiceModule/views/NewInvoiceVC.dart'; class TransactionVC extends StatefulWidget { const TransactionVC({Key? key}) : super(key: key); @@ -31,16 +31,17 @@ class TransactionVC extends StatefulWidget { class _TransactionVCState extends BaseStatefulState implements TransactionCVS { + int limit = 10; bool isPortrait = false; var items = [ 'Cashier', - 'POS Return & Damage', + // 'POS Return & Damage', 'Invoice', 'Quotation', - 'Return Invoice', - 'Damage Invoice' + //'Return Invoice', + //'Damage Invoice' ]; - final viewModel = InventoryViewModel(); + final viewModel = WosulRepository(); List cashierData = []; List invoiceData = []; List returnOrders = []; @@ -58,7 +59,7 @@ class _TransactionVCState extends BaseStatefulState return Scaffold( resizeToAvoidBottomInset: true, body: Container( - padding: const EdgeInsets.all(12), + padding: const EdgeInsets.all(8), color: MyColors.fillColor, child: Column( children: [ @@ -69,50 +70,25 @@ class _TransactionVCState extends BaseStatefulState AppLocalizations.of(context)!.transactions, style: ThemeText.textStylePageHeading, ), - const SizedBox( - width: 4, - ), + AppSpaces.horizontalSmall, SizedBox( - width: 180, - child: Material( - color: MyColors.white, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.only(left: 6, right: 0), - child: SizedBox( - height: 42, - width: double.infinity, - child: DropdownSearch( - selectedItem: selectedReport, - popupProps: const PopupProps.menu( - constraints: BoxConstraints(maxHeight: 200), - ), - items: items, - itemAsString: (String u) => u, - onChanged: (String? data) { - setState(() { - selectedReport = data!; - }); - }, - dropdownDecoratorProps: - const DropDownDecoratorProps( - baseStyle: TextStyle( - fontFamily: MyFonts.Medium, - fontSize: 11, - color: MyColors.textColorBlack), - dropdownSearchDecoration: InputDecoration( - border: InputBorder.none, hintText: 'Choose'), - ), - ), - ), - ), - ), + height: 38, + width: 100, + child: getDropdownSearch(), ), + AppSpaces.horizontalSmall, + Flexible( + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + PageLimitDropdown(onChange: (value) { + limit = int.parse(value!); + }) + ], + )) ], ), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, Expanded(child: getReportsType()) ], ), @@ -121,36 +97,22 @@ class _TransactionVCState extends BaseStatefulState Widget getReportsType() { if (selectedReport == items[0]) { - return CashierTransactionsVC( + return TransactionCashierVC( + limit: limit, + // isPortrait: isPortrait, context: context, - isOrder: false, delegate: this, ); } else if (selectedReport == items[1]) { - return TransactionPOSReturnVC( - context: context, - delegate: this, - ); - } else if (selectedReport == items[2]) { return TransactionInvoicesVC( + limit: limit, filter: 'All', context: context, delegate: this, ); - } else if (selectedReport == items[3]) { + } else if (selectedReport == items[2]) { return TransactionQuotationVC( - context: context, - delegate: this, - ); - } else if (selectedReport == items[4]) { - return ReturnTransactionInvoiceVC( - filter: 'Return', - context: context, - delegate: this, - ); - } else if (selectedReport == items[5]) { - return TransactionDamageInvoiceVC( - filter: 'Damage', + limit: limit, context: context, delegate: this, ); @@ -207,7 +169,7 @@ class _TransactionVCState extends BaseStatefulState Future editCashier(CashierOrder data) async { final result = await Navigator.push( context, - MaterialPageRoute(builder: (context) => EditOrderVC(cashierOrder: data)), + MaterialPageRoute(builder: (context) => ViewCashierTransactionVC(data)), ); if (!mounted) return; @@ -241,4 +203,28 @@ class _TransactionVCState extends BaseStatefulState setState(() {}); } } + + getDropdownSearch() { + return DropdownSearch( + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + selectedItem: selectedReport, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item); + }, + fit: FlexFit.loose, + menuProps: ThemeDropDown.menuProps, + constraints: const BoxConstraints(maxHeight: 200), + ), + items: items, + itemAsString: (String u) => u, + onChanged: (String? data) { + setState(() { + selectedReport = data!; + }); + }, + dropdownDecoratorProps: + MyColors.dropDownStyle(hint: 'Choose', fillColor: MyColors.white), + ); + } } diff --git a/lib/application/views/transactions/ViewPOSReturnVC.dart b/lib/application/views/transactions/ViewPOSReturnVC.dart deleted file mode 100644 index 624f830..0000000 --- a/lib/application/views/transactions/ViewPOSReturnVC.dart +++ /dev/null @@ -1,497 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:wosull/application/model/createOrder/CashierCart.dart'; -import 'package:wosull/application/model/store/StoreItemsResponse.dart'; -import 'package:wosull/application/theme/MyColors.dart'; -import 'package:wosull/widgets/DialogHeader.dart'; - -class ViewPOSReturnVC extends StatefulWidget { - List? orderDetails; - - ViewPOSReturnVC({super.key, required this.orderDetails}); - - @override - State createState() => _ViewPOSReturnVCState(); -} - -class _ViewPOSReturnVCState extends State { - bool isPortrait = true; - - @override - Widget build(BuildContext context) { - return Dialog( - elevation: 0, - backgroundColor: const Color(0xffffffff), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(15.0), - ), - child: OrientationBuilder(builder: (c, orientation) { - isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; - - return SingleChildScrollView( - child: SizedBox( - width: !isPortrait - ? MediaQuery.of(context).size.width / 1.2 - : double.infinity, - child: Column( - crossAxisAlignment: CrossAxisAlignment.end, - mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - DialogHeader(title: 'Order Details'), - const SizedBox( - height: 8, - ), - Container( - padding: const EdgeInsets.fromLTRB(8, 8, 8, 16), - child: Column( - children: [ - Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius.all(Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all( - width: 1, color: MyColors.fillColorGray2), - color: MyColors.fillColor, - ), - height: 48, - child: Row( - children: [ - Expanded( - child: Container( - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: Text( - 'Name', - style: MyColors.textStyleHeading(), - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.only(left: 8), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: Text( - 'Item Note', - style: MyColors.textStyleHeading(), - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.only(left: 8), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: Text( - 'Quantity', - style: MyColors.textStyleHeading(), - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.only(left: 8), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: Text( - 'Total Cost Price', - style: MyColors.textStyleHeading(), - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.only(left: 8), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: Text( - 'Total Price', - style: MyColors.textStyleHeading(), - ), - ), - )), - Container( - width: 84, - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: Text( - 'Total Amount', - style: MyColors.textStyleHeading(), - ), - ), - ), - ], - ), - ), - ListView.builder( - padding: EdgeInsets.zero, - scrollDirection: Axis.vertical, - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - itemBuilder: (context, position) { - return ListView.builder( - padding: EdgeInsets.zero, - scrollDirection: Axis.vertical, - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - itemBuilder: (context, i) { - var item = - widget.orderDetails![position].items![i]; - - return Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all( - width: 1, color: MyColors.fillColorGray2), - color: MyColors.white, - ), - height: 48, - child: Row( - children: [ - Expanded( - child: Container( - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - height: 48, - padding: const EdgeInsets.all(4), - child: Container( - decoration: BoxDecoration( - border: Border.all( - color: Colors.transparent, - width: 1, - ), - color: MyColors.white, - borderRadius: - BorderRadius.circular(8.0), - ), - child: Center( - child: Text( - item.name, - style: MyColors.textStyleValue(), - ), - ), - ), - ), - ), - Expanded( - child: Container( - padding: const EdgeInsets.all(4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: Text( - getItemNote(item), - style: MyColors.textStyleValue(), - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.all(4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: Text( - item.quantity.toString(), - style: MyColors.textStyleValue(), - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.all(4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: Text( - (item.price).toStringAsFixed(2), - style: MyColors.textStyleValue(), - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.all(4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: Text( - (item.price * item.quantity) - .toStringAsFixed(2), - style: MyColors.textStyleValue(), - ), - ), - )), - Container( - width: 84, - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: Text( - '', - style: MyColors.textStyleValue(), - ), - ), - ), - ], - ), - ); - }, - itemCount: - widget.orderDetails![position].items!.length, - ); - }, - itemCount: widget.orderDetails!.length, - ), - Container( - margin: const EdgeInsets.fromLTRB(0, 0, 0, 8), - decoration: BoxDecoration( - borderRadius: const BorderRadius.all(Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all( - width: 1, color: MyColors.fillColorGray2), - color: Colors.white, - ), - height: 48, - child: Row( - children: [ - Expanded( - child: Container( - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: Text( - '', - style: MyColors.textStyleValue(), - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.only(left: 8), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: Text( - '', - style: MyColors.textStyleValue(), - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.only(left: 8), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: Text( - '', - style: MyColors.textStyleValue(), - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.only(left: 8), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: Text( - '', - style: MyColors.textStyleValue(), - ), - ), - )), - Expanded( - child: Container( - padding: const EdgeInsets.only(left: 8), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: Text( - '', - style: MyColors.textStyleValue(), - ), - ), - )), - Container( - width: 84, - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: Text( - getItemsPriceWithModifier(), - style: MyColors.textStyleHeading(), - ), - ), - ), - ], - ), - ), - ], - ), - ) - ], - ), - ), - ); - }), - ); - } - - String getItemsPriceWithModifier() { - double price = 0.0; - for (var order in widget.orderDetails!) { - for (var item in order.items!) { - price += (item.quantity * item.price); - if (item.selectedModifiers!.isNotEmpty) { - for (var modi in item.selectedModifiers!) { - price += modi.price; - } - } - } - } - return price.toStringAsFixed(2); - } - - String getItemsPriceOnly() { - double price = 0.0; - for (var order in widget.orderDetails!) { - for (var item in order.items!) { - price += (item.quantity * item.price); - } - } - - return price.toStringAsFixed(2); - } - - String getItemNote(StoreItems item) { - var text = ""; - for (var note in item.noteForItem!) { - if (text.isEmpty) { - text = note; - } else { - text = "$text,$note"; - } - } - return text; - } -} diff --git a/lib/application/views/transactions/return/ReturnPOS.dart b/lib/application/views/transactions/return/ReturnPOS.dart index f80a007..de8244c 100644 --- a/lib/application/views/transactions/return/ReturnPOS.dart +++ b/lib/application/views/transactions/return/ReturnPOS.dart @@ -1,20 +1,27 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:provider/provider.dart'; -import 'package:wosull/application/model/reports/CashierOrderHistory.dart'; +import 'package:wosull/application/model/reports/CashierOrder.dart'; import 'package:wosull/application/model/store/StoreItemsResponse.dart'; import 'package:wosull/application/model/transaction/states/ReturnOrderState.dart'; import 'package:wosull/application/theme/MyColors.dart'; -import 'package:wosull/application/theme/MyFonts.dart'; +import 'package:wosull/application/utils/AppLoader.dart'; import 'package:wosull/application/views/transactions/return/ReturnReasonPopUp.dart'; import 'package:wosull/application/views/transactions/viewmodels/ReturnPOSOrderVM.dart'; import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/widgets/BorderContainer.dart'; +import 'package:wosull/widgets/ChildContainer.dart'; +import 'package:wosull/widgets/CustomAppBar.dart'; import 'package:wosull/widgets/CustomCheckBox.dart'; import 'package:wosull/widgets/CustomSimpleButton.dart'; +import 'package:wosull/widgets/CustomTextAddProduct.dart'; import 'package:wosull/widgets/CustomTextFieldForm.dart'; +import 'package:wosull/widgets/HeadingContainer.dart'; import 'package:wosull/widgets/HeadingText.dart'; +import 'package:wosull/widgets/PortraitContainer.dart'; import 'package:wosull/widgets/ValueText.dart'; +import 'package:wosull/widgets/WrapHeightContainer.dart'; class ReturnPOS extends StatefulWidget { bool isReturn = false; @@ -29,6 +36,12 @@ class ReturnPOS extends StatefulWidget { class _ReturnPOSState extends State { var viewModel = ReturnPOSOrderVM(); + @override + void initState() { + context.read().setOrder(widget.cashierOrder); + super.initState(); + } + @override void dispose() { viewModel.disposeData(); @@ -38,26 +51,11 @@ class _ReturnPOSState extends State { @override Widget build(BuildContext context) { viewModel = context.watch(); - //viewModel.getOrder('id'); - viewModel.setOrder(widget.cashierOrder); - return Scaffold( backgroundColor: MyColors.fillColor, resizeToAvoidBottomInset: true, - appBar: AppBar( - leading: BackButton( - color: Colors.black, - onPressed: () { - Navigator.pop(context); - }, // <-- SEE HERE - ), - centerTitle: true, - title: Text( - widget.isReturn ? "Return POS" : "Damage POS", - style: ThemeText.textStylePopUpHeading, - ), - backgroundColor: MyColors.white, - elevation: 5, + appBar: CustomAppBar( + heading: widget.isReturn ? "Return POS" : "Damage POS", ), body: OrientationBuilder(builder: (c, orientation) { viewModel.isPortrait = @@ -75,6 +73,7 @@ class _ReturnPOSState extends State { ), AppSpaces.verticalMedium, Card( + elevation: 5, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(4.0), ), @@ -87,136 +86,43 @@ class _ReturnPOSState extends State { Text( AppLocalizations.of(context)! .search_and_add_products, - style: ThemeText.textStylePopUpHeading, + style: ThemeText.textStylePageHeading, ), AppSpaces.verticalMedium, viewModel.isPortrait ? Container() - : Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all( - width: 1, - color: MyColors.fillColorGray2), - color: MyColors.containerBackColor, - ), - height: 48, + : BorderContainer( child: Row( children: [ - Container( - padding: const EdgeInsets.only(left: 4), + HeadingContainer( + heading: AppLocalizations.of(context)! + .return_txt, width: 84, - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Align( - alignment: Alignment.centerLeft, - child: HeadingText( - AppLocalizations.of(context)! - .return_txt), - ), ), Expanded( - child: Container( - padding: const EdgeInsets.only( - left: 4, right: 4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Align( - alignment: Alignment.centerLeft, - child: HeadingText( - AppLocalizations.of(context)! - .name_or_barcode), - ), - )), + child: HeadingContainer( + heading: + AppLocalizations.of(context)! + .name_or_barcode)), Expanded( - child: Container( - padding: const EdgeInsets.only(left: 8), - height: 48, - width: 100, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Align( - alignment: Alignment.centerLeft, - child: HeadingText( - AppLocalizations.of(context)! - .description), - ), + child: HeadingContainer( + heading: AppLocalizations.of(context)! + .description, )), Expanded( - child: Container( - padding: const EdgeInsets.only(left: 4), - height: 48, - width: 60, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Align( - alignment: Alignment.centerLeft, - child: HeadingText( - AppLocalizations.of(context)! - .quantity), - ), - )), + child: HeadingContainer( + heading: + AppLocalizations.of(context)! + .quantity)), Expanded( - child: Container( - padding: const EdgeInsets.only(left: 4), - height: 48, - width: 60, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Align( - alignment: Alignment.centerLeft, - child: HeadingText( - AppLocalizations.of(context)! - .unit_price), - ), + child: HeadingContainer( + heading: AppLocalizations.of(context)! + .unit_price, )), - Container( - padding: const EdgeInsets.only(left: 4), + HeadingContainer( width: 84, - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Align( - alignment: Alignment.centerLeft, - child: HeadingText( - AppLocalizations.of(context)! - .amount), - ), + heading: AppLocalizations.of(context)! + .amount, ), ], ), @@ -237,21 +143,45 @@ class _ReturnPOSState extends State { itemBuilder: (c, child) { var item = order.items![child]; if (viewModel.isPortrait) { - return Container( - padding: - const EdgeInsets.fromLTRB(8, 0, 0, 8), - color: MyColors.containerBackColor, + return WrapHeightContainer( child: Row( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ + Container( + width: 44, + height: 59, + decoration: const BoxDecoration( + border: Border( + bottom: BorderSide( + width: 1.0, + color: MyColors + .fillColorGray2), + )), + child: Align( + alignment: Alignment.center, + child: CustomCheckBox( + value: + item.isCheckedForReturn, + onChange: (bool? value) { + viewModel.onCheck(parent, + child, value, item); + }, + ), + )), Expanded( flex: 2, child: Container( - padding: const EdgeInsets.only( - top: 8), + decoration: const BoxDecoration( + border: Border( + left: BorderSide( + width: 1.0, + color: MyColors + .fillColorGray2), + ), + ), child: Row( crossAxisAlignment: CrossAxisAlignment.start, @@ -267,28 +197,9 @@ class _ReturnPOSState extends State { MainAxisAlignment .start, children: [ - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - left: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), + PortraitContainer( + width: + double.infinity, child: Align( alignment: Alignment .centerLeft, @@ -298,32 +209,9 @@ class _ReturnPOSState extends State { .name_or_barcode), ), ), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - left: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - bottom: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), + PortraitContainer( + width: + double.infinity, child: Align( alignment: Alignment .centerLeft, @@ -333,28 +221,9 @@ class _ReturnPOSState extends State { .description), ), ), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - left: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), + PortraitContainer( + width: + double.infinity, child: Align( alignment: Alignment .centerLeft, @@ -365,28 +234,9 @@ class _ReturnPOSState extends State { ), ), ), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - left: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), + PortraitContainer( + width: + double.infinity, child: Align( alignment: Alignment .centerLeft, @@ -396,32 +246,9 @@ class _ReturnPOSState extends State { .unit_price), ), ), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - left: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - bottom: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), + PortraitContainer( + width: + double.infinity, child: Align( alignment: Alignment .centerLeft, @@ -436,139 +263,61 @@ class _ReturnPOSState extends State { )), Expanded( child: Column( - crossAxisAlignment: - CrossAxisAlignment - .start, - mainAxisAlignment: - MainAxisAlignment - .start, children: [ - Container( - height: 48, - padding: - const EdgeInsets - .only( - left: 8), - decoration: - BoxDecoration( - border: Border.all( - color: Colors - .transparent, - width: 1, - ), - color: MyColors - .fillColor2, - borderRadius: - BorderRadius - .circular( - 8.0), - ), + PortraitContainer( + width: + double.infinity, child: Center( child: Align( alignment: Alignment .centerLeft, - child: ValueText( - item.name), + child: + CustomTextAddProduct( + item.name), ), ), ), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: ValueText(item - .description), + PortraitContainer( + width: + double.infinity, + child: Align( + alignment: Alignment + .centerLeft, + child: CustomTextAddProduct( + item.description), ), ), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), + PortraitContainer( + width: + double.infinity, child: getQuantityWidget( parent, child, item), ), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: ValueText( + PortraitContainer( + width: + double.infinity, + child: Align( + alignment: Alignment + .centerLeft, + child: + CustomTextAddProduct( item.price .toStringAsFixed( 2), ), ), ), - Container( - padding: - const EdgeInsets - .all(4), - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - bottom: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: ValueText( + PortraitContainer( + width: + double.infinity, + child: Align( + alignment: Alignment + .centerLeft, + child: + CustomTextAddProduct( viewModel .getSingleItemPrice( item), @@ -580,20 +329,6 @@ class _ReturnPOSState extends State { ], ), )), - SizedBox( - width: 44, - height: 48, - child: Align( - alignment: Alignment.centerLeft, - child: CustomCheckBox( - value: - item.isCheckedForReturn, - onChange: (bool? value) { - viewModel.onCheck(parent, - child, value, item); - }, - ), - )) ], ), ); @@ -611,19 +346,8 @@ class _ReturnPOSState extends State { ), child: Row( children: [ - Container( - padding: - const EdgeInsets.only(left: 4), + ChildContainer( width: 84, - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), child: Align( alignment: Alignment.centerLeft, child: CustomCheckBox( @@ -636,129 +360,36 @@ class _ReturnPOSState extends State { ), ), Expanded( - child: Container( - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - height: 48, - padding: const EdgeInsets.all(4), - child: Container( - padding: const EdgeInsets.only( - left: 4), - decoration: BoxDecoration( - border: Border.all( - color: Colors.transparent, - width: 1, - ), - color: MyColors.fillColor2, - borderRadius: - BorderRadius.circular(8.0), - ), - child: Expanded( - child: Align( - alignment: - Alignment.centerLeft, - child: ValueText(item.name), - ), - ), + child: ChildContainer( + child: Center( + child: ValueText(item.name), ), )), Expanded( - child: Container( - padding: const EdgeInsets.all(4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Container( - padding: const EdgeInsets.only( - left: 4), - decoration: BoxDecoration( - borderRadius: const BorderRadius - .all( - Radius.circular( - 4.0) // <--- border radius here - ), - color: MyColors.disableColor), - child: Align( - alignment: Alignment.centerLeft, - child: ValueText( - item.description, - ), + child: ChildContainer( + child: Center( + child: ValueText( + item.description, ), ), )), Expanded( - child: Container( - padding: const EdgeInsets.all(4), - height: 48, + child: ChildContainer( width: 60, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), child: getQuantityWidget( parent, child, item), )), Expanded( - child: Container( - padding: const EdgeInsets.all(4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Container( - padding: const EdgeInsets.only( - left: 4), - decoration: BoxDecoration( - borderRadius: const BorderRadius - .all( - Radius.circular( - 4.0) // <--- border radius here - ), - color: MyColors.disableColor), - child: Align( - alignment: Alignment.centerLeft, - child: ValueText( - item.price.toStringAsFixed(2), - ), + child: ChildContainer( + child: Center( + child: ValueText( + item.price.toStringAsFixed(2), ), ), )), - Container( - padding: - const EdgeInsets.only(left: 4), + ChildContainer( width: 84, - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: Alignment.centerLeft, + child: Center( child: ValueText( viewModel .getSingleItemPrice(item), @@ -773,161 +404,62 @@ class _ReturnPOSState extends State { itemCount: order.items!.length, ); }, - itemCount: - widget.cashierOrder.cart!.orderDetails!.length, + itemCount: widget + .cashierOrder.cart?.orderDetails?.length ?? + 0, ), viewModel.isPortrait - ? Container( - margin: const EdgeInsets.fromLTRB(8, 0, 0, 8), - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all( - width: 1, - color: MyColors.fillColorGray2), - color: Colors.white, - ), - height: 48, + ? BorderContainer( + backgroundColor: MyColors.white, child: Row( children: [ + SizedBox( + width: 44, + height: 44, + child: HeadingContainer( + heading: '', + )), Expanded( - child: Container( - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: Text( - 'Grand Total', - style: MyColors.textStyleValue(), - ), - ), + child: HeadingContainer( + heading: 'Grand Total', )), Expanded( - child: Container( - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: Text( + child: HeadingContainer( + heading: viewModel.getTotalProductsPrice(), - style: MyColors.textStyleValue(), - ), - ), )), ], ), ) - : Container( - margin: const EdgeInsets.fromLTRB(0, 0, 0, 8), - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all( - width: 1, - color: MyColors.fillColorGray2), - color: Colors.white, - ), - height: 48, + : BorderContainer( + backgroundColor: MyColors.white, child: Row( children: [ + HeadingContainer( + width: 84, + heading: '', + ), Expanded( - child: Container( - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: Text( - '', - style: MyColors.textStyleValue(), - ), - ), + child: HeadingContainer( + heading: '', )), Expanded( - child: Container( - padding: const EdgeInsets.only(left: 8), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: Text( - '', - style: MyColors.textStyleValue(), - ), - ), + child: HeadingContainer( + heading: '', )), Expanded( - child: Container( - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: Text( - '', - style: MyColors.textStyleValue(), - ), - ), + child: HeadingContainer( + heading: '', )), Expanded( - child: Container( - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: Text( - 'Grand Total', - style: MyColors.textStyleValue(), - ), - ), + child: ChildContainer( + child: HeadingText('Grand Total'), )), - Container( + ChildContainer( width: 84, - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), child: Center( - child: Text( - viewModel.getTotalProductsPrice(), - style: MyColors.textStyleHeading(), - ), + child: HeadingText(viewModel + .getTotalProductsPrice()), ), ), ], @@ -936,7 +468,9 @@ class _ReturnPOSState extends State { AppSpaces.verticalLarge, Row( children: [ - const Expanded(child: Text('')), + viewModel.isPortrait + ? Container() + : const Expanded(child: Text('')), Expanded( child: Row( children: [ @@ -945,7 +479,7 @@ class _ReturnPOSState extends State { alignment: Alignment.centerRight, child: Text( AppLocalizations.of(context)!.discount, - style: ThemeText.textStyleHeading, + style: ThemeText.textStyleAmountHeading, ), )), AppSpaces.horizontalMedium, @@ -955,7 +489,7 @@ class _ReturnPOSState extends State { child: Text( widget.cashierOrder.totalDiscount! .toStringAsFixed(2), - style: ThemeText.textStyleHeading, + style: ThemeText.textStyleAmountValue, ), )), ], @@ -965,7 +499,9 @@ class _ReturnPOSState extends State { AppSpaces.verticalSmall, Row( children: [ - const Expanded(child: Text('')), + viewModel.isPortrait + ? Container() + : const Expanded(child: Text('')), Expanded( child: Row( children: [ @@ -975,7 +511,8 @@ class _ReturnPOSState extends State { child: Text( AppLocalizations.of(context)! .total_amount, - style: ThemeText.textStyleHeading, + style: + ThemeText.textStyleAmountHeadingBlack, ), )), AppSpaces.horizontalMedium, @@ -984,11 +521,8 @@ class _ReturnPOSState extends State { alignment: Alignment.centerRight, child: Text( viewModel.getTotalCartPrice(), - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.bold, - fontSize: 13, - color: MyColors.black), + style: + ThemeText.textStyleAmountValueBlack, ), )), ], @@ -1001,53 +535,28 @@ class _ReturnPOSState extends State { ), AppSpaces.verticalLarge, viewModel.isLoading - ? const Row( - crossAxisAlignment: CrossAxisAlignment.end, - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Center( - child: CircularProgressIndicator(), + ? AppLoader() + : viewModel.isPortrait + ? Column( + children: [ + getReturnWholeOrderButton(), + getParitialOrderButton() + ], ) - ], - ) - : Row( - crossAxisAlignment: CrossAxisAlignment.end, - mainAxisAlignment: MainAxisAlignment.end, - children: [ - SizedBox( - width: 180, - child: CustomSimpleButton( - textColor: MyColors.white, - backGroundColor: MyColors.blueThemeColor, - height: 38, - onPressed: () { - viewModel.setOperation( - ReturnOrderState.returnWhole); - returnWholeOrder(); - }, - heading: widget.isReturn - ? 'Return whole order' - : "Damage whole order", - )), - AppSpaces.horizontalMedium, - SizedBox( - width: 180, - child: CustomSimpleButton( - textColor: MyColors.white, - backGroundColor: MyColors.blueThemeColor, - height: 38, - onPressed: () async { - await viewModel.checkReturn(); - print('herer'); - checkState(); - }, - heading: widget.isReturn - ? 'Return Only Items' - : "Damage Only Items", - ), + : Row( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + SizedBox( + width: 180, + child: getReturnWholeOrderButton()), + AppSpaces.horizontalMedium, + SizedBox( + width: 180, + child: getParitialOrderButton(), + ) + ], ) - ], - ) ], ), ), @@ -1061,9 +570,7 @@ class _ReturnPOSState extends State { initialValue: item.quantity.toString(), keyboardType: TextInputType.number, onChanged: (value) { - setState(() { - viewModel.setQuantity(parent, child, value); - }); + viewModel.setQuantity(parent, child, value); }, hintText: '', ), @@ -1100,4 +607,30 @@ class _ReturnPOSState extends State { returnWholeOrder(); } } + + getReturnWholeOrderButton() { + return CustomSimpleButton( + textColor: MyColors.white, + backGroundColor: MyColors.blueThemeColor, + height: 38, + onPressed: () { + viewModel.setOperation(ReturnOrderState.returnWhole); + returnWholeOrder(); + }, + heading: widget.isReturn ? 'Return whole order' : "Damage whole order", + ); + } + + getParitialOrderButton() { + return CustomSimpleButton( + textColor: MyColors.white, + backGroundColor: MyColors.blueThemeColor, + height: 38, + onPressed: () async { + await viewModel.checkReturn(); + checkState(); + }, + heading: widget.isReturn ? 'Return Only Items' : "Damage Only Items", + ); + } } diff --git a/lib/application/views/transactions/return/ReturnReasonPopUp.dart b/lib/application/views/transactions/return/ReturnReasonPopUp.dart index 5ca4990..6fc6cba 100644 --- a/lib/application/views/transactions/return/ReturnReasonPopUp.dart +++ b/lib/application/views/transactions/return/ReturnReasonPopUp.dart @@ -3,9 +3,11 @@ import 'package:flutter/material.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/utils/Constants.dart'; import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeDropDown.dart'; import 'package:wosull/helpers/Utils.dart'; import 'package:wosull/widgets/CustomSimpleButton.dart'; import 'package:wosull/widgets/DialogHeader.dart'; +import 'package:wosull/widgets/DropdownItemBuilder.dart'; import 'package:wosull/widgets/MandatoryTitleText.dart'; class ReturnReasonPopUp extends StatefulWidget { @@ -37,7 +39,7 @@ class _ReturnReasonPopUpState extends State { elevation: 0, backgroundColor: const Color(0xffffffff), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(15.0), + borderRadius: BorderRadius.circular(8.0), ), child: OrientationBuilder(builder: (c, orientation) { return SingleChildScrollView( @@ -52,7 +54,7 @@ class _ReturnReasonPopUpState extends State { crossAxisAlignment: CrossAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end, children: [ - DialogHeader(title: 'Please Choose A Reason For Return'), + DialogHeader(title: 'Choose A Reason For Return'), Padding( padding: const EdgeInsets.all(12), child: Column( @@ -93,57 +95,50 @@ class _ReturnReasonPopUpState extends State { } Widget paymentMethod() { - return Material( - color: MyColors.backFillColor, - borderRadius: BorderRadius.circular(8), - child: SizedBox( - width: double.infinity, - child: Padding( - padding: const EdgeInsets.only(left: 8, right: 8), - child: DropdownSearch( - popupProps: const PopupProps.menu( - constraints: BoxConstraints(maxHeight: 80)), - items: Constants.paymentMethod, - itemAsString: (String u) => u, - onChanged: (String? data) { - if (data == null) { - selectedPaymentMethod = ''; - } else { - selectedPaymentMethod = data; - } - }, - dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), - ), - ), - ), + return DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item); + }, + constraints: BoxConstraints(maxHeight: 250)), + items: Constants.paymentMethod, + itemAsString: (String u) => u, + onChanged: (String? data) { + if (data == null) { + selectedPaymentMethod = ''; + } else { + selectedPaymentMethod = data; + } + }, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), ); } Widget replaceReason() { - return Material( - color: MyColors.backFillColor, - borderRadius: BorderRadius.circular(8), - child: SizedBox( - width: double.infinity, - child: Padding( - padding: const EdgeInsets.only(left: 8, right: 8), - child: DropdownSearch( - popupProps: const PopupProps.menu( - constraints: BoxConstraints(maxHeight: 150)), - items: Constants.returnProductReason, - itemAsString: (String u) => u, - onChanged: (String? data) { - if (data == null) { - selectedReturnReason = ''; - } else { - selectedReturnReason = data; - } - }, - dropdownDecoratorProps: - MyColors.dropDownStyle(hint: 'Select Reason'), - ), - ), - ), + return DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: BoxConstraints(maxHeight: 250)), + items: Constants.returnProductReason, + itemAsString: (String u) => u, + onChanged: (String? data) { + if (data == null) { + selectedReturnReason = ''; + } else { + selectedReturnReason = data; + } + }, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Select Reason'), ); } } diff --git a/lib/application/views/transactions/viewmodels/CashierTransactionViewModel.dart b/lib/application/views/transactions/viewmodels/CashierTransactionViewModel.dart new file mode 100644 index 0000000..10276a4 --- /dev/null +++ b/lib/application/views/transactions/viewmodels/CashierTransactionViewModel.dart @@ -0,0 +1,102 @@ +import 'package:flutter/cupertino.dart'; +import 'package:wosull/application/enum/DataState.dart'; +import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/application/model/reports/CashierOrder.dart'; +import 'package:wosull/application/model/reports/CashierOrderHistory.dart'; +import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/utils/Constants.dart'; + +class CashierTransactionViewModel with ChangeNotifier { + int _currentPageNumber = 1; + String filterValue = 'all'; + DataState _dataState = DataState.uninitialized; + int limit = 10; + bool _didLastLoad = false; + bool _isLoading = false; + + bool get isLoading => _isLoading; + + DataState get dataState => _dataState; + List _dataList = []; + List _filteredList = []; + + List get dataList => _dataList; + + List get filteredList => _filteredList; + + void setDataState(DataState state) { + _dataState = state; + } + + fetch({bool isRefresh = false, String filter = 'all', int limit = 10}) async { + this.limit = limit; + _isLoading = true; + filterValue = filter; + if (!isRefresh) { + _dataState = (_dataState == DataState.uninitialized) + ? DataState.initialFetching + : DataState.moreFetching; + } else { + _didLastLoad = false; + _currentPageNumber = 1; + _dataState = DataState.refreshing; + } + notifyListeners(); + Map data = { + 'store_id': sharedPrefs.storeId, + 'page': _currentPageNumber, + 'limit': limit, + 'order_status': filter + }; + try { + if (_didLastLoad) { + _dataState = DataState.noMoreData; + } else { + await APIManager() + .fetchData(Constants.GET_CASHIER_ORDER_HISTORY, data) + .then((result) { + final value = CashierOrderHistory.fromJson(result); + if (_dataState == DataState.refreshing) { + _filteredList.clear(); + _dataList.clear(); + } + if (value.success) { + _filteredList.addAll(value.topOrders); + _dataList.addAll(value.topOrders); + if (value.topOrders.length < this.limit) { + _didLastLoad = true; + } else { + _didLastLoad = false; + } + } + _dataState = DataState.fetched; + _currentPageNumber += 1; + }).onError((error, stackTrace) { + _dataState = DataState.error; + }); + } + _isLoading = false; + notifyListeners(); + } catch (e) { + _isLoading = false; + _dataState = DataState.error; + notifyListeners(); + } + } + + Future deleteOrder(String? id) async { + Map data = { + 'orderId': id!, + }; + + await APIManager() + .getResponsePatch(Constants.DELETE_ORDER, data) + .then((value) { + if (value.success) { + _filteredList.removeWhere((element) => element.id == id); + _dataList.removeWhere((element) => element.id == id); + notifyListeners(); + } + }).onError((error, stackTrace) {}); + } +} diff --git a/lib/application/views/transactions/viewmodels/ReturnPOSOrderVM.dart b/lib/application/views/transactions/viewmodels/ReturnPOSOrderVM.dart index 02050aa..b1c5baa 100644 --- a/lib/application/views/transactions/viewmodels/ReturnPOSOrderVM.dart +++ b/lib/application/views/transactions/viewmodels/ReturnPOSOrderVM.dart @@ -5,7 +5,8 @@ import 'package:flutter/cupertino.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; import 'package:wosull/application/model/SimpleResponsModel.dart'; import 'package:wosull/application/model/createOrder/CashierCart.dart'; -import 'package:wosull/application/model/reports/CashierOrderHistory.dart'; +import 'package:wosull/application/model/reports/CashierOrder.dart'; +import 'package:wosull/application/model/reports/CashierSingleOrderHistory.dart'; import 'package:wosull/application/model/store/StoreItemsResponse.dart'; import 'package:wosull/application/model/transaction/cashier/ReturnOrder.dart'; import 'package:wosull/application/model/transaction/cashier/Total.dart'; @@ -75,7 +76,7 @@ class ReturnPOSOrderVM with ChangeNotifier { String getSingleItemPrice(StoreItems item) { double price = 0.0; - price = item.price * item.quantity; + price = item.price * item.quantity!; return price.toStringAsFixed(2); } @@ -83,7 +84,7 @@ class ReturnPOSOrderVM with ChangeNotifier { var price = 0.0; for (var product in cashierOrder!.cart!.orderDetails!) { for (var item in product.items!) { - price += item.quantity * item.price; + price += item.quantity! * item.price; } } // price = price - widget.cashierOrder.totalDiscount!; @@ -104,6 +105,7 @@ class ReturnPOSOrderVM with ChangeNotifier { cashierOrder!.cart!.orderDetails![parent].items![child].quantity = int.parse(value); } + notifyListeners(); } Future returnWholeOrder(result, bool isReturn) async { @@ -158,12 +160,12 @@ class ReturnPOSOrderVM with ChangeNotifier { returnOrder.returnOrderDetails!.add(details); returnOrder.returnOrderDetails!.first.productId = item.productId; returnOrder.returnOrderDetails!.first.totalItemPrice = - item.quantity * item.price; - totalPrice = totalPrice + (item.quantity * item.price); + item.quantity! * item.price; + totalPrice = totalPrice + (item.quantity! * item.price); } else { var details = returnOrder.returnOrderDetails!.first; details.items!.add(item); - totalPrice = totalPrice + (item.quantity * item.price); + totalPrice = totalPrice + (item.quantity! * item.price); returnOrder.returnOrderDetails!.first = details; } } @@ -176,7 +178,7 @@ class ReturnPOSOrderVM with ChangeNotifier { var item = details.items![j]; item.isCheckedForReturn = true; if (returnOrder.returnOrderDetails!.first.items!.contains(item)) { - totalPrice = totalPrice + (item.quantity * item.price); + totalPrice = totalPrice + (item.quantity! * item.price); returnOrder.details![i].items!.removeAt(j); } } diff --git a/lib/application/views/transactions/viewmodels/TransactionQuotationViewModel.dart b/lib/application/views/transactions/viewmodels/TransactionQuotationViewModel.dart index 95c3a7c..cbb0b71 100644 --- a/lib/application/views/transactions/viewmodels/TransactionQuotationViewModel.dart +++ b/lib/application/views/transactions/viewmodels/TransactionQuotationViewModel.dart @@ -16,9 +16,10 @@ class TransactionQuotationViewModel with ChangeNotifier { DataState get dataState => _dataState; List _dataList = []; + List get dataList => _dataList; - fetchQuotations({bool isRefresh = false}) async { + fetchQuotations({bool isRefresh = false, int limit = 10}) async { if (!isRefresh) { _dataState = (_dataState == DataState.uninitialized) ? DataState.initialFetching @@ -32,6 +33,7 @@ class TransactionQuotationViewModel with ChangeNotifier { 'store_id': sharedPrefs.storeId, 'page': _currentPageNumber, 'quotation_status': 'All', + 'limit': limit }; try { if (_didLastLoad) { @@ -46,7 +48,7 @@ class TransactionQuotationViewModel with ChangeNotifier { } if (value.success!) { _dataList.addAll(value.invoices!); - if (value.invoices!.length < 10) { + if (value.invoices!.length < limit) { _didLastLoad = true; } else { _didLastLoad = false; diff --git a/lib/application/views/transactions/views/EditOrderVC.dart b/lib/application/views/transactions/views/EditOrderVC.dart new file mode 100644 index 0000000..3bc1030 --- /dev/null +++ b/lib/application/views/transactions/views/EditOrderVC.dart @@ -0,0 +1,935 @@ +import 'package:dropdown_search/dropdown_search.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:provider/provider.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/application/model/reports/CashierOrder.dart'; +import 'package:wosull/application/model/store/StoreItemsResponse.dart'; +import 'package:wosull/application/model/store/StoreServiceModel.dart'; +import 'package:wosull/application/model/store/WosulStore.dart'; +import 'package:wosull/application/model/tables/GetStoreTable.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/AppLoader.dart'; +import 'package:wosull/application/utils/CRUDOperatoinState.dart'; +import 'package:wosull/application/views/inventorymodule/productviews/SearchProductVC.dart'; +import 'package:wosull/application/views/transactions/widgets/EditOrderViewModel.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeDropDown.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/widgets/ActionPopUpContainer.dart'; +import 'package:wosull/widgets/BorderContainer.dart'; +import 'package:wosull/widgets/ChildContainer.dart'; +import 'package:wosull/widgets/CustomAppBar.dart'; +import 'package:wosull/widgets/CustomOptionalTitle.dart'; +import 'package:wosull/widgets/CustomSimpleButton.dart'; +import 'package:wosull/widgets/CustomTextButtonIcon.dart'; +import 'package:wosull/widgets/CustomTextFieldForm.dart'; +import 'package:wosull/widgets/DropdownItemBuilder.dart'; +import 'package:wosull/widgets/HeadingContainer.dart'; +import 'package:wosull/widgets/HeadingText.dart'; +import 'package:wosull/widgets/PortraitContainer.dart'; +import 'package:wosull/widgets/ValueText.dart'; +import 'package:wosull/widgets/WrapHeightContainer.dart'; + +class EditOrderVC extends StatefulWidget { + CashierOrder cashierOrder; + bool isView = false; + + EditOrderVC({super.key, required this.cashierOrder, this.isView = false}); + + @override + State createState() => _EditOrderVCState(); +} + +class _EditOrderVCState extends State { + var viewModel = EditOrderViewModel(); + + @override + void initState() { + context.read().initData(widget.cashierOrder); + super.initState(); + } + + @override + void dispose() { + viewModel.disposeData(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + viewModel = context.watch(); + return Scaffold( + backgroundColor: MyColors.fillColor, + resizeToAvoidBottomInset: true, + appBar: CustomAppBar( + heading: widget.isView + ? 'View Order' + : AppLocalizations.of(context)!.edit_order, + ), + body: OrientationBuilder(builder: (c, orientation) { + viewModel.isPortrait = + MediaQuery.of(context).orientation == Orientation.portrait; + return SingleChildScrollView( + child: Container( + padding: const EdgeInsets.all(8), + child: Column( + children: [ + AppSpaces.verticalLarge, + Card( + elevation: 5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: Padding( + padding: const EdgeInsets.all(15), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Expanded( + flex: 1, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.status, + ), + AppSpaces.verticalSmall, + getStatusDropdown(), + AppSpaces.verticalMedium, + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.store, + ), + AppSpaces.verticalSmall, + getSubStoresWidget(), + AppSpaces.verticalMedium, + CustomOptionalTitle( + hint: AppLocalizations.of(context)! + .order_type, + ), + AppSpaces.verticalSmall, + getOrderTypeWidget(), + viewModel.isPortrait + ? Column( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + AppSpaces.verticalMedium, + getPaymentModeWidget(), + getTableWidget(), + getAmountWidget(), + AppSpaces.verticalMedium, + getBalanceOrChange(), + AppSpaces.verticalMedium, + getCreatedAtWidget(), + AppSpaces.verticalMedium, + getDeliveryNotesWidget(), + ], + ) + : Container() + ], + ), + ), + viewModel.isPortrait + ? Container() + : AppSpaces.horizontalMedium, + viewModel.isPortrait + ? Container() + : Expanded( + flex: 2, + child: Column( + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + Row( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + getPaymentModeWidget(), + AppSpaces.verticalMedium, + getAmountWidget(), + AppSpaces.verticalMedium, + getBalanceOrChange() + ], + )), + AppSpaces.horizontalMedium, + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + getTableWidget(), + getCreatedAtWidget(), + AppSpaces.verticalMedium, + getDeliveryNotesWidget() + ], + )), + ], + ), + ], + )), + ], + ), + ], + ), + ), + ), + AppSpaces.verticalLarge, + Card( + elevation: 5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: Container( + padding: const EdgeInsets.all(15), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)!.search_and_add_products, + style: ThemeText.textStyleHeadingCart, + ), + AppSpaces.verticalLarge, + viewModel.isPortrait + ? Container() + : BorderContainer( + child: Row( + children: [ + Expanded( + child: HeadingContainer( + heading: AppLocalizations.of(context)! + .name_or_barcode, + )), + Expanded( + child: HeadingContainer( + heading: AppLocalizations.of(context)! + .item_note, + )), + Expanded( + child: HeadingContainer( + heading: AppLocalizations.of(context)! + .quantity, + )), + Expanded( + child: HeadingContainer( + heading: AppLocalizations.of(context)! + .total_cost_price, + )), + HeadingContainer( + width: 84, + heading: AppLocalizations.of(context)! + .total_price, + ), + HeadingContainer( + width: 84, + heading: AppLocalizations.of(context)! + .total_amount, + ), + widget.isView + ? Container() + : HeadingContainer( + width: 44, + heading: '', + ) + ], + ), + ), + ListView.builder( + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (c, position) { + var orderDetails = widget + .cashierOrder.cart!.orderDetails![position]; + return ListView.builder( + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (c, i) { + var item = widget.cashierOrder.cart! + .orderDetails![position].items![i]; + if (viewModel.isPortrait) { + return WrapHeightContainer( + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + Expanded( + flex: 2, + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + PortraitContainer( + width: double.infinity, + child: Align( + alignment: Alignment + .centerLeft, + child: HeadingText( + AppLocalizations.of( + context)! + .name_or_barcode, + ), + ), + ), + PortraitContainer( + width: double.infinity, + child: Align( + alignment: Alignment + .centerLeft, + child: HeadingText( + AppLocalizations.of( + context)! + .item_note, + ), + ), + ), + PortraitContainer( + width: double.infinity, + child: Align( + alignment: Alignment + .centerLeft, + child: HeadingText( + AppLocalizations.of( + context)! + .quantity, + ), + ), + ), + PortraitContainer( + width: double.infinity, + child: Align( + alignment: Alignment + .centerLeft, + child: HeadingText( + AppLocalizations.of( + context)! + .total_cost_price, + ), + ), + ), + PortraitContainer( + width: double.infinity, + child: Align( + alignment: Alignment + .centerLeft, + child: HeadingText( + AppLocalizations.of( + context)! + .total_price, + ), + ), + ), + ], + )), + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + PortraitContainer( + width: double.infinity, + child: + getShowProductsWidget( + item, + position, + i), + ), + PortraitContainer( + width: double.infinity, + child: Center( + child: + getItemNotesWidget( + position, i), + ), + ), + PortraitContainer( + width: double.infinity, + child: Center( + child: + getItemQuantityWidget( + position, i), + ), + ), + PortraitContainer( + width: double.infinity, + child: Center( + child: + getItemCostPriceWidget( + position, i), + ), + ), + PortraitContainer( + width: double.infinity, + child: Center( + child: + getItemPriceWidget( + item), + ), + ), + ], + )), + ], + )), + Visibility( + visible: !widget.isView, + child: getRemoveItemButton( + position, i)) + ], + ), + ); + } else { + return BorderContainer( + backgroundColor: MyColors.white, + child: Row( + children: [ + Expanded( + child: ChildContainer( + child: getShowProductsWidget( + item, position, i), + ), + ), + Expanded( + child: ChildContainer( + child: Center( + child: + getItemNotesWidget(position, i), + ), + )), + Expanded( + child: ChildContainer( + child: Center( + child: getItemQuantityWidget( + position, i), + ), + )), + Expanded( + child: ChildContainer( + child: Center( + child: getItemCostPriceWidget( + position, i), + ), + )), + ChildContainer( + width: 84, + child: getItemPriceWidget(item), + ), + ChildContainer( + width: 84, + child: Center( + child: ValueText( + '', + ), + ), + ), + Visibility( + visible: !widget.isView, + child: + getRemoveItemButton(position, i), + ) + ], + ), + ); + } + }, + itemCount: orderDetails.items!.length, + ); + }, + itemCount: + widget.cashierOrder.cart!.orderDetails!.length, + ), + viewModel.isPortrait + ? BorderContainer( + backgroundColor: MyColors.white, + child: Row( + children: [ + Expanded( + child: ChildContainer( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + AppLocalizations.of(context)! + .total_amount), + ), + )), + Expanded( + child: ChildContainer( + child: Center( + child: HeadingText( + viewModel.getItemsPriceWithModifier(), + ), + ), + )), + Visibility( + visible: !widget.isView, + child: getAddItemButton()) + ], + ), + ) + : BorderContainer( + backgroundColor: MyColors.white, + child: Row( + children: [ + Expanded( + child: HeadingContainer( + heading: '', + )), + Expanded( + child: HeadingContainer( + heading: '', + )), + Expanded( + child: HeadingContainer( + heading: '', + )), + Expanded( + child: HeadingContainer( + heading: '', + )), + HeadingContainer( + width: 84, + heading: viewModel.getItemsPriceOnly(), + ), + HeadingContainer( + width: 84, + heading: + viewModel.getItemsPriceWithModifier(), + ), + Visibility( + visible: !widget.isView, + child: getAddItemButton()) + ], + ), + ), + AppSpaces.verticalLarge, + ], + ), + ), + ), + AppSpaces.verticalLarge, + Visibility( + visible: !widget.isView, + child: Row( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + SizedBox( + width: 120, + child: CustomSimpleButton( + isLoading: viewModel.isLoading, + textColor: MyColors.white, + backGroundColor: MyColors.blueThemeColor, + onPressed: () async { + await viewModel.updateOrder(); + checkState(); + }, + heading: AppLocalizations.of(context)!.save, + )), + ], + )) + ], + ), + ), + ); + }), + ); + } + + void showSheet(int parent, int child) async { + final result = await showDialog( + barrierColor: Colors.black26, + context: context, + builder: (context) { + return const SearchProductVC(); + }, + ); + + if (!mounted) return; + if (result != null) { + viewModel.updateItem(parent, child, result); + } + } + + Widget getOrderTypeWidget() { + return FutureBuilder( + future: viewModel.getService(), + builder: (c, s) { + if (s.hasData) { + var itemsList = s.data!; + return DropdownSearch( + enabled: !widget.isView, + selectedItem: viewModel.selectedOrderType, + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name ?? ''); + }, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: itemsList, + itemAsString: (StoreServiceModel u) => u.name!, + onChanged: (StoreServiceModel? data) { + viewModel.setSelectedOrderType(data); + }, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), + ); + } else { + return AppLoader(); + } + }); + } + + Widget getStoreTables() { + return FutureBuilder( + future: viewModel.getTablesList(), + builder: (c, s) { + if (s.hasData) { + var itemsList = s.data!; + return DropdownSearch( + enabled: !widget.isView, + selectedItem: viewModel.selectedTable ?? + StoreTable(id: '', tableName: 'N/A', noOfOccupants: 0), + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.tableName ?? ''); + }, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: itemsList, + itemAsString: (StoreTable u) => + "${u.tableName} | ${u.noOfOccupants}", + onChanged: (StoreTable? data) { + viewModel.setSelectedTable(data); + }, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), + ); + } else { + return AppLoader(); + } + }); + } + + Widget getSubStoresWidget() { + return FutureBuilder( + future: viewModel.getSubStores(), + builder: (c, s) { + if (s.hasData) { + var itemsList = s.data!; + return DropdownSearch( + enabled: !widget.isView, + selectedItem: viewModel.selectedStore, + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name); + }, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: itemsList, + itemAsString: (WosulStore u) => u.name, + onChanged: (WosulStore? data) { + viewModel.setSelectedStore(data); + }, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), + ); + } else { + return AppLoader(); + } + }); + } + + Widget getSelectedPaymentMode() { + return DropdownSearch( + enabled: !widget.isView, + selectedItem: viewModel.selectedPaymentMode ?? "Choose", + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item); + }, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: viewModel.items, + itemAsString: (String u) => u, + onChanged: (String? data) { + viewModel.setSelectedPaymentMode(data); + }, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), + ); + } + + Widget getStatusDropdown() { + return DropdownSearch( + enabled: !widget.isView, + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item); + }, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + selectedItem: viewModel.selectedStatus ?? "Choose", + items: viewModel.statusItems, + itemAsString: (String u) => u, + onChanged: (String? data) { + viewModel.setOrderStatus(data); + }, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), + ); + } + + Widget getBalanceOrChange() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.balance_change, + ), + AppSpaces.verticalSmall, + CustomTextFieldForm( + readOnly: true, + key: + Key(viewModel.cashierOrder.changeBalanceAmount?.toString() ?? ''), + hintText: 'Enter Amount', + initialValue: + viewModel.cashierOrder.changeBalanceAmount?.toString() ?? '', + onChanged: (String value) {}, + ) + ], + ); + } + + getAmountWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.amount, + ), + AppSpaces.verticalSmall, + CustomTextFieldForm( + readOnly: widget.isView, + keyboardType: TextInputType.number, + hintText: 'Enter Amount', + initialValue: viewModel.cashierOrder.amount?.toString() ?? '', + onChanged: (String value) { + viewModel.updateOrderAmount(value); + }, + ) + ], + ); + } + + Widget getCreatedAtWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.created_at, + ), + AppSpaces.verticalSmall, + CustomTextFieldForm( + hintText: '', + readOnly: true, + initialValue: DataTimeFormat.getFormatDate( + viewModel.cashierOrder.createdAt ?? ''), + onChanged: (String value) {}, + ) + ], + ); + } + + getTableWidget() { + return Visibility( + visible: + widget.cashierOrder.orderType!.toLowerCase().compareTo('dinein') == + 0, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + AppSpaces.verticalMedium, + CustomOptionalTitle(hint: AppLocalizations.of(context)!.table), + AppSpaces.verticalSmall, + getStoreTables(), + AppSpaces.verticalMedium, + ], + )); + } + + Widget getDeliveryNotesWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.delivery_note, + ), + AppSpaces.verticalSmall, + CustomTextFieldForm( + readOnly: widget.isView, + hintText: 'Enter Delivery Note', + initialValue: viewModel.cashierOrder.deliveryNotes ?? '', + onChanged: (String value) { + viewModel.updateDeliveryNotes(value); + }, + ), + ], + ); + } + + getPaymentModeWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.payment_mode, + ), + AppSpaces.verticalSmall, + getSelectedPaymentMode(), + ], + ); + } + + getShowProductsWidget(StoreItems item, int position, int i) { + return CustomTextButtonIcon( + icon: Icons.arrow_drop_down, + heading: item.name.isEmpty ? 'Choose' : item.name, + onPressed: () { + if (!widget.isView) { + showSheet(position, i); + } + }, + ); + } + + getItemNotesWidget(int position, int i) { + return CustomTextFieldForm( + readOnly: widget.isView, + hintText: 'Enter item note', + initialValue: viewModel.itemNotesController[position][i], + onChanged: (value) { + viewModel.updateItemNote(position, i, value); + }, + ); + } + + getItemQuantityWidget(int position, int i) { + return CustomTextFieldForm( + readOnly: widget.isView, + hintText: 'Enter item quantity', + keyboardType: TextInputType.number, + initialValue: viewModel.itemQuantityController[position][i], + onChanged: (value) { + viewModel.updateQuantity(position, i, value); + }, + ); + } + + getItemCostPriceWidget(int position, int i) { + return CustomTextFieldForm( + readOnly: widget.isView, + hintText: 'Enter item price', + keyboardType: TextInputType.number, + initialValue: viewModel.itemCostPriceController[position][i], + onChanged: (value) { + viewModel.updateItemPrice(position, i, value); + }, + ); + } + + getItemPriceWidget(StoreItems item) { + return ValueText( + (item.price * item.quantity!).toStringAsFixed(2), + ); + } + + getRemoveItemButton(int position, int i) { + return SizedBox( + width: 44, + height: 44, + child: Padding( + padding: const EdgeInsets.all(4), + child: ActionPopUpContainer( + child: IconButton( + icon: const Icon( + size: 14, + Icons.close, + color: MyColors.textColorBlack, + ), + onPressed: () { + viewModel.removeItemFromCart(position, i); + }), + ), + )); + } + + getAddItemButton() { + return Center( + child: Container( + margin: const EdgeInsets.all(5), + width: 32, + height: 32, + decoration: const BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(4)), + color: MyColors.fillColorGray2), + child: IconButton( + icon: const Icon( + size: 14, + Icons.add, + color: MyColors.textColorBlack, + ), + onPressed: () { + viewModel.addNewItem(); + }), + ), + ); + } + + void checkState() { + if (viewModel.crudOperation == CRUDOperationState.add) { + Navigator.pop(context, true); + } + } +} diff --git a/lib/application/views/transactions/ReturnTransactionInvoiceVC.dart b/lib/application/views/transactions/views/ReturnTransactionInvoiceVC.dart similarity index 98% rename from lib/application/views/transactions/ReturnTransactionInvoiceVC.dart rename to lib/application/views/transactions/views/ReturnTransactionInvoiceVC.dart index 408bbd7..b2b1550 100644 --- a/lib/application/views/transactions/ReturnTransactionInvoiceVC.dart +++ b/lib/application/views/transactions/views/ReturnTransactionInvoiceVC.dart @@ -1,14 +1,15 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:sizer/sizer.dart'; -import 'package:wosull/application/ViewModel/InventoryViewModel.dart'; import 'package:wosull/application/interfaces/DrawerWidgetSelect.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; import 'package:wosull/application/model/converters/DataTimeFormat.dart'; import 'package:wosull/application/model/invoice/StoreInvoice.dart'; import 'package:wosull/application/model/store/StoreInvoicesModel.dart'; +import 'package:wosull/application/repository/WosulRepository.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/theme/MyFonts.dart'; +import 'package:wosull/application/utils/AppLoader.dart'; import 'package:wosull/application/utils/Constants.dart'; import 'package:wosull/application/views/popups/DeleteRecordPopUp.dart'; import 'package:wosull/application/views/salesandordermodule/views/ReturnInvoiceVC.dart'; @@ -18,11 +19,14 @@ class ReturnTransactionInvoiceVC extends StatefulWidget { TransactionCVS delegate; BuildContext context; String filter = 'All'; + int limit = 10; + ReturnTransactionInvoiceVC( {super.key, required this.filter, required this.delegate, - required this.context}); + required this.context, + this.limit = 10}); @override State createState() => @@ -41,7 +45,7 @@ class _ReturnTransactionInvoiceVCState 'Damage' ]; - InventoryViewModel viewModel = InventoryViewModel(); + var viewModel = WosulRepository(); List filteredInvoices = []; @@ -69,9 +73,7 @@ class _ReturnTransactionInvoiceVCState child: Column( children: [ _isFirstLoadRunning - ? const Center( - child: CircularProgressIndicator(), - ) + ? AppLoader() : filteredInvoices.isEmpty ? const EmptyDataWidget() : Column( @@ -452,7 +454,7 @@ class _ReturnTransactionInvoiceVCState position] .status! .toString(), - style: const TextStyle( + style: TextStyle( fontFamily: MyFonts.Bold, fontWeight: @@ -726,7 +728,7 @@ class _ReturnTransactionInvoiceVCState child: Text( filteredInvoices[position] .status!, - style: const TextStyle( + style: TextStyle( fontStyle: FontStyle.normal, fontFamily: @@ -837,7 +839,7 @@ class _ReturnTransactionInvoiceVCState final response = await viewModel.getResponsePatch(Constants.DELETE_NVOICE, data); - if (response.success!) { + if (response.success) { setState(() { filteredInvoices.removeWhere((element) => element.id! == id); }); @@ -849,7 +851,7 @@ class _ReturnTransactionInvoiceVCState final response = await viewModel.getResponsePatch(Constants.UPDATE_INVOICE, data); - if (response.success!) { + if (response.success) { setState(() {}); } } @@ -869,12 +871,13 @@ class _ReturnTransactionInvoiceVCState 'store_id': sharedPrefs.storeId, 'page': _page, 'invoice_status': widget.filter, + 'limit': widget.limit }; await viewModel.getData(Constants.GET_INVOICE, data).then((response) { final value = StoreInvoicesModel.fromJson(response); if (value.success!) { if (value.invoices!.isNotEmpty) { - if (value.invoices!.length < 10) { + if (value.invoices!.length < widget.limit) { _hasNextPage = false; } setState(() { @@ -909,6 +912,7 @@ class _ReturnTransactionInvoiceVCState 'store_id': sharedPrefs.storeId, 'page': _page, 'invoice_status': widget.filter, + 'limit': widget.limit }; await viewModel.getData(Constants.GET_INVOICE, data).then((response) { @@ -916,7 +920,7 @@ class _ReturnTransactionInvoiceVCState if (value.success!) { filteredInvoices.clear(); filteredInvoices.addAll(value.invoices!); - if (value.invoices!.length < 10) { + if (value.invoices!.length < widget.limit) { _hasNextPage = false; } setState(() { diff --git a/lib/application/views/transactions/views/TransactionCashierVC.dart b/lib/application/views/transactions/views/TransactionCashierVC.dart new file mode 100644 index 0000000..e3bd5f5 --- /dev/null +++ b/lib/application/views/transactions/views/TransactionCashierVC.dart @@ -0,0 +1,97 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:wosull/application/enum/DataState.dart'; +import 'package:wosull/application/interfaces/DrawerWidgetSelect.dart'; +import 'package:wosull/application/model/reports/CashierOrder.dart'; +import 'package:wosull/application/utils/AppError.dart'; +import 'package:wosull/application/utils/AppLoader.dart'; +import 'package:wosull/application/views/transactions/viewmodels/CashierTransactionViewModel.dart'; +import 'package:wosull/application/views/transactions/widgets/TransactionCashierOrderListView.dart'; + +class TransactionCashierVC extends StatefulWidget { + TransactionCVS delegate; + BuildContext context; + int limit = 10; + + // bool isPortrait = false; + + TransactionCashierVC({ + super.key, + required this.context, + required this.delegate, + required this.limit, + // required this.isPortrait, + }); + + @override + State createState() => _TransactionCashierVCState(); +} + +class _TransactionCashierVCState extends State { + late ScrollController _controller; + final viewModel = CashierTransactionViewModel(); + var isPortrait = false; + + @override + void initState() { + _controller = ScrollController()..addListener(_scrollNotification); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return OrientationBuilder(builder: (c, orientation) { + isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; + return SingleChildScrollView( + controller: _controller, + child: ChangeNotifierProvider( + create: (context) => viewModel, + child: Consumer( + builder: (BuildContext context, + CashierTransactionViewModel controller, Widget? _) { + switch (controller.dataState) { + case DataState.uninitialized: + Future(() { + controller.fetch(limit: widget.limit, filter: 'all'); + }); + return showData(controller.filteredList); + case DataState.initialFetching: + return AppLoader(); + case DataState.moreFetching: + case DataState.refreshing: + return showData(controller.filteredList); + case DataState.error: + return AppError(); + case DataState.searching: + case DataState.fetched: + case DataState.noMoreData: + return showData(controller.filteredList); + } + }, + ), + ), + ); + }); + } + + Widget showData(List data) { + return Column( + children: [ + TransactionCashierOrderListView( + onView: (order) { + widget.delegate.editCashier(order); + }, + posOrders: data, + isPortrait: isPortrait), + if (viewModel.dataState == DataState.moreFetching) AppLoader(), + ], + ); + } + + bool _scrollNotification() { + if (!viewModel.isLoading && _controller.position.extentAfter < 300) { + viewModel.fetch(limit: viewModel.limit, filter: 'all'); + } + return true; + } +} diff --git a/lib/application/views/transactions/TransactionDamageInvoiceVC.dart b/lib/application/views/transactions/views/TransactionDamageInvoiceVC.dart similarity index 99% rename from lib/application/views/transactions/TransactionDamageInvoiceVC.dart rename to lib/application/views/transactions/views/TransactionDamageInvoiceVC.dart index ce57493..09eb128 100644 --- a/lib/application/views/transactions/TransactionDamageInvoiceVC.dart +++ b/lib/application/views/transactions/views/TransactionDamageInvoiceVC.dart @@ -1,12 +1,12 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:sizer/sizer.dart'; -import 'package:wosull/application/ViewModel/InventoryViewModel.dart'; import 'package:wosull/application/interfaces/DrawerWidgetSelect.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; import 'package:wosull/application/model/converters/DataTimeFormat.dart'; import 'package:wosull/application/model/invoice/StoreInvoice.dart'; import 'package:wosull/application/model/store/StoreInvoicesModel.dart'; +import 'package:wosull/application/repository/WosulRepository.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/theme/MyFonts.dart'; import 'package:wosull/application/utils/Constants.dart'; @@ -18,9 +18,11 @@ class TransactionDamageInvoiceVC extends StatefulWidget { TransactionCVS delegate; BuildContext context; String filter = 'All'; + int limit = 10; TransactionDamageInvoiceVC( {super.key, + this.limit = 10, required this.filter, required this.delegate, required this.context}); @@ -42,7 +44,7 @@ class _TransactionDamageInvoiceVCState 'Damage' ]; - InventoryViewModel viewModel = InventoryViewModel(); + var viewModel = WosulRepository(); List filteredInvoices = []; @@ -868,12 +870,13 @@ class _TransactionDamageInvoiceVCState 'store_id': sharedPrefs.storeId, 'page': _page, 'invoice_status': widget.filter, + 'limit': widget.limit }; await viewModel.getData(Constants.GET_INVOICE, data).then((response) { final value = StoreInvoicesModel.fromJson(response); if (value.success!) { if (value.invoices!.isNotEmpty) { - if (value.invoices!.length < 10) { + if (value.invoices!.length < widget.limit) { _hasNextPage = false; } setState(() { @@ -908,6 +911,7 @@ class _TransactionDamageInvoiceVCState 'store_id': sharedPrefs.storeId, 'page': _page, 'invoice_status': widget.filter, + 'limit': widget.limit }; await viewModel.getData(Constants.GET_INVOICE, data).then((response) { @@ -915,7 +919,7 @@ class _TransactionDamageInvoiceVCState if (value.success!) { filteredInvoices.clear(); filteredInvoices.addAll(value.invoices!); - if (value.invoices!.length < 10) { + if (value.invoices!.length < widget.limit) { _hasNextPage = false; } setState(() { diff --git a/lib/application/views/transactions/views/TransactionInvoicesVC.dart b/lib/application/views/transactions/views/TransactionInvoicesVC.dart new file mode 100644 index 0000000..a5f7155 --- /dev/null +++ b/lib/application/views/transactions/views/TransactionInvoicesVC.dart @@ -0,0 +1,282 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:wosull/application/interfaces/DrawerWidgetSelect.dart'; +import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/application/model/invoice/StoreInvoice.dart'; +import 'package:wosull/application/model/store/StoreInvoicesModel.dart'; +import 'package:wosull/application/repository/WosulRepository.dart'; +import 'package:wosull/application/utils/AppLoader.dart'; +import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/popups/DeleteRecordPopUp.dart'; +import 'package:wosull/application/views/salesandordermodule/views/ReturnInvoiceVC.dart'; +import 'package:wosull/application/views/salesandordermodule/views/invoiceModule/widgets/InvoiceListView.dart'; +import 'package:wosull/base/BaseStatefulState.dart'; +import 'package:wosull/widgets/CustomPopuoMenuButton.dart'; + +class TransactionInvoicesVC extends StatefulWidget { + TransactionCVS delegate; + BuildContext context; + String filter = 'All'; + int limit = 10; + + TransactionInvoicesVC( + {super.key, + this.limit = 10, + required this.filter, + required this.delegate, + required this.context}); + + @override + State createState() => _TransactionInvoicesVCState(); +} + +class _TransactionInvoicesVCState + extends BaseStatefulState { + bool isPortrait = true; + var itemsList = [ + 'Open', + 'Paid Partially', + 'Paid', + 'Cancelled', + 'Return', + 'Damage' + ]; + + final viewModel = WosulRepository(); + + List filteredInvoices = []; + + int _page = 1; + bool _isFirstLoadRunning = false; + bool _hasNextPage = true; + + bool _isLoadMoreRunning = false; + late ScrollController _controller; + + @override + void initState() { + super.initState(); + _firstLoad(); + _controller = ScrollController()..addListener(_loadMore); + } + + @override + Widget build(BuildContext context) { + return OrientationBuilder(builder: (c, orientation) { + isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; + return SingleChildScrollView( + controller: _controller, + child: Column( + children: [ + _isFirstLoadRunning + ? AppLoader() + : InvoiceListView( + isPortrait: isPortrait, + data: filteredInvoices, + onEdit: (invoice) {}, + onReturn: (invoice) { + onReturnInvoice(invoice, true); + }, + onDamage: (invoice) { + onReturnInvoice(invoice, false); + }, + onUpdate: (invoice, value) {}, + onPrintDownload: (invoice) { + widget.delegate.printDownloadInvoice(invoice); + }, + onDelete: (invoice) { + showDeletePopup(invoice); + }), + ], + ), + ); + }); + } + + Future _delete(String id) async { + Map data = {'invoiceId': id}; + final response = + await viewModel.getResponsePatch(Constants.DELETE_NVOICE, data); + + if (response.success) { + setState(() { + filteredInvoices.removeWhere((element) => element.id! == id); + }); + } + } + + Future _update(String id, String value) async { + Map data = {'invoiceId': id, 'status': value}; + final response = + await viewModel.getResponsePatch(Constants.UPDATE_INVOICE, data); + + if (response.success) { + setState(() {}); + } + } + + void _loadMore() async { + if (_hasNextPage == true && + _isFirstLoadRunning == false && + _isLoadMoreRunning == false && + _controller.position.extentAfter < 300) { + setState(() { + _isLoadMoreRunning = true; // Display a progress indicator at the bottom + }); + + _page += 1; // Increase _page by 1 + + Map data = { + 'store_id': sharedPrefs.storeId, + 'page': _page, + 'invoice_status': widget.filter, + 'limit': widget.limit + }; + await viewModel.getData(Constants.GET_INVOICE, data).then((response) { + final value = StoreInvoicesModel.fromJson(response); + if (value.success!) { + if (value.invoices!.isNotEmpty) { + if (value.invoices!.length < widget.limit) { + _hasNextPage = false; + } + setState(() { + filteredInvoices.addAll(value.invoices!); + }); + } else { + setState(() { + _hasNextPage = false; + }); + } + } + }).onError((error, stackTrace) { + setState(() { + _hasNextPage = false; + }); + }).timeout(const Duration(seconds: 60)); + + setState(() { + _isLoadMoreRunning = false; + }); + } + } + + void _firstLoad() async { + setState(() { + _isFirstLoadRunning = true; + _hasNextPage = true; + }); + _page = 1; + + Map data = { + 'store_id': sharedPrefs.storeId, + 'page': _page, + 'invoice_status': widget.filter, + 'limit': widget.limit + }; + + await viewModel.getData(Constants.GET_INVOICE, data).then((response) { + final value = StoreInvoicesModel.fromJson(response); + if (value.success!) { + filteredInvoices.clear(); + filteredInvoices.addAll(value.invoices!); + if (value.invoices!.length < widget.limit) { + _hasNextPage = false; + } + setState(() { + _isFirstLoadRunning = false; + }); + } + }).onError((error, stackTrace) { + setState(() { + _isFirstLoadRunning = false; + }); + }).timeout(const Duration(seconds: 60)); + } + + Future actionPopUpItemSelected( + String value, StoreInvoice invoice) async { + if (value == 'edit') { + widget.delegate.editOnNewInvoice(invoice); + } else if (value == 'return') { + } else if (value == 'damage') { + final result = await Navigator.push( + widget.context, + MaterialPageRoute( + builder: (context) => ReturnInvoiceVC( + storeInvoice: invoice, + isReturn: false, + )), + ); + if (!mounted) return; + if (result) { + _firstLoad(); + } + } else if (value == 'delete') { + } else { + widget.delegate.printDownloadInvoice(invoice); + } + } + + showDeletePopup(StoreInvoice invoice) async { + final result = await showDialog( + barrierColor: Colors.black26, + context: context, + builder: (context) { + return const DeleteRecordPopUp(); + }, + ); + + if (!mounted) return; + if (result) { + _delete(invoice.id!); + } + } + + Future onReturnInvoice(StoreInvoice invoice, bool isReturn) async { + final result = await Navigator.push( + widget.context, + MaterialPageRoute( + builder: (context) => ReturnInvoiceVC( + storeInvoice: invoice, + isReturn: isReturn, + )), + ); + if (!mounted) return; + if (result) { + _firstLoad(); + } + } + + getPopupMenuButton(BuildContext context, int position) { + return CustomPopupMenuButton( + onSelected: (String value) => + actionPopUpItemSelected(value, filteredInvoices[position]), + items: [ + PopupMenuItem( + value: 'return', + child: Text( + AppLocalizations.of(widget.context)!.return_txt, + ), + ), + const PopupMenuItem( + value: 'damage', + child: Text( + "Damage", + ), + ), + PopupMenuItem( + value: 'view', + child: Text( + AppLocalizations.of(widget.context)!.print_or_download, + ), + ), + PopupMenuItem( + value: 'delete', + child: Text( + AppLocalizations.of(widget.context)!.delete, + ), + ) + ], + ); + } +} diff --git a/lib/application/views/transactions/TransactionQuotationVC.dart b/lib/application/views/transactions/views/TransactionQuotationVC.dart similarity index 98% rename from lib/application/views/transactions/TransactionQuotationVC.dart rename to lib/application/views/transactions/views/TransactionQuotationVC.dart index 3f688c7..2bce680 100644 --- a/lib/application/views/transactions/TransactionQuotationVC.dart +++ b/lib/application/views/transactions/views/TransactionQuotationVC.dart @@ -9,17 +9,22 @@ import 'package:wosull/application/model/invoice/QuotationInvioceModel.dart'; import 'package:wosull/application/network/ApiResponse.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/theme/MyFonts.dart'; +import 'package:wosull/application/utils/AppLoader.dart'; import 'package:wosull/application/views/popups/DeleteRecordPopUp.dart'; import 'package:wosull/base/BaseStatefulState.dart'; -import 'viewmodels/TransactionQuotationViewModel.dart'; +import '../viewmodels/TransactionQuotationViewModel.dart'; class TransactionQuotationVC extends StatefulWidget { TransactionCVS delegate; BuildContext context; + int limit = 10; TransactionQuotationVC( - {super.key, required this.delegate, required this.context}); + {super.key, + required this.delegate, + required this.context, + this.limit = 10}); @override State createState() => _TransactionQuotationVCState(); @@ -66,13 +71,11 @@ class _TransactionQuotationVCState switch (controller.dataState) { case DataState.uninitialized: Future(() { - controller.fetchQuotations(); + controller.fetchQuotations(limit: widget.limit); }); return showList(controller.dataList, true); case DataState.initialFetching: - return const Center( - child: CircularProgressIndicator(), - ); + return AppLoader(); case DataState.moreFetching: case DataState.refreshing: return showList(controller.dataList, true); @@ -208,7 +211,7 @@ class _TransactionQuotationVCState const SizedBox( width: 10, ), - Container( + SizedBox( width: 46, child: Text( AppLocalizations.of(widget.context)!.action, @@ -397,7 +400,7 @@ class _TransactionQuotationVCState alignment: Alignment.centerRight, child: Text( storeInvoice.status ?? '', - style: const TextStyle( + style: TextStyle( fontFamily: MyFonts.Bold, fontWeight: FontWeight.w500, fontSize: MyFonts.normal, @@ -591,7 +594,7 @@ class _TransactionQuotationVCState child: Center( child: Text( storeInvoice.status!, - style: const TextStyle( + style: TextStyle( fontStyle: FontStyle.normal, fontFamily: MyFonts.Bold, fontSize: MyFonts.normal, @@ -704,7 +707,7 @@ class _TransactionQuotationVCState bool _scrollNotification() { if (!_isLoading && _controller.position.extentAfter < 300) { _isLoading = true; - homeViewViewModel.fetchQuotations(); + homeViewViewModel.fetchQuotations(limit: widget.limit); } return true; } diff --git a/lib/application/views/transactions/views/ViewCashierTransactionVC.dart b/lib/application/views/transactions/views/ViewCashierTransactionVC.dart new file mode 100644 index 0000000..6e6a67e --- /dev/null +++ b/lib/application/views/transactions/views/ViewCashierTransactionVC.dart @@ -0,0 +1,637 @@ +import 'package:dropdown_search/dropdown_search.dart'; +import 'package:flutter/material.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/application/model/reports/CashierOrder.dart'; +import 'package:wosull/application/model/store/StoreItemsResponse.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeDropDown.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/helpers/Utils.dart'; +import 'package:wosull/widgets/BorderContainer.dart'; +import 'package:wosull/widgets/ChildContainer.dart'; +import 'package:wosull/widgets/CustomAppBar.dart'; +import 'package:wosull/widgets/CustomOptionalTitle.dart'; +import 'package:wosull/widgets/CustomTextButtonIcon.dart'; +import 'package:wosull/widgets/CustomTextFieldForm.dart'; +import 'package:wosull/widgets/HeadingContainer.dart'; +import 'package:wosull/widgets/HeadingText.dart'; +import 'package:wosull/widgets/PortraitContainer.dart'; +import 'package:wosull/widgets/ValueText.dart'; +import 'package:wosull/widgets/WrapHeightContainer.dart'; + +class ViewCashierTransactionVC extends StatelessWidget { + CashierOrder cashierOrder; + bool isPortrait = false; + + ViewCashierTransactionVC(this.cashierOrder, {super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: MyColors.fillColor, + resizeToAvoidBottomInset: true, + appBar: CustomAppBar( + heading: 'View Order', + ), + body: OrientationBuilder(builder: (c, orientation) { + isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; + return SingleChildScrollView( + child: Container( + padding: const EdgeInsets.all(8), + child: Column( + children: [ + AppSpaces.verticalLarge, + Card( + elevation: 5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: Container( + padding: const EdgeInsets.all(15), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + lang(context).search_and_add_products, + style: ThemeText.textStyleHeadingCart, + ), + AppSpaces.verticalLarge, + isPortrait + ? Container() + : BorderContainer( + child: Row( + children: [ + Expanded( + child: HeadingContainer( + heading: lang(context).name_or_barcode, + )), + Expanded( + child: HeadingContainer( + heading: lang(context).item_note, + )), + Expanded( + child: HeadingContainer( + heading: lang(context).quantity, + )), + Expanded( + child: HeadingContainer( + heading: lang(context).total_cost_price, + )), + HeadingContainer( + width: 84, + heading: lang(context).total_price, + ), + HeadingContainer( + width: 84, + heading: lang(context).total_amount, + ), + ], + ), + ), + ListView.builder( + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (c, position) { + var orderDetails = + cashierOrder.cart!.orderDetails![position]; + return ListView.builder( + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (c, i) { + var item = cashierOrder + .cart!.orderDetails![position].items![i]; + if (isPortrait) { + return WrapHeightContainer( + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + Expanded( + flex: 2, + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + PortraitContainer( + width: double.infinity, + child: Align( + alignment: Alignment + .centerLeft, + child: HeadingText( + lang(context) + .name_or_barcode, + ), + ), + ), + PortraitContainer( + width: double.infinity, + child: Align( + alignment: Alignment + .centerLeft, + child: HeadingText( + lang(context) + .item_note, + ), + ), + ), + PortraitContainer( + width: double.infinity, + child: Align( + alignment: Alignment + .centerLeft, + child: HeadingText( + lang(context) + .quantity, + ), + ), + ), + PortraitContainer( + width: double.infinity, + child: Align( + alignment: Alignment + .centerLeft, + child: HeadingText( + lang(context) + .total_cost_price, + ), + ), + ), + PortraitContainer( + width: double.infinity, + child: Align( + alignment: Alignment + .centerLeft, + child: HeadingText( + lang(context) + .total_price, + ), + ), + ), + ], + )), + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + PortraitContainer( + width: double.infinity, + child: + getShowProductsWidget( + item, + position, + i), + ), + PortraitContainer( + width: double.infinity, + child: Center( + child: getItemNotesWidget( + cashierOrder + .cart! + .orderDetails![ + position] + .items![i] + .noteForItem + .toString()), + ), + ), + PortraitContainer( + width: double.infinity, + child: Center( + child: getItemQuantityWidget( + cashierOrder + .cart! + .orderDetails![ + position] + .items![i] + .quantity + ?.toString() ?? + ''), + ), + ), + PortraitContainer( + width: double.infinity, + child: Center( + child: getItemCostPriceWidget( + cashierOrder + .cart! + .orderDetails![ + position] + .items![i] + .price + ?.toStringAsFixed( + 2) ?? + ''), + ), + ), + PortraitContainer( + width: double.infinity, + child: Center( + child: + getItemPriceWidget( + item), + ), + ), + ], + )), + ], + )), + ], + ), + ); + } else { + return BorderContainer( + backgroundColor: MyColors.white, + child: Row( + children: [ + Expanded( + child: ChildContainer( + child: getShowProductsWidget( + item, position, i), + ), + ), + Expanded( + child: ChildContainer( + child: Center( + child: getItemNotesWidget( + cashierOrder + .cart! + .orderDetails![position] + .items![i] + .noteForItem + ?.toString() ?? + ''), + ), + )), + Expanded( + child: ChildContainer( + child: Center( + child: getItemQuantityWidget( + cashierOrder + .cart! + .orderDetails![position] + .items![i] + .quantity + ?.toString() ?? + ''), + ), + )), + Expanded( + child: ChildContainer( + child: Center( + child: getItemCostPriceWidget( + cashierOrder + .cart! + .orderDetails![position] + .items![i] + .price + ?.toStringAsFixed(2) ?? + ''), + ), + )), + ChildContainer( + width: 84, + child: getItemPriceWidget(item), + ), + ChildContainer( + width: 84, + child: Center( + child: ValueText( + '', + ), + ), + ), + ], + ), + ); + } + }, + itemCount: orderDetails.items!.length, + ); + }, + itemCount: cashierOrder.cart!.orderDetails!.length, + ), + isPortrait + ? BorderContainer( + backgroundColor: MyColors.white, + child: Row( + children: [ + Expanded( + child: ChildContainer( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + lang(context).total_amount), + ), + )), + Expanded( + child: ChildContainer( + child: Center( + child: HeadingText( + getItemsPriceWithModifier(), + ), + ), + )), + ], + ), + ) + : BorderContainer( + backgroundColor: MyColors.white, + child: Row( + children: [ + Expanded( + child: HeadingContainer( + heading: '', + )), + Expanded( + child: HeadingContainer( + heading: '', + )), + Expanded( + child: HeadingContainer( + heading: '', + )), + Expanded( + child: HeadingContainer( + heading: '', + )), + HeadingContainer( + width: 84, + heading: getItemsPriceOnly(), + ), + HeadingContainer( + width: 84, + heading: getItemsPriceWithModifier(), + ), + ], + ), + ), + AppSpaces.verticalLarge, + ], + ), + ), + ), + AppSpaces.verticalLarge, + ], + ), + ), + ); + }), + ); + } + + String getItemsPriceWithModifier() { + double price = 0.0; + for (var order in cashierOrder.cart!.orderDetails!) { + for (var item in order.items!) { + price += (item.quantity! * item.price); + if (item.selectedModifiers.isNotEmpty) { + for (var modi in item.selectedModifiers) { + price += modi.price; + } + } + } + } + cashierOrder.changeBalanceAmount = (cashierOrder.amount! - price); + print(cashierOrder.changeBalanceAmount.toString()); + + return price.toStringAsFixed(2); + } + + String getItemsPriceOnly() { + double price = 0.0; + for (var order in cashierOrder.cart!.orderDetails!) { + for (var item in order.items!) { + price += (item.quantity! * item.price); + } + } + + return price.toStringAsFixed(2); + } + + Widget getOrderTypeWidget(String selectedItem) { + return DropdownSearch( + enabled: false, + selectedItem: selectedItem, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + items: Constants.counterTypes, + itemAsString: (String u) => u, + onChanged: (String? data) {}, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), + ); + } + + Widget getStoreTables(String selectedItem) { + return DropdownSearch( + enabled: false, + selectedItem: selectedItem, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + items: Constants.counterTypes, + itemAsString: (String u) => u, + onChanged: (String? data) {}, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), + ); + } + + Widget getSubStoresWidget(String selectedItem) { + return DropdownSearch( + enabled: false, + selectedItem: selectedItem, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + items: Constants.counterTypes, + itemAsString: (String u) => u, + onChanged: (String? data) {}, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), + ); + } + + Widget getSelectedPaymentMode(String selectedItem) { + return DropdownSearch( + enabled: false, + selectedItem: selectedItem, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + items: Constants.counterTypes, + itemAsString: (String u) => u, + onChanged: (String? data) {}, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), + ); + } + + Widget getStatusDropdown(String selectedItem) { + return DropdownSearch( + enabled: false, + selectedItem: selectedItem, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + items: Constants.counterTypes, + itemAsString: (String u) => u, + onChanged: (String? data) {}, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), + ); + } + + Widget getBalanceOrChange(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: lang(context).balance_change, + ), + AppSpaces.verticalSmall, + CustomTextFieldForm( + readOnly: true, + key: Key(cashierOrder.changeBalanceAmount?.toString() ?? ''), + hintText: 'Enter Amount', + initialValue: cashierOrder.changeBalanceAmount?.toString() ?? '', + onChanged: (String value) {}, + ) + ], + ); + } + + getAmountWidget(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: lang(context).amount, + ), + AppSpaces.verticalSmall, + CustomTextFieldForm( + readOnly: true, + keyboardType: TextInputType.number, + hintText: 'Enter Amount', + initialValue: cashierOrder.amount?.toString() ?? '', + onChanged: (String value) {}, + ) + ], + ); + } + + Widget getCreatedAtWidget(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: lang(context).created_at, + ), + AppSpaces.verticalSmall, + CustomTextFieldForm( + hintText: '', + readOnly: true, + initialValue: + DataTimeFormat.getFormatDate(cashierOrder.createdAt ?? ''), + onChanged: (String value) {}, + ) + ], + ); + } + + getTableWidget(BuildContext context) { + return Visibility( + visible: cashierOrder.orderType!.toLowerCase().compareTo('dinein') == 0, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + AppSpaces.verticalMedium, + CustomOptionalTitle(hint: lang(context).table), + AppSpaces.verticalSmall, + getStoreTables(cashierOrder.table ?? ''), + AppSpaces.verticalMedium, + ], + )); + } + + Widget getDeliveryNotesWidget(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: lang(context).delivery_note, + ), + AppSpaces.verticalSmall, + CustomTextFieldForm( + readOnly: true, + hintText: 'Enter Delivery Note', + initialValue: cashierOrder.deliveryNotes ?? '', + onChanged: (String value) {}, + ), + ], + ); + } + + getPaymentModeWidget(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: lang(context).payment_mode, + ), + AppSpaces.verticalSmall, + getSelectedPaymentMode(cashierOrder.paymentMode ?? ''), + ], + ); + } + + getShowProductsWidget(StoreItems item, int position, int i) { + return CustomTextButtonIcon( + icon: Icons.arrow_drop_down, + heading: item.name.isEmpty ? 'Choose' : item.name, + onPressed: () {}, + ); + } + + getItemNotesWidget(String notes) { + return CustomTextFieldForm( + readOnly: true, + hintText: 'Enter item note', + initialValue: notes, + onChanged: (value) {}, + ); + } + + getItemQuantityWidget(String quantity) { + return CustomTextFieldForm( + readOnly: true, + hintText: 'Enter item quantity', + keyboardType: TextInputType.number, + initialValue: quantity, + onChanged: (value) {}, + ); + } + + getItemCostPriceWidget(String price) { + return CustomTextFieldForm( + readOnly: true, + hintText: 'Enter item price', + keyboardType: TextInputType.number, + initialValue: price, + onChanged: (value) {}, + ); + } + + getItemPriceWidget(StoreItems item) { + return ValueText( + (item.price * item.quantity!).toStringAsFixed(2), + ); + } +} diff --git a/lib/application/views/transactions/views/ViewPOSReturnVC.dart b/lib/application/views/transactions/views/ViewPOSReturnVC.dart new file mode 100644 index 0000000..95f63fd --- /dev/null +++ b/lib/application/views/transactions/views/ViewPOSReturnVC.dart @@ -0,0 +1,260 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/model/createOrder/CashierCart.dart'; +import 'package:wosull/application/model/store/StoreItemsResponse.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/widgets/ChildContainer.dart'; +import 'package:wosull/widgets/DialogHeader.dart'; +import 'package:wosull/widgets/HeadingContainer.dart'; +import 'package:wosull/widgets/HeadingText.dart'; +import 'package:wosull/widgets/ValueText.dart'; + +class ViewPOSReturnVC extends StatefulWidget { + List? orderDetails; + + ViewPOSReturnVC({super.key, required this.orderDetails}); + + @override + State createState() => _ViewPOSReturnVCState(); +} + +class _ViewPOSReturnVCState extends State { + bool isPortrait = true; + + @override + Widget build(BuildContext context) { + return Scaffold( + body: OrientationBuilder(builder: (c, orientation) { + isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; + + return SingleChildScrollView( + child: SizedBox( + width: !isPortrait + ? MediaQuery.of(context).size.width / 1.2 + : double.infinity, + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + DialogHeader(title: 'Order Details'), + AppSpaces.verticalMedium, + Container( + padding: const EdgeInsets.fromLTRB(8, 8, 8, 16), + child: Column( + children: [ + Container( + decoration: BoxDecoration( + borderRadius: const BorderRadius.all(Radius.circular( + 1.0) // <--- border radius here + ), + border: Border.all( + width: 1, color: MyColors.fillColorGray2), + color: MyColors.containerBackColor, + ), + height: 48, + child: Row( + children: [ + Expanded( + child: HeadingContainer( + heading: 'Name', + )), + Expanded( + child: HeadingContainer( + heading: 'Item Note', + )), + Expanded( + child: HeadingContainer( + heading: 'Quantity', + )), + Expanded( + child: HeadingContainer( + heading: 'Total Cost Price', + )), + Expanded( + child: HeadingContainer( + heading: 'Total Price', + )), + HeadingContainer( + width: 84, + heading: 'Total Amount', + ), + ], + ), + ), + ListView.builder( + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (context, position) { + return ListView.builder( + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (context, i) { + var item = + widget.orderDetails![position].items![i]; + + return Container( + decoration: BoxDecoration( + borderRadius: const BorderRadius.all( + Radius.circular( + 1.0) // <--- border radius here + ), + border: Border.all( + width: 1, color: MyColors.fillColorGray2), + color: MyColors.white, + ), + height: 48, + child: Row( + children: [ + Expanded( + child: ChildContainer( + child: Center( + child: ValueText(item.name ?? ''), + ), + ), + ), + Expanded( + child: ChildContainer( + child: Center( + child: ValueText(getItemNote(item)), + ), + )), + Expanded( + child: ChildContainer( + child: Center( + child: + ValueText(item.quantity.toString()), + ), + )), + Expanded( + child: ChildContainer( + child: Center( + child: ValueText( + (item.price).toStringAsFixed(2), + ), + ), + )), + Expanded( + child: ChildContainer( + child: Center( + child: ValueText( + (item.price * item.quantity!) + .toStringAsFixed(2), + ), + ), + )), + ChildContainer( + width: 84, + child: Center( + child: ValueText( + '', + ), + ), + ), + ], + ), + ); + }, + itemCount: + widget.orderDetails![position].items!.length, + ); + }, + itemCount: widget.orderDetails!.length, + ), + Container( + margin: const EdgeInsets.fromLTRB(0, 0, 0, 8), + decoration: BoxDecoration( + borderRadius: const BorderRadius.all(Radius.circular( + 1.0) // <--- border radius here + ), + border: Border.all( + width: 1, color: MyColors.fillColorGray2), + color: Colors.white, + ), + height: 48, + child: Row( + children: [ + Expanded( + child: HeadingContainer( + heading: '', + )), + Expanded( + child: HeadingContainer( + heading: '', + )), + Expanded( + child: HeadingContainer( + heading: '', + )), + Expanded( + child: HeadingContainer( + heading: '', + )), + Expanded( + child: HeadingContainer( + heading: '', + )), + ChildContainer( + width: 84, + child: Center( + child: HeadingText( + getItemsPriceWithModifier(), + ), + ), + ), + ], + ), + ), + ], + ), + ) + ], + ), + ), + ); + }), + ); + } + + String getItemsPriceWithModifier() { + double price = 0.0; + for (var order in widget.orderDetails!) { + for (var item in order.items!) { + price += (item.quantity! * item.price); + if (item.selectedModifiers!.isNotEmpty) { + for (var modi in item.selectedModifiers!) { + price += modi.price; + } + } + } + } + return price.toStringAsFixed(2); + } + + String getItemsPriceOnly() { + double price = 0.0; + for (var order in widget.orderDetails!) { + for (var item in order.items!) { + price += (item.quantity! * item.price); + } + } + + return price.toStringAsFixed(2); + } + + String getItemNote(StoreItems item) { + var text = ""; + for (var note in item.noteForItem!) { + if (text.isEmpty) { + text = note; + } else { + text = "$text,$note"; + } + } + return text; + } +} diff --git a/lib/application/views/transactions/widgets/CashierOrderListView.dart b/lib/application/views/transactions/widgets/CashierOrderListView.dart new file mode 100644 index 0000000..eb516f0 --- /dev/null +++ b/lib/application/views/transactions/widgets/CashierOrderListView.dart @@ -0,0 +1,297 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/application/model/reports/CashierOrder.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/helpers/Utils.dart'; +import 'package:wosull/widgets/ActionPopUpContainer.dart'; +import 'package:wosull/widgets/CustomPopuoMenuButton.dart'; +import 'package:wosull/widgets/EmptyDataWidget.dart'; +import 'package:wosull/widgets/HeadingText.dart'; +import 'package:wosull/widgets/ListHeadingContainer.dart'; +import 'package:wosull/widgets/ValueText.dart'; + +class CashierOrderListView extends StatelessWidget { + List posOrders = []; + bool isPortrait = false; + bool? isOrder = false; + final void Function(CashierOrder order) onReturn; + final void Function(CashierOrder order) onDamage; + final void Function(CashierOrder order) onView; + final void Function(CashierOrder order) onEdit; + final void Function(CashierOrder order) onDelete; + + CashierOrderListView( + {super.key, + required this.onReturn, + required this.onDamage, + required this.onView, + required this.onEdit, + required this.onDelete, + required this.posOrders, + required this.isPortrait, + this.isOrder}); + + @override + Widget build(BuildContext context) { + return posOrders.isEmpty + ? const EmptyDataWidget() + : Column( + children: [ + isPortrait + ? Container() + : ListHeadingContainer( + child: Row( + children: [ + Expanded( + child: HeadingText( + 'Reference Number', + )), + Expanded( + child: HeadingText( + 'Transaction Code', + )), + Expanded( + child: HeadingText(lang(context).order_number)), + Expanded( + child: HeadingText(lang(context).store_name)), + Expanded(child: HeadingText(lang(context).status)), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: + HeadingText(lang(context).created_on))), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: + HeadingText(lang(context).updated_on))), + SizedBox( + width: 56, + child: HeadingText(lang(context).action), + ), + ], + ), + ), + ListView.builder( + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (c, position) { + if (isPortrait) { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + color: MyColors.white, + child: Container( + padding: const EdgeInsets.fromLTRB(8, 0, 0, 8), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + child: Container( + padding: const EdgeInsets.only(top: 16), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + HeadingText( + 'Reference Number', + ), + AppSpaces.verticalMedium, + HeadingText( + 'Transaction Code', + ), + AppSpaces.verticalMedium, + HeadingText( + lang(context).order_number, + ), + AppSpaces.verticalMedium, + HeadingText( + lang(context).store_name, + ), + AppSpaces.verticalMedium, + HeadingText( + lang(context).status, + ), + AppSpaces.verticalMedium, + HeadingText( + lang(context).created_on, + ), + AppSpaces.verticalMedium, + HeadingText(lang(context).updated_on), + AppSpaces.verticalMedium, + ], + )), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + ValueText( + posOrders[position] + .referenceNo! + .toString(), + ), + AppSpaces.verticalMedium, + ValueText( + posOrders[position].transactionId ?? '', + ), + AppSpaces.verticalMedium, + ValueText( + posOrders[position] + .uniqueId! + .toString(), + ), + AppSpaces.verticalMedium, + ValueText( + posOrders[position].storeId!.name ?? '', + ), + AppSpaces.verticalMedium, + Text( + posOrders[position] + .status! + .toCapitalized(), + style: posOrders[position].status == + 'completed' + ? ThemeText.textStyleValueGreen + : ThemeText.textStyleValueRed, + ), + AppSpaces.verticalMedium, + ValueText( + DataTimeFormat.getFormatDate( + posOrders[position].createdAt ?? + ''), + ), + AppSpaces.verticalMedium, + ValueText(DataTimeFormat.getFormatDate( + posOrders[position].updatedAt ?? '')), + AppSpaces.verticalMedium, + ], + )), + ], + ), + )), + getPopUpMenu(position) + ], + ), + ), + ); + } else { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: ListHeadingContainer( + child: Row( + children: [ + Expanded( + child: ValueText( + posOrders[position].referenceNo!.toString(), + )), + Expanded( + child: ValueText( + posOrders[position].transactionId ?? '', + )), + Expanded( + child: ValueText( + posOrders[position].uniqueId!.toString(), + )), + Expanded( + child: ValueText( + posOrders[position].storeId!.name, + )), + Expanded( + child: Text( + posOrders[position].status!.toCapitalized(), + style: posOrders[position].status == 'completed' + ? ThemeText.textStyleValueGreen + : ThemeText.textStyleValueRed, + )), + Expanded( + child: ValueText( + DataTimeFormat.getFormatDate( + posOrders[position].createdAt!), + )), + Expanded( + child: ValueText( + DataTimeFormat.getFormatDate( + posOrders[position].updatedAt!), + )), + Padding( + padding: const EdgeInsets.all(4), + child: Align( + alignment: Alignment.centerRight, + child: ActionPopUpContainer( + child: getPopUpMenu(position), + ), + ), + ) + ], + ), + ), + ); + } + }, + itemCount: posOrders.length, + ) + ], + ); + } + + List> getPopUpMenuButton(String? status) { + if (isOrder! && status! == 'completed') { + return [ + PopupMenuItem( + value: 'return', + child: ValueText('Return'), + ), + PopupMenuItem( + value: 'damage', + child: ValueText('Damage'), + ), + ]; + } else if (isOrder! && status! == 'cancelled') { + return []; + } else { + return [ + PopupMenuItem( + value: 'view', + child: ValueText('View'), + ), + ]; + } + } + + void actionPopUpItemSelected(String value, CashierOrder order) { + if (value == 'delete') { + onDelete(order); + } else if (value == 'edit') { + onEdit(order); + } else if (value == 'return') { + onReturn(order); + } else if (value == 'damage') { + onDamage(order); + } else if (value == 'view') { + onView(order); + } + } + + getPopUpMenu(int position) { + return CustomPopupMenuButton( + onSelected: (String value) => + actionPopUpItemSelected(value, posOrders[position]), + items: getPopUpMenuButton(posOrders[position].status), + ); + } +} diff --git a/lib/application/views/transactions/widgets/EditOrderViewModel.dart b/lib/application/views/transactions/widgets/EditOrderViewModel.dart new file mode 100644 index 0000000..c17cd4f --- /dev/null +++ b/lib/application/views/transactions/widgets/EditOrderViewModel.dart @@ -0,0 +1,351 @@ +import 'package:async/async.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:objectbox/objectbox.dart'; +import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/application/model/SimpleResponsModel.dart'; +import 'package:wosull/application/model/StockTransfer/ProductItemCategoryModel.dart'; +import 'package:wosull/application/model/createOrder/CashierCart.dart'; +import 'package:wosull/application/model/reports/CashierOrder.dart'; +import 'package:wosull/application/model/store/GetSpecificStores.dart'; +import 'package:wosull/application/model/store/StoreItemsResponse.dart'; +import 'package:wosull/application/model/store/StoreServiceModel.dart'; +import 'package:wosull/application/model/store/StoreServiceResponse.dart'; +import 'package:wosull/application/model/store/WosulStore.dart'; +import 'package:wosull/application/model/tables/GetStoreTable.dart'; +import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/utils/CRUDOperatoinState.dart'; +import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/helpers/Utils.dart'; + +class EditOrderViewModel with ChangeNotifier { + var items = [ + 'Cash', + 'Card Machine', + ]; + var statusItems = [ + 'Completed', + 'Cancelled', + 'Return', + ]; + + var storeItems = []; + List tables = []; + List stores = []; + bool isPortrait = true; + late AsyncMemoizer _memoizer; + + late CashierOrder cashierOrder; + List> itemNotesController = [[]]; + List> itemQuantityController = [[]]; + List> itemCostPriceController = [[]]; + + dynamic selectedStatus; + dynamic selectedStore; + dynamic selectedOrderType; + dynamic selectedPaymentMode; + dynamic selectedTable; + + bool isLoading = false; + + var _crudOperation = CRUDOperationState.uninitialized; + + CRUDOperationState get crudOperation => _crudOperation; + + void disposeData() { + isLoading = false; + itemNotesController.clear(); + itemQuantityController.clear(); + itemCostPriceController.clear(); + selectedStatus = null; + selectedStore = null; + selectedOrderType = null; + selectedPaymentMode = null; + selectedTable = null; + } + + setLoading(bool value) { + isLoading = value; + notifyListeners(); + } + + void initData(CashierOrder cashierOrder) { + this.cashierOrder = cashierOrder; + selectedStatus = cashierOrder.status!.toCapitalized(); + selectedPaymentMode = cashierOrder.paymentMode!.toCapitalized(); + fillControllersData(); + _memoizer = AsyncMemoizer(); + } + + void fillControllersData() { + itemNotesController.clear(); + itemQuantityController.clear(); + itemCostPriceController.clear(); + for (int i = 0; i < cashierOrder.cart!.orderDetails!.length; i++) { + itemNotesController.add([]); + itemQuantityController.add([]); + itemCostPriceController.add([]); + for (int j = 0; + j < cashierOrder.cart!.orderDetails![i].items!.length; + j++) { + var item = cashierOrder.cart!.orderDetails![i].items![j]; + var text = ""; + item.noteForItem ??= []; + for (var note in item.noteForItem!) { + if (text.isEmpty) { + text = note; + } else { + text = "$text,$note"; + } + } + + itemNotesController[i].add(text); + itemQuantityController[i].add(item.quantity.toString()); + itemCostPriceController[i].add(item.price.toString()); + } + } + } + + Future updateOrder() async { + setLoading(true); + final map = cashierOrder.toJson(); + + await APIManager() + .fetchData(Constants.UPDATE_CASHIER_ORDER, map) + .then((value) { + final response = SimpleResponseModel.fromJson(value); + Utils.showMessage(response.message); + if (response.success) { + _crudOperation = CRUDOperationState.add; + } else { + _crudOperation = CRUDOperationState.error; + } + setLoading(false); + }).onError((error, stackTrace) { + _crudOperation = CRUDOperationState.error; + setLoading(false); + }); + } + + void addNewItem() { + final orderDetails = CashierOrderDetails(); + orderDetails.productId = ""; + orderDetails.items = []; + final storeItem = StoreItems( + name: 'Choose', + price: 0.0, + quantity: 0, + modifiers: ToMany(items: []), + deliveryPartners: ToMany(items: []), + comboProduct: ToMany(items: []), + ingredients: ToMany(items: []), + selectedModifiers: ToMany(items: []), + selectedCombos: ToMany(items: [])); + orderDetails.items!.add(storeItem); + cashierOrder.cart!.orderDetails!.add(orderDetails); + fillControllersData(); + notifyListeners(); + } + + void removeItemFromCart(int parentPosition, int child) { + cashierOrder.returnOrderDetails! + .add(cashierOrder.cart!.orderDetails![parentPosition]); + + cashierOrder.cart!.orderDetails![parentPosition].items!.removeAt(child); + //check if all items deleted + if (cashierOrder.cart!.orderDetails![parentPosition].items!.isEmpty) { + cashierOrder.cart!.orderDetails!.removeAt(parentPosition); + } + fillControllersData(); + notifyListeners(); + } + + Future> getService() async { + _memoizer.runOnce(() async { + // This below code will call only ones. This will return the same data directly without performing any Future task. + Map data = { + 'store_id': sharedPrefs.storeId, + }; + await APIManager() + .fetchData(Constants.Store_services_URL, data) + .then((value) { + final response = StoreServiceResponse.fromJson(value); + if (response.success) { + storeItems.addAll(response.services); + selectedOrderType = storeItems + .singleWhere((element) => element.name == cashierOrder.orderType); + selectedOrderType ??= StoreServiceModel(name: 'N/A'); + } + notifyListeners(); + }).onError((error, stackTrace) {}); + }); + return storeItems; + } + + Future> getTablesList() async { + if (cashierOrder.orderType!.toLowerCase().compareTo('dinein') == 0) { + await APIManager() + .fetchData(Constants.GET_STORE_TABLES, Constants.getStorePayload()) + .then((value) { + final response = GetStoreTable.fromJson(value); + if (response.success) { + tables.clear(); + tables.addAll(response.storeTables); + // selectedTable = tables.singleWhere((element) => element.id! == cashierOrder.storeId!.id!); + } + }).onError((error, stackTrace) {}); + } + selectedTable ??= StoreTable(id: '', tableName: 'N/A', noOfOccupants: 0); + return tables; + } + + Future> getSubStores() async { + await APIManager() + .fetchData(Constants.GET_STORE_SUB_STORES, Constants.getStorePayload()) + .then((value) { + final response = GetSpecificStores.fromJson(value); + if (response.success) { + stores.clear(); + stores.addAll(response.stores); + selectedStore = stores + .singleWhere((element) => element.id == cashierOrder.storeId!.id); + } + selectedStore ??= WosulStore(id: '', name: 'Choose'); + }).onError((error, stackTrace) {}); + return stores; + } + + void updateItem(int parent, int child, result) { + ProductItem item = result; + final orderDetails = CashierOrderDetails(); + orderDetails.productId = item.productId; + orderDetails.items = []; + final storeItem = StoreItems( + deliveryPartners: ToMany(items: []), + modifiers: ToMany(items: item.modifiers!), + comboProduct: ToMany(items: item.comboProduct!), + ingredients: ToMany(items: item.ingredients!), + selectedModifiers: ToMany(items: []), + name: item.name!, + price: item.price!, + quantity: 0, + uniqueIdForStoreData: item.uniqueIdForStoreData!, + productId: item.productId!, + selectedCombos: ToMany(items: []), + ); + orderDetails.items!.add(storeItem); + cashierOrder.cart!.orderDetails![parent] = orderDetails; + fillControllersData(); + notifyListeners(); + } + + String getItemsPriceWithModifier() { + double price = 0.0; + for (var order in cashierOrder.cart!.orderDetails!) { + for (var item in order.items!) { + price += (item.quantity! * item.price); + if (item.selectedModifiers.isNotEmpty) { + for (var modi in item.selectedModifiers) { + price += modi.price; + } + } + } + } + cashierOrder.changeBalanceAmount = (cashierOrder.amount! - price); + print(cashierOrder.changeBalanceAmount.toString()); + + return price.toStringAsFixed(2); + } + + String getItemsPriceOnly() { + double price = 0.0; + for (var order in cashierOrder.cart!.orderDetails!) { + for (var item in order.items!) { + price += (item.quantity! * item.price); + } + } + + return price.toStringAsFixed(2); + } + + void updateItemNote(int position, int i, String value) { + cashierOrder.cart!.orderDetails![position].items![i].noteForItem! + .add(value); + } + + void updateQuantity(int position, int i, String value) { + if (value.isNotEmpty) { + cashierOrder.cart!.orderDetails![position].items![i].quantity = + int.parse(value); + } else { + cashierOrder.cart!.orderDetails![position].items![i].quantity = 0; + } + notifyListeners(); + } + + void updateItemPrice(int position, int i, String value) { + if (value.isNotEmpty) { + cashierOrder.cart!.orderDetails![position].items![i].price = + double.parse(value); + } else { + cashierOrder.cart!.orderDetails![position].items![i].price = 0; + } + notifyListeners(); + } + + void updateOrderAmount(String value) { + if (value.isNotEmpty) { + cashierOrder.amount = double.parse(value); + } else { + cashierOrder.amount = 0; + } + getItemsPriceWithModifier(); + notifyListeners(); + } + + void updateDeliveryNotes(String value) { + cashierOrder.deliveryNotes = value; + } + + void setSelectedTable(StoreTable? data) { + selectedTable = data; + if (data != null) { + cashierOrder.table = data.tableName; + } else { + cashierOrder.table = ''; + } + } + + void setSelectedOrderType(StoreServiceModel? data) { + selectedOrderType = data; + if (data != null) { + cashierOrder.orderType = data.name!; + } else { + cashierOrder.orderType = ''; + } + } + + void setSelectedStore(WosulStore? data) { + selectedStore = data; + if (data != null) { + cashierOrder.storeId = data; + } + } + + void setSelectedPaymentMode(String? data) { + selectedPaymentMode = data; + if (data != null) { + cashierOrder.paymentMode = data; + } else { + cashierOrder.paymentMode = ''; + } + } + + void setOrderStatus(String? data) { + selectedStatus = data; + if (data != null) { + cashierOrder.status = data.toLowerCase(); + } else { + cashierOrder.status = ''; + } + } +} diff --git a/lib/application/views/transactions/widgets/TransactionCashierOrderListView.dart b/lib/application/views/transactions/widgets/TransactionCashierOrderListView.dart new file mode 100644 index 0000000..4c8ed53 --- /dev/null +++ b/lib/application/views/transactions/widgets/TransactionCashierOrderListView.dart @@ -0,0 +1,400 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/application/model/reports/CashierOrder.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/helpers/Utils.dart'; +import 'package:wosull/widgets/ActionPopUpContainer.dart'; +import 'package:wosull/widgets/CustomPopuoMenuButton.dart'; +import 'package:wosull/widgets/EmptyDataWidget.dart'; +import 'package:wosull/widgets/HeadingText.dart'; +import 'package:wosull/widgets/ListHeadingContainer.dart'; +import 'package:wosull/widgets/ValueText.dart'; + +class TransactionCashierOrderListView extends StatelessWidget { + List posOrders = []; + bool isPortrait = false; + final void Function(CashierOrder order) onView; + + TransactionCashierOrderListView( + {super.key, + required this.posOrders, + required this.onView, + required this.isPortrait}); + + @override + Widget build(BuildContext context) { + return posOrders.isEmpty + ? const EmptyDataWidget() + : Column( + children: [ + isPortrait + ? Container() + : ListHeadingContainer( + child: Row( + children: [ + Expanded( + child: HeadingText( + 'Transaction Number', + )), + Expanded( + child: HeadingText( + 'Reference Number', + )), + Expanded( + child: HeadingText(lang(context).order_number)), + Expanded( + child: HeadingText(lang(context).store_name)), + Expanded(child: HeadingText('Order Type')), + Expanded(child: HeadingText('Payment Mode')), + Expanded(child: HeadingText('Total Amount')), + Expanded( + child: + HeadingText('Amount Received from customer')), + Expanded( + child: HeadingText('Change given to customer')), + Expanded(child: HeadingText('Status')), + Expanded(child: HeadingText('Created On')), + Expanded(child: HeadingText('Updated On')), + SizedBox( + width: 56, + child: HeadingText(lang(context).action), + ), + ], + ), + ), + ListView.builder( + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (c, position) { + if (isPortrait) { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + color: MyColors.white, + child: Container( + padding: const EdgeInsets.fromLTRB(8, 0, 0, 8), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + child: Container( + padding: const EdgeInsets.only(top: 16), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + HeadingText( + 'Transaction Number', + ), + ValueText( + posOrders[position] + .transactionId! + .toString(), + ), + ], + ), + AppSpaces.verticalMedium, + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + HeadingText( + 'Reference Number', + ), + ValueText( + posOrders[position] + .referenceNo + ?.toString() ?? + '', + ), + ], + ), + AppSpaces.verticalMedium, + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + HeadingText( + lang(context).order_number, + ), + ValueText( + posOrders[position] + .uniqueId + ?.toString() ?? + '', + ), + ], + ), + AppSpaces.verticalMedium, + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + HeadingText( + lang(context).store_name, + ), + ValueText( + posOrders[position].storeId!.name ?? + '', + ), + ], + ), + AppSpaces.verticalMedium, + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + HeadingText( + lang(context).order_type, + ), + ValueText( + posOrders[position].orderType ?? '', + ), + ], + ), + AppSpaces.verticalMedium, + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + HeadingText( + lang(context).payment_mode, + ), + ValueText( + posOrders[position].paymentMode ?? + '', + ), + ], + ), + AppSpaces.verticalMedium, + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + HeadingText( + lang(context).total_amount, + ), + ValueText( + posOrders[position] + .totalAmount + ?.toStringAsFixed(2) ?? + '', + ), + ], + ), + AppSpaces.verticalMedium, + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + HeadingText( + 'Amount Received from customer', + ), + ValueText( + posOrders[position] + .amount + ?.toStringAsFixed(2) ?? + '', + ), + ], + ), + AppSpaces.verticalMedium, + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + HeadingText( + 'Change given to customer', + ), + ValueText( + posOrders[position] + .changeBalanceAmount + ?.toStringAsFixed(2) ?? + '', + ), + ], + ), + AppSpaces.verticalMedium, + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + HeadingText( + lang(context).status, + ), + ValueText( + posOrders[position] + .status + ?.toCapitalized() ?? + '', + ), + ], + ), + AppSpaces.verticalMedium, + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + HeadingText( + lang(context).created_on, + ), + ValueText( + DataTimeFormat.getFormatDate( + posOrders[position].createdAt ?? + ''), + ), + ], + ), + AppSpaces.verticalMedium, + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + HeadingText( + lang(context).updated_on, + ), + ValueText( + DataTimeFormat.getFormatDate( + posOrders[position].updatedAt ?? + ''), + ), + ], + ), + ], + )), + ], + ), + )), + getPopUpMenu(position) + ], + ), + ), + ); + } else { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: ListHeadingContainer( + child: Row( + children: [ + Expanded( + child: ValueText( + posOrders[position].transactionId!.toString(), + )), + Expanded( + child: ValueText( + posOrders[position].referenceNo?.toString() ?? '', + )), + Expanded( + child: ValueText( + posOrders[position].uniqueId!.toString(), + )), + Expanded( + child: ValueText( + posOrders[position].storeId!.name, + )), + Expanded( + child: ValueText( + posOrders[position].orderType ?? '', + )), + Expanded( + child: ValueText( + posOrders[position].paymentMode ?? '', + )), + Expanded( + child: ValueText( + posOrders[position] + .totalAmount + ?.toStringAsFixed(2) ?? + '0', + )), + Expanded( + child: ValueText( + posOrders[position].amount?.toStringAsFixed(2) ?? + '0', + )), + Expanded( + child: ValueText( + posOrders[position] + .changeBalanceAmount + ?.toStringAsFixed(2) ?? + '0', + )), + Expanded( + child: Text( + posOrders[position].status!.toCapitalized(), + style: posOrders[position].status == 'completed' + ? ThemeText.textStyleValueGreen + : ThemeText.textStyleValueRed, + )), + Expanded( + child: ValueText( + DataTimeFormat.getFormatDate( + posOrders[position].createdAt!), + )), + Expanded( + child: ValueText( + DataTimeFormat.getFormatDate( + posOrders[position].updatedAt!), + )), + Padding( + padding: const EdgeInsets.all(4), + child: Align( + alignment: Alignment.centerRight, + child: ActionPopUpContainer( + child: getPopUpMenu(position), + ), + ), + ) + ], + ), + ), + ); + } + }, + itemCount: posOrders.length, + ) + ], + ); + } + + getPopUpMenu(int position) { + return CustomPopupMenuButton( + onSelected: (String value) => + actionPopUpItemSelected(value, posOrders[position]), + items: getPopUpMenuButton(posOrders[position].status), + ); + } + + void actionPopUpItemSelected(String value, CashierOrder order) { + if (value == 'view') { + onView(order); + } + } + + List> getPopUpMenuButton(String? status) { + return [ + PopupMenuItem( + value: 'view', + child: ValueText('View'), + ), + ]; + } +} diff --git a/lib/database/SyncDatabase.dart b/lib/database/SyncDatabase.dart index 2e5a8fc..9bb8dbb 100644 --- a/lib/database/SyncDatabase.dart +++ b/lib/database/SyncDatabase.dart @@ -3,10 +3,14 @@ import 'dart:convert'; import 'package:objectbox/objectbox.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; import 'package:wosull/application/model/Combo/GetComboModel.dart'; +import 'package:wosull/application/model/CreateAndUpdateOrder.dart'; import 'package:wosull/application/model/DeliveryPartner/GetDeliveryPartner.dart'; +import 'package:wosull/application/model/cart/GetCartModel.dart'; +import 'package:wosull/application/model/createOrder/OrderDetails.dart'; import 'package:wosull/application/model/discount/StoreDiscountModel.dart'; import 'package:wosull/application/model/inventory/ItemSubCategoryResponse.dart'; import 'package:wosull/application/model/inventory/category/ItemCategoryResponse.dart'; +import 'package:wosull/application/model/store/GetStoreOrderModel.dart'; import 'package:wosull/application/model/store/StoreItemsResponse.dart'; import 'package:wosull/application/model/tables/GetStoreTable.dart'; import 'package:wosull/application/network/APIManager.dart'; @@ -138,7 +142,6 @@ class SyncDatabase { Future fillItems(String selectedProductId, List items) async { for (var item in items) { - item.quantity = 1; item.productId = selectedProductId; itemsList.add(item); } @@ -150,9 +153,9 @@ class SyncDatabase { (combo) => { itemsList.add(StoreItems( imageUrl: '', - quantity: 1, + id: 0, productId: selectedProductId, - id: combo.id!, + itemId: combo.id!, isCombo: true, name: combo.comboName!, price: combo.comboPrice, @@ -184,4 +187,121 @@ class SyncDatabase { return items; } + + Future uploadOrders() async { + var allOrders = await objectbox.getAllOrders(); + + print('order length ' + allOrders.length.toString()); + + await Future.forEach( + allOrders, (element) async => {await createCart(element)}); + + Utils.showMessage('Order Uploaded'); + } + + Future createCart(CreateAndUpdateOrder order) async { + try { + order.orderDetails = ToMany( + items: List.from(jsonDecode(order.orderDetailsOffline!)) + .map((i) => OrderDetails.fromJson(i)) + .toList()); + + await APIManager() + .fetchData(Constants.CREATE_UPDATE_ORDER, order.toJson()) + .then((value) async { + final response = NewCartModel.fromJson(value); + order.cartId = response.cartId ?? ''; + print('cartId ' + order.cartId.toString()); + if (response.success!) { + await objectbox.removeOrder(order.obid); + await createOrder(order); + } + }).onError((error, stackTrace) { + print(stackTrace.toString()); + }); + } catch (e) { + print(e.toString()); + } + } + + //create order + //send to kitchen + //ready from kithcen and payment false + // + + Future createOrder(CreateAndUpdateOrder order) async { + Map data = {}; + + //possiblity + + //order is ready from kitchen + + if (order.paymentStatus) { + //when user did the payment + //send to kitchen after payment preparing + //complete the order after payment + data = { + 'payment_mode': order.paymentMode, + 'total_discount': order.totalDiscount, + 'discountId': order.discountId, + 'billing_counter_id': sharedPrefs.billingCounterId, + 'store_id': sharedPrefs.storeId, + 'cart_id': order.cartId, + 'order_type': order.orderType, + 'status': order.orderStatus, + 'payment_status': order.paymentStatus, + 'change_balance_amount': order.changeBalanceAmount, + 'delivery_notes': order.deliveryNotes, + 'timer': order.timer, + 'amount': order.amount, + 'total_amount': order.totalAmount, + }; + } else { + //simple when user create order and sent to kitchen / hold order + //order status will be preparing/hold order + data = { + 'billing_counter_id': sharedPrefs.billingCounterId, + 'store_id': sharedPrefs.storeId, + 'cart_id': order.cartId, + 'order_type': order.orderType, + 'status': order.orderStatus, + 'payment_status': order.paymentStatus, + // 'orderId': CreateAndUpdateOrder.cartOrder.orderId!, + }; + } + await APIManager() + .fetchData(Constants.CREATE_ORDER, data) + .then((value) async { + final response = GetStoreOrderModel.fromJson(value); + if (response.success!) { + var orderID = response.orderModel!.id ?? ''; + + if (order.orderStatus == Constants.ready && !order.paymentStatus) { + //means order is ready from kitchen but not yet paid + //then will update order to server + await update(orderID, Constants.ready); + } else if (order.paymentStatus && + order.orderStatus == Constants.completed) { + await update(orderID, Constants.completed); + } + } else {} + }).onError((error, stackTrace) { + print(stackTrace.toString()); + }); + } + + Future update(String id, String status) async { + Map data = { + 'store_id': sharedPrefs.storeId, + 'order_id': id, + 'status': status + }; + + print(jsonEncode(data)); + + await APIManager() + .fetchData(Constants.UPDATE_ORDER_STATUS, data) + .then((result) {}) + .onError((error, stackTrace) {}); + } } diff --git a/lib/database/objectbox.dart b/lib/database/objectbox.dart index b4b95b1..19ef302 100644 --- a/lib/database/objectbox.dart +++ b/lib/database/objectbox.dart @@ -1,3 +1,5 @@ +import 'dart:convert'; + import 'package:path/path.dart' as p; import 'package:path_provider/path_provider.dart'; import 'package:wosull/application/model/CreateAndUpdateOrder.dart'; @@ -7,6 +9,7 @@ import 'package:wosull/application/model/inventory/ItemSubCategoryResponse.dart' import 'package:wosull/application/model/inventory/category/ItemCategory.dart'; import 'package:wosull/application/model/store/StoreItemsResponse.dart'; import 'package:wosull/application/model/tables/GetStoreTable.dart'; +import 'package:wosull/application/utils/Constants.dart'; import 'package:wosull/objectbox.g.dart'; import '../application/model/store/StoreServiceModel.dart'; @@ -40,66 +43,33 @@ class ObjectBox { /// Create an instance of ObjectBox to use throughout the app. static Future create() async { - // Note: setting a unique directory is recommended if running on desktop - // platforms. If none is specified, the default directory is created in the - // users documents directory, which will not be unique between apps. - // On mobile this is typically fine, as each app has its own directory - // structure. - - // Future openStore() {...} is defined in the generated objectbox.g.dart final store = await openStore( directory: p.join( (await getApplicationDocumentsDirectory()).path, "obx-wosul")); return ObjectBox._create(store); } - Future updateOrder( - int uniqueId, String productId, String itemId, bool value) async { - var order = _createUpdateOrderBox.get(uniqueId); - var orderDetails = order!.orderDetails[0]; - var items = orderDetails.items[0]; - items.status = true; - - orderDetails.items[0] = items; - order.orderDetails[0] = orderDetails; - - // final query = _createUpdateOrderBox - // .query(CreateAndUpdateOrder_.obid.equals(uniqueId)) - // .build(); - // - // query.find().print('befire' + - // order!.orderDetails - // .singleWhere((element) => element.productId == productId) - // .items - // .singleWhere((element) => element.id == itemId) - // .status - // .toString()); - // order.orderDetails - // .singleWhere((element) => element.productId == productId) - // .items - // .singleWhere((element) => element.id == itemId) - // .status = value; - // print('after' + - // order.orderDetails - // .singleWhere((element) => element.productId == productId) - // .items - // .singleWhere((element) => element.id == itemId) - // .status - // .toString()); - _createUpdateOrderBox.putAsync(order); - } - Future addOrder(CreateAndUpdateOrder order) async { - _createUpdateOrderBox.putAsync(order); + var orderDetails = jsonEncode(order.orderDetails); + + order.orderDetailsOffline = orderDetails; + order.orderDetails.clear(); + await _createUpdateOrderBox.putAsync(order); } - CreateAndUpdateOrder getOrderById(int id) { - return _createUpdateOrderBox.get(id)!; + Future updateOrder(CreateAndUpdateOrder order) async { + var newOrder = await getOrderById(order.cartUniqueId); + newOrder = order; + print(newOrder.orderStatus); + _createUpdateOrderBox.put(newOrder, mode: PutMode.update); + } - // Query query - // = _createUpdateOrderBox.query(CreateAndUpdateOrder_.obid.equals(id)).build(); - // - // return query.find().singleWhere((element) => element.obid == id); + Future getOrderById(int id) async { + var query = _createUpdateOrderBox + .query(CreateAndUpdateOrder_.cartUniqueId.equals(id)) + .build(); + var list = query.find().toList(); + return list.first; } Future removeOrder(int id) async { @@ -107,27 +77,47 @@ class ObjectBox { } Future> getOrdersList(String orderStatus) async { - // QueryBuilder builder; var items = []; var query = _createUpdateOrderBox .query(CreateAndUpdateOrder_.orderStatus.equals(orderStatus)) .build(); - - // final list = - // builder.watch(triggerImmediately: true).map((query) => query.find()); - items.addAll(query.find().toList()); + return items; + } + Future> getAllOrders() async { + var items = []; + var query = _createUpdateOrderBox + .query(CreateAndUpdateOrder_.orderStatus.equals(Constants.ready).or( + CreateAndUpdateOrder_.orderStatus.equals(Constants.preparing).or( + CreateAndUpdateOrder_.orderStatus + .equals(Constants.completed) + .or(CreateAndUpdateOrder_.orderStatus + .equals(Constants.holdOrder)) + .or(CreateAndUpdateOrder_.orderStatus + .equals(Constants.cancelled))))) + .build(); + items.addAll(query.find().toList()); return items; } Stream> getOrders(String orderStatus) { QueryBuilder builder; - builder = _createUpdateOrderBox .query(CreateAndUpdateOrder_.orderStatus.equals(orderStatus)); final list = builder.watch(triggerImmediately: true).map((query) => query.find()); + + return list; + } + + Stream> getHoldOrders() { + QueryBuilder builder; + builder = _createUpdateOrderBox.query(CreateAndUpdateOrder_.orderStatus + .equals(Constants.holdOrder) + .or(CreateAndUpdateOrder_.orderStatus.equals(Constants.ready))); + final list = + builder.watch(triggerImmediately: true).map((query) => query.find()); return list; } @@ -147,7 +137,6 @@ class ObjectBox { .watch(triggerImmediately: true) // Map it to a list of notes to be used by a StreamBuilder. .map((query) => query.find()); - // print('here ' + list.first.asStream().first.toString()); return list; } @@ -155,16 +144,9 @@ class ObjectBox { _storeDiscountBox.putManyAsync(discounts); Stream> getDiscounts() { - // Query for all notes, sorted by their date. - // https://docs.objectbox.io/queries final builder = _storeDiscountBox.query(); - // Build and watch the query, - // set triggerImmediately to emit the query immediately on listen. - final list = builder - .watch(triggerImmediately: true) - // Map it to a list of notes to be used by a StreamBuilder. - .map((query) => query.find()); - // print('here ' + list.first.asStream().first.toString()); + final list = + builder.watch(triggerImmediately: true).map((query) => query.find()); return list; } @@ -172,24 +154,15 @@ class ObjectBox { _storeTablesBox.putManyAsync(tables); Stream> getTablesWithOccupants(int noOfOccupants) { - // Query for all notes, sorted by their date. - // https://docs.objectbox.io/queries QueryBuilder builder; if (noOfOccupants == 0) { - //get all builder = _storeTablesBox.query(); } else { builder = _storeTablesBox .query(StoreTable_.noOfOccupants.equals(noOfOccupants)); } - // final builder = _storeTablesBox.query(); - // Build and watch the query, - // set triggerImmediately to emit the query immediately on listen. - final list = builder - .watch(triggerImmediately: true) - // Map it to a list of notes to be used by a StreamBuilder. - .map((query) => query.find()); - // print('here ' + list.first.asStream().first.toString()); + final list = + builder.watch(triggerImmediately: true).map((query) => query.find()); return list; } @@ -197,15 +170,8 @@ class ObjectBox { _categoryBox.putManyAsync(categories); Stream> getCategories() { - // Query for all notes, sorted by their date. - // https://docs.objectbox.io/queries final builder = _categoryBox.query(); - // Build and watch the query, - // set triggerImmediately to emit the query immediately on listen. - return builder - .watch(triggerImmediately: true) - // Map it to a list of notes to be used by a StreamBuilder. - .map((query) => query.find()); + return builder.watch(triggerImmediately: true).map((query) => query.find()); } Future addItem(StoreItems item) => _itemsBox.putAsync(item); @@ -217,34 +183,23 @@ class ObjectBox { _subCategoryBox.putManyAsync(subCategories); Stream> getItems(String productId, String deliveryId) { - // Query for all notes, sorted by their date. - // https://docs.objectbox.io/queries - // QueryBuilder builder; - // - // builder = _itemsBox.query(StoreItems_.productId.equals(productId)); - final builder = _itemsBox.query(StoreItems_.productId.equals(productId)); + return builder.watch(triggerImmediately: true).map((query) => query.find()); + } - // Build and watch the query, - // set triggerImmediately to emit the query immediately on listen. - return builder - .watch(triggerImmediately: true) - // Map it to a list of notes to be used by a StreamBuilder. - .map((query) => query.find()); + List searchItems(String itemName) { + var items = []; + var query = _itemsBox + .query(StoreItems_.name.startsWith(itemName, caseSensitive: false)) + .build(); + items.addAll(query.find().toList()); + return items; } Stream> getSubCategories(String categoryId) { - // Query for all notes, sorted by their date. - // https://docs.objectbox.io/queries - final builder = _subCategoryBox.query(ItemSubCategory_.categoryId.equals(categoryId)); - // Build and watch the query, - // set triggerImmediately to emit the query immediately on listen. - return builder - .watch(triggerImmediately: true) - // Map it to a list of notes to be used by a StreamBuilder. - .map((query) => query.find()); + return builder.watch(triggerImmediately: true).map((query) => query.find()); } Future addServices(List services) async { @@ -253,15 +208,8 @@ class ObjectBox { } Stream> getServices() { - // Query for all notes, sorted by their date. - // https://docs.objectbox.io/queries final builder = _servicesBox.query(); - // Build and watch the query, - // set triggerImmediately to emit the query immediately on listen. - return builder - .watch(triggerImmediately: true) - // Map it to a list of notes to be used by a StreamBuilder. - .map((query) => query.find()); + return builder.watch(triggerImmediately: true).map((query) => query.find()); } Future remove() async { diff --git a/lib/helpers/DatePicker.dart b/lib/helpers/DatePicker.dart new file mode 100644 index 0000000..9acf929 --- /dev/null +++ b/lib/helpers/DatePicker.dart @@ -0,0 +1,22 @@ +import 'package:flutter/material.dart'; + +class DatePicker { + static Future presentDatePicker( + BuildContext context, bool isStart) async { + // showDatePicker is a pre-made function of Flutter + late DateTime date; + await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime(1965), + lastDate: DateTime(2030)) + .then((pickedDate) { + // Check if no date is selected + if (pickedDate == null) { + return null; + } + date = pickedDate; + }); + return date; + } +} diff --git a/lib/helpers/NetworkStatusService.dart b/lib/helpers/NetworkStatusService.dart new file mode 100644 index 0000000..3827eac --- /dev/null +++ b/lib/helpers/NetworkStatusService.dart @@ -0,0 +1,23 @@ +import 'dart:async'; + +import 'package:connectivity_plus/connectivity_plus.dart'; + +enum NetworkStatus { Online, Offline } + +class NetworkStatusService { + StreamController networkStatusController = + StreamController(); + + NetworkStatusService() { + Connectivity().onConnectivityChanged.listen((status) { + networkStatusController.add(_getNetworkStatus(status)); + }); + } + + NetworkStatus _getNetworkStatus(ConnectivityResult status) { + return status == ConnectivityResult.mobile || + status == ConnectivityResult.wifi + ? NetworkStatus.Online + : NetworkStatus.Offline; + } +} diff --git a/lib/helpers/ThemeDropDown.dart b/lib/helpers/ThemeDropDown.dart index abf0332..ab95359 100644 --- a/lib/helpers/ThemeDropDown.dart +++ b/lib/helpers/ThemeDropDown.dart @@ -1,13 +1,51 @@ import 'package:dropdown_search/dropdown_search.dart'; import 'package:flutter/material.dart'; import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/theme/MyFonts.dart'; +import 'package:wosull/helpers/ThemeText.dart'; abstract class ThemeDropDown { + static MenuProps menuProps = MenuProps( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + ); + + static PopupProps menu = PopupProps.menu( + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)); + + static TextFieldProps textFieldProps = const TextFieldProps( + style: ThemeText.textStyleValue, + decoration: InputDecoration( + constraints: BoxConstraints(maxHeight: 42), + hintText: 'Search', + isDense: true, // + ), + ); + static const ClearButtonProps clearButton = ClearButtonProps( alignment: Alignment.centerRight, padding: EdgeInsets.zero, icon: Icon(Icons.clear, size: 12), - color: MyColors.black, + color: MyColors.textColorBlack20, isVisible: true, ); + + static const PopupProps popupProps = PopupProps.menu( + fit: FlexFit.loose, + constraints: BoxConstraints(maxHeight: 300), + ); + + static DropdownButtonProps dropdownButtonProps = const DropdownButtonProps( + padding: EdgeInsets.only(left: 0, right: 0), + constraints: BoxConstraints(maxHeight: 38)); + + static TextStyle dropDownTextStyle = TextStyle( + fontFamily: MyFonts.Bold, + fontSize: MyFonts.normal, + color: MyColors.black, + fontWeight: FontWeight.w100, + ); } diff --git a/lib/helpers/ThemeImage.dart b/lib/helpers/ThemeImage.dart index fa64720..c83c7e1 100644 --- a/lib/helpers/ThemeImage.dart +++ b/lib/helpers/ThemeImage.dart @@ -3,4 +3,14 @@ abstract class ThemeImage { static const String logo = 'images/logo_sub_title.png'; static const String emptyImage = 'images/empty_cart.png'; static const String wosulLogo = 'images/wosul_logo.png'; + static const String cashierImage = 'images/cashier.png'; + static const String kitchenImage = 'images/kitchen.png'; + static const String accountProfileImage = 'images/account_profile.svg'; + static const String homeImage = 'images/home_icon.svg'; + static const String createOrderImage = 'images/create-order.svg'; + static const String inventoryImage = 'images/inven.svg'; + static const String discountImage = 'images/dis.svg'; + static const String salesImage = 'images/sales_order.svg'; + static const String kitchenIcon = 'images/kitchen.svg'; + static const String settingIcon = 'images/setting.svg'; } diff --git a/lib/helpers/ThemePadding.dart b/lib/helpers/ThemePadding.dart new file mode 100644 index 0000000..f9737a6 --- /dev/null +++ b/lib/helpers/ThemePadding.dart @@ -0,0 +1,6 @@ +abstract class ThemePadding { + static const double small = 4; + static const double medium = 8; + static const double large = 12; + static const double xLarge = 16; +} diff --git a/lib/helpers/ThemeText.dart b/lib/helpers/ThemeText.dart index 1193af1..068d847 100644 --- a/lib/helpers/ThemeText.dart +++ b/lib/helpers/ThemeText.dart @@ -1,8 +1,30 @@ import 'package:flutter/material.dart'; +import 'package:sizer/sizer.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/theme/MyFonts.dart'; abstract class ThemeText { + static const TextStyle textStyleSmallDJMono = TextStyle( + fontStyle: FontStyle.normal, + fontFamily: MyFonts.DejaVu, + fontSize: 10, + fontWeight: FontWeight.w400, + color: MyColors.black); + + static const TextStyle textStyleMediumDJMono = TextStyle( + fontStyle: FontStyle.normal, + fontFamily: MyFonts.DejaVu, + fontSize: 12, + fontWeight: FontWeight.w400, + color: MyColors.black); + + static const TextStyle textStyleBOLDDJMono = TextStyle( + fontStyle: FontStyle.normal, + fontFamily: MyFonts.Bold, + fontSize: 12, + fontWeight: FontWeight.bold, + color: MyColors.black); + static const TextStyle robotoBig = TextStyle( fontFamily: MyFonts.RobotoBold, fontSize: 20, @@ -10,32 +32,25 @@ abstract class ThemeText { color: MyColors.black1, ); - static const TextStyle robotoMediumSmall = TextStyle( - fontStyle: FontStyle.normal, - fontFamily: MyFonts.RobotoMedium, - fontSize: 11, - fontWeight: FontWeight.normal, - color: MyColors.textColorBlack20); - - static const TextStyle medium = TextStyle( + static TextStyle medium = TextStyle( fontFamily: MyFonts.Bold, fontSize: MyFonts.mediumText, color: MyColors.black1, ); - static const TextStyle robotoHeading = TextStyle( + static TextStyle robotoHeading = TextStyle( fontFamily: MyFonts.RobotoBold, fontSize: MyFonts.normal, color: MyColors.black1, fontWeight: FontWeight.bold); - static const TextStyle robotoValue = TextStyle( + static TextStyle robotoValue = TextStyle( fontFamily: MyFonts.RobotoBold, fontSize: MyFonts.normal, color: MyColors.black1, fontWeight: FontWeight.w500); - static const TextStyle robotoNormal = TextStyle( + static TextStyle robotoNormal = TextStyle( fontFamily: MyFonts.RobotoMedium, fontSize: MyFonts.normal, color: MyColors.black, @@ -44,19 +59,32 @@ abstract class ThemeText { static const TextStyle bigHeader = TextStyle( fontWeight: FontWeight.bold, fontSize: 40, fontFamily: MyFonts.Bold); - static TextStyle headingTextWhite = const TextStyle( + static TextStyle headingTextWhite = TextStyle( fontStyle: FontStyle.normal, fontFamily: MyFonts.RobotoMedium, - fontSize: 10, + fontSize: SizerUtil.deviceType == DeviceType.tablet ? 10 : 8, color: MyColors.white); + static TextStyle robotoMediumSmall = TextStyle( + fontStyle: FontStyle.normal, + fontFamily: MyFonts.RobotoMedium, + fontSize: SizerUtil.deviceType == DeviceType.tablet ? 11 : 8, + fontWeight: FontWeight.normal, + color: MyColors.textColorBlack20); + + static TextStyle headingTextBlackRoboto = const TextStyle( + fontStyle: FontStyle.normal, + fontFamily: MyFonts.RobotoMedium, + fontSize: 10, + color: MyColors.black); + static TextStyle boldWithBlueColor = TextStyle( fontSize: MyFonts.H2, fontFamily: MyFonts.Bold, color: MyColors.blueThemeColor); static const TextStyle mediumHeader = TextStyle( - fontSize: 16, fontFamily: MyFonts.DMREGULAR, color: MyColors.black); + fontSize: 16, fontFamily: MyFonts.Medium, color: MyColors.black); static const TextStyle textStylePopUpHeading = TextStyle( fontSize: 13, fontFamily: MyFonts.Medium, color: MyColors.black); @@ -64,38 +92,50 @@ abstract class ThemeText { static const TextStyle textStylePopUpHeadingWhite = TextStyle( fontSize: 13, fontFamily: MyFonts.Medium, color: MyColors.white); - static const TextStyle textStyleViewValue = TextStyle( + static TextStyle textStyleViewValue = TextStyle( fontFamily: MyFonts.DMREGULAR, fontSize: MyFonts.normalButton, color: MyColors.textColorGray); - static const TextStyle textStylePageHeading = TextStyle( + static TextStyle textStylePageHeading = TextStyle( fontWeight: FontWeight.bold, fontFamily: MyFonts.Bold, fontSize: MyFonts.bold, - color: Color(0xFF4b5b73)); + color: const Color(0xFF4b5b73)); - static const TextStyle labelStyleTextField = TextStyle( + static TextStyle labelStyleTextField = TextStyle( fontSize: MyFonts.normalButton, fontFamily: MyFonts.Medium, color: MyColors.black); - static const TextStyle hintStyleTextField = TextStyle( + static TextStyle hintStyleTextField = TextStyle( fontSize: MyFonts.normalButton, fontFamily: MyFonts.DMREGULAR, color: MyColors.black); + static const TextStyle textStyleHeadingSmall = TextStyle( + fontStyle: FontStyle.normal, + fontFamily: MyFonts.Bold, + fontSize: 10, + fontWeight: FontWeight.w300, + color: MyColors.black); + static const TextStyle textStyleHeading = TextStyle( fontStyle: FontStyle.normal, fontFamily: MyFonts.Bold, fontSize: 11, fontWeight: FontWeight.w500, + color: MyColors.textColorBlack20); + + static TextStyle textFliedStyleValue = TextStyle( + fontFamily: MyFonts.DMREGULAR, + fontSize: MyFonts.normal, color: MyColors.black); static const TextStyle textStyleValue = TextStyle( fontStyle: FontStyle.normal, fontFamily: MyFonts.Medium, - fontSize: 10, + fontSize: 11, fontWeight: FontWeight.w100, color: MyColors.textColorBlack20); @@ -104,16 +144,23 @@ abstract class ThemeText { fontFamily: MyFonts.Medium, fontSize: 10, fontWeight: FontWeight.w100, - color: MyColors.greenColor); + color: MyColors.colorGreen); static const TextStyle textStyleValueRed = TextStyle( fontStyle: FontStyle.normal, fontFamily: MyFonts.Medium, fontSize: 10, fontWeight: FontWeight.w100, - color: MyColors.fillRed); + color: MyColors.colorRed); + + static const TextStyle textStyleValueOrange = TextStyle( + fontStyle: FontStyle.normal, + fontFamily: MyFonts.Medium, + fontSize: 10, + fontWeight: FontWeight.w100, + color: MyColors.colorOrange); - static const TextStyle textStyleImageHeading = TextStyle( + static TextStyle textStyleImageHeading = TextStyle( fontSize: MyFonts.normalButton, fontWeight: FontWeight.w600, fontFamily: MyFonts.Medium, @@ -125,25 +172,25 @@ abstract class ThemeText { fontWeight: FontWeight.bold, fontSize: 18); - static const TextStyle textStyleH2Black = TextStyle( + static TextStyle textStyleH2Black = TextStyle( fontSize: MyFonts.H2, fontFamily: MyFonts.Medium, color: MyColors.textColorBlack); - static const TextStyle textStyleH2White = TextStyle( + static TextStyle textStyleH2White = TextStyle( fontSize: MyFonts.H2, fontFamily: MyFonts.Medium, color: MyColors.white); - static const TextStyle textStyleNormalGreen = TextStyle( + static TextStyle textStyleNormalGreen = TextStyle( fontWeight: FontWeight.bold, fontSize: MyFonts.normal, color: MyColors.greenColor); - static const TextStyle textStyleNormalMedium = TextStyle( + static TextStyle textStyleNormalMedium = TextStyle( fontSize: MyFonts.normal, fontFamily: MyFonts.Medium, color: MyColors.black); - static const TextStyle textStyleNormalMediumWhite = TextStyle( + static TextStyle textStyleNormalMediumWhite = TextStyle( fontSize: MyFonts.normal, fontFamily: MyFonts.Medium, color: MyColors.white); @@ -153,17 +200,56 @@ abstract class ThemeText { fontSize: 9, color: MyColors.textColorBlack); + static TextStyle textStyleBlueMedium = TextStyle( + fontSize: MyFonts.mediumText, + color: MyColors.blueThemeColor, + fontFamily: MyFonts.Medium); + static const TextStyle textStyleSmallWhite = TextStyle( fontFamily: MyFonts.DMREGULAR, fontSize: 10, color: MyColors.white); static TextStyle textStyleBlueColorSmall = TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: 10, - color: MyColors.blueThemeColor); + fontFamily: MyFonts.Bold, fontSize: 13, color: MyColors.blueThemeColor); - static const TextStyle textStyleNormalWhite = TextStyle( + static TextStyle textStyleNormalWhite = TextStyle( fontWeight: FontWeight.bold, fontSize: MyFonts.normal, fontFamily: MyFonts.Bold, color: MyColors.white); + + static TextStyle textStyleAmountHeading = TextStyle( + fontFamily: MyFonts.Bold, + fontWeight: FontWeight.bold, + fontSize: MyFonts.normalButton, + color: MyColors.textColorBlack); + + static TextStyle textStyleAmountValue = TextStyle( + fontFamily: MyFonts.Bold, + fontWeight: FontWeight.bold, + fontSize: MyFonts.normalButton, + color: MyColors.textColorBlack); + + static TextStyle textStyleAmountHeadingBlack = TextStyle( + fontFamily: MyFonts.Bold, + fontWeight: FontWeight.bold, + fontSize: MyFonts.normalButton, + color: MyColors.black); + + static TextStyle textStyleAmountValueBlack = TextStyle( + fontFamily: MyFonts.Bold, + fontWeight: FontWeight.bold, + fontSize: MyFonts.normalButton, + color: MyColors.black); + + static TextStyle tabLabelStyle = TextStyle( + fontSize: MyFonts.normalButton, + fontWeight: FontWeight.w500, + fontFamily: MyFonts.Bold, + color: MyColors.blueThemeColor); + + static TextStyle unSelectedTabLabelStyle = TextStyle( + fontSize: MyFonts.normalButton, + fontWeight: FontWeight.w500, + fontFamily: MyFonts.Medium, + color: MyColors.textColorBlack); } diff --git a/lib/l10n/app_ar.arb b/lib/l10n/app_ar.arb index 7daca8a..14e2829 100644 --- a/lib/l10n/app_ar.arb +++ b/lib/l10n/app_ar.arb @@ -45,7 +45,7 @@ "name" : "الاسم", "arabic_name" : "الاسم بالعربية", "apply_category_to" : "تطبيق الفئة على", - "product_image" : "صورة المنتج", + "product_image" : " صورة المنتج ", "all_stores" : "جميع المتاجر", "specific_stores" : "متاجر محددة", "inactive" : "غير نشط", diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 150cf79..a7a46f2 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -1,6 +1,6 @@ { "register": "Register", - "sign_in": "Sign in", + "sign_in": "Sign-in", "cashier": "Cashier", "cart": "Cart", "item_note": "Item Note", @@ -14,11 +14,11 @@ "password": "Password", "already_account_login": "Already have an account? Login", "copyright": "© Copyright 2023. Wosul.sa. All Rights Reserved.", - "welcome_back": "Welcome back! Please enter your details.\"", + "welcome_back": "Welcome back! Please enter your details.", "email": "Email", "remember": "Remember", "forgot_password": "Forgot Password?", - "dont_account": "Don’t have an account? Sign up for free", + "dont_account": "Don’t have an account?", "check_in": "CHECK IN", "available": "Available", "not_available": "Not Available", @@ -41,7 +41,7 @@ "name": "Name", "arabic_name": "Arabic Name", "apply_category_to": "Apply Category To", - "product_image": "Product Image", + "product_image": " Product Image ", "all_stores": "All Stores", "specific_stores": "Specific Stores", "inactive": "Inactive", @@ -192,7 +192,7 @@ "limit_on_discount": "Limit on Discount", "order_id": "Order ID", "payment_status": "Payment Status", - "un_paid": "UnPaid", + "un_paid": "Unpaid", "done": "Done", "pay": "Pay now", "transactions": "Transactions", diff --git a/lib/main.dart b/lib/main.dart index 4a456ec..1feff5e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -15,17 +15,22 @@ Future main() async { WidgetsFlutterBinding.ensureInitialized(); await SharedPrefs().init(); objectbox = await ObjectBox.create(); + await InternetConnectionChecker().hasConnection.then((value) { + isConnected = value; + }); + openService(); + runApp(const MyApp()); +} + +void openService() { InternetConnectionChecker().onStatusChange.listen((status) { switch (status) { case InternetConnectionStatus.connected: - print('Data connection is available.'); isConnected = true; break; case InternetConnectionStatus.disconnected: - print('You are disconnected from the internet.'); isConnected = false; break; } }); - runApp(const MyApp()); } diff --git a/lib/objectbox-model.json b/lib/objectbox-model.json index b8e704f..9f5a1f1 100644 --- a/lib/objectbox-model.json +++ b/lib/objectbox-model.json @@ -4,232 +4,297 @@ "_note3": "If you have VCS merge conflicts, you must resolve them according to ObjectBox docs.", "entities": [ { - "id": "1:6498797812538702468", - "lastPropertyId": "32:328149587239187843", + "id": "1:6932070486419484075", + "lastPropertyId": "45:7417376017248106046", "name": "AddIngredient", "properties": [ { - "id": "1:8007222945507836770", + "id": "1:7981848280187239055", "name": "obid", "type": 6, "flags": 1 }, { - "id": "2:2643175069866444181", + "id": "2:6507658690243097662", "name": "name", "type": 9 }, { - "id": "3:2114350789531166527", + "id": "3:3395703895971754042", "name": "description", "type": 9 }, { - "id": "4:270840335229808482", + "id": "4:8428114704586274810", "name": "value", "type": 9 }, { - "id": "5:7070901295711953145", + "id": "5:6984224418022459617", "name": "categoryId", "type": 9 }, { - "id": "6:7604135356465724998", + "id": "6:3221372751594045638", "name": "productId", "type": 9 }, { - "id": "7:1480373648632723623", + "id": "7:3542964212333407407", "name": "details", "type": 9 }, { - "id": "8:8538648112987374303", + "id": "8:5114251606510446488", "name": "details1", "type": 9 }, { - "id": "9:7026491979597179222", + "id": "9:486783272826808089", "name": "inCartQuantity", "type": 1 }, { - "id": "10:2655120422595327680", + "id": "10:283504580599364121", "name": "noteForItem", "type": 9 }, { - "id": "11:2848755466212338386", + "id": "11:457215009659333720", "name": "uniqueIdForStoreData", "type": 9 }, { - "id": "12:6094058876160129314", + "id": "12:7384620120274209963", "name": "isItemInStock", "type": 1 }, { - "id": "13:4640681993947370289", + "id": "13:4781576831940007700", "name": "isMostPopular", "type": 1 }, { - "id": "14:7201439577036275781", + "id": "14:844949797490688400", "name": "isVisibleInStore", "type": 1 }, { - "id": "15:6900339445466788175", + "id": "15:5419674347799479910", "name": "isRecommendInStore", "type": 1 }, { - "id": "16:1185224677198958257", + "id": "16:6556276257441511772", "name": "isExpressInDelivery", "type": 1 }, { - "id": "17:4075208951797275905", + "id": "17:2652209594801617800", "name": "tags", "type": 9 }, { - "id": "18:1760647822427802883", + "id": "18:667709923587088966", "name": "itemNameArabic", "type": 9 }, { - "id": "19:8957203174680085076", + "id": "19:2806639096284514958", "name": "itemDescriptionArabic", "type": 9 }, { - "id": "20:6089219450136762905", + "id": "20:1756257838778856400", "name": "productCode", "type": 9 }, { - "id": "21:7632479884958606789", + "id": "21:2053390992017573704", "name": "supplier", "type": 9 }, { - "id": "22:7246444095676049459", + "id": "22:2923118251030719757", "name": "discount", "type": 9 }, { - "id": "23:9170109617750744651", + "id": "23:1271837315500437710", "name": "measurementCategory", "type": 9 }, { - "id": "24:1483438898103426436", + "id": "24:272278047904476769", "name": "measurement", "type": 9 }, { - "id": "25:1005150732222650869", + "id": "25:3106919895191304323", "name": "brand", "type": 9 }, { - "id": "26:5833548998465725376", + "id": "26:8422820532049576385", "name": "manufacturerDate", "type": 9 }, { - "id": "27:7250691712258397399", + "id": "27:1760970215467240435", "name": "expiryDate", "type": 9 }, { - "id": "28:4269256361751954967", + "id": "28:501723603686900440", "name": "createdAt", "type": 9 }, { - "id": "29:7871310262944823144", + "id": "29:6335435349161038602", "name": "updatedAt", "type": 9 }, { - "id": "30:1589963074371695155", + "id": "30:8490314444449939016", "name": "measuringUnit", "type": 9 }, { - "id": "31:7410793486120295307", + "id": "31:9191448080767575199", "name": "checked", "type": 1 }, { - "id": "32:328149587239187843", + "id": "32:4971480019915069043", "name": "id", "type": 9 + }, + { + "id": "33:3192907363118089052", + "name": "quantity", + "type": 9 + }, + { + "id": "34:2238411764917183476", + "name": "purchasePrice", + "type": 8 + }, + { + "id": "35:7196444618867668855", + "name": "salePrice", + "type": 8 + }, + { + "id": "36:8977689747948402171", + "name": "defaultSalePrice", + "type": 8 + }, + { + "id": "37:3252613766866604404", + "name": "price", + "type": 8 + }, + { + "id": "38:8913892431716699939", + "name": "purchaseCost", + "type": 8 + }, + { + "id": "39:8699226838073895945", + "name": "itemPriceWithoutOffer", + "type": 8 + }, + { + "id": "40:1432832002157816837", + "name": "totalQuantity", + "type": 6 + }, + { + "id": "41:831818393440077409", + "name": "totalAddedQuantity", + "type": 6 + }, + { + "id": "42:8772810168178165965", + "name": "totalUsedQuantity", + "type": 6 + }, + { + "id": "43:7660350774071188078", + "name": "salePriceExclusiveTax", + "type": 8 + }, + { + "id": "44:198309649357905866", + "name": "stockAlertQuantity", + "type": 6 + }, + { + "id": "45:7417376017248106046", + "name": "salePriceInclusiveTax", + "type": 8 } ], "relations": [] }, { - "id": "2:6790344748329205930", - "lastPropertyId": "11:7387980687848673621", + "id": "2:9043517992733104440", + "lastPropertyId": "11:3570760856727720952", "name": "ComboProduct", "properties": [ { - "id": "1:9169051694919788720", + "id": "1:9102327676585854170", "name": "obid", "type": 6, "flags": 1 }, { - "id": "2:8426011307234032172", + "id": "2:4654000693781743261", "name": "size", "type": 9 }, { - "id": "3:4694055215244247567", + "id": "3:5027722973146588596", "name": "group", "type": 9 }, { - "id": "4:1491045091549825861", + "id": "4:3301647509276860693", "name": "subGroup", "type": 9 }, { - "id": "5:734259087560625105", + "id": "5:8292065665879853540", "name": "product", "type": 9 }, { - "id": "6:566875609517851406", + "id": "6:7479304690880645394", "name": "measurement", "type": 9 }, { - "id": "7:3168788917782558198", + "id": "7:5409076673354774978", "name": "imageUrl", "type": 9 }, { - "id": "8:1428904840978018040", + "id": "8:2654491393414338701", "name": "quantity", "type": 9 }, { - "id": "9:5942138267530188162", + "id": "9:3671278862007020541", "name": "isSelected", "type": 1 }, { - "id": "10:8456265007878964700", + "id": "10:6682317976401673903", "name": "price", "type": 8 }, { - "id": "11:7387980687848673621", + "id": "11:3570760856727720952", "name": "qtyIdx", "type": 6 } @@ -237,112 +302,263 @@ "relations": [] }, { - "id": "3:4584752513891869318", - "lastPropertyId": "8:5275788292319118207", + "id": "3:4216873724564362910", + "lastPropertyId": "27:2521267749891501111", + "name": "CreateAndUpdateOrder", + "properties": [ + { + "id": "1:8782645743790569349", + "name": "obid", + "type": 6, + "flags": 1 + }, + { + "id": "2:6847307730499774059", + "name": "deliveryPartnerId", + "type": 9 + }, + { + "id": "3:6842392940724436161", + "name": "totalCartPrice", + "type": 8 + }, + { + "id": "4:232335603563646994", + "name": "totalItemTax", + "type": 8 + }, + { + "id": "5:1042401098086824475", + "name": "cartUniqueToken", + "type": 9 + }, + { + "id": "6:6243833548473720830", + "name": "destinationAddresses", + "type": 9 + }, + { + "id": "7:4615756598435648112", + "name": "minOrderPrice", + "type": 8 + }, + { + "id": "8:7292307505769565017", + "name": "storeId", + "type": 9 + }, + { + "id": "9:5141825413003350339", + "name": "orderId", + "type": 9 + }, + { + "id": "10:1272056372318403515", + "name": "cartId", + "type": 9 + }, + { + "id": "11:8535786608328373183", + "name": "orderType", + "type": 9 + }, + { + "id": "12:5212512441043671921", + "name": "selectedTableName", + "type": 9 + }, + { + "id": "13:6596805450331895877", + "name": "createdAt", + "type": 9 + }, + { + "id": "14:2935787025291966094", + "name": "cartUniqueId", + "type": 6, + "flags": 32808, + "indexId": "1:5927156836772627792" + }, + { + "id": "15:1163511558304397103", + "name": "orderStatus", + "type": 9 + }, + { + "id": "16:2449277014897781984", + "name": "paymentStatus", + "type": 1 + }, + { + "id": "17:5867173656912970322", + "name": "paymentMode", + "type": 9 + }, + { + "id": "18:3716750750112863329", + "name": "amount", + "type": 8 + }, + { + "id": "19:8701707373292369623", + "name": "totalAmount", + "type": 8 + }, + { + "id": "20:8986876058217691072", + "name": "totalDiscount", + "type": 8 + }, + { + "id": "21:6389057982436109192", + "name": "discountId", + "type": 9 + }, + { + "id": "22:1231168476070572254", + "name": "cardNumber", + "type": 6 + }, + { + "id": "23:2086198146381017025", + "name": "changeBalanceAmount", + "type": 8 + }, + { + "id": "24:1321374266879522054", + "name": "timer", + "type": 6 + }, + { + "id": "25:6908808466255642714", + "name": "orderNumber", + "type": 6 + }, + { + "id": "26:6099010125231510438", + "name": "deliveryNotes", + "type": 9 + }, + { + "id": "27:2521267749891501111", + "name": "orderDetailsOffline", + "type": 9 + } + ], + "relations": [] + }, + { + "id": "4:8500243175982317727", + "lastPropertyId": "9:1843248315901556109", "name": "DeliveryPartner", "properties": [ { - "id": "1:6276789055131597542", + "id": "1:2706400219837957792", "name": "obid", "type": 6, "flags": 1 }, { - "id": "2:7951248785106263351", + "id": "2:9160268048464496671", "name": "id", "type": 9 }, { - "id": "3:1651016506559419705", + "id": "3:8799928808921474772", "name": "name", "type": 9 }, { - "id": "4:3943216297962527561", + "id": "4:1426312057218925299", "name": "nameArabic", "type": 9 }, { - "id": "5:5520816879293363584", + "id": "5:4032314612410253127", "name": "status", "type": 9 }, { - "id": "6:7308236921724275240", + "id": "6:8668298098074060608", "name": "createdAt", "type": 9 }, { - "id": "7:9024356040704387800", + "id": "7:3984188207916320594", "name": "updatedAt", "type": 9 }, { - "id": "8:5275788292319118207", + "id": "8:5336083002345932458", "name": "stores", "type": 30 + }, + { + "id": "9:1843248315901556109", + "name": "totalItemCount", + "type": 6 } ], "relations": [] }, { - "id": "4:4227245312433173753", - "lastPropertyId": "11:3364931044234439257", + "id": "5:1262130616075931860", + "lastPropertyId": "11:6435157189401156667", "name": "ItemCategory", "properties": [ { - "id": "1:4518301805906448857", + "id": "1:2435974588647262523", "name": "obid", "type": 6, "flags": 1 }, { - "id": "2:2220818434804858792", + "id": "2:2317839045249239489", "name": "name", "type": 9 }, { - "id": "3:1758723108055428203", + "id": "3:1581745583621888802", "name": "id", "type": 9 }, { - "id": "4:9204145038224390009", + "id": "4:2950317148797552714", "name": "isVisibleInStore", "type": 1 }, { - "id": "5:584619662180652805", + "id": "5:7484599557756612771", "name": "createdAt", "type": 9 }, { - "id": "6:8458505896633817476", + "id": "6:3154276797409547055", "name": "updatedAt", "type": 9 }, { - "id": "7:6394518247317687179", + "id": "7:3023964437166047702", "name": "description", "type": 9 }, { - "id": "8:5213531707501437350", + "id": "8:6768469232775246660", "name": "arabicName", "type": 9 }, { - "id": "9:8342288434180170600", + "id": "9:4286333694764180017", "name": "categoryAppliedOn", "type": 9 }, { - "id": "10:8578390224625306394", + "id": "10:9015900844520555997", "name": "store_id", "type": 30 }, { - "id": "11:3364931044234439257", + "id": "11:6435157189401156667", "name": "image_url", "type": 9 } @@ -350,58 +566,58 @@ "relations": [] }, { - "id": "5:2738078890918164557", - "lastPropertyId": "10:3129473523278517501", + "id": "6:5339989876985695940", + "lastPropertyId": "10:86467498828981705", "name": "ItemSubCategory", "properties": [ { - "id": "1:6894708354547534226", + "id": "1:467790315906336854", "name": "odid", "type": 6, "flags": 1 }, { - "id": "2:8018652113715277079", + "id": "2:2760391698593162727", "name": "name", "type": 9 }, { - "id": "3:1976907483136691986", + "id": "3:4998037640433722960", "name": "arabicName", "type": 9 }, { - "id": "4:6221140845449844576", + "id": "4:5954977792824817130", "name": "categoryId", "type": 9 }, { - "id": "5:8754881367672020909", + "id": "5:5939828351053483803", "name": "uniqueId", "type": 6 }, { - "id": "6:4986648578820318947", + "id": "6:1712716316218443156", "name": "id", "type": 9 }, { - "id": "7:1780413573954456109", + "id": "7:1841211382285782325", "name": "isVisibleInStore", "type": 1 }, { - "id": "8:3450832140802660997", + "id": "8:8719205242333027247", "name": "createdAt", "type": 9 }, { - "id": "9:872683946281561289", + "id": "9:5700178373066490991", "name": "updatedAt", "type": 9 }, { - "id": "10:3129473523278517501", + "id": "10:86467498828981705", "name": "storeId", "type": 30 } @@ -409,147 +625,232 @@ "relations": [] }, { - "id": "6:7364112204775279110", - "lastPropertyId": "12:2487633387387139483", + "id": "7:6854003909814618353", + "lastPropertyId": "4:3612659568442351451", + "name": "ItemsDeliveryPartner", + "properties": [ + { + "id": "1:8781655311209112650", + "name": "obid", + "type": 6, + "flags": 1 + }, + { + "id": "2:4120427947805097661", + "name": "id", + "type": 9 + }, + { + "id": "3:8644473474125833572", + "name": "name", + "type": 9 + }, + { + "id": "4:3612659568442351451", + "name": "price", + "type": 8 + } + ], + "relations": [] + }, + { + "id": "8:6209748684781024817", + "lastPropertyId": "12:7257607516187943875", "name": "Modifier", "properties": [ { - "id": "1:31614842138449808", + "id": "1:6849550105719945454", "name": "obid", "type": 6, "flags": 1 }, { - "id": "2:4752513802611773209", + "id": "2:7578413037262198412", "name": "id", "type": 9 }, { - "id": "3:4039329795901687540", + "id": "3:4372314385990805768", "name": "name", "type": 9 }, { - "id": "4:4206635446613152651", + "id": "4:8585236684488927321", "name": "arabicName", "type": 9 }, { - "id": "5:6149602349911523952", + "id": "5:4947159768991247580", "name": "description", "type": 9 }, { - "id": "6:8340025120855364863", + "id": "6:2546911597152508538", + "name": "price", + "type": 8 + }, + { + "id": "7:5272721999198342662", "name": "status", "type": 9 }, { - "id": "7:449647377690672430", + "id": "8:3509890783724750307", "name": "isMultiple", "type": 1 }, { - "id": "8:8761070287174813815", + "id": "9:7907863386494865446", "name": "createdOn", "type": 9 }, { - "id": "9:8115464323754126466", + "id": "10:6792516124279163297", "name": "updatedOn", "type": 9 }, { - "id": "10:4654993703480339805", + "id": "11:1927888765875260903", "name": "isSelected", "type": 1 }, { - "id": "11:6726354976204716505", + "id": "12:7257607516187943875", "name": "selectedModifierIndex", "type": 6 - }, - { - "id": "12:2487633387387139483", - "name": "price", - "type": 8 } ], "relations": [ { - "id": "9:6495403200174463118", + "id": "2:8019707152003459000", "name": "options", - "targetId": "7:7147747983318320192" + "targetId": "9:6750695338800619948" }, { - "id": "10:2858092237317708249", + "id": "3:4115333292084283920", "name": "selected", - "targetId": "7:7147747983318320192" + "targetId": "9:6750695338800619948" } ] }, { - "id": "7:7147747983318320192", - "lastPropertyId": "7:7804482501534205211", + "id": "9:6750695338800619948", + "lastPropertyId": "9:3549302534716425338", "name": "ModifierOption", "properties": [ { - "id": "1:3650130437194126966", + "id": "1:6137490228630772880", "name": "obid", "type": 6, "flags": 1 }, { - "id": "2:3417615945285036717", + "id": "2:2124174780099014797", "name": "name", "type": 9 }, { - "id": "3:4868201208959612246", + "id": "3:2431880259224275224", "name": "arabicName", "type": 9 }, { - "id": "4:6104506085330228712", + "id": "4:789780799671590966", "name": "price", "type": 8 }, { - "id": "5:6195885199899103186", + "id": "5:8289329897780453401", "name": "isSelected", "type": 1 }, { - "id": "6:5634445784439554802", + "id": "6:1035387023570074608", "name": "modifierName", "type": 9 }, { - "id": "7:7804482501534205211", + "id": "7:5534011194632221070", "name": "qtyIdx", "type": 6 + }, + { + "id": "8:6879462933610093570", + "name": "id", + "type": 9 + }, + { + "id": "9:3549302534716425338", + "name": "modifierId", + "type": 9 } ], - "relations": [] + "relations": [ + { + "id": "13:3946042636854669420", + "name": "ingredients", + "targetId": "1:6932070486419484075" + } + ] + }, + { + "id": "10:111941495828141118", + "lastPropertyId": "6:9012342498778887020", + "name": "OrderDetails", + "properties": [ + { + "id": "2:2372668576048147616", + "name": "productId", + "type": 9 + }, + { + "id": "3:8476483857971947314", + "name": "totalItemTax", + "type": 8 + }, + { + "id": "4:4710755254650263402", + "name": "totalItemPrice", + "type": 8 + }, + { + "id": "5:7390168550601569904", + "name": "totalItemPriceWithoutModifier", + "type": 8 + }, + { + "id": "6:9012342498778887020", + "name": "id", + "type": 6, + "flags": 129 + } + ], + "relations": [ + { + "id": "12:5672312728119666494", + "name": "items", + "targetId": "13:7237840838583267134" + } + ] }, { - "id": "8:1495441327752723255", - "lastPropertyId": "3:7196896965463181090", + "id": "11:8861440418697604415", + "lastPropertyId": "3:92013223961200490", "name": "ProductId", "properties": [ { - "id": "1:7553877218956149371", + "id": "1:2489790167768459299", "name": "obid", "type": 6, "flags": 1 }, { - "id": "2:2605413231369514106", + "id": "2:5065753830463838312", "name": "productId", "type": 9 }, { - "id": "3:7196896965463181090", + "id": "3:92013223961200490", "name": "categoryId", "type": 9 } @@ -557,138 +858,143 @@ "relations": [] }, { - "id": "9:380896817743615385", - "lastPropertyId": "26:3034847060510499706", + "id": "12:359769175852887597", + "lastPropertyId": "27:1290435665533435983", "name": "StoreDiscount", "properties": [ { - "id": "1:5028352124117611106", + "id": "1:6445150722646435629", "name": "obid", "type": 6, "flags": 1 }, { - "id": "2:7343920819373159169", + "id": "2:7429016959051114650", "name": "discountValue", "type": 9 }, { - "id": "3:6155456516094692693", + "id": "3:9049721166619966445", "name": "id", "type": 9 }, { - "id": "4:1168105739513542724", + "id": "4:8168768369385362196", "name": "name", "type": 9 }, { - "id": "5:5099999686808624698", + "id": "5:6473576378469552874", "name": "description", "type": 9 }, { - "id": "6:3700404833236245599", + "id": "6:1772641358802766670", "name": "value", "type": 9 }, { - "id": "7:4426677026845730501", + "id": "7:643051265652122345", "name": "type", "type": 9 }, { - "id": "8:5119239741838398277", + "id": "8:2210193501679588156", "name": "storeId", "type": 9 }, { - "id": "9:640117821944036678", + "id": "9:7961780184678705474", "name": "categories", "type": 30 }, { - "id": "10:7694712079560615443", + "id": "10:4146568131203183009", "name": "products", "type": 30 }, { - "id": "11:3825925023664943941", + "id": "11:398460701782956200", "name": "status", "type": 9 }, { - "id": "12:4288523063368625499", + "id": "12:5287875914150278007", "name": "minAmountLimit", "type": 8 }, { - "id": "13:4736125235426708997", + "id": "13:5440218771307430889", "name": "maxDiscountLimit", "type": 8 }, { - "id": "14:4362223601930594268", + "id": "14:6609109389968416476", "name": "discountPercentage", "type": 9 }, { - "id": "15:8366986669343933826", + "id": "15:5475410960660329351", "name": "discountType", "type": 9 }, { - "id": "16:3975398652400092257", + "id": "16:182604640740315391", "name": "discountTypeLabel", "type": 9 }, { - "id": "17:2144399513846153072", + "id": "17:535246710764893270", "name": "limitOfDiscount", "type": 8 }, { - "id": "18:3911068429281516849", + "id": "18:6543439877156273446", + "name": "isUserUsed", + "type": 8 + }, + { + "id": "19:8447285295495754149", "name": "discountStartDate", "type": 9 }, { - "id": "19:5033616087984125126", + "id": "20:4926649590055545869", "name": "discountEndDate", "type": 9 }, { - "id": "20:2567253907127089697", + "id": "21:9136605718908793655", "name": "isDeleted", "type": 1 }, { - "id": "21:7854116501808983578", + "id": "22:4973396371082592102", "name": "createdAt", "type": 9 }, { - "id": "22:3042630856775587804", + "id": "23:4589875173532718845", "name": "updatedAt", "type": 9 }, { - "id": "23:7566990052564653054", + "id": "24:1561001850302921598", "name": "isAlways", "type": 1 }, { - "id": "24:5135818371499975941", + "id": "25:6790679650625325119", "name": "isMaxDiscount", "type": 1 }, { - "id": "25:2812156313948340883", + "id": "26:2050203782374263726", "name": "isMinAmount", "type": 1 }, { - "id": "26:3034847060510499706", + "id": "27:1290435665533435983", "name": "isUnlimited", "type": 1 } @@ -696,248 +1002,238 @@ "relations": [] }, { - "id": "10:2288317989854260117", - "lastPropertyId": "37:5859059689724047650", + "id": "13:7237840838583267134", + "lastPropertyId": "40:3875508194163230144", "name": "StoreItems", "properties": [ { - "id": "1:7410141107574814830", - "name": "obid", - "type": 6, - "flags": 1 - }, - { - "id": "2:4394976733109508978", - "name": "id", - "type": 9 - }, - { - "id": "3:4671560801394981824", + "id": "3:4958576527940168777", "name": "name", "type": 9 }, { - "id": "4:1552044710638124843", + "id": "4:9062656542476470462", "name": "noteForItem", "type": 30 }, { - "id": "5:4309101463572028249", + "id": "5:2852859211497583234", "name": "storeId", "type": 9 }, { - "id": "6:5132604327359607815", + "id": "6:8587330522952900550", "name": "isUnlimitedQuantity", "type": 1 }, { - "id": "7:2142268648804299113", + "id": "7:1262987101012624439", "name": "itemNameArabic", "type": 9 }, { - "id": "8:1810896513421119618", + "id": "8:9044279015107828767", "name": "productId", "type": 9 }, { - "id": "9:2873600865795178103", + "id": "9:151664495032751801", "name": "product_product_id", "type": 9 }, { - "id": "10:1114255910445442738", + "id": "10:2210936851544564561", "name": "price", "type": 8 }, { - "id": "11:676073744206351151", + "id": "11:5742797677253967016", "name": "uniqueId", "type": 6 }, { - "id": "12:4289543664257030937", + "id": "12:4100528378407358303", "name": "uniqueIdForStoreData", "type": 9 }, { - "id": "13:8235828653301523370", - "name": "quantity", - "type": 6 - }, - { - "id": "14:5528999198812266453", + "id": "14:1481926270811339848", "name": "imageUrl", "type": 9 }, { - "id": "15:2303938806992615574", + "id": "15:1009606679482895245", "name": "updatedAt", "type": 9 }, { - "id": "16:2922825851039641478", + "id": "16:6346005304494223161", "name": "isItemInStock", "type": 1 }, { - "id": "17:6974239222366395116", + "id": "17:6899703730083428245", "name": "description", "type": 9 }, { - "id": "18:8961654230991290000", + "id": "18:2659560871703784013", "name": "descriptionArabic", "type": 9 }, { - "id": "19:2138595187708736217", + "id": "19:2082055095228296794", "name": "purchasePrice", "type": 8 }, { - "id": "20:7796961168236082795", + "id": "20:7811563145759664663", "name": "stockAlertQuantity", "type": 6 }, { - "id": "21:7783991895870061602", + "id": "21:5779190410490656253", "name": "itemPriceWithOutOffer", "type": 8 }, { - "id": "22:3037678182683211729", + "id": "22:2762607783449571446", "name": "totalAddedQuantity", "type": 6 }, { - "id": "23:1664067934203148569", + "id": "23:2310095844985213292", "name": "totalUsedQuantity", "type": 6 }, { - "id": "24:3093153207112086325", + "id": "24:7021402503491276441", "name": "salePriceExclusiveTax", "type": 8 }, { - "id": "25:3533451860886583383", - "name": "totalItemPrice", - "type": 8 - }, - { - "id": "26:5776881116382928994", + "id": "26:7364768681960967864", "name": "supplier", "type": 9 }, { - "id": "27:8981072800066829016", + "id": "27:8602677682009227494", "name": "discount", "type": 9 }, { - "id": "28:5507737861017589933", + "id": "28:4126651945297317163", "name": "measurementCategory", "type": 9 }, { - "id": "29:674168376816893154", + "id": "29:2556514976971519106", "name": "measurement", "type": 9 }, { - "id": "30:1900297012838859234", + "id": "30:2990432193784194544", "name": "brand", "type": 9 }, { - "id": "31:8118231242299684994", + "id": "31:8822451222451193390", "name": "deliveryPartner", "type": 9 }, { - "id": "32:1291129482716380135", + "id": "32:8193815347893538295", "name": "manufactureDate", "type": 9 }, { - "id": "33:686442788182914243", + "id": "33:3459984508948526160", "name": "expireDate", "type": 9 }, { - "id": "34:5330947190597924454", + "id": "34:8378646367215214255", "name": "status", "type": 1 }, { - "id": "35:776324325780216328", + "id": "35:4895970661923842231", "name": "isCombo", "type": 1 }, { - "id": "37:5859059689724047650", + "id": "36:5887228472890409901", "name": "isCheckedForReturn", "type": 1 - } - ], - "relations": [ + }, { - "id": "3:8262821186915006569", - "name": "deliveryPartners", - "targetId": "13:5996081504664112046" + "id": "37:2604940360734861438", + "name": "id", + "type": 6, + "flags": 129 }, { - "id": "4:1110273155378753501", - "name": "selectedCombos", - "targetId": "2:6790344748329205930" + "id": "38:37678979497952472", + "name": "itemId", + "type": 9 }, { - "id": "5:7372223286280386227", - "name": "selectedModifiers", - "targetId": "7:7147747983318320192" + "id": "39:2732682916567639228", + "name": "quantity", + "type": 6 }, { - "id": "6:8842382863215134604", + "id": "40:3875508194163230144", + "name": "totalItemPrice", + "type": 8 + } + ], + "relations": [ + { + "id": "7:7226676855356751712", "name": "ingredients", - "targetId": "1:6498797812538702468" + "targetId": "1:6932070486419484075" }, { - "id": "7:6470019879990042995", + "id": "8:3717611086071110575", "name": "modifiers", - "targetId": "6:7364112204775279110" + "targetId": "8:6209748684781024817" + }, + { + "id": "9:4265877760756686195", + "name": "deliveryPartners", + "targetId": "7:6854003909814618353" }, { - "id": "8:4922321800841909780", + "id": "10:8262039401801861006", "name": "comboProduct", - "targetId": "2:6790344748329205930" + "targetId": "2:9043517992733104440" } ] }, { - "id": "11:6857482764020692386", - "lastPropertyId": "4:8428996618209659663", + "id": "14:2913376536965938279", + "lastPropertyId": "4:892866427853170301", "name": "StoreServiceModel", "properties": [ { - "id": "1:3160925790909753601", + "id": "1:8422740907836916563", "name": "obid", "type": 6, "flags": 1 }, { - "id": "2:6946621502310729241", + "id": "2:9062838732358773381", "name": "id", "type": 9 }, { - "id": "3:4147818944337097577", + "id": "3:7240968004395834695", "name": "storeId", "type": 9 }, { - "id": "4:8428996618209659663", + "id": "4:892866427853170301", "name": "name", "type": 9 } @@ -945,283 +1241,83 @@ "relations": [] }, { - "id": "12:4792946829926694975", - "lastPropertyId": "9:7339624305009640005", + "id": "15:1489637104339473454", + "lastPropertyId": "9:3324089846938173439", "name": "StoreTable", "properties": [ { - "id": "1:5161461464205471313", + "id": "1:1569712141162636099", "name": "obid", "type": 6, "flags": 1 }, { - "id": "2:2250330636427721712", + "id": "2:3471933483649547679", "name": "id", "type": 9 }, { - "id": "3:7078228715944385642", + "id": "3:8526951040320487372", "name": "storeId", "type": 9 }, { - "id": "4:6907441787714879967", + "id": "4:7479315922939182336", "name": "tableName", "type": 9 }, { - "id": "5:1807830950883981205", + "id": "5:4858683358714605179", "name": "isAvailable", "type": 1 }, { - "id": "6:1320114005794250118", + "id": "6:7456420564747859667", "name": "noOfOccupants", "type": 6 }, { - "id": "7:1364019554975041073", + "id": "7:1955120184216864004", "name": "status", "type": 9 }, { - "id": "8:7803212150605615248", + "id": "8:2449972005791983419", "name": "createdAt", "type": 9 }, { - "id": "9:7339624305009640005", + "id": "9:3324089846938173439", "name": "updatedAt", "type": 9 } ], "relations": [] - }, - { - "id": "13:5996081504664112046", - "lastPropertyId": "4:413229903388265541", - "name": "ItemsDeliveryPartner", - "properties": [ - { - "id": "1:7558591377752814699", - "name": "obid", - "type": 6, - "flags": 1 - }, - { - "id": "2:5321051554644965730", - "name": "id", - "type": 9 - }, - { - "id": "3:5900908455665998319", - "name": "name", - "type": 9 - }, - { - "id": "4:413229903388265541", - "name": "price", - "type": 8 - } - ], - "relations": [] - }, - { - "id": "14:2243559031857156403", - "lastPropertyId": "25:5380152695145525158", - "name": "CreateAndUpdateOrder", - "properties": [ - { - "id": "1:463771832971349129", - "name": "obid", - "type": 6, - "flags": 1 - }, - { - "id": "2:8205635080192462875", - "name": "deliveryPartnerId", - "type": 9 - }, - { - "id": "3:1295421854826451219", - "name": "totalCartPrice", - "type": 8 - }, - { - "id": "4:4260940299009078774", - "name": "totalItemTax", - "type": 8 - }, - { - "id": "5:9213819911654038065", - "name": "cartUniqueToken", - "type": 9 - }, - { - "id": "6:7696189442168776726", - "name": "destinationAddresses", - "type": 9 - }, - { - "id": "7:206104808651765719", - "name": "minOrderPrice", - "type": 8 - }, - { - "id": "8:246907667287481202", - "name": "storeId", - "type": 9 - }, - { - "id": "9:7836359085725272770", - "name": "orderId", - "type": 9 - }, - { - "id": "10:8994870949807330771", - "name": "cartId", - "type": 9 - }, - { - "id": "11:7037308027108259390", - "name": "orderType", - "type": 9 - }, - { - "id": "12:4085412202121581938", - "name": "selectedTableName", - "type": 9 - }, - { - "id": "13:7379496384525075640", - "name": "createdAt", - "type": 9 - }, - { - "id": "14:1451785132581962717", - "name": "cartUniqueId", - "type": 6 - }, - { - "id": "15:8882612019402084984", - "name": "orderStatus", - "type": 9 - }, - { - "id": "16:2210373624469224774", - "name": "paymentStatus", - "type": 1 - }, - { - "id": "17:5742303538396335710", - "name": "paymentMode", - "type": 9 - }, - { - "id": "18:6954546626390917395", - "name": "amount", - "type": 8 - }, - { - "id": "19:3329670262914621917", - "name": "totalAmount", - "type": 8 - }, - { - "id": "20:2101442183486083730", - "name": "totalDiscount", - "type": 8 - }, - { - "id": "21:6052881256330509555", - "name": "cardNumber", - "type": 6 - }, - { - "id": "22:8316649940982602697", - "name": "changeBalanceAmount", - "type": 8 - }, - { - "id": "23:1322101751630018123", - "name": "timer", - "type": 6 - }, - { - "id": "24:1365695547169021744", - "name": "orderNumber", - "type": 6 - }, - { - "id": "25:5380152695145525158", - "name": "deliveryNotes", - "type": 9 - } - ], - "relations": [ - { - "id": "11:5546190593844039407", - "name": "orderDetails", - "targetId": "15:8907175224708130311" - } - ] - }, - { - "id": "15:8907175224708130311", - "lastPropertyId": "5:1658943849080100081", - "name": "OrderDetails", - "properties": [ - { - "id": "1:1240404718098977815", - "name": "obid", - "type": 6, - "flags": 1 - }, - { - "id": "2:3097928661595020588", - "name": "productId", - "type": 9 - }, - { - "id": "3:2104286542884585499", - "name": "totalItemTax", - "type": 8 - }, - { - "id": "4:7518986807521211001", - "name": "totalItemPrice", - "type": 8 - }, - { - "id": "5:1658943849080100081", - "name": "totalItemPriceWithoutModifier", - "type": 8 - } - ], - "relations": [ - { - "id": "12:2910557659214800545", - "name": "items", - "targetId": "10:2288317989854260117" - } - ] } ], - "lastEntityId": "15:8907175224708130311", - "lastIndexId": "0:0", - "lastRelationId": "12:2910557659214800545", + "lastEntityId": "15:1489637104339473454", + "lastIndexId": "2:697578080641452147", + "lastRelationId": "13:3946042636854669420", "lastSequenceId": "0:0", "modelVersion": 5, "modelVersionParserMinimum": 5, "retiredEntityUids": [], - "retiredIndexUids": [], + "retiredIndexUids": [ + 697578080641452147 + ], "retiredPropertyUids": [ - 3983827389374598831 + 6464732619707652235, + 5115272601749912683, + 332528716817670633, + 6806772396680135695, + 4308207840496701392 ], "retiredRelationUids": [ - 3987703562461513320, - 6157209775966721309 + 5306917274628500179, + 7868966108033718381, + 1374064699460362314, + 3322629234919122826, + 6448746763438190656 ], "version": 1 } \ No newline at end of file diff --git a/lib/objectbox.g.dart b/lib/objectbox.g.dart index 5c63f0d..59cb63c 100644 --- a/lib/objectbox.g.dart +++ b/lib/objectbox.g.dart @@ -18,10 +18,12 @@ import 'application/model/Combo/GetComboModel.dart'; import 'application/model/CreateAndUpdateOrder.dart'; import 'application/model/DeliveryPartner/GetDeliveryPartner.dart'; import 'application/model/DeliveryPartner/ItemsDeliveryPartner.dart'; -import 'application/model/Modifiers/GetModifiersModel.dart'; +import 'application/model/Modifiers/Modifier.dart'; +import 'application/model/Modifiers/ModifierOption.dart'; +import 'application/model/Products/ProductId.dart'; import 'application/model/createOrder/OrderDetails.dart'; import 'application/model/discount/StoreDiscountModel.dart'; -import 'application/model/inventory/AddIngredientModel.dart'; +import 'application/model/ingredients/AddIngredient.dart'; import 'application/model/inventory/ItemSubCategoryResponse.dart'; import 'application/model/inventory/category/ItemCategory.dart'; import 'application/model/store/StoreItemsResponse.dart'; @@ -32,232 +34,297 @@ export 'package:objectbox/objectbox.dart'; // so that callers only have to impor final _entities = [ ModelEntity( - id: const IdUid(1, 6498797812538702468), + id: const IdUid(1, 6932070486419484075), name: 'AddIngredient', - lastPropertyId: const IdUid(32, 328149587239187843), + lastPropertyId: const IdUid(45, 7417376017248106046), flags: 0, properties: [ ModelProperty( - id: const IdUid(1, 8007222945507836770), + id: const IdUid(1, 7981848280187239055), name: 'obid', type: 6, flags: 1), ModelProperty( - id: const IdUid(2, 2643175069866444181), + id: const IdUid(2, 6507658690243097662), name: 'name', type: 9, flags: 0), ModelProperty( - id: const IdUid(3, 2114350789531166527), + id: const IdUid(3, 3395703895971754042), name: 'description', type: 9, flags: 0), ModelProperty( - id: const IdUid(4, 270840335229808482), + id: const IdUid(4, 8428114704586274810), name: 'value', type: 9, flags: 0), ModelProperty( - id: const IdUid(5, 7070901295711953145), + id: const IdUid(5, 6984224418022459617), name: 'categoryId', type: 9, flags: 0), ModelProperty( - id: const IdUid(6, 7604135356465724998), + id: const IdUid(6, 3221372751594045638), name: 'productId', type: 9, flags: 0), ModelProperty( - id: const IdUid(7, 1480373648632723623), + id: const IdUid(7, 3542964212333407407), name: 'details', type: 9, flags: 0), ModelProperty( - id: const IdUid(8, 8538648112987374303), + id: const IdUid(8, 5114251606510446488), name: 'details1', type: 9, flags: 0), ModelProperty( - id: const IdUid(9, 7026491979597179222), + id: const IdUid(9, 486783272826808089), name: 'inCartQuantity', type: 1, flags: 0), ModelProperty( - id: const IdUid(10, 2655120422595327680), + id: const IdUid(10, 283504580599364121), name: 'noteForItem', type: 9, flags: 0), ModelProperty( - id: const IdUid(11, 2848755466212338386), + id: const IdUid(11, 457215009659333720), name: 'uniqueIdForStoreData', type: 9, flags: 0), ModelProperty( - id: const IdUid(12, 6094058876160129314), + id: const IdUid(12, 7384620120274209963), name: 'isItemInStock', type: 1, flags: 0), ModelProperty( - id: const IdUid(13, 4640681993947370289), + id: const IdUid(13, 4781576831940007700), name: 'isMostPopular', type: 1, flags: 0), ModelProperty( - id: const IdUid(14, 7201439577036275781), + id: const IdUid(14, 844949797490688400), name: 'isVisibleInStore', type: 1, flags: 0), ModelProperty( - id: const IdUid(15, 6900339445466788175), + id: const IdUid(15, 5419674347799479910), name: 'isRecommendInStore', type: 1, flags: 0), ModelProperty( - id: const IdUid(16, 1185224677198958257), + id: const IdUid(16, 6556276257441511772), name: 'isExpressInDelivery', type: 1, flags: 0), ModelProperty( - id: const IdUid(17, 4075208951797275905), + id: const IdUid(17, 2652209594801617800), name: 'tags', type: 9, flags: 0), ModelProperty( - id: const IdUid(18, 1760647822427802883), + id: const IdUid(18, 667709923587088966), name: 'itemNameArabic', type: 9, flags: 0), ModelProperty( - id: const IdUid(19, 8957203174680085076), + id: const IdUid(19, 2806639096284514958), name: 'itemDescriptionArabic', type: 9, flags: 0), ModelProperty( - id: const IdUid(20, 6089219450136762905), + id: const IdUid(20, 1756257838778856400), name: 'productCode', type: 9, flags: 0), ModelProperty( - id: const IdUid(21, 7632479884958606789), + id: const IdUid(21, 2053390992017573704), name: 'supplier', type: 9, flags: 0), ModelProperty( - id: const IdUid(22, 7246444095676049459), + id: const IdUid(22, 2923118251030719757), name: 'discount', type: 9, flags: 0), ModelProperty( - id: const IdUid(23, 9170109617750744651), + id: const IdUid(23, 1271837315500437710), name: 'measurementCategory', type: 9, flags: 0), ModelProperty( - id: const IdUid(24, 1483438898103426436), + id: const IdUid(24, 272278047904476769), name: 'measurement', type: 9, flags: 0), ModelProperty( - id: const IdUid(25, 1005150732222650869), + id: const IdUid(25, 3106919895191304323), name: 'brand', type: 9, flags: 0), ModelProperty( - id: const IdUid(26, 5833548998465725376), + id: const IdUid(26, 8422820532049576385), name: 'manufacturerDate', type: 9, flags: 0), ModelProperty( - id: const IdUid(27, 7250691712258397399), + id: const IdUid(27, 1760970215467240435), name: 'expiryDate', type: 9, flags: 0), ModelProperty( - id: const IdUid(28, 4269256361751954967), + id: const IdUid(28, 501723603686900440), name: 'createdAt', type: 9, flags: 0), ModelProperty( - id: const IdUid(29, 7871310262944823144), + id: const IdUid(29, 6335435349161038602), name: 'updatedAt', type: 9, flags: 0), ModelProperty( - id: const IdUid(30, 1589963074371695155), + id: const IdUid(30, 8490314444449939016), name: 'measuringUnit', type: 9, flags: 0), ModelProperty( - id: const IdUid(31, 7410793486120295307), + id: const IdUid(31, 9191448080767575199), name: 'checked', type: 1, flags: 0), ModelProperty( - id: const IdUid(32, 328149587239187843), + id: const IdUid(32, 4971480019915069043), name: 'id', type: 9, + flags: 0), + ModelProperty( + id: const IdUid(33, 3192907363118089052), + name: 'quantity', + type: 9, + flags: 0), + ModelProperty( + id: const IdUid(34, 2238411764917183476), + name: 'purchasePrice', + type: 8, + flags: 0), + ModelProperty( + id: const IdUid(35, 7196444618867668855), + name: 'salePrice', + type: 8, + flags: 0), + ModelProperty( + id: const IdUid(36, 8977689747948402171), + name: 'defaultSalePrice', + type: 8, + flags: 0), + ModelProperty( + id: const IdUid(37, 3252613766866604404), + name: 'price', + type: 8, + flags: 0), + ModelProperty( + id: const IdUid(38, 8913892431716699939), + name: 'purchaseCost', + type: 8, + flags: 0), + ModelProperty( + id: const IdUid(39, 8699226838073895945), + name: 'itemPriceWithoutOffer', + type: 8, + flags: 0), + ModelProperty( + id: const IdUid(40, 1432832002157816837), + name: 'totalQuantity', + type: 6, + flags: 0), + ModelProperty( + id: const IdUid(41, 831818393440077409), + name: 'totalAddedQuantity', + type: 6, + flags: 0), + ModelProperty( + id: const IdUid(42, 8772810168178165965), + name: 'totalUsedQuantity', + type: 6, + flags: 0), + ModelProperty( + id: const IdUid(43, 7660350774071188078), + name: 'salePriceExclusiveTax', + type: 8, + flags: 0), + ModelProperty( + id: const IdUid(44, 198309649357905866), + name: 'stockAlertQuantity', + type: 6, + flags: 0), + ModelProperty( + id: const IdUid(45, 7417376017248106046), + name: 'salePriceInclusiveTax', + type: 8, flags: 0) ], relations: [], backlinks: []), ModelEntity( - id: const IdUid(2, 6790344748329205930), + id: const IdUid(2, 9043517992733104440), name: 'ComboProduct', - lastPropertyId: const IdUid(11, 7387980687848673621), + lastPropertyId: const IdUid(11, 3570760856727720952), flags: 0, properties: [ ModelProperty( - id: const IdUid(1, 9169051694919788720), + id: const IdUid(1, 9102327676585854170), name: 'obid', type: 6, flags: 1), ModelProperty( - id: const IdUid(2, 8426011307234032172), + id: const IdUid(2, 4654000693781743261), name: 'size', type: 9, flags: 0), ModelProperty( - id: const IdUid(3, 4694055215244247567), + id: const IdUid(3, 5027722973146588596), name: 'group', type: 9, flags: 0), ModelProperty( - id: const IdUid(4, 1491045091549825861), + id: const IdUid(4, 3301647509276860693), name: 'subGroup', type: 9, flags: 0), ModelProperty( - id: const IdUid(5, 734259087560625105), + id: const IdUid(5, 8292065665879853540), name: 'product', type: 9, flags: 0), ModelProperty( - id: const IdUid(6, 566875609517851406), + id: const IdUid(6, 7479304690880645394), name: 'measurement', type: 9, flags: 0), ModelProperty( - id: const IdUid(7, 3168788917782558198), + id: const IdUid(7, 5409076673354774978), name: 'imageUrl', type: 9, flags: 0), ModelProperty( - id: const IdUid(8, 1428904840978018040), + id: const IdUid(8, 2654491393414338701), name: 'quantity', type: 9, flags: 0), ModelProperty( - id: const IdUid(9, 5942138267530188162), + id: const IdUid(9, 3671278862007020541), name: 'isSelected', type: 1, flags: 0), ModelProperty( - id: const IdUid(10, 8456265007878964700), + id: const IdUid(10, 6682317976401673903), name: 'price', type: 8, flags: 0), ModelProperty( - id: const IdUid(11, 7387980687848673621), + id: const IdUid(11, 3570760856727720952), name: 'qtyIdx', type: 6, flags: 0) @@ -265,112 +332,262 @@ final _entities = [ relations: [], backlinks: []), ModelEntity( - id: const IdUid(3, 4584752513891869318), + id: const IdUid(3, 4216873724564362910), + name: 'CreateAndUpdateOrder', + lastPropertyId: const IdUid(27, 2521267749891501111), + flags: 0, + properties: [ + ModelProperty( + id: const IdUid(1, 8782645743790569349), + name: 'obid', + type: 6, + flags: 1), + ModelProperty( + id: const IdUid(2, 6847307730499774059), + name: 'deliveryPartnerId', + type: 9, + flags: 0), + ModelProperty( + id: const IdUid(3, 6842392940724436161), + name: 'totalCartPrice', + type: 8, + flags: 0), + ModelProperty( + id: const IdUid(4, 232335603563646994), + name: 'totalItemTax', + type: 8, + flags: 0), + ModelProperty( + id: const IdUid(5, 1042401098086824475), + name: 'cartUniqueToken', + type: 9, + flags: 0), + ModelProperty( + id: const IdUid(6, 6243833548473720830), + name: 'destinationAddresses', + type: 9, + flags: 0), + ModelProperty( + id: const IdUid(7, 4615756598435648112), + name: 'minOrderPrice', + type: 8, + flags: 0), + ModelProperty( + id: const IdUid(8, 7292307505769565017), + name: 'storeId', + type: 9, + flags: 0), + ModelProperty( + id: const IdUid(9, 5141825413003350339), + name: 'orderId', + type: 9, + flags: 0), + ModelProperty( + id: const IdUid(10, 1272056372318403515), + name: 'cartId', + type: 9, + flags: 0), + ModelProperty( + id: const IdUid(11, 8535786608328373183), + name: 'orderType', + type: 9, + flags: 0), + ModelProperty( + id: const IdUid(12, 5212512441043671921), + name: 'selectedTableName', + type: 9, + flags: 0), + ModelProperty( + id: const IdUid(13, 6596805450331895877), + name: 'createdAt', + type: 9, + flags: 0), + ModelProperty( + id: const IdUid(14, 2935787025291966094), + name: 'cartUniqueId', + type: 6, + flags: 32808, + indexId: const IdUid(1, 5927156836772627792)), + ModelProperty( + id: const IdUid(15, 1163511558304397103), + name: 'orderStatus', + type: 9, + flags: 0), + ModelProperty( + id: const IdUid(16, 2449277014897781984), + name: 'paymentStatus', + type: 1, + flags: 0), + ModelProperty( + id: const IdUid(17, 5867173656912970322), + name: 'paymentMode', + type: 9, + flags: 0), + ModelProperty( + id: const IdUid(18, 3716750750112863329), + name: 'amount', + type: 8, + flags: 0), + ModelProperty( + id: const IdUid(19, 8701707373292369623), + name: 'totalAmount', + type: 8, + flags: 0), + ModelProperty( + id: const IdUid(20, 8986876058217691072), + name: 'totalDiscount', + type: 8, + flags: 0), + ModelProperty( + id: const IdUid(21, 6389057982436109192), + name: 'discountId', + type: 9, + flags: 0), + ModelProperty( + id: const IdUid(22, 1231168476070572254), + name: 'cardNumber', + type: 6, + flags: 0), + ModelProperty( + id: const IdUid(23, 2086198146381017025), + name: 'changeBalanceAmount', + type: 8, + flags: 0), + ModelProperty( + id: const IdUid(24, 1321374266879522054), + name: 'timer', + type: 6, + flags: 0), + ModelProperty( + id: const IdUid(25, 6908808466255642714), + name: 'orderNumber', + type: 6, + flags: 0), + ModelProperty( + id: const IdUid(26, 6099010125231510438), + name: 'deliveryNotes', + type: 9, + flags: 0), + ModelProperty( + id: const IdUid(27, 2521267749891501111), + name: 'orderDetailsOffline', + type: 9, + flags: 0) + ], + relations: [], + backlinks: []), + ModelEntity( + id: const IdUid(4, 8500243175982317727), name: 'DeliveryPartner', - lastPropertyId: const IdUid(8, 5275788292319118207), + lastPropertyId: const IdUid(9, 1843248315901556109), flags: 0, properties: [ ModelProperty( - id: const IdUid(1, 6276789055131597542), + id: const IdUid(1, 2706400219837957792), name: 'obid', type: 6, flags: 1), ModelProperty( - id: const IdUid(2, 7951248785106263351), + id: const IdUid(2, 9160268048464496671), name: 'id', type: 9, flags: 0), ModelProperty( - id: const IdUid(3, 1651016506559419705), + id: const IdUid(3, 8799928808921474772), name: 'name', type: 9, flags: 0), ModelProperty( - id: const IdUid(4, 3943216297962527561), + id: const IdUid(4, 1426312057218925299), name: 'nameArabic', type: 9, flags: 0), ModelProperty( - id: const IdUid(5, 5520816879293363584), + id: const IdUid(5, 4032314612410253127), name: 'status', type: 9, flags: 0), ModelProperty( - id: const IdUid(6, 7308236921724275240), + id: const IdUid(6, 8668298098074060608), name: 'createdAt', type: 9, flags: 0), ModelProperty( - id: const IdUid(7, 9024356040704387800), + id: const IdUid(7, 3984188207916320594), name: 'updatedAt', type: 9, flags: 0), ModelProperty( - id: const IdUid(8, 5275788292319118207), + id: const IdUid(8, 5336083002345932458), name: 'stores', type: 30, + flags: 0), + ModelProperty( + id: const IdUid(9, 1843248315901556109), + name: 'totalItemCount', + type: 6, flags: 0) ], relations: [], backlinks: []), ModelEntity( - id: const IdUid(4, 4227245312433173753), + id: const IdUid(5, 1262130616075931860), name: 'ItemCategory', - lastPropertyId: const IdUid(11, 3364931044234439257), + lastPropertyId: const IdUid(11, 6435157189401156667), flags: 0, properties: [ ModelProperty( - id: const IdUid(1, 4518301805906448857), + id: const IdUid(1, 2435974588647262523), name: 'obid', type: 6, flags: 1), ModelProperty( - id: const IdUid(2, 2220818434804858792), + id: const IdUid(2, 2317839045249239489), name: 'name', type: 9, flags: 0), ModelProperty( - id: const IdUid(3, 1758723108055428203), + id: const IdUid(3, 1581745583621888802), name: 'id', type: 9, flags: 0), ModelProperty( - id: const IdUid(4, 9204145038224390009), + id: const IdUid(4, 2950317148797552714), name: 'isVisibleInStore', type: 1, flags: 0), ModelProperty( - id: const IdUid(5, 584619662180652805), + id: const IdUid(5, 7484599557756612771), name: 'createdAt', type: 9, flags: 0), ModelProperty( - id: const IdUid(6, 8458505896633817476), + id: const IdUid(6, 3154276797409547055), name: 'updatedAt', type: 9, flags: 0), ModelProperty( - id: const IdUid(7, 6394518247317687179), + id: const IdUid(7, 3023964437166047702), name: 'description', type: 9, flags: 0), ModelProperty( - id: const IdUid(8, 5213531707501437350), + id: const IdUid(8, 6768469232775246660), name: 'arabicName', type: 9, flags: 0), ModelProperty( - id: const IdUid(9, 8342288434180170600), + id: const IdUid(9, 4286333694764180017), name: 'categoryAppliedOn', type: 9, flags: 0), ModelProperty( - id: const IdUid(10, 8578390224625306394), + id: const IdUid(10, 9015900844520555997), name: 'store_id', type: 30, flags: 0), ModelProperty( - id: const IdUid(11, 3364931044234439257), + id: const IdUid(11, 6435157189401156667), name: 'image_url', type: 9, flags: 0) @@ -378,58 +595,58 @@ final _entities = [ relations: [], backlinks: []), ModelEntity( - id: const IdUid(5, 2738078890918164557), + id: const IdUid(6, 5339989876985695940), name: 'ItemSubCategory', - lastPropertyId: const IdUid(10, 3129473523278517501), + lastPropertyId: const IdUid(10, 86467498828981705), flags: 0, properties: [ ModelProperty( - id: const IdUid(1, 6894708354547534226), + id: const IdUid(1, 467790315906336854), name: 'odid', type: 6, flags: 1), ModelProperty( - id: const IdUid(2, 8018652113715277079), + id: const IdUid(2, 2760391698593162727), name: 'name', type: 9, flags: 0), ModelProperty( - id: const IdUid(3, 1976907483136691986), + id: const IdUid(3, 4998037640433722960), name: 'arabicName', type: 9, flags: 0), ModelProperty( - id: const IdUid(4, 6221140845449844576), + id: const IdUid(4, 5954977792824817130), name: 'categoryId', type: 9, flags: 0), ModelProperty( - id: const IdUid(5, 8754881367672020909), + id: const IdUid(5, 5939828351053483803), name: 'uniqueId', type: 6, flags: 0), ModelProperty( - id: const IdUid(6, 4986648578820318947), + id: const IdUid(6, 1712716316218443156), name: 'id', type: 9, flags: 0), ModelProperty( - id: const IdUid(7, 1780413573954456109), + id: const IdUid(7, 1841211382285782325), name: 'isVisibleInStore', type: 1, flags: 0), ModelProperty( - id: const IdUid(8, 3450832140802660997), + id: const IdUid(8, 8719205242333027247), name: 'createdAt', type: 9, flags: 0), ModelProperty( - id: const IdUid(9, 872683946281561289), + id: const IdUid(9, 5700178373066490991), name: 'updatedAt', type: 9, flags: 0), ModelProperty( - id: const IdUid(10, 3129473523278517501), + id: const IdUid(10, 86467498828981705), name: 'storeId', type: 30, flags: 0) @@ -437,145 +654,228 @@ final _entities = [ relations: [], backlinks: []), ModelEntity( - id: const IdUid(6, 7364112204775279110), + id: const IdUid(7, 6854003909814618353), + name: 'ItemsDeliveryPartner', + lastPropertyId: const IdUid(4, 3612659568442351451), + flags: 0, + properties: [ + ModelProperty( + id: const IdUid(1, 8781655311209112650), + name: 'obid', + type: 6, + flags: 1), + ModelProperty( + id: const IdUid(2, 4120427947805097661), + name: 'id', + type: 9, + flags: 0), + ModelProperty( + id: const IdUid(3, 8644473474125833572), + name: 'name', + type: 9, + flags: 0), + ModelProperty( + id: const IdUid(4, 3612659568442351451), + name: 'price', + type: 8, + flags: 0) + ], + relations: [], + backlinks: []), + ModelEntity( + id: const IdUid(8, 6209748684781024817), name: 'Modifier', - lastPropertyId: const IdUid(12, 2487633387387139483), + lastPropertyId: const IdUid(12, 7257607516187943875), flags: 0, properties: [ ModelProperty( - id: const IdUid(1, 31614842138449808), + id: const IdUid(1, 6849550105719945454), name: 'obid', type: 6, flags: 1), ModelProperty( - id: const IdUid(2, 4752513802611773209), + id: const IdUid(2, 7578413037262198412), name: 'id', type: 9, flags: 0), ModelProperty( - id: const IdUid(3, 4039329795901687540), + id: const IdUid(3, 4372314385990805768), name: 'name', type: 9, flags: 0), ModelProperty( - id: const IdUid(4, 4206635446613152651), + id: const IdUid(4, 8585236684488927321), name: 'arabicName', type: 9, flags: 0), ModelProperty( - id: const IdUid(5, 6149602349911523952), + id: const IdUid(5, 4947159768991247580), name: 'description', type: 9, flags: 0), ModelProperty( - id: const IdUid(6, 8340025120855364863), + id: const IdUid(6, 2546911597152508538), + name: 'price', + type: 8, + flags: 0), + ModelProperty( + id: const IdUid(7, 5272721999198342662), name: 'status', type: 9, flags: 0), ModelProperty( - id: const IdUid(7, 449647377690672430), + id: const IdUid(8, 3509890783724750307), name: 'isMultiple', type: 1, flags: 0), ModelProperty( - id: const IdUid(8, 8761070287174813815), + id: const IdUid(9, 7907863386494865446), name: 'createdOn', type: 9, flags: 0), ModelProperty( - id: const IdUid(9, 8115464323754126466), + id: const IdUid(10, 6792516124279163297), name: 'updatedOn', type: 9, flags: 0), ModelProperty( - id: const IdUid(10, 4654993703480339805), + id: const IdUid(11, 1927888765875260903), name: 'isSelected', type: 1, flags: 0), ModelProperty( - id: const IdUid(11, 6726354976204716505), + id: const IdUid(12, 7257607516187943875), name: 'selectedModifierIndex', type: 6, - flags: 0), - ModelProperty( - id: const IdUid(12, 2487633387387139483), - name: 'price', - type: 8, flags: 0) ], relations: [ ModelRelation( - id: const IdUid(9, 6495403200174463118), + id: const IdUid(2, 8019707152003459000), name: 'options', - targetId: const IdUid(7, 7147747983318320192)), + targetId: const IdUid(9, 6750695338800619948)), ModelRelation( - id: const IdUid(10, 2858092237317708249), + id: const IdUid(3, 4115333292084283920), name: 'selected', - targetId: const IdUid(7, 7147747983318320192)) + targetId: const IdUid(9, 6750695338800619948)) ], backlinks: []), ModelEntity( - id: const IdUid(7, 7147747983318320192), + id: const IdUid(9, 6750695338800619948), name: 'ModifierOption', - lastPropertyId: const IdUid(7, 7804482501534205211), + lastPropertyId: const IdUid(9, 3549302534716425338), flags: 0, properties: [ ModelProperty( - id: const IdUid(1, 3650130437194126966), + id: const IdUid(1, 6137490228630772880), name: 'obid', type: 6, flags: 1), ModelProperty( - id: const IdUid(2, 3417615945285036717), + id: const IdUid(2, 2124174780099014797), name: 'name', type: 9, flags: 0), ModelProperty( - id: const IdUid(3, 4868201208959612246), + id: const IdUid(3, 2431880259224275224), name: 'arabicName', type: 9, flags: 0), ModelProperty( - id: const IdUid(4, 6104506085330228712), + id: const IdUid(4, 789780799671590966), name: 'price', type: 8, flags: 0), ModelProperty( - id: const IdUid(5, 6195885199899103186), + id: const IdUid(5, 8289329897780453401), name: 'isSelected', type: 1, flags: 0), ModelProperty( - id: const IdUid(6, 5634445784439554802), + id: const IdUid(6, 1035387023570074608), name: 'modifierName', type: 9, flags: 0), ModelProperty( - id: const IdUid(7, 7804482501534205211), + id: const IdUid(7, 5534011194632221070), name: 'qtyIdx', type: 6, + flags: 0), + ModelProperty( + id: const IdUid(8, 6879462933610093570), + name: 'id', + type: 9, + flags: 0), + ModelProperty( + id: const IdUid(9, 3549302534716425338), + name: 'modifierId', + type: 9, flags: 0) ], - relations: [], + relations: [ + ModelRelation( + id: const IdUid(13, 3946042636854669420), + name: 'ingredients', + targetId: const IdUid(1, 6932070486419484075)) + ], + backlinks: []), + ModelEntity( + id: const IdUid(10, 111941495828141118), + name: 'OrderDetails', + lastPropertyId: const IdUid(6, 9012342498778887020), + flags: 0, + properties: [ + ModelProperty( + id: const IdUid(2, 2372668576048147616), + name: 'productId', + type: 9, + flags: 0), + ModelProperty( + id: const IdUid(3, 8476483857971947314), + name: 'totalItemTax', + type: 8, + flags: 0), + ModelProperty( + id: const IdUid(4, 4710755254650263402), + name: 'totalItemPrice', + type: 8, + flags: 0), + ModelProperty( + id: const IdUid(5, 7390168550601569904), + name: 'totalItemPriceWithoutModifier', + type: 8, + flags: 0), + ModelProperty( + id: const IdUid(6, 9012342498778887020), + name: 'id', + type: 6, + flags: 129) + ], + relations: [ + ModelRelation( + id: const IdUid(12, 5672312728119666494), + name: 'items', + targetId: const IdUid(13, 7237840838583267134)) + ], backlinks: []), ModelEntity( - id: const IdUid(8, 1495441327752723255), + id: const IdUid(11, 8861440418697604415), name: 'ProductId', - lastPropertyId: const IdUid(3, 7196896965463181090), + lastPropertyId: const IdUid(3, 92013223961200490), flags: 0, properties: [ ModelProperty( - id: const IdUid(1, 7553877218956149371), + id: const IdUid(1, 2489790167768459299), name: 'obid', type: 6, flags: 1), ModelProperty( - id: const IdUid(2, 2605413231369514106), + id: const IdUid(2, 5065753830463838312), name: 'productId', type: 9, flags: 0), ModelProperty( - id: const IdUid(3, 7196896965463181090), + id: const IdUid(3, 92013223961200490), name: 'categoryId', type: 9, flags: 0) @@ -583,138 +883,143 @@ final _entities = [ relations: [], backlinks: []), ModelEntity( - id: const IdUid(9, 380896817743615385), + id: const IdUid(12, 359769175852887597), name: 'StoreDiscount', - lastPropertyId: const IdUid(26, 3034847060510499706), + lastPropertyId: const IdUid(27, 1290435665533435983), flags: 0, properties: [ ModelProperty( - id: const IdUid(1, 5028352124117611106), + id: const IdUid(1, 6445150722646435629), name: 'obid', type: 6, flags: 1), ModelProperty( - id: const IdUid(2, 7343920819373159169), + id: const IdUid(2, 7429016959051114650), name: 'discountValue', type: 9, flags: 0), ModelProperty( - id: const IdUid(3, 6155456516094692693), + id: const IdUid(3, 9049721166619966445), name: 'id', type: 9, flags: 0), ModelProperty( - id: const IdUid(4, 1168105739513542724), + id: const IdUid(4, 8168768369385362196), name: 'name', type: 9, flags: 0), ModelProperty( - id: const IdUid(5, 5099999686808624698), + id: const IdUid(5, 6473576378469552874), name: 'description', type: 9, flags: 0), ModelProperty( - id: const IdUid(6, 3700404833236245599), + id: const IdUid(6, 1772641358802766670), name: 'value', type: 9, flags: 0), ModelProperty( - id: const IdUid(7, 4426677026845730501), + id: const IdUid(7, 643051265652122345), name: 'type', type: 9, flags: 0), ModelProperty( - id: const IdUid(8, 5119239741838398277), + id: const IdUid(8, 2210193501679588156), name: 'storeId', type: 9, flags: 0), ModelProperty( - id: const IdUid(9, 640117821944036678), + id: const IdUid(9, 7961780184678705474), name: 'categories', type: 30, flags: 0), ModelProperty( - id: const IdUid(10, 7694712079560615443), + id: const IdUid(10, 4146568131203183009), name: 'products', type: 30, flags: 0), ModelProperty( - id: const IdUid(11, 3825925023664943941), + id: const IdUid(11, 398460701782956200), name: 'status', type: 9, flags: 0), ModelProperty( - id: const IdUid(12, 4288523063368625499), + id: const IdUid(12, 5287875914150278007), name: 'minAmountLimit', type: 8, flags: 0), ModelProperty( - id: const IdUid(13, 4736125235426708997), + id: const IdUid(13, 5440218771307430889), name: 'maxDiscountLimit', type: 8, flags: 0), ModelProperty( - id: const IdUid(14, 4362223601930594268), + id: const IdUid(14, 6609109389968416476), name: 'discountPercentage', type: 9, flags: 0), ModelProperty( - id: const IdUid(15, 8366986669343933826), + id: const IdUid(15, 5475410960660329351), name: 'discountType', type: 9, flags: 0), ModelProperty( - id: const IdUid(16, 3975398652400092257), + id: const IdUid(16, 182604640740315391), name: 'discountTypeLabel', type: 9, flags: 0), ModelProperty( - id: const IdUid(17, 2144399513846153072), + id: const IdUid(17, 535246710764893270), name: 'limitOfDiscount', type: 8, flags: 0), ModelProperty( - id: const IdUid(18, 3911068429281516849), + id: const IdUid(18, 6543439877156273446), + name: 'isUserUsed', + type: 8, + flags: 0), + ModelProperty( + id: const IdUid(19, 8447285295495754149), name: 'discountStartDate', type: 9, flags: 0), ModelProperty( - id: const IdUid(19, 5033616087984125126), + id: const IdUid(20, 4926649590055545869), name: 'discountEndDate', type: 9, flags: 0), ModelProperty( - id: const IdUid(20, 2567253907127089697), + id: const IdUid(21, 9136605718908793655), name: 'isDeleted', type: 1, flags: 0), ModelProperty( - id: const IdUid(21, 7854116501808983578), + id: const IdUid(22, 4973396371082592102), name: 'createdAt', type: 9, flags: 0), ModelProperty( - id: const IdUid(22, 3042630856775587804), + id: const IdUid(23, 4589875173532718845), name: 'updatedAt', type: 9, flags: 0), ModelProperty( - id: const IdUid(23, 7566990052564653054), + id: const IdUid(24, 1561001850302921598), name: 'isAlways', type: 1, flags: 0), ModelProperty( - id: const IdUid(24, 5135818371499975941), + id: const IdUid(25, 6790679650625325119), name: 'isMaxDiscount', type: 1, flags: 0), ModelProperty( - id: const IdUid(25, 2812156313948340883), + id: const IdUid(26, 2050203782374263726), name: 'isMinAmount', type: 1, flags: 0), ModelProperty( - id: const IdUid(26, 3034847060510499706), + id: const IdUid(27, 1290435665533435983), name: 'isUnlimited', type: 1, flags: 0) @@ -722,242 +1027,234 @@ final _entities = [ relations: [], backlinks: []), ModelEntity( - id: const IdUid(10, 2288317989854260117), + id: const IdUid(13, 7237840838583267134), name: 'StoreItems', - lastPropertyId: const IdUid(37, 5859059689724047650), + lastPropertyId: const IdUid(40, 3875508194163230144), flags: 0, properties: [ ModelProperty( - id: const IdUid(1, 7410141107574814830), - name: 'obid', - type: 6, - flags: 1), - ModelProperty( - id: const IdUid(2, 4394976733109508978), - name: 'id', - type: 9, - flags: 0), - ModelProperty( - id: const IdUid(3, 4671560801394981824), + id: const IdUid(3, 4958576527940168777), name: 'name', type: 9, flags: 0), ModelProperty( - id: const IdUid(4, 1552044710638124843), + id: const IdUid(4, 9062656542476470462), name: 'noteForItem', type: 30, flags: 0), ModelProperty( - id: const IdUid(5, 4309101463572028249), + id: const IdUid(5, 2852859211497583234), name: 'storeId', type: 9, flags: 0), ModelProperty( - id: const IdUid(6, 5132604327359607815), + id: const IdUid(6, 8587330522952900550), name: 'isUnlimitedQuantity', type: 1, flags: 0), ModelProperty( - id: const IdUid(7, 2142268648804299113), + id: const IdUid(7, 1262987101012624439), name: 'itemNameArabic', type: 9, flags: 0), ModelProperty( - id: const IdUid(8, 1810896513421119618), + id: const IdUid(8, 9044279015107828767), name: 'productId', type: 9, flags: 0), ModelProperty( - id: const IdUid(9, 2873600865795178103), + id: const IdUid(9, 151664495032751801), name: 'product_product_id', type: 9, flags: 0), ModelProperty( - id: const IdUid(10, 1114255910445442738), + id: const IdUid(10, 2210936851544564561), name: 'price', type: 8, flags: 0), ModelProperty( - id: const IdUid(11, 676073744206351151), + id: const IdUid(11, 5742797677253967016), name: 'uniqueId', type: 6, flags: 0), ModelProperty( - id: const IdUid(12, 4289543664257030937), + id: const IdUid(12, 4100528378407358303), name: 'uniqueIdForStoreData', type: 9, flags: 0), ModelProperty( - id: const IdUid(13, 8235828653301523370), - name: 'quantity', - type: 6, - flags: 0), - ModelProperty( - id: const IdUid(14, 5528999198812266453), + id: const IdUid(14, 1481926270811339848), name: 'imageUrl', type: 9, flags: 0), ModelProperty( - id: const IdUid(15, 2303938806992615574), + id: const IdUid(15, 1009606679482895245), name: 'updatedAt', type: 9, flags: 0), ModelProperty( - id: const IdUid(16, 2922825851039641478), + id: const IdUid(16, 6346005304494223161), name: 'isItemInStock', type: 1, flags: 0), ModelProperty( - id: const IdUid(17, 6974239222366395116), + id: const IdUid(17, 6899703730083428245), name: 'description', type: 9, flags: 0), ModelProperty( - id: const IdUid(18, 8961654230991290000), + id: const IdUid(18, 2659560871703784013), name: 'descriptionArabic', type: 9, flags: 0), ModelProperty( - id: const IdUid(19, 2138595187708736217), + id: const IdUid(19, 2082055095228296794), name: 'purchasePrice', type: 8, flags: 0), ModelProperty( - id: const IdUid(20, 7796961168236082795), + id: const IdUid(20, 7811563145759664663), name: 'stockAlertQuantity', type: 6, flags: 0), ModelProperty( - id: const IdUid(21, 7783991895870061602), + id: const IdUid(21, 5779190410490656253), name: 'itemPriceWithOutOffer', type: 8, flags: 0), ModelProperty( - id: const IdUid(22, 3037678182683211729), + id: const IdUid(22, 2762607783449571446), name: 'totalAddedQuantity', type: 6, flags: 0), ModelProperty( - id: const IdUid(23, 1664067934203148569), + id: const IdUid(23, 2310095844985213292), name: 'totalUsedQuantity', type: 6, flags: 0), ModelProperty( - id: const IdUid(24, 3093153207112086325), + id: const IdUid(24, 7021402503491276441), name: 'salePriceExclusiveTax', type: 8, flags: 0), ModelProperty( - id: const IdUid(25, 3533451860886583383), - name: 'totalItemPrice', - type: 8, - flags: 0), - ModelProperty( - id: const IdUid(26, 5776881116382928994), + id: const IdUid(26, 7364768681960967864), name: 'supplier', type: 9, flags: 0), ModelProperty( - id: const IdUid(27, 8981072800066829016), + id: const IdUid(27, 8602677682009227494), name: 'discount', type: 9, flags: 0), ModelProperty( - id: const IdUid(28, 5507737861017589933), + id: const IdUid(28, 4126651945297317163), name: 'measurementCategory', type: 9, flags: 0), ModelProperty( - id: const IdUid(29, 674168376816893154), + id: const IdUid(29, 2556514976971519106), name: 'measurement', type: 9, flags: 0), ModelProperty( - id: const IdUid(30, 1900297012838859234), + id: const IdUid(30, 2990432193784194544), name: 'brand', type: 9, flags: 0), ModelProperty( - id: const IdUid(31, 8118231242299684994), + id: const IdUid(31, 8822451222451193390), name: 'deliveryPartner', type: 9, flags: 0), ModelProperty( - id: const IdUid(32, 1291129482716380135), + id: const IdUid(32, 8193815347893538295), name: 'manufactureDate', type: 9, flags: 0), ModelProperty( - id: const IdUid(33, 686442788182914243), + id: const IdUid(33, 3459984508948526160), name: 'expireDate', type: 9, flags: 0), ModelProperty( - id: const IdUid(34, 5330947190597924454), + id: const IdUid(34, 8378646367215214255), name: 'status', type: 1, flags: 0), ModelProperty( - id: const IdUid(35, 776324325780216328), + id: const IdUid(35, 4895970661923842231), name: 'isCombo', type: 1, flags: 0), ModelProperty( - id: const IdUid(37, 5859059689724047650), + id: const IdUid(36, 5887228472890409901), name: 'isCheckedForReturn', type: 1, - flags: 0) - ], - relations: [ - ModelRelation( - id: const IdUid(3, 8262821186915006569), - name: 'deliveryPartners', - targetId: const IdUid(13, 5996081504664112046)), - ModelRelation( - id: const IdUid(4, 1110273155378753501), - name: 'selectedCombos', - targetId: const IdUid(2, 6790344748329205930)), - ModelRelation( - id: const IdUid(5, 7372223286280386227), - name: 'selectedModifiers', - targetId: const IdUid(7, 7147747983318320192)), + flags: 0), + ModelProperty( + id: const IdUid(37, 2604940360734861438), + name: 'id', + type: 6, + flags: 129), + ModelProperty( + id: const IdUid(38, 37678979497952472), + name: 'itemId', + type: 9, + flags: 0), + ModelProperty( + id: const IdUid(39, 2732682916567639228), + name: 'quantity', + type: 6, + flags: 0), + ModelProperty( + id: const IdUid(40, 3875508194163230144), + name: 'totalItemPrice', + type: 8, + flags: 0) + ], + relations: [ ModelRelation( - id: const IdUid(6, 8842382863215134604), + id: const IdUid(7, 7226676855356751712), name: 'ingredients', - targetId: const IdUid(1, 6498797812538702468)), + targetId: const IdUid(1, 6932070486419484075)), ModelRelation( - id: const IdUid(7, 6470019879990042995), + id: const IdUid(8, 3717611086071110575), name: 'modifiers', - targetId: const IdUid(6, 7364112204775279110)), + targetId: const IdUid(8, 6209748684781024817)), ModelRelation( - id: const IdUid(8, 4922321800841909780), + id: const IdUid(9, 4265877760756686195), + name: 'deliveryPartners', + targetId: const IdUid(7, 6854003909814618353)), + ModelRelation( + id: const IdUid(10, 8262039401801861006), name: 'comboProduct', - targetId: const IdUid(2, 6790344748329205930)) + targetId: const IdUid(2, 9043517992733104440)) ], backlinks: []), ModelEntity( - id: const IdUid(11, 6857482764020692386), + id: const IdUid(14, 2913376536965938279), name: 'StoreServiceModel', - lastPropertyId: const IdUid(4, 8428996618209659663), + lastPropertyId: const IdUid(4, 892866427853170301), flags: 0, properties: [ ModelProperty( - id: const IdUid(1, 3160925790909753601), + id: const IdUid(1, 8422740907836916563), name: 'obid', type: 6, flags: 1), ModelProperty( - id: const IdUid(2, 6946621502310729241), + id: const IdUid(2, 9062838732358773381), name: 'id', type: 9, flags: 0), ModelProperty( - id: const IdUid(3, 4147818944337097577), + id: const IdUid(3, 7240968004395834695), name: 'storeId', type: 9, flags: 0), ModelProperty( - id: const IdUid(4, 8428996618209659663), + id: const IdUid(4, 892866427853170301), name: 'name', type: 9, flags: 0) @@ -965,265 +1262,58 @@ final _entities = [ relations: [], backlinks: []), ModelEntity( - id: const IdUid(12, 4792946829926694975), + id: const IdUid(15, 1489637104339473454), name: 'StoreTable', - lastPropertyId: const IdUid(9, 7339624305009640005), + lastPropertyId: const IdUid(9, 3324089846938173439), flags: 0, properties: [ ModelProperty( - id: const IdUid(1, 5161461464205471313), + id: const IdUid(1, 1569712141162636099), name: 'obid', type: 6, flags: 1), ModelProperty( - id: const IdUid(2, 2250330636427721712), + id: const IdUid(2, 3471933483649547679), name: 'id', type: 9, flags: 0), ModelProperty( - id: const IdUid(3, 7078228715944385642), + id: const IdUid(3, 8526951040320487372), name: 'storeId', type: 9, flags: 0), ModelProperty( - id: const IdUid(4, 6907441787714879967), + id: const IdUid(4, 7479315922939182336), name: 'tableName', type: 9, flags: 0), ModelProperty( - id: const IdUid(5, 1807830950883981205), + id: const IdUid(5, 4858683358714605179), name: 'isAvailable', type: 1, flags: 0), ModelProperty( - id: const IdUid(6, 1320114005794250118), + id: const IdUid(6, 7456420564747859667), name: 'noOfOccupants', type: 6, flags: 0), ModelProperty( - id: const IdUid(7, 1364019554975041073), + id: const IdUid(7, 1955120184216864004), name: 'status', type: 9, flags: 0), ModelProperty( - id: const IdUid(8, 7803212150605615248), + id: const IdUid(8, 2449972005791983419), name: 'createdAt', type: 9, flags: 0), ModelProperty( - id: const IdUid(9, 7339624305009640005), + id: const IdUid(9, 3324089846938173439), name: 'updatedAt', type: 9, flags: 0) ], relations: [], - backlinks: []), - ModelEntity( - id: const IdUid(13, 5996081504664112046), - name: 'ItemsDeliveryPartner', - lastPropertyId: const IdUid(4, 413229903388265541), - flags: 0, - properties: [ - ModelProperty( - id: const IdUid(1, 7558591377752814699), - name: 'obid', - type: 6, - flags: 1), - ModelProperty( - id: const IdUid(2, 5321051554644965730), - name: 'id', - type: 9, - flags: 0), - ModelProperty( - id: const IdUid(3, 5900908455665998319), - name: 'name', - type: 9, - flags: 0), - ModelProperty( - id: const IdUid(4, 413229903388265541), - name: 'price', - type: 8, - flags: 0) - ], - relations: [], - backlinks: []), - ModelEntity( - id: const IdUid(14, 2243559031857156403), - name: 'CreateAndUpdateOrder', - lastPropertyId: const IdUid(25, 5380152695145525158), - flags: 0, - properties: [ - ModelProperty( - id: const IdUid(1, 463771832971349129), - name: 'obid', - type: 6, - flags: 1), - ModelProperty( - id: const IdUid(2, 8205635080192462875), - name: 'deliveryPartnerId', - type: 9, - flags: 0), - ModelProperty( - id: const IdUid(3, 1295421854826451219), - name: 'totalCartPrice', - type: 8, - flags: 0), - ModelProperty( - id: const IdUid(4, 4260940299009078774), - name: 'totalItemTax', - type: 8, - flags: 0), - ModelProperty( - id: const IdUid(5, 9213819911654038065), - name: 'cartUniqueToken', - type: 9, - flags: 0), - ModelProperty( - id: const IdUid(6, 7696189442168776726), - name: 'destinationAddresses', - type: 9, - flags: 0), - ModelProperty( - id: const IdUid(7, 206104808651765719), - name: 'minOrderPrice', - type: 8, - flags: 0), - ModelProperty( - id: const IdUid(8, 246907667287481202), - name: 'storeId', - type: 9, - flags: 0), - ModelProperty( - id: const IdUid(9, 7836359085725272770), - name: 'orderId', - type: 9, - flags: 0), - ModelProperty( - id: const IdUid(10, 8994870949807330771), - name: 'cartId', - type: 9, - flags: 0), - ModelProperty( - id: const IdUid(11, 7037308027108259390), - name: 'orderType', - type: 9, - flags: 0), - ModelProperty( - id: const IdUid(12, 4085412202121581938), - name: 'selectedTableName', - type: 9, - flags: 0), - ModelProperty( - id: const IdUid(13, 7379496384525075640), - name: 'createdAt', - type: 9, - flags: 0), - ModelProperty( - id: const IdUid(14, 1451785132581962717), - name: 'cartUniqueId', - type: 6, - flags: 0), - ModelProperty( - id: const IdUid(15, 8882612019402084984), - name: 'orderStatus', - type: 9, - flags: 0), - ModelProperty( - id: const IdUid(16, 2210373624469224774), - name: 'paymentStatus', - type: 1, - flags: 0), - ModelProperty( - id: const IdUid(17, 5742303538396335710), - name: 'paymentMode', - type: 9, - flags: 0), - ModelProperty( - id: const IdUid(18, 6954546626390917395), - name: 'amount', - type: 8, - flags: 0), - ModelProperty( - id: const IdUid(19, 3329670262914621917), - name: 'totalAmount', - type: 8, - flags: 0), - ModelProperty( - id: const IdUid(20, 2101442183486083730), - name: 'totalDiscount', - type: 8, - flags: 0), - ModelProperty( - id: const IdUid(21, 6052881256330509555), - name: 'cardNumber', - type: 6, - flags: 0), - ModelProperty( - id: const IdUid(22, 8316649940982602697), - name: 'changeBalanceAmount', - type: 8, - flags: 0), - ModelProperty( - id: const IdUid(23, 1322101751630018123), - name: 'timer', - type: 6, - flags: 0), - ModelProperty( - id: const IdUid(24, 1365695547169021744), - name: 'orderNumber', - type: 6, - flags: 0), - ModelProperty( - id: const IdUid(25, 5380152695145525158), - name: 'deliveryNotes', - type: 9, - flags: 0) - ], - relations: [ - ModelRelation( - id: const IdUid(11, 5546190593844039407), - name: 'orderDetails', - targetId: const IdUid(15, 8907175224708130311)) - ], - backlinks: []), - ModelEntity( - id: const IdUid(15, 8907175224708130311), - name: 'OrderDetails', - lastPropertyId: const IdUid(5, 1658943849080100081), - flags: 0, - properties: [ - ModelProperty( - id: const IdUid(1, 1240404718098977815), - name: 'obid', - type: 6, - flags: 1), - ModelProperty( - id: const IdUid(2, 3097928661595020588), - name: 'productId', - type: 9, - flags: 0), - ModelProperty( - id: const IdUid(3, 2104286542884585499), - name: 'totalItemTax', - type: 8, - flags: 0), - ModelProperty( - id: const IdUid(4, 7518986807521211001), - name: 'totalItemPrice', - type: 8, - flags: 0), - ModelProperty( - id: const IdUid(5, 1658943849080100081), - name: 'totalItemPriceWithoutModifier', - type: 8, - flags: 0) - ], - relations: [ - ModelRelation( - id: const IdUid(12, 2910557659214800545), - name: 'items', - targetId: const IdUid(10, 2288317989854260117)) - ], backlinks: []) ]; @@ -1254,14 +1344,26 @@ Future openStore( ModelDefinition getObjectBoxModel() { final model = ModelInfo( entities: _entities, - lastEntityId: const IdUid(15, 8907175224708130311), - lastIndexId: const IdUid(0, 0), - lastRelationId: const IdUid(12, 2910557659214800545), + lastEntityId: const IdUid(15, 1489637104339473454), + lastIndexId: const IdUid(2, 697578080641452147), + lastRelationId: const IdUid(13, 3946042636854669420), lastSequenceId: const IdUid(0, 0), retiredEntityUids: const [], - retiredIndexUids: const [], - retiredPropertyUids: const [3983827389374598831], - retiredRelationUids: const [3987703562461513320, 6157209775966721309], + retiredIndexUids: const [697578080641452147], + retiredPropertyUids: const [ + 6464732619707652235, + 5115272601749912683, + 332528716817670633, + 6806772396680135695, + 4308207840496701392 + ], + retiredRelationUids: const [ + 5306917274628500179, + 7868966108033718381, + 1374064699460362314, + 3322629234919122826, + 6448746763438190656 + ], modelVersion: 5, modelVersionParserMinimum: 5, version: 1); @@ -1304,7 +1406,8 @@ ModelDefinition getObjectBoxModel() { final updatedAtOffset = fbb.writeString(object.updatedAt); final measuringUnitOffset = fbb.writeString(object.measuringUnit); final idOffset = fbb.writeString(object.id); - fbb.startTable(33); + final quantityOffset = fbb.writeString(object.quantity); + fbb.startTable(46); fbb.addInt64(0, object.obid); fbb.addOffset(1, nameOffset); fbb.addOffset(2, descriptionOffset); @@ -1337,6 +1440,19 @@ ModelDefinition getObjectBoxModel() { fbb.addOffset(29, measuringUnitOffset); fbb.addBool(30, object.checked); fbb.addOffset(31, idOffset); + fbb.addOffset(32, quantityOffset); + fbb.addFloat64(33, object.purchasePrice); + fbb.addFloat64(34, object.salePrice); + fbb.addFloat64(35, object.defaultSalePrice); + fbb.addFloat64(36, object.price); + fbb.addFloat64(37, object.purchaseCost); + fbb.addFloat64(38, object.itemPriceWithoutOffer); + fbb.addInt64(39, object.totalQuantity); + fbb.addInt64(40, object.totalAddedQuantity); + fbb.addInt64(41, object.totalUsedQuantity); + fbb.addFloat64(42, object.salePriceExclusiveTax); + fbb.addInt64(43, object.stockAlertQuantity); + fbb.addFloat64(44, object.salePriceInclusiveTax); fbb.finish(fbb.endTable()); return object.obid; }, @@ -1350,6 +1466,14 @@ ModelDefinition getObjectBoxModel() { .vTableGet(buffer, rootOffset, 8, ''); final valueParam = const fb.StringReader(asciiOptimization: true) .vTableGet(buffer, rootOffset, 10, ''); + final quantityParam = const fb.StringReader(asciiOptimization: true) + .vTableGet(buffer, rootOffset, 68, ''); + final purchasePriceParam = const fb.Float64Reader() + .vTableGetNullable(buffer, rootOffset, 70); + final salePriceParam = const fb.Float64Reader() + .vTableGetNullable(buffer, rootOffset, 72); + final defaultSalePriceParam = const fb.Float64Reader() + .vTableGetNullable(buffer, rootOffset, 74); final categoryIdParam = const fb.StringReader(asciiOptimization: true) .vTableGet(buffer, rootOffset, 12, ''); final productIdParam = const fb.StringReader(asciiOptimization: true) @@ -1358,8 +1482,20 @@ ModelDefinition getObjectBoxModel() { .vTableGet(buffer, rootOffset, 16, ''); final details1Param = const fb.StringReader(asciiOptimization: true) .vTableGet(buffer, rootOffset, 18, ''); + final priceParam = const fb.Float64Reader() + .vTableGetNullable(buffer, rootOffset, 76); + final purchaseCostParam = const fb.Float64Reader() + .vTableGetNullable(buffer, rootOffset, 78); + final itemPriceWithoutOfferParam = const fb.Float64Reader() + .vTableGetNullable(buffer, rootOffset, 80); + final totalQuantityParam = + const fb.Int64Reader().vTableGetNullable(buffer, rootOffset, 82); final inCartQuantityParam = const fb.BoolReader().vTableGet(buffer, rootOffset, 20, false); + final totalAddedQuantityParam = + const fb.Int64Reader().vTableGetNullable(buffer, rootOffset, 84); + final totalUsedQuantityParam = + const fb.Int64Reader().vTableGetNullable(buffer, rootOffset, 86); final noteForItemParam = const fb.StringReader(asciiOptimization: true) .vTableGet(buffer, rootOffset, 22, ''); @@ -1384,9 +1520,15 @@ ModelDefinition getObjectBoxModel() { final itemDescriptionArabicParam = const fb.StringReader(asciiOptimization: true) .vTableGet(buffer, rootOffset, 40, ''); + final salePriceExclusiveTaxParam = const fb.Float64Reader() + .vTableGetNullable(buffer, rootOffset, 88); final productCodeParam = const fb.StringReader(asciiOptimization: true) .vTableGet(buffer, rootOffset, 42, ''); + final stockAlertQuantityParam = + const fb.Int64Reader().vTableGetNullable(buffer, rootOffset, 90); + final salePriceInclusiveTaxParam = const fb.Float64Reader() + .vTableGetNullable(buffer, rootOffset, 92); final supplierParam = const fb.StringReader(asciiOptimization: true) .vTableGet(buffer, rootOffset, 44, ''); final discountParam = const fb.StringReader(asciiOptimization: true) @@ -1419,11 +1561,21 @@ ModelDefinition getObjectBoxModel() { name: nameParam, description: descriptionParam, value: valueParam, + quantity: quantityParam, + purchasePrice: purchasePriceParam, + salePrice: salePriceParam, + defaultSalePrice: defaultSalePriceParam, categoryId: categoryIdParam, productId: productIdParam, details: detailsParam, details1: details1Param, + price: priceParam, + purchaseCost: purchaseCostParam, + itemPriceWithoutOffer: itemPriceWithoutOfferParam, + totalQuantity: totalQuantityParam, inCartQuantity: inCartQuantityParam, + totalAddedQuantity: totalAddedQuantityParam, + totalUsedQuantity: totalUsedQuantityParam, noteForItem: noteForItemParam, uniqueIdForStoreData: uniqueIdForStoreDataParam, isItemInStock: isItemInStockParam, @@ -1434,7 +1586,10 @@ ModelDefinition getObjectBoxModel() { tags: tagsParam, itemNameArabic: itemNameArabicParam, itemDescriptionArabic: itemDescriptionArabicParam, + salePriceExclusiveTax: salePriceExclusiveTaxParam, productCode: productCodeParam, + stockAlertQuantity: stockAlertQuantityParam, + salePriceInclusiveTax: salePriceInclusiveTaxParam, supplier: supplierParam, discount: discountParam, measurementCategory: measurementCategoryParam, @@ -1532,36 +1687,185 @@ ModelDefinition getObjectBoxModel() { return object; }), - DeliveryPartner: EntityDefinition( + CreateAndUpdateOrder: EntityDefinition( model: _entities[2], - toOneRelations: (DeliveryPartner object) => [], - toManyRelations: (DeliveryPartner object) => {}, - getId: (DeliveryPartner object) => object.obid, - setId: (DeliveryPartner object, int id) { + toOneRelations: (CreateAndUpdateOrder object) => [], + toManyRelations: (CreateAndUpdateOrder object) => {}, + getId: (CreateAndUpdateOrder object) => object.obid, + setId: (CreateAndUpdateOrder object, int id) { object.obid = id; }, - objectToFB: (DeliveryPartner object, fb.Builder fbb) { - final idOffset = fbb.writeString(object.id); - final nameOffset = fbb.writeString(object.name); - final nameArabicOffset = fbb.writeString(object.nameArabic); - final statusOffset = fbb.writeString(object.status); + objectToFB: (CreateAndUpdateOrder object, fb.Builder fbb) { + final deliveryPartnerIdOffset = + fbb.writeString(object.deliveryPartnerId); + final cartUniqueTokenOffset = object.cartUniqueToken == null + ? null + : fbb.writeString(object.cartUniqueToken!); + final destinationAddressesOffset = object.destinationAddresses == null + ? null + : fbb.writeString(object.destinationAddresses!); + final storeIdOffset = + object.storeId == null ? null : fbb.writeString(object.storeId!); + final orderIdOffset = + object.orderId == null ? null : fbb.writeString(object.orderId!); + final cartIdOffset = + object.cartId == null ? null : fbb.writeString(object.cartId!); + final orderTypeOffset = object.orderType == null + ? null + : fbb.writeString(object.orderType!); + final selectedTableNameOffset = + fbb.writeString(object.selectedTableName); final createdAtOffset = fbb.writeString(object.createdAt); - final updatedAtOffset = fbb.writeString(object.updatedAt); - final storesOffset = object.stores == null + final orderStatusOffset = object.orderStatus == null ? null - : fbb.writeList( - object.stores!.map(fbb.writeString).toList(growable: false)); - fbb.startTable(9); + : fbb.writeString(object.orderStatus!); + final paymentModeOffset = object.paymentMode == null + ? null + : fbb.writeString(object.paymentMode!); + final discountIdOffset = object.discountId == null + ? null + : fbb.writeString(object.discountId!); + final deliveryNotesOffset = object.deliveryNotes == null + ? null + : fbb.writeString(object.deliveryNotes!); + final orderDetailsOfflineOffset = object.orderDetailsOffline == null + ? null + : fbb.writeString(object.orderDetailsOffline!); + fbb.startTable(28); fbb.addInt64(0, object.obid); - fbb.addOffset(1, idOffset); - fbb.addOffset(2, nameOffset); - fbb.addOffset(3, nameArabicOffset); - fbb.addOffset(4, statusOffset); - fbb.addOffset(5, createdAtOffset); - fbb.addOffset(6, updatedAtOffset); - fbb.addOffset(7, storesOffset); - fbb.finish(fbb.endTable()); - return object.obid; + fbb.addOffset(1, deliveryPartnerIdOffset); + fbb.addFloat64(2, object.totalCartPrice); + fbb.addFloat64(3, object.totalItemTax); + fbb.addOffset(4, cartUniqueTokenOffset); + fbb.addOffset(5, destinationAddressesOffset); + fbb.addFloat64(6, object.minOrderPrice); + fbb.addOffset(7, storeIdOffset); + fbb.addOffset(8, orderIdOffset); + fbb.addOffset(9, cartIdOffset); + fbb.addOffset(10, orderTypeOffset); + fbb.addOffset(11, selectedTableNameOffset); + fbb.addOffset(12, createdAtOffset); + fbb.addInt64(13, object.cartUniqueId); + fbb.addOffset(14, orderStatusOffset); + fbb.addBool(15, object.paymentStatus); + fbb.addOffset(16, paymentModeOffset); + fbb.addFloat64(17, object.amount); + fbb.addFloat64(18, object.totalAmount); + fbb.addFloat64(19, object.totalDiscount); + fbb.addOffset(20, discountIdOffset); + fbb.addInt64(21, object.cardNumber); + fbb.addFloat64(22, object.changeBalanceAmount); + fbb.addInt64(23, object.timer); + fbb.addInt64(24, object.orderNumber); + fbb.addOffset(25, deliveryNotesOffset); + fbb.addOffset(26, orderDetailsOfflineOffset); + fbb.finish(fbb.endTable()); + return object.obid; + }, + objectFromFB: (Store store, ByteData fbData) { + final buffer = fb.BufferContext(fbData); + final rootOffset = buffer.derefObject(0); + final totalCartPriceParam = + const fb.Float64Reader().vTableGetNullable(buffer, rootOffset, 8); + final totalItemTaxParam = const fb.Float64Reader() + .vTableGetNullable(buffer, rootOffset, 10); + final cartUniqueTokenParam = + const fb.StringReader(asciiOptimization: true) + .vTableGetNullable(buffer, rootOffset, 12); + final destinationAddressesParam = + const fb.StringReader(asciiOptimization: true) + .vTableGetNullable(buffer, rootOffset, 14); + final minOrderPriceParam = const fb.Float64Reader() + .vTableGetNullable(buffer, rootOffset, 16); + final orderDetailsParam = ToMany(); + final storeIdParam = const fb.StringReader(asciiOptimization: true) + .vTableGetNullable(buffer, rootOffset, 18); + final orderIdParam = const fb.StringReader(asciiOptimization: true) + .vTableGetNullable(buffer, rootOffset, 20); + final cartIdParam = const fb.StringReader(asciiOptimization: true) + .vTableGetNullable(buffer, rootOffset, 22); + final object = CreateAndUpdateOrder( + totalCartPrice: totalCartPriceParam, + totalItemTax: totalItemTaxParam, + cartUniqueToken: cartUniqueTokenParam, + destinationAddresses: destinationAddressesParam, + minOrderPrice: minOrderPriceParam, + orderDetails: orderDetailsParam, + storeId: storeIdParam, + orderId: orderIdParam, + cartId: cartIdParam) + ..obid = const fb.Int64Reader().vTableGet(buffer, rootOffset, 4, 0) + ..deliveryPartnerId = const fb.StringReader(asciiOptimization: true) + .vTableGet(buffer, rootOffset, 6, '') + ..orderType = const fb.StringReader(asciiOptimization: true) + .vTableGetNullable(buffer, rootOffset, 24) + ..selectedTableName = const fb.StringReader(asciiOptimization: true) + .vTableGet(buffer, rootOffset, 26, '') + ..createdAt = const fb.StringReader(asciiOptimization: true) + .vTableGet(buffer, rootOffset, 28, '') + ..cartUniqueId = + const fb.Int64Reader().vTableGet(buffer, rootOffset, 30, 0) + ..orderStatus = const fb.StringReader(asciiOptimization: true) + .vTableGetNullable(buffer, rootOffset, 32) + ..paymentStatus = + const fb.BoolReader().vTableGet(buffer, rootOffset, 34, false) + ..paymentMode = const fb.StringReader(asciiOptimization: true) + .vTableGetNullable(buffer, rootOffset, 36) + ..amount = const fb.Float64Reader() + .vTableGetNullable(buffer, rootOffset, 38) + ..totalAmount = const fb.Float64Reader() + .vTableGetNullable(buffer, rootOffset, 40) + ..totalDiscount = const fb.Float64Reader() + .vTableGetNullable(buffer, rootOffset, 42) + ..discountId = const fb.StringReader(asciiOptimization: true) + .vTableGetNullable(buffer, rootOffset, 44) + ..cardNumber = + const fb.Int64Reader().vTableGetNullable(buffer, rootOffset, 46) + ..changeBalanceAmount = const fb.Float64Reader() + .vTableGetNullable(buffer, rootOffset, 48) + ..timer = + const fb.Int64Reader().vTableGetNullable(buffer, rootOffset, 50) + ..orderNumber = + const fb.Int64Reader().vTableGetNullable(buffer, rootOffset, 52) + ..deliveryNotes = const fb.StringReader(asciiOptimization: true) + .vTableGetNullable(buffer, rootOffset, 54) + ..orderDetailsOffline = + const fb.StringReader(asciiOptimization: true) + .vTableGetNullable(buffer, rootOffset, 56); + + return object; + }), + DeliveryPartner: EntityDefinition( + model: _entities[3], + toOneRelations: (DeliveryPartner object) => [], + toManyRelations: (DeliveryPartner object) => {}, + getId: (DeliveryPartner object) => object.obid, + setId: (DeliveryPartner object, int id) { + object.obid = id; + }, + objectToFB: (DeliveryPartner object, fb.Builder fbb) { + final idOffset = fbb.writeString(object.id); + final nameOffset = fbb.writeString(object.name); + final nameArabicOffset = fbb.writeString(object.nameArabic); + final statusOffset = fbb.writeString(object.status); + final createdAtOffset = fbb.writeString(object.createdAt); + final updatedAtOffset = fbb.writeString(object.updatedAt); + final storesOffset = object.stores == null + ? null + : fbb.writeList( + object.stores!.map(fbb.writeString).toList(growable: false)); + fbb.startTable(10); + fbb.addInt64(0, object.obid); + fbb.addOffset(1, idOffset); + fbb.addOffset(2, nameOffset); + fbb.addOffset(3, nameArabicOffset); + fbb.addOffset(4, statusOffset); + fbb.addOffset(5, createdAtOffset); + fbb.addOffset(6, updatedAtOffset); + fbb.addOffset(7, storesOffset); + fbb.addInt64(8, object.totalItemCount); + fbb.finish(fbb.endTable()); + return object.obid; }, objectFromFB: (Store store, ByteData fbData) { final buffer = fb.BufferContext(fbData); @@ -1582,6 +1886,8 @@ ModelDefinition getObjectBoxModel() { .vTableGet(buffer, rootOffset, 14, ''); final updatedAtParam = const fb.StringReader(asciiOptimization: true) .vTableGet(buffer, rootOffset, 16, ''); + final totalItemCountParam = + const fb.Int64Reader().vTableGetNullable(buffer, rootOffset, 20); final object = DeliveryPartner( id: idParam, status: statusParam, @@ -1589,13 +1895,14 @@ ModelDefinition getObjectBoxModel() { stores: storesParam, name: nameParam, createdAt: createdAtParam, - updatedAt: updatedAtParam) + updatedAt: updatedAtParam, + totalItemCount: totalItemCountParam) ..obid = const fb.Int64Reader().vTableGet(buffer, rootOffset, 4, 0); return object; }), ItemCategory: EntityDefinition( - model: _entities[3], + model: _entities[4], toOneRelations: (ItemCategory object) => [], toManyRelations: (ItemCategory object) => {}, getId: (ItemCategory object) => object.obid, @@ -1675,7 +1982,7 @@ ModelDefinition getObjectBoxModel() { return object; }), ItemSubCategory: EntityDefinition( - model: _entities[4], + model: _entities[5], toOneRelations: (ItemSubCategory object) => [], toManyRelations: (ItemSubCategory object) => {}, getId: (ItemSubCategory object) => object.odid, @@ -1740,14 +2047,48 @@ ModelDefinition getObjectBoxModel() { storeId: storeIdParam) ..odid = const fb.Int64Reader().vTableGet(buffer, rootOffset, 4, 0); + return object; + }), + ItemsDeliveryPartner: EntityDefinition( + model: _entities[6], + toOneRelations: (ItemsDeliveryPartner object) => [], + toManyRelations: (ItemsDeliveryPartner object) => {}, + getId: (ItemsDeliveryPartner object) => object.obid, + setId: (ItemsDeliveryPartner object, int id) { + object.obid = id; + }, + objectToFB: (ItemsDeliveryPartner object, fb.Builder fbb) { + final idOffset = fbb.writeString(object.id); + final nameOffset = fbb.writeString(object.name); + fbb.startTable(5); + fbb.addInt64(0, object.obid); + fbb.addOffset(1, idOffset); + fbb.addOffset(2, nameOffset); + fbb.addFloat64(3, object.price); + fbb.finish(fbb.endTable()); + return object.obid; + }, + objectFromFB: (Store store, ByteData fbData) { + final buffer = fb.BufferContext(fbData); + final rootOffset = buffer.derefObject(0); + final idParam = const fb.StringReader(asciiOptimization: true) + .vTableGet(buffer, rootOffset, 6, ''); + final nameParam = const fb.StringReader(asciiOptimization: true) + .vTableGet(buffer, rootOffset, 8, ''); + final priceParam = + const fb.Float64Reader().vTableGet(buffer, rootOffset, 10, 0); + final object = ItemsDeliveryPartner( + id: idParam, name: nameParam, price: priceParam) + ..obid = const fb.Int64Reader().vTableGet(buffer, rootOffset, 4, 0); + return object; }), Modifier: EntityDefinition( - model: _entities[5], + model: _entities[7], toOneRelations: (Modifier object) => [], toManyRelations: (Modifier object) => { - RelInfo.toMany(9, object.obid): object.options, - RelInfo.toMany(10, object.obid): object.selected + RelInfo.toMany(2, object.obid): object.options, + RelInfo.toMany(3, object.obid): object.selected }, getId: (Modifier object) => object.obid, setId: (Modifier object, int id) { @@ -1767,13 +2108,13 @@ ModelDefinition getObjectBoxModel() { fbb.addOffset(2, nameOffset); fbb.addOffset(3, arabicNameOffset); fbb.addOffset(4, descriptionOffset); - fbb.addOffset(5, statusOffset); - fbb.addBool(6, object.isMultiple); - fbb.addOffset(7, createdOnOffset); - fbb.addOffset(8, updatedOnOffset); - fbb.addBool(9, object.isSelected); - fbb.addInt64(10, object.selectedModifierIndex); - fbb.addFloat64(11, object.price); + fbb.addFloat64(5, object.price); + fbb.addOffset(6, statusOffset); + fbb.addBool(7, object.isMultiple); + fbb.addOffset(8, createdOnOffset); + fbb.addOffset(9, updatedOnOffset); + fbb.addBool(10, object.isSelected); + fbb.addInt64(11, object.selectedModifierIndex); fbb.finish(fbb.endTable()); return object.obid; }, @@ -1790,19 +2131,19 @@ ModelDefinition getObjectBoxModel() { const fb.StringReader(asciiOptimization: true) .vTableGet(buffer, rootOffset, 12, ''); final priceParam = - const fb.Float64Reader().vTableGet(buffer, rootOffset, 26, 0); + const fb.Float64Reader().vTableGet(buffer, rootOffset, 14, 0); final optionsParam = ToMany(); final selectedParam = ToMany(); final statusParam = const fb.StringReader(asciiOptimization: true) - .vTableGet(buffer, rootOffset, 14, ''); + .vTableGet(buffer, rootOffset, 16, ''); final isSelectedParam = - const fb.BoolReader().vTableGet(buffer, rootOffset, 22, false); + const fb.BoolReader().vTableGet(buffer, rootOffset, 24, false); final isMultipleParam = - const fb.BoolReader().vTableGet(buffer, rootOffset, 16, false); + const fb.BoolReader().vTableGet(buffer, rootOffset, 18, false); final createdOnParam = const fb.StringReader(asciiOptimization: true) - .vTableGet(buffer, rootOffset, 18, ''); - final updatedOnParam = const fb.StringReader(asciiOptimization: true) .vTableGet(buffer, rootOffset, 20, ''); + final updatedOnParam = const fb.StringReader(asciiOptimization: true) + .vTableGet(buffer, rootOffset, 22, ''); final object = Modifier( id: idParam, name: nameParam, @@ -1818,17 +2159,20 @@ ModelDefinition getObjectBoxModel() { updatedOn: updatedOnParam) ..obid = const fb.Int64Reader().vTableGet(buffer, rootOffset, 4, 0) ..selectedModifierIndex = - const fb.Int64Reader().vTableGet(buffer, rootOffset, 24, 0); + const fb.Int64Reader().vTableGet(buffer, rootOffset, 26, 0); + InternalToManyAccess.setRelInfo( + object.options, store, RelInfo.toMany(2, object.obid)); InternalToManyAccess.setRelInfo( - object.options, store, RelInfo.toMany(9, object.obid)); - InternalToManyAccess.setRelInfo(object.selected, store, - RelInfo.toMany(10, object.obid)); + object.selected, store, RelInfo.toMany(3, object.obid)); return object; }), ModifierOption: EntityDefinition( - model: _entities[6], + model: _entities[8], toOneRelations: (ModifierOption object) => [], - toManyRelations: (ModifierOption object) => {}, + toManyRelations: (ModifierOption object) => { + RelInfo.toMany(13, object.obid): + object.ingredients + }, getId: (ModifierOption object) => object.obid, setId: (ModifierOption object, int id) { object.obid = id; @@ -1837,7 +2181,9 @@ ModelDefinition getObjectBoxModel() { final nameOffset = fbb.writeString(object.name); final arabicNameOffset = fbb.writeString(object.arabicName); final modifierNameOffset = fbb.writeString(object.modifierName); - fbb.startTable(8); + final idOffset = fbb.writeString(object.id); + final modifierIdOffset = fbb.writeString(object.modifierId); + fbb.startTable(10); fbb.addInt64(0, object.obid); fbb.addOffset(1, nameOffset); fbb.addOffset(2, arabicNameOffset); @@ -1845,6 +2191,8 @@ ModelDefinition getObjectBoxModel() { fbb.addBool(4, object.isSelected); fbb.addOffset(5, modifierNameOffset); fbb.addInt64(6, object.qtyIdx); + fbb.addOffset(7, idOffset); + fbb.addOffset(8, modifierIdOffset); fbb.finish(fbb.endTable()); return object.obid; }, @@ -1853,10 +2201,15 @@ ModelDefinition getObjectBoxModel() { final rootOffset = buffer.derefObject(0); final nameParam = const fb.StringReader(asciiOptimization: true) .vTableGet(buffer, rootOffset, 6, ''); + final idParam = const fb.StringReader(asciiOptimization: true) + .vTableGet(buffer, rootOffset, 18, ''); + final modifierIdParam = const fb.StringReader(asciiOptimization: true) + .vTableGet(buffer, rootOffset, 20, ''); final arabicNameParam = const fb.StringReader(asciiOptimization: true) .vTableGet(buffer, rootOffset, 8, ''); final priceParam = const fb.Float64Reader().vTableGet(buffer, rootOffset, 10, 0); + final ingredientsParam = ToMany(); final isSelectedParam = const fb.BoolReader().vTableGet(buffer, rootOffset, 12, false); final modifierNameParam = @@ -1866,17 +2219,69 @@ ModelDefinition getObjectBoxModel() { const fb.Int64Reader().vTableGet(buffer, rootOffset, 16, 0); final object = ModifierOption( name: nameParam, + id: idParam, + modifierId: modifierIdParam, arabicName: arabicNameParam, price: priceParam, + ingredients: ingredientsParam, isSelected: isSelectedParam, modifierName: modifierNameParam, qtyIdx: qtyIdxParam) ..obid = const fb.Int64Reader().vTableGet(buffer, rootOffset, 4, 0); - + InternalToManyAccess.setRelInfo(object.ingredients, + store, RelInfo.toMany(13, object.obid)); + return object; + }), + OrderDetails: EntityDefinition( + model: _entities[9], + toOneRelations: (OrderDetails object) => [], + toManyRelations: (OrderDetails object) => + {RelInfo.toMany(12, object.id): object.items}, + getId: (OrderDetails object) => object.id, + setId: (OrderDetails object, int id) { + object.id = id; + }, + objectToFB: (OrderDetails object, fb.Builder fbb) { + final productIdOffset = object.productId == null + ? null + : fbb.writeString(object.productId!); + fbb.startTable(7); + fbb.addOffset(1, productIdOffset); + fbb.addFloat64(2, object.totalItemTax); + fbb.addFloat64(3, object.totalItemPrice); + fbb.addFloat64(4, object.totalItemPriceWithoutModifier); + fbb.addInt64(5, object.id); + fbb.finish(fbb.endTable()); + return object.id; + }, + objectFromFB: (Store store, ByteData fbData) { + final buffer = fb.BufferContext(fbData); + final rootOffset = buffer.derefObject(0); + final productIdParam = const fb.StringReader(asciiOptimization: true) + .vTableGetNullable(buffer, rootOffset, 6); + final idParam = + const fb.Int64Reader().vTableGet(buffer, rootOffset, 14, 0); + final totalItemTaxParam = + const fb.Float64Reader().vTableGetNullable(buffer, rootOffset, 8); + final totalItemPriceParam = const fb.Float64Reader() + .vTableGetNullable(buffer, rootOffset, 10); + final itemsParam = ToMany(); + final totalItemPriceWithoutModifierParam = const fb.Float64Reader() + .vTableGetNullable(buffer, rootOffset, 12); + final object = OrderDetails( + productId: productIdParam, + id: idParam, + totalItemTax: totalItemTaxParam, + totalItemPrice: totalItemPriceParam, + items: itemsParam, + totalItemPriceWithoutModifier: + totalItemPriceWithoutModifierParam); + InternalToManyAccess.setRelInfo( + object.items, store, RelInfo.toMany(12, object.id)); return object; }), ProductId: EntityDefinition( - model: _entities[7], + model: _entities[10], toOneRelations: (ProductId object) => [], toManyRelations: (ProductId object) => {}, getId: (ProductId object) => object.obid, @@ -1900,18 +2305,18 @@ ModelDefinition getObjectBoxModel() { objectFromFB: (Store store, ByteData fbData) { final buffer = fb.BufferContext(fbData); final rootOffset = buffer.derefObject(0); - - final object = ProductId() - ..obid = const fb.Int64Reader().vTableGet(buffer, rootOffset, 4, 0) - ..productId = const fb.StringReader(asciiOptimization: true) - .vTableGetNullable(buffer, rootOffset, 6) - ..categoryId = const fb.StringReader(asciiOptimization: true) - .vTableGetNullable(buffer, rootOffset, 8); + final productIdParam = const fb.StringReader(asciiOptimization: true) + .vTableGetNullable(buffer, rootOffset, 6); + final categoryIdParam = const fb.StringReader(asciiOptimization: true) + .vTableGetNullable(buffer, rootOffset, 8); + final object = ProductId( + productId: productIdParam, categoryId: categoryIdParam) + ..obid = const fb.Int64Reader().vTableGet(buffer, rootOffset, 4, 0); return object; }), StoreDiscount: EntityDefinition( - model: _entities[8], + model: _entities[11], toOneRelations: (StoreDiscount object) => [], toManyRelations: (StoreDiscount object) => {}, getId: (StoreDiscount object) => object.obid, @@ -1968,7 +2373,7 @@ ModelDefinition getObjectBoxModel() { final updatedAtOffset = object.updatedAt == null ? null : fbb.writeString(object.updatedAt!); - fbb.startTable(27); + fbb.startTable(28); fbb.addInt64(0, object.obid); fbb.addOffset(1, discountValueOffset); fbb.addOffset(2, idOffset); @@ -1986,15 +2391,16 @@ ModelDefinition getObjectBoxModel() { fbb.addOffset(14, discountTypeOffset); fbb.addOffset(15, discountTypeLabelOffset); fbb.addFloat64(16, object.limitOfDiscount); - fbb.addOffset(17, discountStartDateOffset); - fbb.addOffset(18, discountEndDateOffset); - fbb.addBool(19, object.isDeleted); - fbb.addOffset(20, createdAtOffset); - fbb.addOffset(21, updatedAtOffset); - fbb.addBool(22, object.isAlways); - fbb.addBool(23, object.isMaxDiscount); - fbb.addBool(24, object.isMinAmount); - fbb.addBool(25, object.isUnlimited); + fbb.addFloat64(17, object.isUserUsed); + fbb.addOffset(18, discountStartDateOffset); + fbb.addOffset(19, discountEndDateOffset); + fbb.addBool(20, object.isDeleted); + fbb.addOffset(21, createdAtOffset); + fbb.addOffset(22, updatedAtOffset); + fbb.addBool(23, object.isAlways); + fbb.addBool(24, object.isMaxDiscount); + fbb.addBool(25, object.isMinAmount); + fbb.addBool(26, object.isUnlimited); fbb.finish(fbb.endTable()); return object.obid; }, @@ -2017,6 +2423,8 @@ ModelDefinition getObjectBoxModel() { .vTableGetNullable(buffer, rootOffset, 16); final storeIdParam = const fb.StringReader(asciiOptimization: true) .vTableGetNullable(buffer, rootOffset, 18); + final isUserUsedParam = const fb.Float64Reader() + .vTableGetNullable(buffer, rootOffset, 38); final categoriesParam = const fb.ListReader( fb.StringReader(asciiOptimization: true), lazy: false) @@ -2044,24 +2452,24 @@ ModelDefinition getObjectBoxModel() { .vTableGetNullable(buffer, rootOffset, 36); final discountStartDateParam = const fb.StringReader(asciiOptimization: true) - .vTableGetNullable(buffer, rootOffset, 38); + .vTableGetNullable(buffer, rootOffset, 40); final discountEndDateParam = const fb.StringReader(asciiOptimization: true) - .vTableGetNullable(buffer, rootOffset, 40); + .vTableGetNullable(buffer, rootOffset, 42); final isDeletedParam = - const fb.BoolReader().vTableGetNullable(buffer, rootOffset, 42); + const fb.BoolReader().vTableGetNullable(buffer, rootOffset, 44); final createdAtParam = const fb.StringReader(asciiOptimization: true) - .vTableGetNullable(buffer, rootOffset, 44); - final updatedAtParam = const fb.StringReader(asciiOptimization: true) .vTableGetNullable(buffer, rootOffset, 46); + final updatedAtParam = const fb.StringReader(asciiOptimization: true) + .vTableGetNullable(buffer, rootOffset, 48); final isAlwaysParam = - const fb.BoolReader().vTableGetNullable(buffer, rootOffset, 48); - final isMaxDiscountParam = const fb.BoolReader().vTableGetNullable(buffer, rootOffset, 50); - final isMinAmountParam = + final isMaxDiscountParam = const fb.BoolReader().vTableGetNullable(buffer, rootOffset, 52); - final isUnlimitedParam = + final isMinAmountParam = const fb.BoolReader().vTableGetNullable(buffer, rootOffset, 54); + final isUnlimitedParam = + const fb.BoolReader().vTableGetNullable(buffer, rootOffset, 56); final object = StoreDiscount( discountValue: discountValueParam, id: idParam, @@ -2070,6 +2478,7 @@ ModelDefinition getObjectBoxModel() { value: valueParam, type: typeParam, storeId: storeIdParam, + isUserUsed: isUserUsedParam, categories: categoriesParam, products: productsParam, status: statusParam, @@ -2093,24 +2502,19 @@ ModelDefinition getObjectBoxModel() { return object; }), StoreItems: EntityDefinition( - model: _entities[9], + model: _entities[12], toOneRelations: (StoreItems object) => [], toManyRelations: (StoreItems object) => { - RelInfo.toMany(3, object.obid): - object.deliveryPartners, - RelInfo.toMany(4, object.obid): object.selectedCombos, - RelInfo.toMany(5, object.obid): - object.selectedModifiers, - RelInfo.toMany(6, object.obid): object.ingredients, - RelInfo.toMany(7, object.obid): object.modifiers, - RelInfo.toMany(8, object.obid): object.comboProduct + RelInfo.toMany(7, object.id): object.ingredients, + RelInfo.toMany(8, object.id): object.modifiers, + RelInfo.toMany(9, object.id): object.deliveryPartners, + RelInfo.toMany(10, object.id): object.comboProduct }, - getId: (StoreItems object) => object.obid, + getId: (StoreItems object) => object.id, setId: (StoreItems object, int id) { - object.obid = id; + object.id = id; }, objectToFB: (StoreItems object, fb.Builder fbb) { - final idOffset = fbb.writeString(object.id); final nameOffset = fbb.writeString(object.name); final noteForItemOffset = object.noteForItem == null ? null @@ -2138,9 +2542,8 @@ ModelDefinition getObjectBoxModel() { final deliveryPartnerOffset = fbb.writeString(object.deliveryPartner); final manufactureDateOffset = fbb.writeString(object.manufactureDate); final expireDateOffset = fbb.writeString(object.expireDate); - fbb.startTable(38); - fbb.addInt64(0, object.obid); - fbb.addOffset(1, idOffset); + final itemIdOffset = fbb.writeString(object.itemId); + fbb.startTable(41); fbb.addOffset(2, nameOffset); fbb.addOffset(3, noteForItemOffset); fbb.addOffset(4, storeIdOffset); @@ -2151,7 +2554,6 @@ ModelDefinition getObjectBoxModel() { fbb.addFloat64(9, object.price); fbb.addInt64(10, object.uniqueId); fbb.addOffset(11, uniqueIdForStoreDataOffset); - fbb.addInt64(12, object.quantity); fbb.addOffset(13, imageUrlOffset); fbb.addOffset(14, updatedAtOffset); fbb.addBool(15, object.isItemInStock); @@ -2163,7 +2565,6 @@ ModelDefinition getObjectBoxModel() { fbb.addInt64(21, object.totalAddedQuantity); fbb.addInt64(22, object.totalUsedQuantity); fbb.addFloat64(23, object.salePriceExclusiveTax); - fbb.addFloat64(24, object.totalItemPrice); fbb.addOffset(25, supplierOffset); fbb.addOffset(26, discountOffset); fbb.addOffset(27, measurementCategoryOffset); @@ -2174,17 +2575,23 @@ ModelDefinition getObjectBoxModel() { fbb.addOffset(32, expireDateOffset); fbb.addBool(33, object.status); fbb.addBool(34, object.isCombo); - fbb.addBool(36, object.isCheckedForReturn); + fbb.addBool(35, object.isCheckedForReturn); + fbb.addInt64(36, object.id); + fbb.addOffset(37, itemIdOffset); + fbb.addInt64(38, object.quantity); + fbb.addFloat64(39, object.totalItemPrice); fbb.finish(fbb.endTable()); - return object.obid; + return object.id; }, objectFromFB: (Store store, ByteData fbData) { final buffer = fb.BufferContext(fbData); final rootOffset = buffer.derefObject(0); final nameParam = const fb.StringReader(asciiOptimization: true) .vTableGet(buffer, rootOffset, 8, ''); - final idParam = const fb.StringReader(asciiOptimization: true) - .vTableGet(buffer, rootOffset, 6, ''); + final itemIdParam = const fb.StringReader(asciiOptimization: true) + .vTableGet(buffer, rootOffset, 78, ''); + final idParam = + const fb.Int64Reader().vTableGet(buffer, rootOffset, 76, 0); final deliveryPartnersParam = ToMany(); final isUnlimitedQuantityParam = const fb.BoolReader().vTableGet(buffer, rootOffset, 14, false); @@ -2207,13 +2614,13 @@ ModelDefinition getObjectBoxModel() { const fb.StringReader(asciiOptimization: true) .vTableGet(buffer, rootOffset, 26, ''); final quantityParam = - const fb.Int64Reader().vTableGet(buffer, rootOffset, 28, 0); + const fb.Int64Reader().vTableGetNullable(buffer, rootOffset, 80); final imageUrlParam = const fb.StringReader(asciiOptimization: true) .vTableGet(buffer, rootOffset, 30, ''); final updatedAtParam = const fb.StringReader(asciiOptimization: true) .vTableGet(buffer, rootOffset, 32, ''); - final totalItemPriceParam = - const fb.Float64Reader().vTableGet(buffer, rootOffset, 52, 0); + final totalItemPriceParam = const fb.Float64Reader() + .vTableGetNullable(buffer, rootOffset, 82); final isItemInStockParam = const fb.BoolReader().vTableGet(buffer, rootOffset, 34, false); final descriptionParam = @@ -2265,6 +2672,7 @@ ModelDefinition getObjectBoxModel() { const fb.BoolReader().vTableGet(buffer, rootOffset, 70, false); final object = StoreItems( name: nameParam, + itemId: itemIdParam, id: idParam, deliveryPartners: deliveryPartnersParam, isUnlimitedQuantity: isUnlimitedQuantityParam, @@ -2303,28 +2711,23 @@ ModelDefinition getObjectBoxModel() { manufactureDate: manufactureDateParam, expireDate: expireDateParam, status: statusParam) - ..obid = const fb.Int64Reader().vTableGet(buffer, rootOffset, 4, 0) ..product_product_id = const fb.StringReader(asciiOptimization: true) .vTableGet(buffer, rootOffset, 20, '') ..isCheckedForReturn = - const fb.BoolReader().vTableGet(buffer, rootOffset, 76, false); - InternalToManyAccess.setRelInfo(object.deliveryPartners, - store, RelInfo.toMany(3, object.obid)); - InternalToManyAccess.setRelInfo(object.selectedCombos, - store, RelInfo.toMany(4, object.obid)); - InternalToManyAccess.setRelInfo(object.selectedModifiers, - store, RelInfo.toMany(5, object.obid)); + const fb.BoolReader().vTableGet(buffer, rootOffset, 74, false); InternalToManyAccess.setRelInfo(object.ingredients, store, - RelInfo.toMany(6, object.obid)); + RelInfo.toMany(7, object.id)); InternalToManyAccess.setRelInfo(object.modifiers, store, - RelInfo.toMany(7, object.obid)); + RelInfo.toMany(8, object.id)); + InternalToManyAccess.setRelInfo(object.deliveryPartners, + store, RelInfo.toMany(9, object.id)); InternalToManyAccess.setRelInfo(object.comboProduct, - store, RelInfo.toMany(8, object.obid)); + store, RelInfo.toMany(10, object.id)); return object; }), StoreServiceModel: EntityDefinition( - model: _entities[10], + model: _entities[13], toOneRelations: (StoreServiceModel object) => [], toManyRelations: (StoreServiceModel object) => {}, getId: (StoreServiceModel object) => object.obid, @@ -2362,7 +2765,7 @@ ModelDefinition getObjectBoxModel() { return object; }), StoreTable: EntityDefinition( - model: _entities[11], + model: _entities[14], toOneRelations: (StoreTable object) => [], toManyRelations: (StoreTable object) => {}, getId: (StoreTable object) => object.obid, @@ -2420,226 +2823,6 @@ ModelDefinition getObjectBoxModel() { ..obid = const fb.Int64Reader().vTableGet(buffer, rootOffset, 4, 0); return object; - }), - ItemsDeliveryPartner: EntityDefinition( - model: _entities[12], - toOneRelations: (ItemsDeliveryPartner object) => [], - toManyRelations: (ItemsDeliveryPartner object) => {}, - getId: (ItemsDeliveryPartner object) => object.obid, - setId: (ItemsDeliveryPartner object, int id) { - object.obid = id; - }, - objectToFB: (ItemsDeliveryPartner object, fb.Builder fbb) { - final idOffset = fbb.writeString(object.id); - final nameOffset = fbb.writeString(object.name); - fbb.startTable(5); - fbb.addInt64(0, object.obid); - fbb.addOffset(1, idOffset); - fbb.addOffset(2, nameOffset); - fbb.addFloat64(3, object.price); - fbb.finish(fbb.endTable()); - return object.obid; - }, - objectFromFB: (Store store, ByteData fbData) { - final buffer = fb.BufferContext(fbData); - final rootOffset = buffer.derefObject(0); - final idParam = const fb.StringReader(asciiOptimization: true) - .vTableGet(buffer, rootOffset, 6, ''); - final nameParam = const fb.StringReader(asciiOptimization: true) - .vTableGet(buffer, rootOffset, 8, ''); - final priceParam = - const fb.Float64Reader().vTableGet(buffer, rootOffset, 10, 0); - final object = ItemsDeliveryPartner( - id: idParam, name: nameParam, price: priceParam) - ..obid = const fb.Int64Reader().vTableGet(buffer, rootOffset, 4, 0); - - return object; - }), - CreateAndUpdateOrder: EntityDefinition( - model: _entities[13], - toOneRelations: (CreateAndUpdateOrder object) => [], - toManyRelations: (CreateAndUpdateOrder object) => { - RelInfo.toMany(11, object.obid): - object.orderDetails - }, - getId: (CreateAndUpdateOrder object) => object.obid, - setId: (CreateAndUpdateOrder object, int id) { - object.obid = id; - }, - objectToFB: (CreateAndUpdateOrder object, fb.Builder fbb) { - final deliveryPartnerIdOffset = - fbb.writeString(object.deliveryPartnerId); - final cartUniqueTokenOffset = object.cartUniqueToken == null - ? null - : fbb.writeString(object.cartUniqueToken!); - final destinationAddressesOffset = object.destinationAddresses == null - ? null - : fbb.writeString(object.destinationAddresses!); - final storeIdOffset = - object.storeId == null ? null : fbb.writeString(object.storeId!); - final orderIdOffset = - object.orderId == null ? null : fbb.writeString(object.orderId!); - final cartIdOffset = - object.cartId == null ? null : fbb.writeString(object.cartId!); - final orderTypeOffset = object.orderType == null - ? null - : fbb.writeString(object.orderType!); - final selectedTableNameOffset = - fbb.writeString(object.selectedTableName); - final createdAtOffset = fbb.writeString(object.createdAt); - final orderStatusOffset = object.orderStatus == null - ? null - : fbb.writeString(object.orderStatus!); - final paymentModeOffset = object.paymentMode == null - ? null - : fbb.writeString(object.paymentMode!); - final deliveryNotesOffset = object.deliveryNotes == null - ? null - : fbb.writeString(object.deliveryNotes!); - fbb.startTable(26); - fbb.addInt64(0, object.obid); - fbb.addOffset(1, deliveryPartnerIdOffset); - fbb.addFloat64(2, object.totalCartPrice); - fbb.addFloat64(3, object.totalItemTax); - fbb.addOffset(4, cartUniqueTokenOffset); - fbb.addOffset(5, destinationAddressesOffset); - fbb.addFloat64(6, object.minOrderPrice); - fbb.addOffset(7, storeIdOffset); - fbb.addOffset(8, orderIdOffset); - fbb.addOffset(9, cartIdOffset); - fbb.addOffset(10, orderTypeOffset); - fbb.addOffset(11, selectedTableNameOffset); - fbb.addOffset(12, createdAtOffset); - fbb.addInt64(13, object.cartUniqueId); - fbb.addOffset(14, orderStatusOffset); - fbb.addBool(15, object.paymentStatus); - fbb.addOffset(16, paymentModeOffset); - fbb.addFloat64(17, object.amount); - fbb.addFloat64(18, object.totalAmount); - fbb.addFloat64(19, object.totalDiscount); - fbb.addInt64(20, object.cardNumber); - fbb.addFloat64(21, object.changeBalanceAmount); - fbb.addInt64(22, object.timer); - fbb.addInt64(23, object.orderNumber); - fbb.addOffset(24, deliveryNotesOffset); - fbb.finish(fbb.endTable()); - return object.obid; - }, - objectFromFB: (Store store, ByteData fbData) { - final buffer = fb.BufferContext(fbData); - final rootOffset = buffer.derefObject(0); - final totalCartPriceParam = - const fb.Float64Reader().vTableGetNullable(buffer, rootOffset, 8); - final totalItemTaxParam = const fb.Float64Reader() - .vTableGetNullable(buffer, rootOffset, 10); - final cartUniqueTokenParam = - const fb.StringReader(asciiOptimization: true) - .vTableGetNullable(buffer, rootOffset, 12); - final destinationAddressesParam = - const fb.StringReader(asciiOptimization: true) - .vTableGetNullable(buffer, rootOffset, 14); - final minOrderPriceParam = const fb.Float64Reader() - .vTableGetNullable(buffer, rootOffset, 16); - final orderDetailsParam = ToMany(); - final storeIdParam = const fb.StringReader(asciiOptimization: true) - .vTableGetNullable(buffer, rootOffset, 18); - final orderIdParam = const fb.StringReader(asciiOptimization: true) - .vTableGetNullable(buffer, rootOffset, 20); - final cartIdParam = const fb.StringReader(asciiOptimization: true) - .vTableGetNullable(buffer, rootOffset, 22); - final object = CreateAndUpdateOrder( - totalCartPrice: totalCartPriceParam, - totalItemTax: totalItemTaxParam, - cartUniqueToken: cartUniqueTokenParam, - destinationAddresses: destinationAddressesParam, - minOrderPrice: minOrderPriceParam, - orderDetails: orderDetailsParam, - storeId: storeIdParam, - orderId: orderIdParam, - cartId: cartIdParam) - ..obid = const fb.Int64Reader().vTableGet(buffer, rootOffset, 4, 0) - ..deliveryPartnerId = const fb.StringReader(asciiOptimization: true) - .vTableGet(buffer, rootOffset, 6, '') - ..orderType = const fb.StringReader(asciiOptimization: true) - .vTableGetNullable(buffer, rootOffset, 24) - ..selectedTableName = const fb.StringReader(asciiOptimization: true) - .vTableGet(buffer, rootOffset, 26, '') - ..createdAt = const fb.StringReader(asciiOptimization: true) - .vTableGet(buffer, rootOffset, 28, '') - ..cartUniqueId = - const fb.Int64Reader().vTableGet(buffer, rootOffset, 30, 0) - ..orderStatus = const fb.StringReader(asciiOptimization: true) - .vTableGetNullable(buffer, rootOffset, 32) - ..paymentStatus = - const fb.BoolReader().vTableGet(buffer, rootOffset, 34, false) - ..paymentMode = const fb.StringReader(asciiOptimization: true) - .vTableGetNullable(buffer, rootOffset, 36) - ..amount = const fb.Float64Reader() - .vTableGetNullable(buffer, rootOffset, 38) - ..totalAmount = const fb.Float64Reader() - .vTableGetNullable(buffer, rootOffset, 40) - ..totalDiscount = const fb.Float64Reader() - .vTableGetNullable(buffer, rootOffset, 42) - ..cardNumber = - const fb.Int64Reader().vTableGetNullable(buffer, rootOffset, 44) - ..changeBalanceAmount = const fb.Float64Reader() - .vTableGetNullable(buffer, rootOffset, 46) - ..timer = - const fb.Int64Reader().vTableGetNullable(buffer, rootOffset, 48) - ..orderNumber = - const fb.Int64Reader().vTableGetNullable(buffer, rootOffset, 50) - ..deliveryNotes = const fb.StringReader(asciiOptimization: true) - .vTableGetNullable(buffer, rootOffset, 52); - InternalToManyAccess.setRelInfo( - object.orderDetails, - store, - RelInfo.toMany(11, object.obid)); - return object; - }), - OrderDetails: EntityDefinition( - model: _entities[14], - toOneRelations: (OrderDetails object) => [], - toManyRelations: (OrderDetails object) => - {RelInfo.toMany(12, object.obid): object.items}, - getId: (OrderDetails object) => object.obid, - setId: (OrderDetails object, int id) { - object.obid = id; - }, - objectToFB: (OrderDetails object, fb.Builder fbb) { - final productIdOffset = object.productId == null - ? null - : fbb.writeString(object.productId!); - fbb.startTable(6); - fbb.addInt64(0, object.obid); - fbb.addOffset(1, productIdOffset); - fbb.addFloat64(2, object.totalItemTax); - fbb.addFloat64(3, object.totalItemPrice); - fbb.addFloat64(4, object.totalItemPriceWithoutModifier); - fbb.finish(fbb.endTable()); - return object.obid; - }, - objectFromFB: (Store store, ByteData fbData) { - final buffer = fb.BufferContext(fbData); - final rootOffset = buffer.derefObject(0); - final productIdParam = const fb.StringReader(asciiOptimization: true) - .vTableGetNullable(buffer, rootOffset, 6); - final totalItemTaxParam = - const fb.Float64Reader().vTableGetNullable(buffer, rootOffset, 8); - final totalItemPriceParam = const fb.Float64Reader() - .vTableGetNullable(buffer, rootOffset, 10); - final itemsParam = ToMany(); - final totalItemPriceWithoutModifierParam = const fb.Float64Reader() - .vTableGetNullable(buffer, rootOffset, 12); - final object = OrderDetails( - productId: productIdParam, - totalItemTax: totalItemTaxParam, - totalItemPrice: totalItemPriceParam, - items: itemsParam, - totalItemPriceWithoutModifier: totalItemPriceWithoutModifierParam) - ..obid = const fb.Int64Reader().vTableGet(buffer, rootOffset, 4, 0); - InternalToManyAccess.setRelInfo(object.items, store, - RelInfo.toMany(12, object.obid)); - return object; }) }; @@ -2764,781 +2947,848 @@ class AddIngredient_ { static final updatedAt = QueryStringProperty(_entities[0].properties[28]); - /// see [AddIngredient.measuringUnit] - static final measuringUnit = - QueryStringProperty(_entities[0].properties[29]); + /// see [AddIngredient.measuringUnit] + static final measuringUnit = + QueryStringProperty(_entities[0].properties[29]); + + /// see [AddIngredient.checked] + static final checked = + QueryBooleanProperty(_entities[0].properties[30]); + + /// see [AddIngredient.id] + static final id = + QueryStringProperty(_entities[0].properties[31]); + + /// see [AddIngredient.quantity] + static final quantity = + QueryStringProperty(_entities[0].properties[32]); + + /// see [AddIngredient.purchasePrice] + static final purchasePrice = + QueryDoubleProperty(_entities[0].properties[33]); + + /// see [AddIngredient.salePrice] + static final salePrice = + QueryDoubleProperty(_entities[0].properties[34]); + + /// see [AddIngredient.defaultSalePrice] + static final defaultSalePrice = + QueryDoubleProperty(_entities[0].properties[35]); + + /// see [AddIngredient.price] + static final price = + QueryDoubleProperty(_entities[0].properties[36]); + + /// see [AddIngredient.purchaseCost] + static final purchaseCost = + QueryDoubleProperty(_entities[0].properties[37]); + + /// see [AddIngredient.itemPriceWithoutOffer] + static final itemPriceWithoutOffer = + QueryDoubleProperty(_entities[0].properties[38]); + + /// see [AddIngredient.totalQuantity] + static final totalQuantity = + QueryIntegerProperty(_entities[0].properties[39]); + + /// see [AddIngredient.totalAddedQuantity] + static final totalAddedQuantity = + QueryIntegerProperty(_entities[0].properties[40]); + + /// see [AddIngredient.totalUsedQuantity] + static final totalUsedQuantity = + QueryIntegerProperty(_entities[0].properties[41]); + + /// see [AddIngredient.salePriceExclusiveTax] + static final salePriceExclusiveTax = + QueryDoubleProperty(_entities[0].properties[42]); + + /// see [AddIngredient.stockAlertQuantity] + static final stockAlertQuantity = + QueryIntegerProperty(_entities[0].properties[43]); + + /// see [AddIngredient.salePriceInclusiveTax] + static final salePriceInclusiveTax = + QueryDoubleProperty(_entities[0].properties[44]); +} + +/// [ComboProduct] entity fields to define ObjectBox queries. +class ComboProduct_ { + /// see [ComboProduct.obid] + static final obid = + QueryIntegerProperty(_entities[1].properties[0]); + + /// see [ComboProduct.size] + static final size = + QueryStringProperty(_entities[1].properties[1]); + + /// see [ComboProduct.group] + static final group = + QueryStringProperty(_entities[1].properties[2]); + + /// see [ComboProduct.subGroup] + static final subGroup = + QueryStringProperty(_entities[1].properties[3]); + + /// see [ComboProduct.product] + static final product = + QueryStringProperty(_entities[1].properties[4]); + + /// see [ComboProduct.measurement] + static final measurement = + QueryStringProperty(_entities[1].properties[5]); + + /// see [ComboProduct.imageUrl] + static final imageUrl = + QueryStringProperty(_entities[1].properties[6]); + + /// see [ComboProduct.quantity] + static final quantity = + QueryStringProperty(_entities[1].properties[7]); + + /// see [ComboProduct.isSelected] + static final isSelected = + QueryBooleanProperty(_entities[1].properties[8]); + + /// see [ComboProduct.price] + static final price = + QueryDoubleProperty(_entities[1].properties[9]); + + /// see [ComboProduct.qtyIdx] + static final qtyIdx = + QueryIntegerProperty(_entities[1].properties[10]); +} + +/// [CreateAndUpdateOrder] entity fields to define ObjectBox queries. +class CreateAndUpdateOrder_ { + /// see [CreateAndUpdateOrder.obid] + static final obid = + QueryIntegerProperty(_entities[2].properties[0]); + + /// see [CreateAndUpdateOrder.deliveryPartnerId] + static final deliveryPartnerId = + QueryStringProperty(_entities[2].properties[1]); + + /// see [CreateAndUpdateOrder.totalCartPrice] + static final totalCartPrice = + QueryDoubleProperty(_entities[2].properties[2]); + + /// see [CreateAndUpdateOrder.totalItemTax] + static final totalItemTax = + QueryDoubleProperty(_entities[2].properties[3]); + + /// see [CreateAndUpdateOrder.cartUniqueToken] + static final cartUniqueToken = + QueryStringProperty(_entities[2].properties[4]); + + /// see [CreateAndUpdateOrder.destinationAddresses] + static final destinationAddresses = + QueryStringProperty(_entities[2].properties[5]); + + /// see [CreateAndUpdateOrder.minOrderPrice] + static final minOrderPrice = + QueryDoubleProperty(_entities[2].properties[6]); + + /// see [CreateAndUpdateOrder.storeId] + static final storeId = + QueryStringProperty(_entities[2].properties[7]); + + /// see [CreateAndUpdateOrder.orderId] + static final orderId = + QueryStringProperty(_entities[2].properties[8]); + + /// see [CreateAndUpdateOrder.cartId] + static final cartId = + QueryStringProperty(_entities[2].properties[9]); + + /// see [CreateAndUpdateOrder.orderType] + static final orderType = + QueryStringProperty(_entities[2].properties[10]); + + /// see [CreateAndUpdateOrder.selectedTableName] + static final selectedTableName = + QueryStringProperty(_entities[2].properties[11]); + + /// see [CreateAndUpdateOrder.createdAt] + static final createdAt = + QueryStringProperty(_entities[2].properties[12]); + + /// see [CreateAndUpdateOrder.cartUniqueId] + static final cartUniqueId = + QueryIntegerProperty(_entities[2].properties[13]); - /// see [AddIngredient.checked] - static final checked = - QueryBooleanProperty(_entities[0].properties[30]); + /// see [CreateAndUpdateOrder.orderStatus] + static final orderStatus = + QueryStringProperty(_entities[2].properties[14]); - /// see [AddIngredient.id] - static final id = - QueryStringProperty(_entities[0].properties[31]); -} + /// see [CreateAndUpdateOrder.paymentStatus] + static final paymentStatus = + QueryBooleanProperty(_entities[2].properties[15]); -/// [ComboProduct] entity fields to define ObjectBox queries. -class ComboProduct_ { - /// see [ComboProduct.obid] - static final obid = - QueryIntegerProperty(_entities[1].properties[0]); + /// see [CreateAndUpdateOrder.paymentMode] + static final paymentMode = + QueryStringProperty(_entities[2].properties[16]); - /// see [ComboProduct.size] - static final size = - QueryStringProperty(_entities[1].properties[1]); + /// see [CreateAndUpdateOrder.amount] + static final amount = + QueryDoubleProperty(_entities[2].properties[17]); - /// see [ComboProduct.group] - static final group = - QueryStringProperty(_entities[1].properties[2]); + /// see [CreateAndUpdateOrder.totalAmount] + static final totalAmount = + QueryDoubleProperty(_entities[2].properties[18]); - /// see [ComboProduct.subGroup] - static final subGroup = - QueryStringProperty(_entities[1].properties[3]); + /// see [CreateAndUpdateOrder.totalDiscount] + static final totalDiscount = + QueryDoubleProperty(_entities[2].properties[19]); - /// see [ComboProduct.product] - static final product = - QueryStringProperty(_entities[1].properties[4]); + /// see [CreateAndUpdateOrder.discountId] + static final discountId = + QueryStringProperty(_entities[2].properties[20]); - /// see [ComboProduct.measurement] - static final measurement = - QueryStringProperty(_entities[1].properties[5]); + /// see [CreateAndUpdateOrder.cardNumber] + static final cardNumber = + QueryIntegerProperty(_entities[2].properties[21]); - /// see [ComboProduct.imageUrl] - static final imageUrl = - QueryStringProperty(_entities[1].properties[6]); + /// see [CreateAndUpdateOrder.changeBalanceAmount] + static final changeBalanceAmount = + QueryDoubleProperty(_entities[2].properties[22]); - /// see [ComboProduct.quantity] - static final quantity = - QueryStringProperty(_entities[1].properties[7]); + /// see [CreateAndUpdateOrder.timer] + static final timer = + QueryIntegerProperty(_entities[2].properties[23]); - /// see [ComboProduct.isSelected] - static final isSelected = - QueryBooleanProperty(_entities[1].properties[8]); + /// see [CreateAndUpdateOrder.orderNumber] + static final orderNumber = + QueryIntegerProperty(_entities[2].properties[24]); - /// see [ComboProduct.price] - static final price = - QueryDoubleProperty(_entities[1].properties[9]); + /// see [CreateAndUpdateOrder.deliveryNotes] + static final deliveryNotes = + QueryStringProperty(_entities[2].properties[25]); - /// see [ComboProduct.qtyIdx] - static final qtyIdx = - QueryIntegerProperty(_entities[1].properties[10]); + /// see [CreateAndUpdateOrder.orderDetailsOffline] + static final orderDetailsOffline = + QueryStringProperty(_entities[2].properties[26]); } /// [DeliveryPartner] entity fields to define ObjectBox queries. class DeliveryPartner_ { /// see [DeliveryPartner.obid] static final obid = - QueryIntegerProperty(_entities[2].properties[0]); + QueryIntegerProperty(_entities[3].properties[0]); /// see [DeliveryPartner.id] static final id = - QueryStringProperty(_entities[2].properties[1]); + QueryStringProperty(_entities[3].properties[1]); /// see [DeliveryPartner.name] static final name = - QueryStringProperty(_entities[2].properties[2]); + QueryStringProperty(_entities[3].properties[2]); /// see [DeliveryPartner.nameArabic] static final nameArabic = - QueryStringProperty(_entities[2].properties[3]); + QueryStringProperty(_entities[3].properties[3]); /// see [DeliveryPartner.status] static final status = - QueryStringProperty(_entities[2].properties[4]); + QueryStringProperty(_entities[3].properties[4]); /// see [DeliveryPartner.createdAt] static final createdAt = - QueryStringProperty(_entities[2].properties[5]); + QueryStringProperty(_entities[3].properties[5]); /// see [DeliveryPartner.updatedAt] static final updatedAt = - QueryStringProperty(_entities[2].properties[6]); + QueryStringProperty(_entities[3].properties[6]); /// see [DeliveryPartner.stores] static final stores = - QueryStringVectorProperty(_entities[2].properties[7]); + QueryStringVectorProperty(_entities[3].properties[7]); + + /// see [DeliveryPartner.totalItemCount] + static final totalItemCount = + QueryIntegerProperty(_entities[3].properties[8]); } /// [ItemCategory] entity fields to define ObjectBox queries. class ItemCategory_ { /// see [ItemCategory.obid] static final obid = - QueryIntegerProperty(_entities[3].properties[0]); + QueryIntegerProperty(_entities[4].properties[0]); /// see [ItemCategory.name] static final name = - QueryStringProperty(_entities[3].properties[1]); + QueryStringProperty(_entities[4].properties[1]); /// see [ItemCategory.id] static final id = - QueryStringProperty(_entities[3].properties[2]); + QueryStringProperty(_entities[4].properties[2]); /// see [ItemCategory.isVisibleInStore] static final isVisibleInStore = - QueryBooleanProperty(_entities[3].properties[3]); + QueryBooleanProperty(_entities[4].properties[3]); /// see [ItemCategory.createdAt] static final createdAt = - QueryStringProperty(_entities[3].properties[4]); + QueryStringProperty(_entities[4].properties[4]); /// see [ItemCategory.updatedAt] static final updatedAt = - QueryStringProperty(_entities[3].properties[5]); + QueryStringProperty(_entities[4].properties[5]); /// see [ItemCategory.description] static final description = - QueryStringProperty(_entities[3].properties[6]); + QueryStringProperty(_entities[4].properties[6]); /// see [ItemCategory.arabicName] static final arabicName = - QueryStringProperty(_entities[3].properties[7]); + QueryStringProperty(_entities[4].properties[7]); /// see [ItemCategory.categoryAppliedOn] static final categoryAppliedOn = - QueryStringProperty(_entities[3].properties[8]); + QueryStringProperty(_entities[4].properties[8]); /// see [ItemCategory.store_id] static final store_id = - QueryStringVectorProperty(_entities[3].properties[9]); + QueryStringVectorProperty(_entities[4].properties[9]); /// see [ItemCategory.image_url] static final image_url = - QueryStringProperty(_entities[3].properties[10]); + QueryStringProperty(_entities[4].properties[10]); } /// [ItemSubCategory] entity fields to define ObjectBox queries. class ItemSubCategory_ { /// see [ItemSubCategory.odid] static final odid = - QueryIntegerProperty(_entities[4].properties[0]); + QueryIntegerProperty(_entities[5].properties[0]); /// see [ItemSubCategory.name] static final name = - QueryStringProperty(_entities[4].properties[1]); + QueryStringProperty(_entities[5].properties[1]); /// see [ItemSubCategory.arabicName] static final arabicName = - QueryStringProperty(_entities[4].properties[2]); + QueryStringProperty(_entities[5].properties[2]); /// see [ItemSubCategory.categoryId] static final categoryId = - QueryStringProperty(_entities[4].properties[3]); + QueryStringProperty(_entities[5].properties[3]); /// see [ItemSubCategory.uniqueId] static final uniqueId = - QueryIntegerProperty(_entities[4].properties[4]); + QueryIntegerProperty(_entities[5].properties[4]); /// see [ItemSubCategory.id] static final id = - QueryStringProperty(_entities[4].properties[5]); + QueryStringProperty(_entities[5].properties[5]); /// see [ItemSubCategory.isVisibleInStore] static final isVisibleInStore = - QueryBooleanProperty(_entities[4].properties[6]); + QueryBooleanProperty(_entities[5].properties[6]); /// see [ItemSubCategory.createdAt] static final createdAt = - QueryStringProperty(_entities[4].properties[7]); + QueryStringProperty(_entities[5].properties[7]); /// see [ItemSubCategory.updatedAt] static final updatedAt = - QueryStringProperty(_entities[4].properties[8]); + QueryStringProperty(_entities[5].properties[8]); /// see [ItemSubCategory.storeId] static final storeId = - QueryStringVectorProperty(_entities[4].properties[9]); + QueryStringVectorProperty(_entities[5].properties[9]); +} + +/// [ItemsDeliveryPartner] entity fields to define ObjectBox queries. +class ItemsDeliveryPartner_ { + /// see [ItemsDeliveryPartner.obid] + static final obid = + QueryIntegerProperty(_entities[6].properties[0]); + + /// see [ItemsDeliveryPartner.id] + static final id = + QueryStringProperty(_entities[6].properties[1]); + + /// see [ItemsDeliveryPartner.name] + static final name = + QueryStringProperty(_entities[6].properties[2]); + + /// see [ItemsDeliveryPartner.price] + static final price = + QueryDoubleProperty(_entities[6].properties[3]); } /// [Modifier] entity fields to define ObjectBox queries. class Modifier_ { /// see [Modifier.obid] static final obid = - QueryIntegerProperty(_entities[5].properties[0]); + QueryIntegerProperty(_entities[7].properties[0]); /// see [Modifier.id] - static final id = QueryStringProperty(_entities[5].properties[1]); + static final id = QueryStringProperty(_entities[7].properties[1]); /// see [Modifier.name] - static final name = QueryStringProperty(_entities[5].properties[2]); + static final name = QueryStringProperty(_entities[7].properties[2]); /// see [Modifier.arabicName] static final arabicName = - QueryStringProperty(_entities[5].properties[3]); + QueryStringProperty(_entities[7].properties[3]); /// see [Modifier.description] static final description = - QueryStringProperty(_entities[5].properties[4]); + QueryStringProperty(_entities[7].properties[4]); + + /// see [Modifier.price] + static final price = + QueryDoubleProperty(_entities[7].properties[5]); /// see [Modifier.status] static final status = - QueryStringProperty(_entities[5].properties[5]); + QueryStringProperty(_entities[7].properties[6]); /// see [Modifier.isMultiple] static final isMultiple = - QueryBooleanProperty(_entities[5].properties[6]); + QueryBooleanProperty(_entities[7].properties[7]); /// see [Modifier.createdOn] static final createdOn = - QueryStringProperty(_entities[5].properties[7]); + QueryStringProperty(_entities[7].properties[8]); /// see [Modifier.updatedOn] static final updatedOn = - QueryStringProperty(_entities[5].properties[8]); + QueryStringProperty(_entities[7].properties[9]); /// see [Modifier.isSelected] static final isSelected = - QueryBooleanProperty(_entities[5].properties[9]); + QueryBooleanProperty(_entities[7].properties[10]); /// see [Modifier.selectedModifierIndex] static final selectedModifierIndex = - QueryIntegerProperty(_entities[5].properties[10]); - - /// see [Modifier.price] - static final price = - QueryDoubleProperty(_entities[5].properties[11]); + QueryIntegerProperty(_entities[7].properties[11]); /// see [Modifier.options] static final options = - QueryRelationToMany(_entities[5].relations[0]); + QueryRelationToMany(_entities[7].relations[0]); /// see [Modifier.selected] static final selected = - QueryRelationToMany(_entities[5].relations[1]); + QueryRelationToMany(_entities[7].relations[1]); } /// [ModifierOption] entity fields to define ObjectBox queries. class ModifierOption_ { /// see [ModifierOption.obid] static final obid = - QueryIntegerProperty(_entities[6].properties[0]); + QueryIntegerProperty(_entities[8].properties[0]); /// see [ModifierOption.name] static final name = - QueryStringProperty(_entities[6].properties[1]); + QueryStringProperty(_entities[8].properties[1]); /// see [ModifierOption.arabicName] static final arabicName = - QueryStringProperty(_entities[6].properties[2]); + QueryStringProperty(_entities[8].properties[2]); /// see [ModifierOption.price] static final price = - QueryDoubleProperty(_entities[6].properties[3]); + QueryDoubleProperty(_entities[8].properties[3]); /// see [ModifierOption.isSelected] static final isSelected = - QueryBooleanProperty(_entities[6].properties[4]); + QueryBooleanProperty(_entities[8].properties[4]); /// see [ModifierOption.modifierName] static final modifierName = - QueryStringProperty(_entities[6].properties[5]); + QueryStringProperty(_entities[8].properties[5]); /// see [ModifierOption.qtyIdx] static final qtyIdx = - QueryIntegerProperty(_entities[6].properties[6]); + QueryIntegerProperty(_entities[8].properties[6]); + + /// see [ModifierOption.id] + static final id = + QueryStringProperty(_entities[8].properties[7]); + + /// see [ModifierOption.modifierId] + static final modifierId = + QueryStringProperty(_entities[8].properties[8]); + + /// see [ModifierOption.ingredients] + static final ingredients = QueryRelationToMany( + _entities[8].relations[0]); +} + +/// [OrderDetails] entity fields to define ObjectBox queries. +class OrderDetails_ { + /// see [OrderDetails.productId] + static final productId = + QueryStringProperty(_entities[9].properties[0]); + + /// see [OrderDetails.totalItemTax] + static final totalItemTax = + QueryDoubleProperty(_entities[9].properties[1]); + + /// see [OrderDetails.totalItemPrice] + static final totalItemPrice = + QueryDoubleProperty(_entities[9].properties[2]); + + /// see [OrderDetails.totalItemPriceWithoutModifier] + static final totalItemPriceWithoutModifier = + QueryDoubleProperty(_entities[9].properties[3]); + + /// see [OrderDetails.id] + static final id = + QueryIntegerProperty(_entities[9].properties[4]); + + /// see [OrderDetails.items] + static final items = + QueryRelationToMany(_entities[9].relations[0]); } /// [ProductId] entity fields to define ObjectBox queries. class ProductId_ { /// see [ProductId.obid] static final obid = - QueryIntegerProperty(_entities[7].properties[0]); + QueryIntegerProperty(_entities[10].properties[0]); /// see [ProductId.productId] static final productId = - QueryStringProperty(_entities[7].properties[1]); + QueryStringProperty(_entities[10].properties[1]); /// see [ProductId.categoryId] static final categoryId = - QueryStringProperty(_entities[7].properties[2]); + QueryStringProperty(_entities[10].properties[2]); } /// [StoreDiscount] entity fields to define ObjectBox queries. class StoreDiscount_ { /// see [StoreDiscount.obid] static final obid = - QueryIntegerProperty(_entities[8].properties[0]); + QueryIntegerProperty(_entities[11].properties[0]); /// see [StoreDiscount.discountValue] static final discountValue = - QueryStringProperty(_entities[8].properties[1]); + QueryStringProperty(_entities[11].properties[1]); /// see [StoreDiscount.id] static final id = - QueryStringProperty(_entities[8].properties[2]); + QueryStringProperty(_entities[11].properties[2]); /// see [StoreDiscount.name] static final name = - QueryStringProperty(_entities[8].properties[3]); + QueryStringProperty(_entities[11].properties[3]); /// see [StoreDiscount.description] static final description = - QueryStringProperty(_entities[8].properties[4]); + QueryStringProperty(_entities[11].properties[4]); /// see [StoreDiscount.value] static final value = - QueryStringProperty(_entities[8].properties[5]); + QueryStringProperty(_entities[11].properties[5]); /// see [StoreDiscount.type] static final type = - QueryStringProperty(_entities[8].properties[6]); + QueryStringProperty(_entities[11].properties[6]); /// see [StoreDiscount.storeId] static final storeId = - QueryStringProperty(_entities[8].properties[7]); + QueryStringProperty(_entities[11].properties[7]); /// see [StoreDiscount.categories] static final categories = - QueryStringVectorProperty(_entities[8].properties[8]); + QueryStringVectorProperty(_entities[11].properties[8]); /// see [StoreDiscount.products] static final products = - QueryStringVectorProperty(_entities[8].properties[9]); + QueryStringVectorProperty(_entities[11].properties[9]); /// see [StoreDiscount.status] static final status = - QueryStringProperty(_entities[8].properties[10]); + QueryStringProperty(_entities[11].properties[10]); /// see [StoreDiscount.minAmountLimit] static final minAmountLimit = - QueryDoubleProperty(_entities[8].properties[11]); + QueryDoubleProperty(_entities[11].properties[11]); /// see [StoreDiscount.maxDiscountLimit] static final maxDiscountLimit = - QueryDoubleProperty(_entities[8].properties[12]); + QueryDoubleProperty(_entities[11].properties[12]); /// see [StoreDiscount.discountPercentage] static final discountPercentage = - QueryStringProperty(_entities[8].properties[13]); + QueryStringProperty(_entities[11].properties[13]); /// see [StoreDiscount.discountType] static final discountType = - QueryStringProperty(_entities[8].properties[14]); + QueryStringProperty(_entities[11].properties[14]); /// see [StoreDiscount.discountTypeLabel] static final discountTypeLabel = - QueryStringProperty(_entities[8].properties[15]); + QueryStringProperty(_entities[11].properties[15]); /// see [StoreDiscount.limitOfDiscount] static final limitOfDiscount = - QueryDoubleProperty(_entities[8].properties[16]); + QueryDoubleProperty(_entities[11].properties[16]); + + /// see [StoreDiscount.isUserUsed] + static final isUserUsed = + QueryDoubleProperty(_entities[11].properties[17]); /// see [StoreDiscount.discountStartDate] static final discountStartDate = - QueryStringProperty(_entities[8].properties[17]); + QueryStringProperty(_entities[11].properties[18]); /// see [StoreDiscount.discountEndDate] static final discountEndDate = - QueryStringProperty(_entities[8].properties[18]); + QueryStringProperty(_entities[11].properties[19]); /// see [StoreDiscount.isDeleted] static final isDeleted = - QueryBooleanProperty(_entities[8].properties[19]); + QueryBooleanProperty(_entities[11].properties[20]); /// see [StoreDiscount.createdAt] static final createdAt = - QueryStringProperty(_entities[8].properties[20]); + QueryStringProperty(_entities[11].properties[21]); /// see [StoreDiscount.updatedAt] static final updatedAt = - QueryStringProperty(_entities[8].properties[21]); + QueryStringProperty(_entities[11].properties[22]); /// see [StoreDiscount.isAlways] static final isAlways = - QueryBooleanProperty(_entities[8].properties[22]); + QueryBooleanProperty(_entities[11].properties[23]); /// see [StoreDiscount.isMaxDiscount] static final isMaxDiscount = - QueryBooleanProperty(_entities[8].properties[23]); + QueryBooleanProperty(_entities[11].properties[24]); /// see [StoreDiscount.isMinAmount] static final isMinAmount = - QueryBooleanProperty(_entities[8].properties[24]); + QueryBooleanProperty(_entities[11].properties[25]); /// see [StoreDiscount.isUnlimited] static final isUnlimited = - QueryBooleanProperty(_entities[8].properties[25]); + QueryBooleanProperty(_entities[11].properties[26]); } /// [StoreItems] entity fields to define ObjectBox queries. class StoreItems_ { - /// see [StoreItems.obid] - static final obid = - QueryIntegerProperty(_entities[9].properties[0]); - - /// see [StoreItems.id] - static final id = QueryStringProperty(_entities[9].properties[1]); - /// see [StoreItems.name] static final name = - QueryStringProperty(_entities[9].properties[2]); + QueryStringProperty(_entities[12].properties[0]); /// see [StoreItems.noteForItem] static final noteForItem = - QueryStringVectorProperty(_entities[9].properties[3]); + QueryStringVectorProperty(_entities[12].properties[1]); /// see [StoreItems.storeId] static final storeId = - QueryStringProperty(_entities[9].properties[4]); + QueryStringProperty(_entities[12].properties[2]); /// see [StoreItems.isUnlimitedQuantity] static final isUnlimitedQuantity = - QueryBooleanProperty(_entities[9].properties[5]); + QueryBooleanProperty(_entities[12].properties[3]); /// see [StoreItems.itemNameArabic] static final itemNameArabic = - QueryStringProperty(_entities[9].properties[6]); + QueryStringProperty(_entities[12].properties[4]); /// see [StoreItems.productId] static final productId = - QueryStringProperty(_entities[9].properties[7]); + QueryStringProperty(_entities[12].properties[5]); /// see [StoreItems.product_product_id] static final product_product_id = - QueryStringProperty(_entities[9].properties[8]); + QueryStringProperty(_entities[12].properties[6]); /// see [StoreItems.price] static final price = - QueryDoubleProperty(_entities[9].properties[9]); + QueryDoubleProperty(_entities[12].properties[7]); /// see [StoreItems.uniqueId] static final uniqueId = - QueryIntegerProperty(_entities[9].properties[10]); + QueryIntegerProperty(_entities[12].properties[8]); /// see [StoreItems.uniqueIdForStoreData] static final uniqueIdForStoreData = - QueryStringProperty(_entities[9].properties[11]); - - /// see [StoreItems.quantity] - static final quantity = - QueryIntegerProperty(_entities[9].properties[12]); + QueryStringProperty(_entities[12].properties[9]); /// see [StoreItems.imageUrl] static final imageUrl = - QueryStringProperty(_entities[9].properties[13]); + QueryStringProperty(_entities[12].properties[10]); /// see [StoreItems.updatedAt] static final updatedAt = - QueryStringProperty(_entities[9].properties[14]); + QueryStringProperty(_entities[12].properties[11]); /// see [StoreItems.isItemInStock] static final isItemInStock = - QueryBooleanProperty(_entities[9].properties[15]); + QueryBooleanProperty(_entities[12].properties[12]); /// see [StoreItems.description] static final description = - QueryStringProperty(_entities[9].properties[16]); + QueryStringProperty(_entities[12].properties[13]); /// see [StoreItems.descriptionArabic] static final descriptionArabic = - QueryStringProperty(_entities[9].properties[17]); + QueryStringProperty(_entities[12].properties[14]); /// see [StoreItems.purchasePrice] static final purchasePrice = - QueryDoubleProperty(_entities[9].properties[18]); + QueryDoubleProperty(_entities[12].properties[15]); /// see [StoreItems.stockAlertQuantity] static final stockAlertQuantity = - QueryIntegerProperty(_entities[9].properties[19]); + QueryIntegerProperty(_entities[12].properties[16]); /// see [StoreItems.itemPriceWithOutOffer] static final itemPriceWithOutOffer = - QueryDoubleProperty(_entities[9].properties[20]); + QueryDoubleProperty(_entities[12].properties[17]); /// see [StoreItems.totalAddedQuantity] static final totalAddedQuantity = - QueryIntegerProperty(_entities[9].properties[21]); + QueryIntegerProperty(_entities[12].properties[18]); /// see [StoreItems.totalUsedQuantity] static final totalUsedQuantity = - QueryIntegerProperty(_entities[9].properties[22]); + QueryIntegerProperty(_entities[12].properties[19]); /// see [StoreItems.salePriceExclusiveTax] static final salePriceExclusiveTax = - QueryDoubleProperty(_entities[9].properties[23]); - - /// see [StoreItems.totalItemPrice] - static final totalItemPrice = - QueryDoubleProperty(_entities[9].properties[24]); + QueryDoubleProperty(_entities[12].properties[20]); /// see [StoreItems.supplier] static final supplier = - QueryStringProperty(_entities[9].properties[25]); + QueryStringProperty(_entities[12].properties[21]); /// see [StoreItems.discount] static final discount = - QueryStringProperty(_entities[9].properties[26]); + QueryStringProperty(_entities[12].properties[22]); /// see [StoreItems.measurementCategory] static final measurementCategory = - QueryStringProperty(_entities[9].properties[27]); + QueryStringProperty(_entities[12].properties[23]); /// see [StoreItems.measurement] static final measurement = - QueryStringProperty(_entities[9].properties[28]); + QueryStringProperty(_entities[12].properties[24]); /// see [StoreItems.brand] static final brand = - QueryStringProperty(_entities[9].properties[29]); + QueryStringProperty(_entities[12].properties[25]); /// see [StoreItems.deliveryPartner] static final deliveryPartner = - QueryStringProperty(_entities[9].properties[30]); + QueryStringProperty(_entities[12].properties[26]); /// see [StoreItems.manufactureDate] static final manufactureDate = - QueryStringProperty(_entities[9].properties[31]); + QueryStringProperty(_entities[12].properties[27]); /// see [StoreItems.expireDate] static final expireDate = - QueryStringProperty(_entities[9].properties[32]); + QueryStringProperty(_entities[12].properties[28]); /// see [StoreItems.status] static final status = - QueryBooleanProperty(_entities[9].properties[33]); + QueryBooleanProperty(_entities[12].properties[29]); /// see [StoreItems.isCombo] static final isCombo = - QueryBooleanProperty(_entities[9].properties[34]); + QueryBooleanProperty(_entities[12].properties[30]); /// see [StoreItems.isCheckedForReturn] static final isCheckedForReturn = - QueryBooleanProperty(_entities[9].properties[35]); + QueryBooleanProperty(_entities[12].properties[31]); - /// see [StoreItems.deliveryPartners] - static final deliveryPartners = - QueryRelationToMany( - _entities[9].relations[0]); + /// see [StoreItems.id] + static final id = + QueryIntegerProperty(_entities[12].properties[32]); + + /// see [StoreItems.itemId] + static final itemId = + QueryStringProperty(_entities[12].properties[33]); - /// see [StoreItems.selectedCombos] - static final selectedCombos = - QueryRelationToMany(_entities[9].relations[1]); + /// see [StoreItems.quantity] + static final quantity = + QueryIntegerProperty(_entities[12].properties[34]); - /// see [StoreItems.selectedModifiers] - static final selectedModifiers = - QueryRelationToMany( - _entities[9].relations[2]); + /// see [StoreItems.totalItemPrice] + static final totalItemPrice = + QueryDoubleProperty(_entities[12].properties[35]); /// see [StoreItems.ingredients] - static final ingredients = - QueryRelationToMany(_entities[9].relations[3]); + static final ingredients = QueryRelationToMany( + _entities[12].relations[0]); /// see [StoreItems.modifiers] static final modifiers = - QueryRelationToMany(_entities[9].relations[4]); + QueryRelationToMany(_entities[12].relations[1]); + + /// see [StoreItems.deliveryPartners] + static final deliveryPartners = + QueryRelationToMany( + _entities[12].relations[2]); /// see [StoreItems.comboProduct] static final comboProduct = - QueryRelationToMany(_entities[9].relations[5]); + QueryRelationToMany(_entities[12].relations[3]); } /// [StoreServiceModel] entity fields to define ObjectBox queries. class StoreServiceModel_ { /// see [StoreServiceModel.obid] static final obid = - QueryIntegerProperty(_entities[10].properties[0]); + QueryIntegerProperty(_entities[13].properties[0]); /// see [StoreServiceModel.id] static final id = - QueryStringProperty(_entities[10].properties[1]); + QueryStringProperty(_entities[13].properties[1]); /// see [StoreServiceModel.storeId] static final storeId = - QueryStringProperty(_entities[10].properties[2]); + QueryStringProperty(_entities[13].properties[2]); /// see [StoreServiceModel.name] static final name = - QueryStringProperty(_entities[10].properties[3]); + QueryStringProperty(_entities[13].properties[3]); } /// [StoreTable] entity fields to define ObjectBox queries. class StoreTable_ { /// see [StoreTable.obid] static final obid = - QueryIntegerProperty(_entities[11].properties[0]); + QueryIntegerProperty(_entities[14].properties[0]); /// see [StoreTable.id] static final id = - QueryStringProperty(_entities[11].properties[1]); + QueryStringProperty(_entities[14].properties[1]); /// see [StoreTable.storeId] static final storeId = - QueryStringProperty(_entities[11].properties[2]); + QueryStringProperty(_entities[14].properties[2]); /// see [StoreTable.tableName] static final tableName = - QueryStringProperty(_entities[11].properties[3]); + QueryStringProperty(_entities[14].properties[3]); /// see [StoreTable.isAvailable] static final isAvailable = - QueryBooleanProperty(_entities[11].properties[4]); + QueryBooleanProperty(_entities[14].properties[4]); /// see [StoreTable.noOfOccupants] static final noOfOccupants = - QueryIntegerProperty(_entities[11].properties[5]); + QueryIntegerProperty(_entities[14].properties[5]); /// see [StoreTable.status] static final status = - QueryStringProperty(_entities[11].properties[6]); + QueryStringProperty(_entities[14].properties[6]); /// see [StoreTable.createdAt] static final createdAt = - QueryStringProperty(_entities[11].properties[7]); + QueryStringProperty(_entities[14].properties[7]); /// see [StoreTable.updatedAt] static final updatedAt = - QueryStringProperty(_entities[11].properties[8]); -} - -/// [ItemsDeliveryPartner] entity fields to define ObjectBox queries. -class ItemsDeliveryPartner_ { - /// see [ItemsDeliveryPartner.obid] - static final obid = - QueryIntegerProperty(_entities[12].properties[0]); - - /// see [ItemsDeliveryPartner.id] - static final id = - QueryStringProperty(_entities[12].properties[1]); - - /// see [ItemsDeliveryPartner.name] - static final name = - QueryStringProperty(_entities[12].properties[2]); - - /// see [ItemsDeliveryPartner.price] - static final price = - QueryDoubleProperty(_entities[12].properties[3]); -} - -/// [CreateAndUpdateOrder] entity fields to define ObjectBox queries. -class CreateAndUpdateOrder_ { - /// see [CreateAndUpdateOrder.obid] - static final obid = - QueryIntegerProperty(_entities[13].properties[0]); - - /// see [CreateAndUpdateOrder.deliveryPartnerId] - static final deliveryPartnerId = - QueryStringProperty(_entities[13].properties[1]); - - /// see [CreateAndUpdateOrder.totalCartPrice] - static final totalCartPrice = - QueryDoubleProperty(_entities[13].properties[2]); - - /// see [CreateAndUpdateOrder.totalItemTax] - static final totalItemTax = - QueryDoubleProperty(_entities[13].properties[3]); - - /// see [CreateAndUpdateOrder.cartUniqueToken] - static final cartUniqueToken = - QueryStringProperty(_entities[13].properties[4]); - - /// see [CreateAndUpdateOrder.destinationAddresses] - static final destinationAddresses = - QueryStringProperty(_entities[13].properties[5]); - - /// see [CreateAndUpdateOrder.minOrderPrice] - static final minOrderPrice = - QueryDoubleProperty(_entities[13].properties[6]); - - /// see [CreateAndUpdateOrder.storeId] - static final storeId = - QueryStringProperty(_entities[13].properties[7]); - - /// see [CreateAndUpdateOrder.orderId] - static final orderId = - QueryStringProperty(_entities[13].properties[8]); - - /// see [CreateAndUpdateOrder.cartId] - static final cartId = - QueryStringProperty(_entities[13].properties[9]); - - /// see [CreateAndUpdateOrder.orderType] - static final orderType = - QueryStringProperty(_entities[13].properties[10]); - - /// see [CreateAndUpdateOrder.selectedTableName] - static final selectedTableName = - QueryStringProperty(_entities[13].properties[11]); - - /// see [CreateAndUpdateOrder.createdAt] - static final createdAt = - QueryStringProperty(_entities[13].properties[12]); - - /// see [CreateAndUpdateOrder.cartUniqueId] - static final cartUniqueId = - QueryIntegerProperty(_entities[13].properties[13]); - - /// see [CreateAndUpdateOrder.orderStatus] - static final orderStatus = - QueryStringProperty(_entities[13].properties[14]); - - /// see [CreateAndUpdateOrder.paymentStatus] - static final paymentStatus = - QueryBooleanProperty(_entities[13].properties[15]); - - /// see [CreateAndUpdateOrder.paymentMode] - static final paymentMode = - QueryStringProperty(_entities[13].properties[16]); - - /// see [CreateAndUpdateOrder.amount] - static final amount = - QueryDoubleProperty(_entities[13].properties[17]); - - /// see [CreateAndUpdateOrder.totalAmount] - static final totalAmount = - QueryDoubleProperty(_entities[13].properties[18]); - - /// see [CreateAndUpdateOrder.totalDiscount] - static final totalDiscount = - QueryDoubleProperty(_entities[13].properties[19]); - - /// see [CreateAndUpdateOrder.cardNumber] - static final cardNumber = - QueryIntegerProperty(_entities[13].properties[20]); - - /// see [CreateAndUpdateOrder.changeBalanceAmount] - static final changeBalanceAmount = - QueryDoubleProperty(_entities[13].properties[21]); - - /// see [CreateAndUpdateOrder.timer] - static final timer = - QueryIntegerProperty(_entities[13].properties[22]); - - /// see [CreateAndUpdateOrder.orderNumber] - static final orderNumber = - QueryIntegerProperty(_entities[13].properties[23]); - - /// see [CreateAndUpdateOrder.deliveryNotes] - static final deliveryNotes = - QueryStringProperty(_entities[13].properties[24]); - - /// see [CreateAndUpdateOrder.orderDetails] - static final orderDetails = - QueryRelationToMany( - _entities[13].relations[0]); -} - -/// [OrderDetails] entity fields to define ObjectBox queries. -class OrderDetails_ { - /// see [OrderDetails.obid] - static final obid = - QueryIntegerProperty(_entities[14].properties[0]); - - /// see [OrderDetails.productId] - static final productId = - QueryStringProperty(_entities[14].properties[1]); - - /// see [OrderDetails.totalItemTax] - static final totalItemTax = - QueryDoubleProperty(_entities[14].properties[2]); - - /// see [OrderDetails.totalItemPrice] - static final totalItemPrice = - QueryDoubleProperty(_entities[14].properties[3]); - - /// see [OrderDetails.totalItemPriceWithoutModifier] - static final totalItemPriceWithoutModifier = - QueryDoubleProperty(_entities[14].properties[4]); - - /// see [OrderDetails.items] - static final items = - QueryRelationToMany(_entities[14].relations[0]); + QueryStringProperty(_entities[14].properties[8]); } diff --git a/lib/widgets/ActionPopUpContainer.dart b/lib/widgets/ActionPopUpContainer.dart new file mode 100644 index 0000000..64593f1 --- /dev/null +++ b/lib/widgets/ActionPopUpContainer.dart @@ -0,0 +1,20 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/theme/MyColors.dart'; + +class ActionPopUpContainer extends StatelessWidget { + Widget child; + + ActionPopUpContainer({super.key, required this.child}); + + @override + Widget build(BuildContext context) { + return Container( + width: 38, + height: 38, + decoration: BoxDecoration( + borderRadius: const BorderRadius.all(Radius.circular(4)), + color: MyColors.backFillColor), + child: child, + ); + } +} diff --git a/lib/widgets/BackButtonWidget.dart b/lib/widgets/BackButtonWidget.dart new file mode 100644 index 0000000..dfb4e8b --- /dev/null +++ b/lib/widgets/BackButtonWidget.dart @@ -0,0 +1,39 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/theme/MyFonts.dart'; +import 'package:wosull/helpers/Utils.dart'; + +class BackButtonWidget extends StatelessWidget { + final void Function() onPressed; + + const BackButtonWidget({super.key, required this.onPressed}); + + @override + Widget build(BuildContext context) { + return Container( + margin: const EdgeInsets.only(left: 8), + child: ElevatedButton.icon( + onPressed: onPressed, + icon: const Icon( + size: 14, + Icons.arrow_back_ios, + color: MyColors.textColorBlack, + ), + label: Text( + lang(context).back, + style: const TextStyle( + color: MyColors.textColorBlack, + fontFamily: MyFonts.Medium, + fontSize: 14), + ), + style: ElevatedButton.styleFrom( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5.0), + ), + elevation: 0, + backgroundColor: MyColors.backFillColor, + ), + ), + ); + } +} diff --git a/lib/widgets/BackHeaderContainer.dart b/lib/widgets/BackHeaderContainer.dart new file mode 100644 index 0000000..5113562 --- /dev/null +++ b/lib/widgets/BackHeaderContainer.dart @@ -0,0 +1,16 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/theme/MyColors.dart'; + +class BackHeaderContainer extends StatelessWidget { + const BackHeaderContainer({super.key}); + + @override + Widget build(BuildContext context) { + return Container( + margin: const EdgeInsets.only(bottom: 6.0, top: 6.0), + height: 25, + width: 1, + color: MyColors.fillColorGray2, + ); + } +} diff --git a/lib/widgets/BackTabBarContainer.dart b/lib/widgets/BackTabBarContainer.dart new file mode 100644 index 0000000..e7a400a --- /dev/null +++ b/lib/widgets/BackTabBarContainer.dart @@ -0,0 +1,51 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/widgets/BackButtonWidget.dart'; +import 'package:wosull/widgets/BackHeaderContainer.dart'; + +class BackTabBarContainer extends StatelessWidget { + final void Function() onPressed; + List tabs; + + BackTabBarContainer({super.key, required this.onPressed, required this.tabs}); + + @override + Widget build(BuildContext context) { + return Container( + width: double.infinity, + margin: const EdgeInsets.only(bottom: 6.0), + //Same as `blurRadius` i guess + decoration: const BoxDecoration( + color: Colors.white, + boxShadow: [ + BoxShadow( + color: Colors.grey, + offset: Offset(0.0, 1.0), //(x,y) + blurRadius: 6.0, + ), + ], + ), + child: Row( + children: [ + BackButtonWidget( + onPressed: onPressed, + ), + AppSpaces.horizontalMedium, + const BackHeaderContainer(), + Flexible( + child: TabBar( + indicatorColor: Colors.white, + labelStyle: ThemeText.tabLabelStyle, + isScrollable: true, + unselectedLabelStyle: ThemeText.unSelectedTabLabelStyle, + unselectedLabelColor: MyColors.textColorBlack, + labelColor: MyColors.blueThemeColor, + tabs: tabs, + )) + ], + ), + ); + } +} diff --git a/lib/widgets/BorderContainer.dart b/lib/widgets/BorderContainer.dart new file mode 100644 index 0000000..d583603 --- /dev/null +++ b/lib/widgets/BorderContainer.dart @@ -0,0 +1,23 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/theme/MyColors.dart'; + +class BorderContainer extends StatelessWidget { + Widget child; + Color? backgroundColor; + BorderContainer({super.key, this.backgroundColor, required this.child}); + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + borderRadius: const BorderRadius.all( + Radius.circular(1.0) // <--- border radius here + ), + border: Border.all(width: 1, color: MyColors.fillColorGray2), + color: backgroundColor ?? MyColors.backFillColor, + ), + height: 48, + child: child, + ); + } +} diff --git a/lib/widgets/BoxContainer.dart b/lib/widgets/BoxContainer.dart new file mode 100644 index 0000000..192ec01 --- /dev/null +++ b/lib/widgets/BoxContainer.dart @@ -0,0 +1,31 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeText.dart'; + +class BoxContainer extends StatelessWidget { + Color fillColor; + String title; + BoxContainer({super.key, required this.fillColor, required this.title}); + + @override + Widget build(BuildContext context) { + return Row( + children: [ + Container( + width: 20, + height: 20, + decoration: BoxDecoration( + color: fillColor, + borderRadius: const BorderRadius.all(Radius.circular(4)), + ), + ), + AppSpaces.horizontalSmall, + Flexible( + child: Text( + title, + style: ThemeText.textStyleNormalMedium, + )), + ], + ); + } +} diff --git a/lib/widgets/ButtonText.dart b/lib/widgets/ButtonText.dart index 07a43d6..5e811a5 100644 --- a/lib/widgets/ButtonText.dart +++ b/lib/widgets/ButtonText.dart @@ -11,6 +11,7 @@ class ButtonText extends StatelessWidget { Widget build(BuildContext context) { return Text( heading, + textAlign: TextAlign.center, style: MyColors.textStyleButton(textColor: textColor!), ); } diff --git a/lib/widgets/ChildContainer.dart b/lib/widgets/ChildContainer.dart new file mode 100644 index 0000000..f30dea1 --- /dev/null +++ b/lib/widgets/ChildContainer.dart @@ -0,0 +1,29 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/theme/MyColors.dart'; + +class ChildContainer extends StatelessWidget { + Widget? child; + double? width; + double? height; + + ChildContainer( + {super.key, required this.child, this.width = 44, this.height = 58}); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.all(4), + width: width, + height: height, + decoration: const BoxDecoration( + border: Border( + right: BorderSide(width: 1.0, color: MyColors.fillColorGray2), + ), + ), + child: Align( + alignment: Alignment.centerLeft, + child: child, + ), + ); + } +} diff --git a/lib/widgets/CustomAddButton.dart b/lib/widgets/CustomAddButton.dart new file mode 100644 index 0000000..9f1ceb2 --- /dev/null +++ b/lib/widgets/CustomAddButton.dart @@ -0,0 +1,35 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/theme/MyColors.dart'; + +class CustomAddButton extends StatelessWidget { + final void Function() onPressed; + Color? backgroundColor; + Color? iconColor; + + CustomAddButton( + {super.key, + required this.onPressed, + this.backgroundColor, + this.iconColor}); + + @override + Widget build(BuildContext context) { + return Center( + child: Container( + margin: const EdgeInsets.all(6), + width: 32, + height: 32, + decoration: BoxDecoration( + borderRadius: const BorderRadius.all(Radius.circular(4)), + color: backgroundColor ?? MyColors.fillColorGray2), + child: IconButton( + icon: Icon( + size: 14, + Icons.add, + color: iconColor ?? MyColors.textColorBlack, + ), + onPressed: onPressed), + ), + ); + } +} diff --git a/lib/widgets/CustomAppBar.dart b/lib/widgets/CustomAppBar.dart new file mode 100644 index 0000000..b7714c9 --- /dev/null +++ b/lib/widgets/CustomAppBar.dart @@ -0,0 +1,34 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/theme/MyFonts.dart'; + +class CustomAppBar extends StatelessWidget implements PreferredSizeWidget { + String heading; + + CustomAppBar({super.key, required this.heading}); + + @override + Widget build(BuildContext context) { + return AppBar( + leading: BackButton( + color: Colors.black, + onPressed: () { + Navigator.pop(context); + }, // <-- SEE HERE + ), + centerTitle: true, + title: Text( + heading, + style: const TextStyle( + color: MyColors.textColorBlack, + fontFamily: MyFonts.Bold, + fontSize: 22), + ), + backgroundColor: MyColors.white, + elevation: 5, + ); + } + + @override + Size get preferredSize => const Size.fromHeight(kToolbarHeight); +} diff --git a/lib/widgets/CustomCheckBox.dart b/lib/widgets/CustomCheckBox.dart index c3fc1b0..f38bad2 100644 --- a/lib/widgets/CustomCheckBox.dart +++ b/lib/widgets/CustomCheckBox.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/helpers/ThemeText.dart'; class CustomCheckBox extends StatelessWidget { @@ -12,15 +13,24 @@ class CustomCheckBox extends StatelessWidget { @override Widget build(BuildContext context) { - return Row(mainAxisAlignment: MainAxisAlignment.center, children: [ - SizedBox( + return Row(mainAxisAlignment: MainAxisAlignment.end, children: [ + Container( height: 20, width: 20, + decoration: BoxDecoration( + borderRadius: const BorderRadius.all( + Radius.circular(4.0) // <--- border radius here + ), + border: Border.all(width: 1, color: MyColors.fillColorGray2), + color: MyColors.backFillColor, + ), child: Transform.scale( scale: 1, child: Checkbox( + shape: + RoundedRectangleBorder(borderRadius: BorderRadius.circular(4)), value: value, - side: const BorderSide(color: MyColors.fillColorGray2), + side: const BorderSide(color: Colors.transparent), onChanged: onChange, activeColor: MyColors.blueThemeColor, checkColor: Colors.white, @@ -28,6 +38,7 @@ class CustomCheckBox extends StatelessWidget { ), ), ), + AppSpaces.horizontalSmall, Text( heading ?? '', style: ThemeText.textStyleHeading, diff --git a/lib/widgets/CustomControllerTextFieldForm.dart b/lib/widgets/CustomControllerTextFieldForm.dart new file mode 100644 index 0000000..d222847 --- /dev/null +++ b/lib/widgets/CustomControllerTextFieldForm.dart @@ -0,0 +1,58 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/helpers/ThemeText.dart'; + +class CustomControllerTextFieldForm extends StatelessWidget { + CustomControllerTextFieldForm( + {super.key, + required this.controller, + this.readOnly = false, + required this.onChanged, + required this.hintText, + this.maxLines = 1, + this.height = 48, + this.keyboardType = TextInputType.text}); + + TextEditingController controller; + int maxLines; + final double height; + final bool readOnly; + final void Function(String value) onChanged; + + final String hintText; + final TextInputType keyboardType; + + @override + Widget build(BuildContext context) { + return TextFormField( + textAlignVertical: TextAlignVertical.center, + readOnly: readOnly, + keyboardType: keyboardType, + controller: controller, + maxLines: maxLines, + style: ThemeText.textFliedStyleValue, + decoration: InputDecoration( + constraints: BoxConstraints(maxHeight: height), + fillColor: readOnly ? MyColors.disableColor : MyColors.backFillColor, + filled: true, + border: InputBorder.none, + hintText: hintText, + isDense: true, + // + focusedBorder: OutlineInputBorder( + borderSide: + const BorderSide(color: MyColors.textColorGray, width: 0.5), + borderRadius: BorderRadius.circular(8.0), + ), + enabledBorder: OutlineInputBorder( + borderSide: const BorderSide( + width: 1, //<-- SEE HERE + color: Colors.transparent, + ), + borderRadius: BorderRadius.circular(8.0), + ), + ), + onChanged: onChanged, + ); + } +} diff --git a/lib/widgets/CustomIconButton.dart b/lib/widgets/CustomIconButton.dart new file mode 100644 index 0000000..56f3753 --- /dev/null +++ b/lib/widgets/CustomIconButton.dart @@ -0,0 +1,39 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/helpers/ThemeText.dart'; + +class CustomIconButton extends StatelessWidget { + String heading; + String svgIconPath; + final void Function() onPressed; + + CustomIconButton( + {super.key, + required this.onPressed, + required this.heading, + required this.svgIconPath}); + + @override + Widget build(BuildContext context) { + return ElevatedButton.icon( + style: ElevatedButton.styleFrom( + elevation: 0, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + backgroundColor: MyColors.backFillColor, + minimumSize: const Size.fromHeight(38), // NEW + ), + onPressed: onPressed, + label: Text( + heading, + style: ThemeText.textStyleBlueMedium, + ), + icon: ImageIcon( + color: MyColors.blueThemeColor, + AssetImage(svgIconPath), + size: 18, + ), + ); + } +} diff --git a/lib/widgets/CustomListTIle.dart b/lib/widgets/CustomListTIle.dart index cc28d23..85dfd08 100644 --- a/lib/widgets/CustomListTIle.dart +++ b/lib/widgets/CustomListTIle.dart @@ -6,10 +6,12 @@ import 'package:wosull/application/theme/MyFonts.dart'; class CustomListTile extends StatelessWidget { String path; String title; + final bool wasTaped; final void Function() onTap; CustomListTile( {super.key, + required this.wasTaped, required this.path, required this.title, required this.onTap}); @@ -23,10 +25,12 @@ class CustomListTile extends StatelessWidget { child: SvgPicture.asset(path), ), title: Text(title, - style: const TextStyle( + style: TextStyle( fontSize: 14, fontFamily: MyFonts.Bold, - color: MyColors.textColorBlack)), + color: wasTaped + ? MyColors.blueThemeColor + : MyColors.textColorBlack)), onTap: onTap, ); } diff --git a/lib/widgets/CustomOptionalTitle.dart b/lib/widgets/CustomOptionalTitle.dart index c90b27e..4411a90 100644 --- a/lib/widgets/CustomOptionalTitle.dart +++ b/lib/widgets/CustomOptionalTitle.dart @@ -11,7 +11,7 @@ class CustomOptionalTitle extends StatelessWidget { Widget build(BuildContext context) { return Text( hint, - style: const TextStyle( + style: TextStyle( fontSize: MyFonts.normalButton, fontFamily: MyFonts.Medium, color: MyColors.black), diff --git a/lib/widgets/CustomPopuoMenuButton.dart b/lib/widgets/CustomPopuoMenuButton.dart new file mode 100644 index 0000000..e962df0 --- /dev/null +++ b/lib/widgets/CustomPopuoMenuButton.dart @@ -0,0 +1,24 @@ +import 'package:flutter/material.dart'; + +class CustomPopupMenuButton extends StatelessWidget { + final void Function(String value) onSelected; + List> items; + + CustomPopupMenuButton( + {super.key, required this.items, required this.onSelected}); + + @override + Widget build(BuildContext context) { + return PopupMenuButton( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + padding: EdgeInsets.zero, + icon: const Icon(Icons.more_vert), + itemBuilder: (c) { + return items; + }, + onSelected: onSelected, + ); + } +} diff --git a/lib/widgets/CustomRemoveItemButton.dart b/lib/widgets/CustomRemoveItemButton.dart new file mode 100644 index 0000000..786c9a2 --- /dev/null +++ b/lib/widgets/CustomRemoveItemButton.dart @@ -0,0 +1,31 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/theme/MyColors.dart'; + +class CustomRemoveItemButton extends StatelessWidget { + final void Function() onPressed; + + const CustomRemoveItemButton({super.key, required this.onPressed}); + + @override + Widget build(BuildContext context) { + return SizedBox( + width: 44, + height: 48, + child: Center( + child: Container( + width: 32, + height: 32, + decoration: const BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(4)), + color: MyColors.fillColorGray2), + child: IconButton( + icon: const Icon( + size: 14, + Icons.close, + color: MyColors.textColorBlack, + ), + onPressed: onPressed), + ), + )); + } +} diff --git a/lib/widgets/CustomSimpleButton.dart b/lib/widgets/CustomSimpleButton.dart index 575ceba..9374dfa 100644 --- a/lib/widgets/CustomSimpleButton.dart +++ b/lib/widgets/CustomSimpleButton.dart @@ -11,12 +11,14 @@ class CustomSimpleButton extends StatelessWidget { Color? textColor = MyColors.black; double? height; bool? isEnable = true; + double? radius; CustomSimpleButton( {super.key, this.isLoading, this.textColor, this.height = 38, + this.radius = 8, this.isEnable = true, this.backGroundColor, required this.heading, @@ -33,7 +35,7 @@ class CustomSimpleButton extends StatelessWidget { elevation: 0, padding: EdgeInsets.zero, shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), + borderRadius: BorderRadius.circular(radius ?? 8), ), backgroundColor: backGroundColor, minimumSize: Size.fromHeight(height!), // NEW diff --git a/lib/widgets/CustomSwitch.dart b/lib/widgets/CustomSwitch.dart index b31c2f9..6e145b5 100644 --- a/lib/widgets/CustomSwitch.dart +++ b/lib/widgets/CustomSwitch.dart @@ -15,15 +15,23 @@ class CustomSwitch extends StatelessWidget { @override Widget build(BuildContext context) { - return FlutterSwitch( - height: 20.0, - width: 40.0, - padding: 4.0, - toggleSize: 15.0, - borderRadius: 10.0, - activeColor: MyColors.blueThemeColor, - value: value, - onToggle: onToggle, + return Align( + alignment: Alignment.centerLeft, + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + FlutterSwitch( + height: 20.0, + width: 40.0, + padding: 4.0, + toggleSize: 15.0, + borderRadius: 10.0, + activeColor: MyColors.blueThemeColor, + value: value, + onToggle: onToggle, + ) + ], + ), ); } } diff --git a/lib/widgets/CustomTabBar.dart b/lib/widgets/CustomTabBar.dart new file mode 100644 index 0000000..b5dd997 --- /dev/null +++ b/lib/widgets/CustomTabBar.dart @@ -0,0 +1,22 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/helpers/ThemeText.dart'; + +class CustomTabBar extends StatelessWidget { + List tabs; + + CustomTabBar({super.key, required this.tabs}); + + @override + Widget build(BuildContext context) { + return TabBar( + indicatorColor: Colors.white, + labelStyle: ThemeText.tabLabelStyle, + isScrollable: true, + unselectedLabelStyle: ThemeText.unSelectedTabLabelStyle, + unselectedLabelColor: MyColors.textColorBlack, + labelColor: MyColors.blueThemeColor, + tabs: tabs, + ); + } +} diff --git a/lib/widgets/CustomTabView.dart b/lib/widgets/CustomTabView.dart index f60f734..19ddf66 100644 --- a/lib/widgets/CustomTabView.dart +++ b/lib/widgets/CustomTabView.dart @@ -110,9 +110,9 @@ class _CustomTabsState extends State child: TabBar( isScrollable: true, controller: controller, - labelStyle: const TextStyle( + labelStyle: TextStyle( fontSize: MyFonts.mediumText, fontFamily: MyFonts.Medium), - unselectedLabelStyle: const TextStyle( + unselectedLabelStyle: TextStyle( fontSize: MyFonts.mediumText, fontFamily: MyFonts.Medium), labelColor: MyColors.blueThemeColor, unselectedLabelColor: MyColors.textColorBlack, diff --git a/lib/widgets/CustomTextAddProduct.dart b/lib/widgets/CustomTextAddProduct.dart new file mode 100644 index 0000000..2dbcf20 --- /dev/null +++ b/lib/widgets/CustomTextAddProduct.dart @@ -0,0 +1,16 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/helpers/ThemeText.dart'; + +class CustomTextAddProduct extends StatelessWidget { + String heading; + + CustomTextAddProduct(this.heading, {super.key}); + + @override + Widget build(BuildContext context) { + return Text( + heading, + style: ThemeText.textFliedStyleValue, + ); + } +} diff --git a/lib/widgets/CustomTextButton.dart b/lib/widgets/CustomTextButton.dart index 89054f3..cc2ed95 100644 --- a/lib/widgets/CustomTextButton.dart +++ b/lib/widgets/CustomTextButton.dart @@ -13,9 +13,12 @@ class CustomTextButton extends StatelessWidget { return TextButton( onPressed: onPressed, child: Text(heading, - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: 15, - color: MyColors.black))); + style: TextStyle( + fontStyle: FontStyle.normal, + fontFamily: MyFonts.Medium, + fontSize: MyFonts.normal, + fontWeight: FontWeight.w500, + color: MyColors.black, + ))); } } diff --git a/lib/widgets/CustomTextButtonIcon.dart b/lib/widgets/CustomTextButtonIcon.dart index 650aef8..b699ba1 100644 --- a/lib/widgets/CustomTextButtonIcon.dart +++ b/lib/widgets/CustomTextButtonIcon.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:wosull/application/theme/MyColors.dart'; -import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/application/theme/MyFonts.dart'; class CustomTextButtonIcon extends StatelessWidget { String heading; @@ -14,47 +14,55 @@ class CustomTextButtonIcon extends StatelessWidget { {super.key, this.height = 48, this.iconSize = 24, - this.backgroundColor = MyColors.fillColor2, + this.backgroundColor, required this.heading, required this.onPressed, this.icon = Icons.arrow_drop_down}); @override Widget build(BuildContext context) { - return Container( - height: height, - padding: const EdgeInsets.only(right: 8), - decoration: BoxDecoration( - border: Border.all( - color: Colors.transparent, - width: 1, + return GestureDetector( + onTap: () { + onPressed(); + }, + child: Container( + height: height, + padding: const EdgeInsets.only(right: 8), + decoration: BoxDecoration( + border: Border.all( + color: Colors.transparent, + width: 1, + ), + color: backgroundColor ?? MyColors.backFillColor, + borderRadius: BorderRadius.circular(8.0), ), - color: backgroundColor, - borderRadius: BorderRadius.circular(8.0), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Expanded( - child: TextButton( - onPressed: onPressed, - child: Align( - alignment: Alignment.centerLeft, - child: Text( - heading, - textAlign: TextAlign.left, - style: ThemeText.textStyleValue, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Expanded( + child: TextButton( + onPressed: onPressed, + child: Align( + alignment: Alignment.centerLeft, + child: Text( + heading, + textAlign: TextAlign.left, + style: TextStyle( + fontFamily: MyFonts.DMREGULAR, + fontSize: MyFonts.normal, + color: MyColors.black), + ), ), - ), - )), - Icon( - // <-- Icon - icon, - size: iconSize, - color: MyColors.textColorGray, - ) - ], + )), + Icon( + // <-- Icon + icon, + size: iconSize, + color: MyColors.textColorGray, + ) + ], + ), ), ); } diff --git a/lib/widgets/CustomTextButtonUnderLine.dart b/lib/widgets/CustomTextButtonUnderLine.dart index 4092912..dbd9838 100644 --- a/lib/widgets/CustomTextButtonUnderLine.dart +++ b/lib/widgets/CustomTextButtonUnderLine.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/theme/MyFonts.dart'; class CustomTextButtonUnderLine extends StatelessWidget { String heading; @@ -14,8 +15,13 @@ class CustomTextButtonUnderLine extends StatelessWidget { onPressed: () {}, child: Text( heading, - style: const TextStyle( - color: MyColors.black, decoration: TextDecoration.underline), + style: TextStyle( + fontStyle: FontStyle.normal, + fontFamily: MyFonts.Medium, + fontSize: MyFonts.normal, + fontWeight: FontWeight.w500, + color: MyColors.black, + decoration: TextDecoration.underline), ), ); } diff --git a/lib/widgets/CustomTextFieldForm.dart b/lib/widgets/CustomTextFieldForm.dart index 5c4ff24..62eb175 100644 --- a/lib/widgets/CustomTextFieldForm.dart +++ b/lib/widgets/CustomTextFieldForm.dart @@ -25,37 +25,35 @@ class CustomTextFieldForm extends StatelessWidget { @override Widget build(BuildContext context) { - return SizedBox( - height: height, - child: TextFormField( - // style: ThemeText.textStyleValue, - textAlign: TextAlign.start, - textAlignVertical: TextAlignVertical.bottom, - readOnly: readOnly, - keyboardType: keyboardType, - initialValue: initialValue, - maxLines: maxLines, - decoration: InputDecoration( - fillColor: readOnly ? MyColors.disableColor : MyColors.backFillColor, - filled: true, - border: InputBorder.none, - labelStyle: ThemeText.textStyleValue, - hintStyle: ThemeText.hintStyleTextField, - hintText: hintText, - focusedBorder: OutlineInputBorder( - borderSide: const BorderSide(color: Colors.transparent, width: 1.0), - borderRadius: BorderRadius.circular(8.0), - ), - enabledBorder: OutlineInputBorder( - borderSide: const BorderSide( - width: 1, //<-- SEE HERE - color: Colors.transparent, - ), - borderRadius: BorderRadius.circular(8.0), + return TextFormField( + textAlignVertical: TextAlignVertical.center, + readOnly: readOnly, + keyboardType: keyboardType, + initialValue: initialValue, + maxLines: maxLines, + style: ThemeText.textFliedStyleValue, + decoration: InputDecoration( + constraints: BoxConstraints(maxHeight: height), + fillColor: readOnly ? MyColors.disableColor : MyColors.backFillColor, + filled: true, + border: InputBorder.none, + hintText: hintText, + isDense: true, + // + focusedBorder: OutlineInputBorder( + borderSide: + const BorderSide(color: MyColors.textColorGray, width: 0.5), + borderRadius: BorderRadius.circular(8.0), + ), + enabledBorder: OutlineInputBorder( + borderSide: const BorderSide( + width: 1, //<-- SEE HERE + color: Colors.transparent, ), + borderRadius: BorderRadius.circular(8.0), ), - onChanged: onChanged, ), + onChanged: onChanged, ); } } diff --git a/lib/widgets/CustomTextFieldPassword.dart b/lib/widgets/CustomTextFieldPassword.dart index 77e27fa..9dcbb7c 100644 --- a/lib/widgets/CustomTextFieldPassword.dart +++ b/lib/widgets/CustomTextFieldPassword.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/theme/MyFonts.dart'; -import 'package:wosull/helpers/ThemeText.dart'; class CustomTextFieldPassword extends StatelessWidget { const CustomTextFieldPassword( @@ -28,13 +27,29 @@ class CustomTextFieldPassword extends StatelessWidget { flex: 1, child: TextFormField( obscureText: obscure ?? false, + style: TextStyle( + fontFamily: MyFonts.DMREGULAR, + fontSize: MyFonts.normal, + color: MyColors.black), decoration: InputDecoration( border: InputBorder.none, fillColor: MyColors.backFillColor, filled: true, - labelStyle: ThemeText.labelStyleTextField, - hintStyle: ThemeText.hintStyleTextField, + // labelStyle: ThemeText.labelStyleTextField, + // hintStyle: ThemeText.hintStyleTextField, hintText: 'Enter your password', + focusedBorder: OutlineInputBorder( + borderSide: + const BorderSide(color: Colors.transparent, width: 1.0), + borderRadius: BorderRadius.circular(8.0), + ), + enabledBorder: OutlineInputBorder( + borderSide: const BorderSide( + width: 1, //<-- SEE HERE + color: Colors.transparent, + ), + borderRadius: BorderRadius.circular(8.0), + ), ), onChanged: onChanged, ), diff --git a/lib/widgets/DialogHeader.dart b/lib/widgets/DialogHeader.dart index 2ef994f..0d02da1 100644 --- a/lib/widgets/DialogHeader.dart +++ b/lib/widgets/DialogHeader.dart @@ -20,7 +20,7 @@ class DialogHeader extends StatelessWidget { padding: const EdgeInsets.only(left: 16), child: Text( title, - style: ThemeText.textStylePopUpHeading, + style: ThemeText.textStylePageHeading, ), )), Align( diff --git a/lib/widgets/DiscountDropdown.dart b/lib/widgets/DiscountDropdown.dart new file mode 100644 index 0000000..5e585b4 --- /dev/null +++ b/lib/widgets/DiscountDropdown.dart @@ -0,0 +1,91 @@ +import 'package:dropdown_search/dropdown_search.dart'; +import 'package:flutter/material.dart'; +import 'package:wosull/application/model/discount/StoreDiscountModel.dart'; +import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/AppLoader.dart'; +import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/helpers/ThemeDropDown.dart'; +import 'package:wosull/main.dart'; +import 'package:wosull/widgets/DropdownItemBuilder.dart'; + +class DiscountDropdown extends StatelessWidget { + Color fillColor; + final void Function(StoreDiscount? data) onChanged; + + DiscountDropdown({ + super.key, + required this.onChanged, + this.fillColor = const Color(0xFFF4F6FB), + }); + + @override + Widget build(BuildContext context) { + return isConnected ? getFromServer() : getFromDb(); + } + + getFromServer() { + return FutureBuilder( + future: getDiscount(), + builder: (c, s) { + if (s.hasData) { + var itemsList = s.data ?? []; + return dropDown(itemsList); + } else { + return AppLoader(); + } + }); + } + + getFromDb() { + return StreamBuilder( + stream: objectbox.getDiscounts(), + builder: (c, s) { + if (s.hasData) { + var itemsList = s.data ?? []; + return dropDown(itemsList); + } else { + return AppLoader(); + } + }); + } + + Widget dropDown(List itemsList) { + return SizedBox( + width: double.infinity, + child: DropdownSearch( + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name ?? ''); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 200)), + clearButtonProps: ThemeDropDown.clearButton, + items: itemsList, + itemAsString: (StoreDiscount u) => u.name!, + onChanged: onChanged, + dropdownDecoratorProps: + MyColors.dropDownStyle(hint: 'Choose', fillColor: fillColor), + ), + ); + } + + Future> getDiscount() async { + var items = []; + + await APIManager() + .fetchData(Constants.GET_DISCOUNT, Constants.getStorePayload()) + .then((value) { + final response = StoreDiscountModel.fromJson(value); + if (response.success!) { + items.addAll(response.storeDiscount!); + } + }).onError((error, stackTrace) { + print(error.toString()); + }); + + return items; + } +} diff --git a/lib/widgets/DropdownItemBuilder.dart b/lib/widgets/DropdownItemBuilder.dart new file mode 100644 index 0000000..b8ee943 --- /dev/null +++ b/lib/widgets/DropdownItemBuilder.dart @@ -0,0 +1,21 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/helpers/ThemeText.dart'; + +class DropdownItemBuilder extends StatelessWidget { + String title; + + DropdownItemBuilder({super.key, required this.title}); + + @override + Widget build(BuildContext context) { + return Container( + height: 42, + padding: const EdgeInsets.only(left: 8, right: 8), + child: Align( + alignment: Alignment.centerLeft, + child: Text(title, + textAlign: TextAlign.left, style: ThemeText.textStyleValue), + ), + ); + } +} diff --git a/lib/widgets/EmptyDataWidget.dart b/lib/widgets/EmptyDataWidget.dart index 83538fc..afcde14 100644 --- a/lib/widgets/EmptyDataWidget.dart +++ b/lib/widgets/EmptyDataWidget.dart @@ -1,19 +1,23 @@ import 'package:flutter/material.dart'; +import 'package:wosull/application/utils/AppError.dart'; class EmptyDataWidget extends StatelessWidget { const EmptyDataWidget({super.key}); @override Widget build(BuildContext context) { - return Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Image.asset( - 'images/empty_box.png', - height: 256, - ) - ], + return AppError( + error: 'No Data Available', ); + // return Column( + // mainAxisAlignment: MainAxisAlignment.center, + // crossAxisAlignment: CrossAxisAlignment.center, + // children: [ + // Image.asset( + // 'images/empty_box.png', + // height: 256, + // ) + // ], + // ); } } diff --git a/lib/widgets/ItemCategoryDropdown.dart b/lib/widgets/ItemCategoryDropdown.dart new file mode 100644 index 0000000..2f0bd57 --- /dev/null +++ b/lib/widgets/ItemCategoryDropdown.dart @@ -0,0 +1,101 @@ +import 'package:dropdown_search/dropdown_search.dart'; +import 'package:flutter/material.dart'; +import 'package:wosull/application/model/inventory/category/ItemCategory.dart'; +import 'package:wosull/application/model/inventory/category/ItemCategoryResponse.dart'; +import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/AppLoader.dart'; +import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/helpers/ThemeDropDown.dart'; +import 'package:wosull/widgets/DropdownItemBuilder.dart'; + +class ItemCategoryDropdown extends StatelessWidget { + final void Function(ItemCategory? data) onChanged; + final void Function(ItemCategory? data)? returnFirst; + late ItemCategory? selectedCategoryDropDown; + Color fillColor; + bool isEdit = false; + bool showFirst = false; + String categoryId = ''; + List items = []; + + ItemCategoryDropdown({ + super.key, + this.categoryId = '', + this.showFirst = false, + this.isEdit = false, + this.returnFirst, + required this.onChanged, + this.selectedCategoryDropDown, + this.fillColor = const Color(0xFFF4F6FB), + }); + + @override + Widget build(BuildContext context) { + return getFromServer(); + } + + Widget getFromServer() { + return FutureBuilder( + future: getCategoriesData(), + builder: (c, s) { + if (s.hasData) { + var itemsList = s.data ?? []; + return DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name); + }, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + selectedItem: selectedCategoryDropDown, + items: itemsList, + itemAsString: (ItemCategory u) => u.name, + onChanged: onChanged, + dropdownDecoratorProps: + MyColors.dropDownStyle(hint: 'Choose', fillColor: fillColor), + ); + } else { + return AppLoader(); + } + }); + } + + Future> getCategoriesData() async { + var items = []; + print('called'); + await APIManager() + .fetchData(Constants.GET_STORE_CATEGORY, Constants.getStorePayload()) + .then((value) { + final response = ItemCategoryResponse.fromJson(value); + if (response.success) { + items.addAll(response.categories); + if (items.isNotEmpty) { + if (isEdit) { + if (selectedCategoryDropDown == null) { + Future.forEach(items, (element) { + if (element.id == categoryId) { + selectedCategoryDropDown = element; + return; + } + }); + } + categoryId = selectedCategoryDropDown!.id; + } + + if (showFirst) { + selectedCategoryDropDown ??= items.first; + } + + // if (categoryId.isEmpty) { + // categoryId = selectedCategoryDropDown!.id; + // } + } + } + }).onError((error, stackTrace) {}); + return items; + } +} diff --git a/lib/widgets/LanguageDropdown.dart b/lib/widgets/LanguageDropdown.dart new file mode 100644 index 0000000..5180bea --- /dev/null +++ b/lib/widgets/LanguageDropdown.dart @@ -0,0 +1,72 @@ +import 'package:dropdown_search/dropdown_search.dart'; +import 'package:flutter/material.dart'; +import 'package:wosull/application/language/AppLanguage.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/helpers/ThemeDropDown.dart'; + +class LanguageDropdown extends StatelessWidget { + Color? fillColor; + AppLanguage dropdownValue = AppLanguage.languages().first; + final void Function(AppLanguage? language) onChange; + + LanguageDropdown( + {super.key, + this.fillColor, + required this.dropdownValue, + required this.onChange}); + + @override + Widget build(BuildContext context) { + return SizedBox( + width: 100, + child: DropdownSearch( + selectedItem: dropdownValue, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return SizedBox( + height: 38, + child: Center( + child: + Text(item.name, style: ThemeDropDown.dropDownTextStyle), + ), + ); + }, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: AppLanguage.languages(), + itemAsString: (AppLanguage u) => u.name, + onChanged: onChange, + dropdownDecoratorProps: DropDownDecoratorProps( + baseStyle: ThemeDropDown.dropDownTextStyle, + textAlignVertical: TextAlignVertical.center, + textAlign: TextAlign.right, + dropdownSearchDecoration: InputDecoration( + isCollapsed: true, + constraints: const BoxConstraints(maxHeight: 38), + fillColor: fillColor ?? MyColors.disableColor, + filled: true, + hintStyle: ThemeDropDown.dropDownTextStyle, + labelStyle: ThemeDropDown.dropDownTextStyle, + focusedBorder: OutlineInputBorder( + borderSide: const BorderSide( + width: 0.5, //<-- SEE HERE + color: MyColors.textColorGray, + ), + borderRadius: BorderRadius.circular(8.0), + ), + // Added + enabledBorder: OutlineInputBorder( + borderSide: const BorderSide( + width: 0, //<-- SEE HERE + color: Colors.transparent, + ), + borderRadius: BorderRadius.circular(8.0), + ), + hintText: 'Choose', + ), + ), + ), + ); + } +} diff --git a/lib/widgets/LineView.dart b/lib/widgets/LineView.dart new file mode 100644 index 0000000..98c27f6 --- /dev/null +++ b/lib/widgets/LineView.dart @@ -0,0 +1,15 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/theme/MyColors.dart'; + +class LineView extends StatelessWidget { + const LineView({super.key}); + + @override + Widget build(BuildContext context) { + return Container( + width: double.infinity, + height: 1, + color: MyColors.fillColorGray, + ); + } +} diff --git a/lib/widgets/ListHeadingContainer.dart b/lib/widgets/ListHeadingContainer.dart new file mode 100644 index 0000000..8003e9d --- /dev/null +++ b/lib/widgets/ListHeadingContainer.dart @@ -0,0 +1,18 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/theme/MyColors.dart'; + +class ListHeadingContainer extends StatelessWidget { + Widget child; + + ListHeadingContainer({super.key, required this.child}); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.only(left: 8, right: 8), + height: 48, + color: MyColors.containerBackColor, + child: child, + ); + } +} diff --git a/lib/widgets/MandatoryTitleText.dart b/lib/widgets/MandatoryTitleText.dart index da7d8b4..4d04a3a 100644 --- a/lib/widgets/MandatoryTitleText.dart +++ b/lib/widgets/MandatoryTitleText.dart @@ -13,12 +13,12 @@ class MandatoryTitleText extends StatelessWidget { children: [ Text( hint, - style: const TextStyle( + style: TextStyle( fontSize: MyFonts.normalButton, fontFamily: MyFonts.Medium, color: MyColors.black), ), - const Text( + Text( '*', style: TextStyle( fontSize: MyFonts.normalButton, diff --git a/lib/widgets/PageLimitDropDown.dart b/lib/widgets/PageLimitDropDown.dart new file mode 100644 index 0000000..b6164fa --- /dev/null +++ b/lib/widgets/PageLimitDropDown.dart @@ -0,0 +1,100 @@ +import 'package:dropdown_search/dropdown_search.dart'; +import 'package:flutter/material.dart'; +import 'package:sizer/sizer.dart'; +import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/helpers/ThemeDropDown.dart'; +import 'package:wosull/helpers/ThemePadding.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/widgets/DropdownItemBuilder.dart'; + +class PageLimitDropdown extends StatelessWidget { + final void Function(String? limit) onChange; + String? value; + + PageLimitDropdown({super.key, this.value, required this.onChange}); + + @override + Widget build(BuildContext context) { + return Container( + height: 38, + decoration: const BoxDecoration( + color: MyColors.disableColor, + borderRadius: BorderRadius.all(Radius.circular(ThemePadding.medium)), + ), + padding: const EdgeInsets.only( + left: ThemePadding.small, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox( + width: 2, + ), + const Text( + 'Show', + style: ThemeText.textStyleValue, + ), + const SizedBox( + width: 2, + ), + SizedBox( + width: SizerUtil.deviceType == DeviceType.mobile ? 90 : 105, + child: DropdownSearch( + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item); + }, + constraints: const BoxConstraints(maxHeight: 220)), + items: Constants.pageLimits, + itemAsString: (String u) => u, + onChanged: onChange, + dropdownDecoratorProps: const DropDownDecoratorProps( + baseStyle: ThemeText.textStyleValue, + textAlignVertical: TextAlignVertical.center, + dropdownSearchDecoration: InputDecoration( + contentPadding: EdgeInsets.zero, + isDense: true, + labelStyle: ThemeText.textStyleValue, + hintStyle: ThemeText.textStyleValue, + border: InputBorder.none, + hintText: 'Page Limit', + ), + ), + )) + ], + ), + ); + } + +// +// DropdownButton( +// value: value ?? Constants.pageLimits.first, +// underline: Container(), +// hint: const Text( +// 'Page Limit', +// softWrap: true, +// style: ThemeText.textStyleValue, +// ), +// borderRadius: BorderRadius.circular(8), +// icon: const Icon(Icons.arrow_drop_down_outlined), +// elevation: 0, +// padding: EdgeInsets.zero, +// style: ThemeText.textStyleValue, +// onChanged: onChange, +// items: Constants.pageLimits +// .map>((String value) { +// return DropdownMenuItem( +// value: value, +// child: Text( +// value, +// style: ThemeText.textStyleValue, +// ), +// ); +// }).toList(), +// ) +} diff --git a/lib/widgets/PortraitContainer.dart b/lib/widgets/PortraitContainer.dart new file mode 100644 index 0000000..83ec835 --- /dev/null +++ b/lib/widgets/PortraitContainer.dart @@ -0,0 +1,27 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/theme/MyColors.dart'; + +class PortraitContainer extends StatelessWidget { + Widget? child; + double? width; + double? height; + + PortraitContainer( + {super.key, required this.child, this.width = 44, this.height = 58}); + + @override + Widget build(BuildContext context) { + return Container( + width: width, + height: height, + padding: const EdgeInsets.all(4), + decoration: const BoxDecoration( + border: Border( + right: BorderSide(width: 1.0, color: MyColors.fillColorGray2), + top: BorderSide(width: 1.0, color: MyColors.fillColorGray2), + ), + ), + child: child, + ); + } +} diff --git a/lib/widgets/QRCodeGenerate.dart b/lib/widgets/QRCodeGenerate.dart index 25d404c..ab4556d 100644 --- a/lib/widgets/QRCodeGenerate.dart +++ b/lib/widgets/QRCodeGenerate.dart @@ -34,7 +34,7 @@ class QRCodeGenerate extends StatelessWidget { Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const Text( + Text( 'SIMPLIFIED TAX INVOICE', style: TextStyle( fontFamily: MyFonts.RobotoBold, @@ -48,7 +48,7 @@ class QRCodeGenerate extends StatelessWidget { children: [ Text( lang(context).invoice_no, - style: const TextStyle( + style: TextStyle( fontFamily: MyFonts.RobotoMedium, fontSize: MyFonts.H1, color: MyColors.black1, @@ -57,7 +57,7 @@ class QRCodeGenerate extends StatelessWidget { AppSpaces.horizontalMedium, Text( invoiceNumber.toString(), - style: const TextStyle( + style: TextStyle( fontFamily: MyFonts.RobotoBold, fontSize: MyFonts.H1, color: MyColors.black1, diff --git a/lib/widgets/SearchBox.dart b/lib/widgets/SearchBox.dart index ab0f5cd..2444f27 100644 --- a/lib/widgets/SearchBox.dart +++ b/lib/widgets/SearchBox.dart @@ -21,23 +21,31 @@ class SearchBox extends StatelessWidget { shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.0), ), - child: TextField( + child: TextFormField( controller: searchController, onEditingComplete: () { onEditingDone(searchController.text); }, onChanged: onChanged, - style: const TextStyle( - fontSize: MyFonts.normalButton, + style: TextStyle( fontFamily: MyFonts.DMREGULAR, - color: MyColors.textColorBlack), + fontSize: MyFonts.normal, + color: MyColors.black), decoration: InputDecoration( contentPadding: const EdgeInsets.symmetric(vertical: 0), hintText: hint, - prefixIcon: const Icon(Icons.search), + prefixIconColor: MaterialStateColor.resolveWith((states) => + states.contains(MaterialState.focused) + ? MyColors.textColorBlack20 + : MyColors.textColorBlack20), + prefixIcon: const Icon( + Icons.search, + size: 18, + color: MyColors.textColorBlack20, + ), focusedBorder: OutlineInputBorder( borderSide: - const BorderSide(color: Colors.transparent, width: 1.0), + const BorderSide(color: MyColors.textColorGray, width: 0.5), borderRadius: BorderRadius.circular(8.0), ), enabledBorder: OutlineInputBorder( diff --git a/lib/widgets/TransprentBorderContainer.dart b/lib/widgets/TransprentBorderContainer.dart new file mode 100644 index 0000000..34b959a --- /dev/null +++ b/lib/widgets/TransprentBorderContainer.dart @@ -0,0 +1,33 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/theme/MyColors.dart'; + +class TransparentBorderContainer extends StatelessWidget { + Widget? child; + double? width; + double? height; + Color? backgroundColor; + + TransparentBorderContainer( + {super.key, + this.backgroundColor, + required this.child, + this.width = 44, + this.height = 48}); + + @override + Widget build(BuildContext context) { + return Container( + height: 48, + padding: const EdgeInsets.only(right: 8, left: 8), + decoration: BoxDecoration( + border: Border.all( + color: Colors.transparent, + width: 1, + ), + color: backgroundColor ?? MyColors.backFillColor, + borderRadius: BorderRadius.circular(8.0), + ), + child: child, + ); + } +} diff --git a/lib/widgets/WrapHeightContainer.dart b/lib/widgets/WrapHeightContainer.dart new file mode 100644 index 0000000..31db657 --- /dev/null +++ b/lib/widgets/WrapHeightContainer.dart @@ -0,0 +1,22 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/theme/MyColors.dart'; + +class WrapHeightContainer extends StatelessWidget { + Widget child; + + WrapHeightContainer({super.key, required this.child}); + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + borderRadius: const BorderRadius.all( + Radius.circular(1.0) // <--- border radius here + ), + border: Border.all(width: 1, color: MyColors.fillColorGray2), + color: MyColors.white, + ), + child: child, + ); + } +} diff --git a/pubspec.lock b/pubspec.lock index e0373fb..2a554b0 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -9,6 +9,14 @@ packages: url: "https://pub.dev" source: hosted version: "64.0.0" + amdjs: + dependency: transitive + description: + name: amdjs + sha256: "97e6d96fd0e64d3eeb6fc85f386160322a23b1192662aac1fa4139569add2434" + url: "https://pub.dev" + source: hosted + version: "2.0.3" analyzer: dependency: transitive description: @@ -17,6 +25,22 @@ packages: url: "https://pub.dev" source: hosted version: "6.2.0" + android_path_provider: + dependency: "direct main" + description: + name: android_path_provider + sha256: "398fb6f83476ba2c6b0930d997ca19376a242d3264c615d3f09ea77382fa09c3" + url: "https://pub.dev" + source: hosted + version: "0.3.0" + archive: + dependency: transitive + description: + name: archive + sha256: e0902a06f0e00414e4e3438a084580161279f137aeb862274710f29ec10cf01e + url: "https://pub.dev" + source: hosted + version: "3.3.9" args: dependency: transitive description: @@ -33,6 +57,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.11.0" + async_extension: + dependency: transitive + description: + name: async_extension + sha256: f5589e5e0611648f610b7ad00c40fbee4cb7398061ea73463bbeb8ec29fc8a28 + url: "https://pub.dev" + source: hosted + version: "1.2.5" auto_height_grid_view: dependency: "direct main" description: @@ -41,6 +73,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.0" + barcode: + dependency: transitive + description: + name: barcode + sha256: "789f898eef0bd88312470bdb2cc996f895ad7dd5f89e9adde84b204546a90b45" + url: "https://pub.dev" + source: hosted + version: "2.2.4" + bidi: + dependency: transitive + description: + name: bidi + sha256: "2c162a66885167f1f92c41583efea9a435cb268d58322ba266613b9582440f87" + url: "https://pub.dev" + source: hosted + version: "2.0.8" boolean_selector: dependency: transitive description: @@ -77,10 +125,10 @@ packages: dependency: transitive description: name: build_resolvers - sha256: "6c4dd11d05d056e76320b828a1db0fc01ccd376922526f8e9d6c796a5adbac20" + sha256: d912852cce27c9e80a93603db721c267716894462e7033165178b91138587972 url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.3.2" build_runner: dependency: "direct dev" description: @@ -109,10 +157,10 @@ packages: dependency: transitive description: name: built_value - sha256: "598a2a682e2a7a90f08ba39c0aaa9374c5112340f0a2e275f61b59389543d166" + sha256: ff627b645b28fb8bdb69e645f910c2458fd6b65f6585c3a53e0626024897dedf url: "https://pub.dev" source: hosted - version: "8.6.1" + version: "8.6.2" characters: dependency: transitive description: @@ -141,10 +189,10 @@ packages: dependency: transitive description: name: code_builder - sha256: "4ad01d6e56db961d29661561effde45e519939fdaeb46c351275b182eac70189" + sha256: "315a598c7fbe77f22de1c9da7cfd6fd21816312f16ffa124453b4fc679e540f1" url: "https://pub.dev" source: hosted - version: "4.5.0" + version: "4.6.0" collection: dependency: transitive description: @@ -181,10 +229,18 @@ packages: dependency: transitive description: name: cross_file - sha256: "0b0036e8cccbfbe0555fd83c1d31a6f30b77a96b598b35a5d36dd41f718695e9" + sha256: fd832b5384d0d6da4f6df60b854d33accaaeb63aa9e10e736a87381f08dee2cb url: "https://pub.dev" source: hosted - version: "0.3.3+4" + version: "0.3.3+5" + cross_scroll: + dependency: "direct main" + description: + name: cross_scroll + sha256: "50d2006d51c0640887928200c8561c6833a6f98d576f6fcb62f4f2f5916d0056" + url: "https://pub.dev" + source: hosted + version: "0.0.76" crypto: dependency: transitive description: @@ -213,18 +269,18 @@ packages: dependency: "direct main" description: name: cupertino_icons - sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be + sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d url: "https://pub.dev" source: hosted - version: "1.0.5" + version: "1.0.6" dart_style: dependency: transitive description: name: dart_style - sha256: "1efa911ca7086affd35f463ca2fc1799584fb6aa89883cf0af8e3664d6a02d55" + sha256: abd7625e16f51f554ea244d090292945ec4d4be7bfbaf2ec8cccea568919d334 url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.3.3" dbus: dependency: transitive description: @@ -241,6 +297,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.3.2" + dom_tools: + dependency: transitive + description: + name: dom_tools + sha256: "55f1a0d30e2bb51fed0d0354514546d3f967bf0781a1f8562646b82a4da14c81" + url: "https://pub.dev" + source: hosted + version: "2.1.17" dropdown_search: dependency: "direct main" description: @@ -249,6 +313,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.0.6" + enum_to_string: + dependency: transitive + description: + name: enum_to_string + sha256: bd9e83a33b754cb43a75b36a9af2a0b92a757bfd9847d2621ca0b1bed45f8e7a + url: "https://pub.dev" + source: hosted + version: "2.0.1" equatable: dependency: transitive description: @@ -293,42 +365,50 @@ packages: dependency: "direct main" description: name: file_picker - sha256: "21145c9c268d54b1f771d8380c195d2d6f655e0567dc1ca2f9c134c02c819e0a" + sha256: be325344c1f3070354a1d84a231a1ba75ea85d413774ec4bdf444c023342e030 url: "https://pub.dev" source: hosted - version: "5.3.3" + version: "5.5.0" + file_saver: + dependency: "direct main" + description: + name: file_saver + sha256: "566c0029cccf79848cb5c261c7fb161873d4109dbc145bfeea1f7e4097b62dc7" + url: "https://pub.dev" + source: hosted + version: "0.2.6" file_selector_linux: dependency: transitive description: name: file_selector_linux - sha256: "770eb1ab057b5ae4326d1c24cc57710758b9a46026349d021d6311bd27580046" + sha256: "045d372bf19b02aeb69cacf8b4009555fb5f6f0b7ad8016e5f46dd1387ddd492" url: "https://pub.dev" source: hosted - version: "0.9.2" + version: "0.9.2+1" file_selector_macos: dependency: transitive description: name: file_selector_macos - sha256: "4ada532862917bf16e3adb3891fe3a5917a58bae03293e497082203a80909412" + sha256: "182c3f8350cee659f7b115e956047ee3dc672a96665883a545e81581b9a82c72" url: "https://pub.dev" source: hosted - version: "0.9.3+1" + version: "0.9.3+2" file_selector_platform_interface: dependency: transitive description: name: file_selector_platform_interface - sha256: "412705a646a0ae90f33f37acfae6a0f7cbc02222d6cd34e479421c3e74d3853c" + sha256: "0aa47a725c346825a2bd396343ce63ac00bda6eff2fbc43eabe99737dede8262" url: "https://pub.dev" source: hosted - version: "2.6.0" + version: "2.6.1" file_selector_windows: dependency: transitive description: name: file_selector_windows - sha256: "1372760c6b389842b77156203308940558a2817360154084368608413835fc26" + sha256: d3547240c20cabf205c7c7f01a50ecdbc413755814d6677f3cb366f04abcead0 url: "https://pub.dev" source: hosted - version: "0.9.3" + version: "0.9.3+1" fixnum: dependency: transitive description: @@ -386,10 +466,10 @@ packages: dependency: "direct dev" description: name: flutter_lints - sha256: "2118df84ef0c3ca93f96123a616ae8540879991b8b57af2f81b76a7ada49b2a4" + sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04 url: "https://pub.dev" source: hosted - version: "2.0.2" + version: "2.0.3" flutter_localizations: dependency: "direct dev" description: flutter @@ -399,10 +479,10 @@ packages: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: "950e77c2bbe1692bc0874fc7fb491b96a4dc340457f4ea1641443d0a6c1ea360" + sha256: f185ac890306b5779ecbd611f52502d8d4d63d27703ef73161ca0407e815f02c url: "https://pub.dev" source: hosted - version: "2.0.15" + version: "2.0.16" flutter_spinkit: dependency: "direct main" description: @@ -517,6 +597,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.2" + image: + dependency: transitive + description: + name: image + sha256: a72242c9a0ffb65d03de1b7113bc4e189686fc07c7147b8b41811d0dd0e0d9bf + url: "https://pub.dev" + source: hosted + version: "4.0.17" image_picker: dependency: "direct main" description: @@ -529,10 +617,10 @@ packages: dependency: transitive description: name: image_picker_android - sha256: "8179b54039b50eee561676232304f487602e2950ffb3e8995ed9034d6505ca34" + sha256: "47da2161c2e9f8f8a9cbbd89d466d174333fbdd769aeed848912e0b16d9cb369" url: "https://pub.dev" source: hosted - version: "0.8.7+4" + version: "0.8.8" image_picker_for_web: dependency: transitive description: @@ -545,42 +633,42 @@ packages: dependency: transitive description: name: image_picker_ios - sha256: b3e2f21feb28b24dd73a35d7ad6e83f568337c70afab5eabac876e23803f264b + sha256: c5538cacefacac733c724be7484377923b476216ad1ead35a0d2eadcdc0fc497 url: "https://pub.dev" source: hosted - version: "0.8.8" + version: "0.8.8+2" image_picker_linux: dependency: transitive description: name: image_picker_linux - sha256: "02cbc21fe1706b97942b575966e5fbbeaac535e76deef70d3a242e4afb857831" + sha256: "4ed1d9bb36f7cd60aa6e6cd479779cc56a4cb4e4de8f49d487b1aaad831300fa" url: "https://pub.dev" source: hosted - version: "0.2.1" + version: "0.2.1+1" image_picker_macos: dependency: transitive description: name: image_picker_macos - sha256: cee2aa86c56780c13af2c77b5f2f72973464db204569e1ba2dd744459a065af4 + sha256: "3f5ad1e8112a9a6111c46d0b57a7be2286a9a07fc6e1976fdf5be2bd31d4ff62" url: "https://pub.dev" source: hosted - version: "0.2.1" + version: "0.2.1+1" image_picker_platform_interface: dependency: transitive description: name: image_picker_platform_interface - sha256: c1134543ae2187e85299996d21c526b2f403854994026d575ae4cf30d7bb2a32 + sha256: ed9b00e63977c93b0d2d2b343685bed9c324534ba5abafbb3dfbd6a780b1b514 url: "https://pub.dev" source: hosted - version: "2.9.0" + version: "2.9.1" image_picker_windows: dependency: transitive description: name: image_picker_windows - sha256: c3066601ea42113922232c7b7b3330a2d86f029f685bba99d82c30e799914952 + sha256: "6ad07afc4eb1bc25f3a01084d28520496c4a3bb0cb13685435838167c9dcedeb" url: "https://pub.dev" source: hosted - version: "0.2.1" + version: "0.2.1+1" infinite_scroll_pagination: dependency: "direct main" description: @@ -629,6 +717,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.8.1" + json_object_mapper: + dependency: transitive + description: + name: json_object_mapper + sha256: "8566947565045eb2a8dd679029c4fcbb84dfd0e10309a1693e67e83e174893a2" + url: "https://pub.dev" + source: hosted + version: "2.0.1" lints: dependency: transitive description: @@ -645,6 +741,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.0" + markdown: + dependency: transitive + description: + name: markdown + sha256: c2b81e184067b41d0264d514f7cdaa2c02d38511e39d6521a1ccc238f6d7b3f2 + url: "https://pub.dev" + source: hosted + version: "6.0.1" matcher: dependency: transitive description: @@ -705,26 +809,26 @@ packages: dependency: "direct main" description: name: objectbox - sha256: "73b1533d84f538a6912775ba5880b4b4a708ede58df0adc58391506b284d9feb" + sha256: "3c9d13df69e0d0084f5c395b11dc9c8fbe6d9dbca5051f9ac981b5d93c773461" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.2.1" objectbox_flutter_libs: dependency: "direct main" description: name: objectbox_flutter_libs - sha256: f29c0d31da142e9e96424edf382f901c0360688b5a063129cafb5b7c9530c6dd + sha256: b2589ed58a04fd7c44a00baa38431ce0e980d052808f87e35a3ee338e586dba9 url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.2.1" objectbox_generator: dependency: "direct dev" description: name: objectbox_generator - sha256: bfad1cf58c71461f9b5190064fe637004b8faed38656a4c23288ed34d7d48197 + sha256: adb562ce5fe39439255b05890e748021250d9102726d8603f54d51e4620c7b33 url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.2.1" package_config: dependency: transitive description: @@ -769,50 +873,58 @@ packages: dependency: "direct main" description: name: path_provider - sha256: "909b84830485dbcd0308edf6f7368bc8fd76afa26a270420f34cabea2a6467a0" + sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: "5d44fc3314d969b84816b569070d7ace0f1dea04bd94a83f74c4829615d22ad8" + sha256: "6b8b19bd80da4f11ce91b2d1fb931f3006911477cec227cce23d3253d80df3f1" url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.2.0" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "1b744d3d774e5a879bb76d6cd1ecee2ba2c6960c03b1020cd35212f6aa267ac5" + sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d" url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.3.1" path_provider_linux: dependency: transitive description: name: path_provider_linux - sha256: ba2b77f0c52a33db09fc8caf85b12df691bf28d983e84cf87ff6d693cfa007b3 + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.2.1" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - sha256: bced5679c7df11190e1ddc35f3222c858f328fff85c3942e46e7f5589bf9eb84 + sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c" url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" path_provider_windows: dependency: transitive description: name: path_provider_windows - sha256: ee0e0d164516b90ae1f970bdf29f726f1aa730d7cfc449ecc74c495378b705da + sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.2.1" + pdf: + dependency: "direct main" + description: + name: pdf + sha256: "9f75fc7f5580ea5e635b5724de58fb27f684c9ad03ed46fdc1aac768e4557315" + url: "https://pub.dev" + source: hosted + version: "3.10.4" percent_indicator: dependency: "direct main" description: @@ -825,18 +937,18 @@ packages: dependency: "direct main" description: name: permission_handler - sha256: "63e5216aae014a72fe9579ccd027323395ce7a98271d9defa9d57320d001af81" + sha256: bc56bfe9d3f44c3c612d8d393bd9b174eb796d706759f9b495ac254e4294baa5 url: "https://pub.dev" source: hosted - version: "10.4.3" + version: "10.4.5" permission_handler_android: dependency: transitive description: name: permission_handler_android - sha256: "2ffaf52a21f64ac9b35fe7369bb9533edbd4f698e5604db8645b1064ff4cf221" + sha256: "59c6322171c29df93a22d150ad95f3aa19ed86542eaec409ab2691b8f35f9a47" url: "https://pub.dev" source: hosted - version: "10.3.3" + version: "10.3.6" permission_handler_apple: dependency: transitive description: @@ -849,10 +961,10 @@ packages: dependency: transitive description: name: permission_handler_platform_interface - sha256: "7c6b1500385dd1d2ca61bb89e2488ca178e274a69144d26bbd65e33eae7c02a9" + sha256: f2343e9fa9c22ae4fd92d4732755bfe452214e7189afcc097380950cf567b4b2 url: "https://pub.dev" source: hosted - version: "3.11.3" + version: "3.11.5" permission_handler_windows: dependency: transitive description: @@ -865,26 +977,34 @@ packages: dependency: transitive description: name: petitparser - sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750 + sha256: eeb2d1428ee7f4170e2bd498827296a18d4e7fc462b71727d111c0ac7707cfa6 url: "https://pub.dev" source: hosted - version: "5.4.0" + version: "6.0.1" platform: dependency: transitive description: name: platform - sha256: "57c07bf82207aee366dfaa3867b3164e4f03a238a461a11b0e8a3a510d51203d" + sha256: ae68c7bfcd7383af3629daafb32fb4e8681c7154428da4febcff06200585f102 url: "https://pub.dev" source: hosted - version: "3.1.1" + version: "3.1.2" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - sha256: "43798d895c929056255600343db8f049921cbec94d31ec87f1dc5c16c01935dd" + sha256: da3fdfeccc4d4ff2da8f8c556704c08f912542c5fb3cf2233ed75372384a034d url: "https://pub.dev" source: hosted - version: "2.1.5" + version: "2.1.6" + pointycastle: + dependency: transitive + description: + name: pointycastle + sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c" + url: "https://pub.dev" + source: hosted + version: "3.7.3" pool: dependency: transitive description: @@ -933,6 +1053,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.1.0" + resource_portable: + dependency: transitive + description: + name: resource_portable + sha256: "76af61ea5af4719f0a5a9776dddb7bc61e0a85fa5b7978423cc20566f2f97b53" + url: "https://pub.dev" + source: hosted + version: "3.1.0" rxdart: dependency: transitive description: @@ -941,62 +1069,70 @@ packages: url: "https://pub.dev" source: hosted version: "0.26.0" + screenshot: + dependency: "direct main" + description: + name: screenshot + sha256: "455284ff1f5b911d94a43c25e1385485cf6b4f288293eba68f15dad711c7b81c" + url: "https://pub.dev" + source: hosted + version: "2.1.0" shared_preferences: dependency: "direct main" description: name: shared_preferences - sha256: "0344316c947ffeb3a529eac929e1978fcd37c26be4e8468628bac399365a3ca1" + sha256: b7f41bad7e521d205998772545de63ff4e6c97714775902c199353f8bf1511ac url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.2.1" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - sha256: fe8401ec5b6dcd739a0fe9588802069e608c3fdbfd3c3c93e546cf2f90438076 + sha256: "8568a389334b6e83415b6aae55378e158fbc2314e074983362d20c562780fb06" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.2.1" shared_preferences_foundation: dependency: transitive description: name: shared_preferences_foundation - sha256: d29753996d8eb8f7619a1f13df6ce65e34bc107bef6330739ed76f18b22310ef + sha256: "7bf53a9f2d007329ee6f3df7268fd498f8373602f943c975598bbb34649b62a7" url: "https://pub.dev" source: hosted - version: "2.3.3" + version: "2.3.4" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux - sha256: "71d6806d1449b0a9d4e85e0c7a917771e672a3d5dc61149cc9fac871115018e1" + sha256: c2eb5bf57a2fe9ad6988121609e47d3e07bb3bdca5b6f8444e4cf302428a128a url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.3.1" shared_preferences_platform_interface: dependency: transitive description: name: shared_preferences_platform_interface - sha256: "23b052f17a25b90ff2b61aad4cc962154da76fb62848a9ce088efe30d7c50ab1" + sha256: d4ec5fc9ebb2f2e056c617112aa75dcf92fc2e4faaf2ae999caa297473f75d8a url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.3.1" shared_preferences_web: dependency: transitive description: name: shared_preferences_web - sha256: "7347b194fb0bbeb4058e6a4e87ee70350b6b2b90f8ac5f8bd5b3a01548f6d33a" + sha256: d762709c2bbe80626ecc819143013cc820fa49ca5e363620ee20a8b15a3e3daf url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.2.1" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows - sha256: f95e6a43162bce43c9c3405f3eb6f39e5b5d11f65fab19196cf8225e2777624d + sha256: f763a101313bd3be87edffe0560037500967de9c394a714cd598d945517f694f url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.3.1" shelf: dependency: transitive description: @@ -1082,6 +1218,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.0" + swiss_knife: + dependency: transitive + description: + name: swiss_knife + sha256: "3066fc2ed9a90139cf69f1733f6f9714f7a0a4e6a9d668451d5a1e371da8897b" + url: "https://pub.dev" + source: hosted + version: "3.1.5" term_glyph: dependency: transitive description: @@ -1174,26 +1318,26 @@ packages: dependency: transitive description: name: win32 - sha256: f2add6fa510d3ae152903412227bda57d0d5a8da61d2c39c1fb022c9429a41c0 + sha256: "9e82a402b7f3d518fb9c02d0e9ae45952df31b9bf34d77baf19da2de03fc2aaa" url: "https://pub.dev" source: hosted - version: "5.0.6" + version: "5.0.7" xdg_directories: dependency: transitive description: name: xdg_directories - sha256: f0c26453a2d47aa4c2570c6a033246a3fc62da2fe23c7ffdd0a7495086dc0247 + sha256: "589ada45ba9e39405c198fe34eb0f607cddb2108527e658136120892beac46d2" url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "1.0.3" xml: dependency: transitive description: name: xml - sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84" + sha256: af5e77e9b83f2f4adc5d3f0a4ece1c7f45a2467b695c2540381bac793e34e556 url: "https://pub.dev" source: hosted - version: "6.3.0" + version: "6.4.2" yaml: dependency: transitive description: @@ -1204,4 +1348,4 @@ packages: version: "3.1.2" sdks: dart: ">=3.0.0 <4.0.0" - flutter: ">=3.7.0" + flutter: ">=3.10.0" diff --git a/pubspec.yaml b/pubspec.yaml index b9e50da..3c4d027 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -66,6 +66,11 @@ dependencies: internet_connection_checker: ^1.0.0+1 connectivity_plus: ^4.0.2 fl_chart: ^0.63.0 + pdf: ^3.10.4 + screenshot: ^2.1.0 + android_path_provider: ^0.3.0 + cross_scroll: ^0.0.76 + file_saver: ^0.2.6 dev_dependencies: flutter_test: sdk: flutter @@ -123,6 +128,9 @@ flutter: - family: RobotoMedium fonts: - asset: fonts/Roboto-Medium.ttf + - family: DejaVuSansMono + fonts: + - asset: fonts/DejaVuSansMono.ttf # For details regarding fonts from package dependencies, # see https://flutter.dev/custom-fonts/#from-packages flutter_intl: