From 85b70a67e8a992c4a1c7b05e4566524b74bf89eb Mon Sep 17 00:00:00 2001 From: waqasYeepeey Date: Tue, 26 Sep 2023 13:30:43 +0500 Subject: [PATCH 01/11] 'before changes' --- android/app/src/main/AndroidManifest.xml | 11 +- android/app/src/profile/AndroidManifest.xml | 3 + fonts/DejaVuSansMono.ttf | Bin 0 -> 335068 bytes ios/Podfile.lock | 32 +- ios/Runner/Info.plist | 4 + lib/application/MyApp.dart | 37 +- lib/application/localdb/SharedPrefs.dart | 8 +- .../model/Combo/AddNewComboModel.dart | 2 +- lib/application/model/Combo/ComboProduct.dart | 16 +- .../model/CreateAndUpdateOrder.dart | 157 +- lib/application/model/auth/AccessToken.dart | 11 + .../model/auth/AccessTokenModel.dart | 14 + .../BillingCounterDashboard.dart | 21 + .../billingCounter/BillingPaymentModes.dart | 46 + .../billingCounter/CounterDashboard.dart | 25 + .../billingCounter/GetBillingCounter.dart | 6 + .../model/billingCounter/PaymentModes.dart | 13 + .../model/converters/DataTimeFormat.dart | 27 + .../model/createOrder/OrderDetails.dart | 24 +- .../dashboard/graph/AllInvoiceStatus.dart | 10 +- .../model/dashboard/graph/AllPosStatus.dart | 8 +- .../dashboard/graph/POSValueDataWise.dart | 6 +- .../graph/PosOrderCountTodayTimewise.dart | 6 +- .../model/dashboard/graph/TodaySales.dart | 6 +- .../dashboard/graph/TotalIncomeExpense.dart | 10 +- .../model/discount/StoreDiscountModel.dart | 3 + .../inventory/InventoryMeasurementModel.dart | 28 +- .../model/reports/CashierOrderHistory.dart | 6 + .../model/store/GetStoreOrderByIdModel.dart | 1 - .../model/store/StoreItemsResponse.dart | 38 +- lib/application/network/APIManager.dart | 12 + lib/application/network/ApiServices.dart | 4 +- lib/application/theme/MyColors.dart | 30 +- lib/application/theme/MyFonts.dart | 7 +- lib/application/utils/AppError.dart | 18 +- lib/application/utils/Constants.dart | 46 +- .../authModule/loginViews/CheckInPopUp.dart | 487 ++- .../views/authModule/loginViews/LoginVC.dart | 276 +- .../viewModel/CheckInViewModel.dart | 32 +- .../authModule/viewModel/LoginViewModel.dart | 68 +- .../BillingCounterDashBoard.dart | 155 + .../BillingCounterMainVC.dart | 116 + .../viewModels/BillingCounterViewModel.dart | 103 + .../widgets/BillingCounterGrid.dart | 28 + .../widgets/BillingCounterView.dart | 179 + .../widgets/DetailsView.dart | 43 + .../views/create_order_module/CartVC.dart | 71 +- .../create_order_module/HoldOrderVC.dart | 492 +-- .../viewModels/CartViewModel.dart | 266 +- .../viewModels/CreateOrderViewModel.dart | 259 +- .../viewModels/PaymentOptionViewModel.dart | 228 + .../viewModels/PrintInvoiceViewModel.dart | 152 +- .../views/PrintInvoiceVC.dart | 4 +- .../views/PrintReceiptVC.dart | 705 ++++ .../views/TabBarHomeVC.dart | 292 +- .../views/popups/CashOutVC.dart | 140 +- .../views/popups/CounterCloseVC.dart | 88 + .../views/popups/DeliveryPartnerPopUp.dart | 15 +- .../views/popups/DineInPopup.dart | 2 + .../views/popups/ItemModifiersPopUp.dart | 71 +- .../views/popups/LogoutVC.dart | 11 +- .../views/popups/PaymentOptionPopUpVC.dart | 1347 ++---- .../views/popups/RegisterCashVC.dart | 142 +- .../widgets/CartItemView.dart | 8 +- .../widgets/ProductItemView.dart | 94 +- lib/application/views/dashboard/HomeVC.dart | 721 ++-- .../viewModel/DashboardViewModel.dart | 28 +- .../widgets/POSOrderCountDayWiseGraph.dart | 356 +- .../widgets/POSOrderCountTimeWiseGraph.dart | 369 +- .../widgets/POSOrderValueDayWise.dart | 380 +- .../widgets/POSOrderValueTimeWise.dart | 372 +- .../views/dashboard/widgets/RevenueGraph.dart | 46 +- .../dashboard/widgets/TodayPOSSales.dart | 128 +- .../dashboard/widgets/TodaySaleGraph.dart | 129 +- .../viewModels/DiscountViewModel.dart | 49 +- .../viewModels/NewDiscountViewModel.dart | 305 ++ .../discountModule/views/DiscountVC.dart | 493 +-- .../discountModule/views/NewDiscountVC.dart | 1501 ++----- .../widgets/DiscountListView.dart | 301 ++ lib/application/views/home/HomePage.dart | 284 +- .../views/home/HomePageViewModel.dart | 139 +- .../categoryviews/InventoryAddCategoryVC.dart | 7 +- .../InventoryCategoriesModule.dart | 254 +- .../viewModels/CategoryViewModel.dart | 13 +- .../comboviews/ComboAddSizesVC.dart | 429 +- .../comboviews/CreateComboGroupVC.dart | 335 +- .../comboviews/InventoryComboVC.dart | 180 +- .../comboviews/InventoryNewComboVC.dart | 1738 ++------ .../viewModels/AddComboGroupViewModel.dart | 82 + .../viewModels/AddComboSizeViewModel.dart | 103 + .../viewModels/AddNewComboViewModel.dart | 284 ++ .../comboviews/viewModels/ComboViewModel.dart | 14 +- .../InventoryDeliveryPartnerPriceVC.dart | 77 +- .../inventoryAddDeliveryPriceVC.dart | 532 +-- .../DeliveryPartnerPriceViewModel.dart | 9 +- .../NewDeliveryPartnerViewModel.dart | 128 + .../ingredientsViews/IngredientsVC.dart | 172 +- .../viewModels/IngredientViewModel.dart | 8 +- .../InventoryAddMeasurementVC.dart | 37 +- .../InventoryMeasurementVC.dart | 292 +- .../viewModels/AddMeasurementViewModel.dart | 9 +- .../viewModels/MeasurementViewModel.dart | 8 +- .../modifierviews/InventoryModifierVC.dart | 17 +- .../modifierviews/InventoryNewModifierVC.dart | 10 +- .../viewModels/ModiferViewModel.dart | 8 +- .../viewModels/NewModifierVM.dart | 24 +- .../AddNewInventoryProductVC.dart | 3732 ++++++++--------- .../productviews/InventoryProductVC.dart | 280 +- .../viewModels/AddProductViewModel.dart | 2 +- .../viewModels/ProductViewModel.dart | 22 +- .../InventoryStockTransferVC.dart | 92 +- .../viewModels/StockTransferViewModel.dart | 8 +- .../InventorySubCategoryVC.dart | 57 +- .../subCategoryViews/SubCategoryVC.dart | 277 +- .../viewModels/AddSubCategoryViewModel.dart | 2 + .../viewModels/SubCategoryViewModel.dart | 42 +- .../viewmodel/ProductViewModel.dart | 9 +- .../viewModel/KitchenViewModel.dart | 29 +- .../viewModel/TablesViewModel.dart | 9 +- .../views/KitchenMainTableVC.dart | 4 +- .../views/kitchen/KitchenViewVC.dart | 23 +- .../kitchen/widgets/KitchenListView.dart | 11 +- .../widgets/KitchenListViewHeader.dart | 32 +- .../offline/KitchenOfflineListView.dart | 30 +- .../views/table/KitchenTableVC.dart | 33 +- .../viewModel/QuotationViewModel.dart | 8 +- .../views/AddInvoiceAndPrintVC.dart | 12 +- .../views/ReturnInvoiceVC.dart | 1851 ++------ .../views/invoiceModule/InvoicesVC.dart | 947 +---- .../views/invoiceModule/NewInvoiceVC.dart | 2230 ++-------- .../viewModels}/InvoiceViewModel.dart | 8 +- .../viewModels/NewInvoiceViewModel.dart | 535 +++ .../ReturnDamageInvoiceViewModel.dart | 226 + .../widgets/InvoiceListView.dart | 523 +++ .../views/ordersModule/OrderVC.dart | 139 +- .../viewModel/OrderViewModel.dart | 7 +- .../quotataionModule/NewQuotationsVC.dart | 34 +- .../views/quotataionModule/QuotationsVC.dart | 191 +- lib/application/views/settings/ReportsVC.dart | 274 +- .../reportsViews/BestSuppliersVC.dart | 11 +- .../settings/reportsViews/POSCompleteVC.dart | 11 +- .../reportsViews/POSReturnOrderVC.dart | 12 +- .../reportsViews/ReportsCategoryVC.dart | 11 +- .../reportsViews/ReportsInvoiceVC.dart | 11 +- .../reportsViews/ReportsProductsVC.dart | 12 +- .../reportsViews/ReportsQuotationVC.dart | 11 +- .../viewModels/BestSupplierViewModel.dart | 19 +- .../viewModels/POSCompleteViewModel.dart | 8 +- .../viewModels/POSReturnOrderViewModel.dart | 8 +- .../viewModels/ReportsInvoiceViewModel.dart | 9 +- .../settings/viewModels/ReportsViewModel.dart | 14 +- .../transactions/CashierTransactionsVC.dart | 528 +-- .../views/transactions/EditOrderVC.dart | 3410 ++++----------- .../ReturnTransactionInvoiceVC.dart | 17 +- .../TransactionDamageInvoiceVC.dart | 10 +- .../transactions/TransactionInvoicesVC.dart | 12 +- .../transactions/TransactionPOSReturnVC.dart | 12 +- .../transactions/TransactionQuotationVC.dart | 15 +- .../views/transactions/TransactionVC.dart | 71 +- .../views/transactions/ViewPOSReturnVC.dart | 328 +- .../views/transactions/return/ReturnPOS.dart | 632 +-- .../return/ReturnReasonPopUp.dart | 78 +- .../CashierTransactionViewModel.dart | 102 + .../viewmodels/ReturnPOSOrderVM.dart | 13 +- .../TransactionQuotationViewModel.dart | 6 +- .../widgets/CashierOrderListView.dart | 317 ++ .../widgets/EditOrderViewModel.dart | 351 ++ lib/database/SyncDatabase.dart | 126 +- lib/database/objectbox.dart | 176 +- lib/helpers/NetworkStatusService.dart | 23 + lib/helpers/ThemeDropDown.dart | 9 + lib/helpers/ThemeText.dart | 46 +- lib/main.dart | 9 +- lib/objectbox-model.json | 914 ++-- lib/objectbox.g.dart | 2154 +++++----- lib/widgets/ActionPopUpContainer.dart | 20 + lib/widgets/BorderContainer.dart | 23 + lib/widgets/ChildContainer.dart | 29 + lib/widgets/CustomAddButton.dart | 29 + lib/widgets/CustomAppBar.dart | 34 + lib/widgets/CustomCheckBox.dart | 4 +- lib/widgets/CustomListTIle.dart | 8 +- lib/widgets/CustomRemoveItemButton.dart | 31 + lib/widgets/CustomSimpleButton.dart | 4 +- lib/widgets/CustomSwitch.dart | 26 +- lib/widgets/CustomTextButtonIcon.dart | 74 +- lib/widgets/CustomTextFieldForm.dart | 61 +- lib/widgets/CustomTextFieldPassword.dart | 21 +- lib/widgets/DiscountDropdown.dart | 86 + lib/widgets/ItemCategoryDropdown.dart | 96 + lib/widgets/LanguageDropdown.dart | 32 + lib/widgets/LineView.dart | 15 + lib/widgets/ListHeadingContainer.dart | 18 + lib/widgets/PageLimitDropDown.dart | 46 + lib/widgets/PortraitContainer.dart | 27 + lib/widgets/TransprentBorderContainer.dart | 33 + pubspec.lock | 242 +- pubspec.yaml | 6 + 198 files changed, 17503 insertions(+), 21578 deletions(-) create mode 100644 fonts/DejaVuSansMono.ttf create mode 100644 lib/application/model/auth/AccessToken.dart create mode 100644 lib/application/model/auth/AccessTokenModel.dart create mode 100644 lib/application/model/billingCounter/BillingCounterDashboard.dart create mode 100644 lib/application/model/billingCounter/BillingPaymentModes.dart create mode 100644 lib/application/model/billingCounter/CounterDashboard.dart create mode 100644 lib/application/model/billingCounter/PaymentModes.dart create mode 100644 lib/application/views/billingCounterDashboard/BillingCounterDashBoard.dart create mode 100644 lib/application/views/billingCounterDashboard/BillingCounterMainVC.dart create mode 100644 lib/application/views/billingCounterDashboard/viewModels/BillingCounterViewModel.dart create mode 100644 lib/application/views/billingCounterDashboard/widgets/BillingCounterGrid.dart create mode 100644 lib/application/views/billingCounterDashboard/widgets/BillingCounterView.dart create mode 100644 lib/application/views/billingCounterDashboard/widgets/DetailsView.dart create mode 100644 lib/application/views/create_order_module/viewModels/PaymentOptionViewModel.dart create mode 100644 lib/application/views/create_order_module/views/PrintReceiptVC.dart create mode 100644 lib/application/views/create_order_module/views/popups/CounterCloseVC.dart create mode 100644 lib/application/views/discountModule/viewModels/NewDiscountViewModel.dart create mode 100644 lib/application/views/discountModule/widgets/DiscountListView.dart create mode 100644 lib/application/views/inventorymodule/comboviews/viewModels/AddComboGroupViewModel.dart create mode 100644 lib/application/views/inventorymodule/comboviews/viewModels/AddComboSizeViewModel.dart create mode 100644 lib/application/views/inventorymodule/comboviews/viewModels/AddNewComboViewModel.dart create mode 100644 lib/application/views/inventorymodule/deliveryPartnerViews/viewModels/NewDeliveryPartnerViewModel.dart rename lib/application/views/salesandordermodule/{viewModel => views/invoiceModule/viewModels}/InvoiceViewModel.dart (94%) create mode 100644 lib/application/views/salesandordermodule/views/invoiceModule/viewModels/NewInvoiceViewModel.dart create mode 100644 lib/application/views/salesandordermodule/views/invoiceModule/viewModels/ReturnDamageInvoiceViewModel.dart create mode 100644 lib/application/views/salesandordermodule/views/invoiceModule/widgets/InvoiceListView.dart create mode 100644 lib/application/views/transactions/viewmodels/CashierTransactionViewModel.dart create mode 100644 lib/application/views/transactions/widgets/CashierOrderListView.dart create mode 100644 lib/application/views/transactions/widgets/EditOrderViewModel.dart create mode 100644 lib/helpers/NetworkStatusService.dart create mode 100644 lib/widgets/ActionPopUpContainer.dart create mode 100644 lib/widgets/BorderContainer.dart create mode 100644 lib/widgets/ChildContainer.dart create mode 100644 lib/widgets/CustomAddButton.dart create mode 100644 lib/widgets/CustomAppBar.dart create mode 100644 lib/widgets/CustomRemoveItemButton.dart create mode 100644 lib/widgets/DiscountDropdown.dart create mode 100644 lib/widgets/ItemCategoryDropdown.dart create mode 100644 lib/widgets/LanguageDropdown.dart create mode 100644 lib/widgets/LineView.dart create mode 100644 lib/widgets/ListHeadingContainer.dart create mode 100644 lib/widgets/PageLimitDropDown.dart create mode 100644 lib/widgets/PortraitContainer.dart create mode 100644 lib/widgets/TransprentBorderContainer.dart 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 0000000000000000000000000000000000000000..8b7bb2a4e1b2c27786398c320e9020bcc24c3af3 GIT binary patch literal 335068 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�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

b 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 literal 0 HcmV?d00001 diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 3ec9ff2..47e5c87 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 @@ -37,13 +40,14 @@ PODS: - 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,40 +55,42 @@ 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`) - 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" Flutter: @@ -95,6 +101,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 +111,24 @@ 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 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..b2cd6e8 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -4,6 +4,10 @@ CADisableMinimumFrameDurationOnPhone + LSSupportsOpeningDocumentsInPlace + + UIFileSharingEnabled + CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleDisplayName diff --git a/lib/application/MyApp.dart b/lib/application/MyApp.dart index b41d9f9..c6a0194 100644 --- a/lib/application/MyApp.dart +++ b/lib/application/MyApp.dart @@ -9,11 +9,17 @@ import 'package:wosull/application/views/authModule/viewModel/CheckInViewModel.d import 'package:wosull/application/views/authModule/viewModel/LoginViewModel.dart'; import 'package:wosull/application/views/create_order_module/viewModels/CartViewModel.dart'; import 'package:wosull/application/views/create_order_module/viewModels/CreateOrderViewModel.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/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/measurementviews/viewModels/AddMeasurementUnitVM.dart'; import 'package:wosull/application/views/inventorymodule/measurementviews/viewModels/AddMeasurementViewModel.dart'; import 'package:wosull/application/views/inventorymodule/modifierviews/viewModels/NewModifierVM.dart'; @@ -21,11 +27,16 @@ import 'package:wosull/application/views/inventorymodule/productviews/viewModels import 'package:wosull/application/views/inventorymodule/productviews/viewModels/AddProductViewModel.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/NewInvoiceViewModel.dart'; import 'package:wosull/application/views/salesandordermodule/views/ordersModule/viewModel/OrderViewModel.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/stockTransferViews/viewModels/NewStockTransferVM.dart'; import 'views/transactions/viewmodels/ReturnPOSOrderVM.dart'; @@ -38,6 +49,28 @@ class MyApp extends StatelessWidget { Widget build(BuildContext context) { return MultiProvider( providers: [ + 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 +124,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/localdb/SharedPrefs.dart b/lib/application/localdb/SharedPrefs.dart index f4cb191..768a4f4 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); 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/CreateAndUpdateOrder.dart b/lib/application/model/CreateAndUpdateOrder.dart index 23a8056..9eed3d5 100644 --- a/lib/application/model/CreateAndUpdateOrder.dart +++ b/lib/application/model/CreateAndUpdateOrder.dart @@ -2,6 +2,7 @@ import 'package:flutter/foundation.dart'; import 'package:objectbox/objectbox.dart'; import 'package:wosull/application/model/Combo/GetComboModel.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'; @@ -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/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..98f4838 --- /dev/null +++ b/lib/application/model/auth/AccessTokenModel.dart @@ -0,0 +1,14 @@ +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: AccessToken.fromJson(json['access_token'])); + } +} 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/converters/DataTimeFormat.dart b/lib/application/model/converters/DataTimeFormat.dart index dc7caff..a2b4ec6 100644 --- a/lib/application/model/converters/DataTimeFormat.dart +++ b/lib/application/model/converters/DataTimeFormat.dart @@ -11,6 +11,12 @@ class DataTimeFormat { return formattedDate; } + static String getFormatDateWithTime() { + String formattedDate = + DateFormat("dd-MM-yyyy, hh:mm a").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))); @@ -24,6 +30,7 @@ class DataTimeFormat { static String getFormatDateString(String date) { var dateValue = DateFormat("yyyy-MM-ddTHH:mm:ssZ").parseUTC(date).toLocal(); + String formattedDate = DateFormat("yyyy-MM-dd").format(dateValue); return formattedDate; } @@ -32,7 +39,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/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/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..a009481 100644 --- a/lib/application/model/discount/StoreDiscountModel.dart +++ b/lib/application/model/discount/StoreDiscountModel.dart @@ -41,6 +41,7 @@ class StoreDiscount { String? discountType; String? discountTypeLabel; double? limitOfDiscount; + double? isUserUsed; String? discountStartDate; String? discountEndDate; bool? isDeleted; @@ -59,6 +60,7 @@ class StoreDiscount { this.value, this.type, this.storeId, + this.isUserUsed, this.categories, this.products, this.status, @@ -95,6 +97,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/inventory/InventoryMeasurementModel.dart b/lib/application/model/inventory/InventoryMeasurementModel.dart index 961091e..27a3393 100644 --- a/lib/application/model/inventory/InventoryMeasurementModel.dart +++ b/lib/application/model/inventory/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/reports/CashierOrderHistory.dart b/lib/application/model/reports/CashierOrderHistory.dart index ead2895..ca330ad 100644 --- a/lib/application/model/reports/CashierOrderHistory.dart +++ b/lib/application/model/reports/CashierOrderHistory.dart @@ -57,12 +57,16 @@ class CashierOrder { 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, @@ -117,6 +121,8 @@ class CashierOrder { : null, 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'] ?? "", 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/StoreItemsResponse.dart b/lib/application/model/store/StoreItemsResponse.dart index 3235fb7..9c27735 100644 --- a/lib/application/model/store/StoreItemsResponse.dart +++ b/lib/application/model/store/StoreItemsResponse.dart @@ -53,14 +53,16 @@ class SearchItemsResponse { @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 +72,7 @@ class StoreItems { int uniqueId; String uniqueIdForStoreData; - int quantity; + int? quantity; String imageUrl = ""; String updatedAt; bool isItemInStock = false; @@ -82,7 +84,8 @@ class StoreItems { int totalAddedQuantity; int totalUsedQuantity; double salePriceExclusiveTax; - double totalItemPrice; + + double? totalItemPrice; String supplier; String discount; String measurementCategory; @@ -94,8 +97,9 @@ class StoreItems { bool status; bool isCombo = false; bool isCheckedForReturn = false; - + @Transient() var selectedCombos = ToMany(); + @Transient() var selectedModifiers = ToMany(); var ingredients = ToMany(); var modifiers = ToMany(); @@ -106,7 +110,8 @@ class StoreItems { StoreItems( {this.name = '', - this.id = '', + this.itemId = '', + this.id = 0, required this.deliveryPartners, this.isUnlimitedQuantity = false, required this.comboProduct, @@ -117,7 +122,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 +152,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 +174,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 +189,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 +235,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; @@ -275,7 +279,7 @@ class StoreItems { data['item_name_arabic'] = itemNameArabic; data['item_description_arabic'] = descriptionArabic; data['details'] = description; - data['total_quantity'] = totalAddedQuantity ?? 1; + data['total_quantity'] = totalAddedQuantity; data['sale_price_exclusive_tax'] = salePriceExclusiveTax; data['stock_alert_quantity'] = stockAlertQuantity; data['is_visible_in_store'] = true; @@ -304,7 +308,7 @@ class StoreItems { data['name'] = name; data['unlimited_quantity'] = isUnlimitedQuantity ?? false; data['productId'] = product_product_id ?? "0"; - data['_id'] = id; + data['_id'] = itemId; data['unique_id_for_store_data'] = uniqueId; data['is_item_in_stock'] = isItemInStock; data['item_name_arabic'] = itemNameArabic; diff --git a/lib/application/network/APIManager.dart b/lib/application/network/APIManager.dart index 151ae78..960ad8b 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 { 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/theme/MyColors.dart b/lib/application/theme/MyColors.dart index 1e918c8..7b033d8 100644 --- a/lib/application/theme/MyColors.dart +++ b/lib/application/theme/MyColors.dart @@ -56,12 +56,16 @@ 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 redLabelColor = Color(0xFFdc3545); + + static const redAlpha50 = Color(0x10dc3545); + static const fillColor3 = Color(0xFFE1E8EF); static const fillColorGray = Color(0xFFE8ECF0); @@ -100,12 +104,30 @@ class MyColors { fontSize: 13, fontFamily: MyFonts.Medium, color: MyColors.black); } - static DropDownDecoratorProps dropDownStyle({String hint = 'Choose'}) { + static DropDownDecoratorProps dropDownStyle( + {String hint = 'Choose', Color fillColor = const Color(0xFFF4F6FB)}) { return DropDownDecoratorProps( - baseStyle: ThemeText.textStyleValue, + baseStyle: const TextStyle( + fontFamily: MyFonts.Medium, + fontSize: 11, + color: MyColors.textColorBlack20, + fontWeight: FontWeight.w100, + ), textAlignVertical: TextAlignVertical.center, dropdownSearchDecoration: InputDecoration( - border: InputBorder.none, + fillColor: fillColor, + filled: true, + labelStyle: ThemeText.textStyleValue, + hintStyle: ThemeText.hintStyleTextField, + isDense: true, + contentPadding: const EdgeInsets.only(left: 8), // Added + enabledBorder: OutlineInputBorder( + borderSide: const BorderSide( + width: 0, //<-- SEE HERE + color: Colors.transparent, + ), + borderRadius: BorderRadius.circular(8.0), + ), hintText: hint, ), ); diff --git a/lib/application/theme/MyFonts.dart b/lib/application/theme/MyFonts.dart index 27ffb3c..1c241dc 100644 --- a/lib/application/theme/MyFonts.dart +++ b/lib/application/theme/MyFonts.dart @@ -1,5 +1,3 @@ -import 'package:flutter/material.dart'; - class MyFonts { static const Medium = 'DMSansMedium'; @@ -11,6 +9,8 @@ class MyFonts { static const RobotoBold = 'RobotoBold'; + static const DejaVu = 'DejaVuSansMono'; + static const bold = 18.0; static const H1 = 16.0; @@ -20,7 +20,6 @@ class MyFonts { static const normal = 12.0; static const normalButton = 14.0; - - + static const mediumText = 13.0; } diff --git a/lib/application/utils/AppError.dart b/lib/application/utils/AppError.dart index 3973601..4d0caca 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; @@ -9,8 +10,17 @@ class AppError extends StatelessWidget { @override Widget build(BuildContext context) { // TODO: implement build - return Center( - child: HeadingText(error), - ); + return Container( + 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/Constants.dart b/lib/application/utils/Constants.dart index e326179..c7aa586 100644 --- a/lib/application/utils/Constants.dart +++ b/lib/application/utils/Constants.dart @@ -15,7 +15,7 @@ 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 = @@ -179,6 +179,7 @@ class Constants { 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'; //ingredients static const getIngredientsList = 'api/store/get_ingrediant_list'; @@ -196,12 +197,19 @@ class Constants { 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 invoiceFilterType = [ 'All', @@ -245,10 +253,27 @@ 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 paymentMethod = [ 'Cash', ]; + static const pageLimits = ['10', '25', '50', '100']; + static const discountTypes = ['Automatic', 'Manual']; static const returnProductReason = [ @@ -257,6 +282,25 @@ class Constants { 'Other', ]; + static const chooseInvoiceForTypes = [ + 'Customer', + 'Company', + ]; + + static const statusTypes = [ + 'Open', + 'Paid Partially', + 'Paid', + '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/loginViews/CheckInPopUp.dart b/lib/application/views/authModule/loginViews/CheckInPopUp.dart index 5417768..158e490 100644 --- a/lib/application/views/authModule/loginViews/CheckInPopUp.dart +++ b/lib/application/views/authModule/loginViews/CheckInPopUp.dart @@ -44,269 +44,250 @@ class _CheckInPopUpState extends BaseStatefulState { 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, + return 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), ), - const SizedBox( - height: 8, - ), - Container( - margin: const EdgeInsets.all(12), - child: Column( - crossAxisAlignment: CrossAxisAlignment.end, + ), + ), + 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: 'Enter Cash in amount'), + AppSpaces.verticalLarge, + Row( + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.max, 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), - ), - ], + 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.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( + 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: [ - Expanded( - child: Column( - mainAxisAlignment: - MainAxisAlignment - .center, - children: [ - Text( - counters[i] - .counterCode, - style: TextStyle( - fontSize: MyFonts - .mediumText, - fontFamily: - MyFonts - .Bold, - color: !counters[ - i] - .isAvailable + Text( + counters[i].counterCode, + style: TextStyle( + fontSize: MyFonts + .mediumText, + fontFamily: + MyFonts.Bold, + color: !counters[i] + .isAvailable + ? MyColors.white + : viewModel.selectedItem == + i ? 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 + .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 - : viewModel.selectedItem == - i - ? MyColors - .white - : MyColors - .textColorBlack), - ), - ], - )) + : 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(); - } - }, - ), - ), - ], + )) + ], + ), + )); + }); + } else { + return AppLoader(); + } + }), + const SizedBox( + height: 8, ), - ) - ], - ), - ), - ); - }), - )), - onWillPop: () { - viewModel.dispose(); - return Future.value(false); - }); + 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() { diff --git a/lib/application/views/authModule/loginViews/LoginVC.dart b/lib/application/views/authModule/loginViews/LoginVC.dart index 3a0290b..a12eec1 100644 --- a/lib/application/views/authModule/loginViews/LoginVC.dart +++ b/lib/application/views/authModule/loginViews/LoginVC.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:wosull/application/localdb/SharedPrefs.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/views/authModule/loginViews/AlreadyLoggedView.dart'; import 'package:wosull/application/views/authModule/loginViews/CheckInPopUp.dart'; @@ -8,6 +9,7 @@ import 'package:wosull/application/views/authModule/registerViews/RegisterVC.dar 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'; @@ -16,6 +18,8 @@ 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,167 @@ 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, - ), - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, + viewModel = context.watch(); + return Directionality( + textDirection: TextDirection.ltr, + 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: [ + AppSpaces.verticalLarge, + Image.asset(ThemeImage.logo, height: 80), + AppSpaces.verticalLarge, + AppSpaces.verticalLarge, + Row( + mainAxisAlignment: MainAxisAlignment.end, 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( + height: 48, + width: 100, + padding: const EdgeInsets.all(8), + margin: const EdgeInsets.only(right: 16), + decoration: const BoxDecoration( + color: MyColors.white, + borderRadius: BorderRadius.all(Radius.circular(4)), + ), + 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: [ - 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, - children: [ - buildCheckBox(context, viewModel), - CustomTextButtonUnderLine( - onPressed: () {}, - heading: AppLocalizations.of(context)! - .forgot_password, - ) - ], - ), - 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) + buildCheckBox(context, viewModel), + CustomTextButtonUnderLine( + onPressed: () {}, + heading: AppLocalizations.of(context)! + .forgot_password, + ) ], ), - ), + 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 */, - ), - ), - ))), - onWillPop: () { - viewModel.dispose(); - return Future.value(false); + ), + ), + ], + ) /* add child content here */, + ), + ), + )); + } + + Widget getLangDropdown() { + return LanguageDropdown( + dropdownValue: viewModel.dropdownValue, + onChange: (language) { + viewModel.dropdownValue = language!; + viewModel.setLanguage(context, language); }); } @@ -181,6 +211,9 @@ class _LoginVCState extends State { } Future toHome() async { + if (viewModel.rememberValue) { + viewModel.setRememberedValues(); + } viewModel.disposeData(); push(); } @@ -221,7 +254,6 @@ class _LoginVCState extends State { } void checkState() { - print(viewModel.dataState); if (viewModel.dataState == LoginState.showAccessAccount) { showAccessPop(); } else if (viewModel.dataState == LoginState.showCounters) { @@ -233,7 +265,6 @@ class _LoginVCState extends State { } Future showAccessPop() async { - print(viewModel.accessMessage); final result = await showDialog( barrierColor: Colors.black26, context: context, @@ -248,7 +279,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/CheckInViewModel.dart b/lib/application/views/authModule/viewModel/CheckInViewModel.dart index 18bb390..353bcf4 100644 --- a/lib/application/views/authModule/viewModel/CheckInViewModel.dart +++ b/lib/application/views/authModule/viewModel/CheckInViewModel.dart @@ -1,5 +1,3 @@ -import 'dart:convert'; - import 'package:flutter/material.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; import 'package:wosull/application/model/SimpleResponsModel.dart'; @@ -16,7 +14,7 @@ class CheckInViewModel with ChangeNotifier { bool get isLoading => _isLoading; - bool _isGettingData = true; + bool _isGettingData = false; bool get isGettingData => _isGettingData; @@ -31,10 +29,10 @@ class CheckInViewModel with ChangeNotifier { 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; @@ -99,6 +97,18 @@ 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(); + } + Future getCounterById() async { await APIManager() .getResponseAuth( @@ -107,10 +117,9 @@ class CheckInViewModel with ChangeNotifier { final response = BillingCounterById.fromJson(value); if (response.success) { actualBalanceInHand = response.billingCounter.availableCash; - print(actualBalanceInHand); balanceInHand = actualBalanceInHand.toStringAsFixed(2); await getStoreAccounts(); - notifyListeners(); + // notifyListeners(); } }).onError((error, stackTrace) { setLoadingData(false); @@ -126,7 +135,6 @@ class CheckInViewModel with ChangeNotifier { actualAvailableCash = response.storeAccounts .singleWhere((element) => element.accountType == 'INCOME') .initialBalance; - print(actualAvailableCash); availableCash = actualAvailableCash.toStringAsFixed(2); inComeAccountId = response.storeAccounts @@ -215,7 +223,6 @@ 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 { @@ -233,7 +240,6 @@ 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 { @@ -245,9 +251,9 @@ class CheckInViewModel with ChangeNotifier { Utils.showMessage(response.message); _crudOperationState = CRUDOperationState.error; } + // setLoading(false); }).onError((error, stackTrace) { - print(error.toString()); setLoading(false); }); } diff --git a/lib/application/views/authModule/viewModel/LoginViewModel.dart b/lib/application/views/authModule/viewModel/LoginViewModel.dart index bec8f43..b69a9d0 100644 --- a/lib/application/views/authModule/viewModel/LoginViewModel.dart +++ b/lib/application/views/authModule/viewModel/LoginViewModel.dart @@ -1,6 +1,10 @@ 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/auth/AccessTokenModel.dart'; import 'package:wosull/application/model/store/StoreResponse.dart'; import 'package:wosull/application/model/store/StoreServiceResponse.dart'; import 'package:wosull/application/network/APIManager.dart'; @@ -10,6 +14,8 @@ import 'package:wosull/helpers/Utils.dart'; import 'package:wosull/main.dart'; class LoginViewModel with ChangeNotifier { + AppLanguage dropdownValue = AppLanguage.languages().first; + var password = ''; var name = sharedPrefs.storeEmail; @@ -31,12 +37,35 @@ 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); + } + bool isValidate() { if (name.isEmpty) { Utils.showMessage('Enter your email'); @@ -66,7 +95,6 @@ class LoginViewModel with ChangeNotifier { void setLoading(bool value) { _isLoading = value; - print('called'); notifyListeners(); } @@ -130,22 +158,43 @@ class LoginViewModel with ChangeNotifier { 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}") + .getResponseAuth('${Constants.getAccessToken}/${sharedPrefs.storeId}') + .then((value) async { + final response = AccessTokenModel.fromJson(value); + if (response.success!) { + sharedPrefs.token = response.access!.accessToken ?? ''; + _dataState = LoginState.showAccessAccount; + setLoading(false); + } + }).onError((error, stackTrace) async { + print(stackTrace.toString()); + _dataState = LoginState.error; + setLoading(false); + }); + } + + Future createAccessToken(String token) async { + setLoading(true); + Map data = { + 'token': token, + }; + await APIManager() + .fetchData(Constants.CREATE_ACCESS_TOKEN, data) .then((value) async { final response = SimpleResponseModel.fromJson(value); await checkResponse(response); setLoading(false); }).onError((error, stackTrace) async { print(stackTrace.toString()); - _dataState = LoginState.showCounters; - notifyListeners(); + _dataState = LoginState.error; + setLoading(false); }); } @@ -154,16 +203,15 @@ class LoginViewModel with ChangeNotifier { sharedPrefs.storeid = result.store.id; sharedPrefs.currency = result.currency; sharedPrefs.token = result.token; + print(sharedPrefs.token); } 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/billingCounterDashboard/BillingCounterDashBoard.dart b/lib/application/views/billingCounterDashboard/BillingCounterDashBoard.dart new file mode 100644 index 0000000..654553f --- /dev/null +++ b/lib/application/views/billingCounterDashboard/BillingCounterDashBoard.dart @@ -0,0 +1,155 @@ +import 'package:dropdown_search/dropdown_search.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:wosull/application/model/billingCounter/CounterDashboard.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'; + +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: [ + const 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: [ + const Text( + 'Billing Counter Dashboard', + style: ThemeText.textStylePageHeading, + ), + AppSpaces.horizontalSmall, + Expanded( + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + SizedBox( + width: 120, + child: getCounterTypeDropdown(), + ), + AppSpaces.horizontalSmall, + SizedBox( + width: 120, + child: getStartDateButton(), + ), + AppSpaces.horizontalSmall, + SizedBox( + width: 120, + child: getEndDateButton(), + ), + ], + )) + ], + ), + AppSpaces.verticalLarge, + viewModel.isLoading + ? AppLoader() + : showList(viewModel.filteredList) + ], + ), + ), + ); + })); + } + + Widget showList(List counters) { + return BillingCounterGrid(isPortrait: isPortrait, data: counters); + } + + Widget getCounterTypeDropdown() { + return DropdownSearch( + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + selectedItem: Constants.counterTypes.first, + popupProps: + const PopupProps.menu(constraints: 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..ff1ceff --- /dev/null +++ b/lib/application/views/billingCounterDashboard/BillingCounterMainVC.dart @@ -0,0 +1,116 @@ +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/billingCounterDashboard/BillingCounterDashBoard.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, + ), + 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, + ), + 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: 'Billing Counter Dashboard', + ), + ], + ) + ], + ), + ), + const Expanded( + child: TabBarView( + children: [BillingCounterDashBoard()], + )) + ], + ), + ), + ); + } +} diff --git a/lib/application/views/billingCounterDashboard/viewModels/BillingCounterViewModel.dart b/lib/application/views/billingCounterDashboard/viewModels/BillingCounterViewModel.dart new file mode 100644 index 0000000..4927efa --- /dev/null +++ b/lib/application/views/billingCounterDashboard/viewModels/BillingCounterViewModel.dart @@ -0,0 +1,103 @@ +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/BillingCounterDashboard.dart'; +import 'package:wosull/application/model/billingCounter/CounterDashboard.dart'; +import 'package:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/utils/Constants.dart'; + +class BillingCounterViewModel with ChangeNotifier { + String startDate = ""; + String endDate = ""; + + var _isLoading = true; + + bool get isLoading => _isLoading; + + //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 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; + } + 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 APIManager() + .getResponseAuth(Constants.billingDashboardData, data) + .then((value) { + final response = BillingCounterDashboard.fromJson(value); + 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) { + print(stackTrace.toString()); + _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..f992de5 --- /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, + const 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, + const 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, + const 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/create_order_module/CartVC.dart b/lib/application/views/create_order_module/CartVC.dart index 5fd3a55..8116eca 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/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'; @@ -22,10 +24,13 @@ 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'; class CartVC extends StatefulWidget { - CartVC({ + final DrawerWidgetSelect delegateDrawer; + const CartVC({ Key? key, + required this.delegateDrawer, }) : super(key: key); @override @@ -40,7 +45,6 @@ class _CartVCState extends BaseStatefulState { @override void initState() { super.initState(); - //openDB(); } @override @@ -56,7 +60,7 @@ class _CartVCState extends BaseStatefulState { Visibility( visible: count() || CreateAndUpdateOrder - .cartOrder.selectedTableName!.isNotEmpty, + .cartOrder.selectedTableName.isNotEmpty, child: Column( children: [ const SizedBox( @@ -143,7 +147,7 @@ class _CartVCState 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: const TextStyle( fontWeight: FontWeight.bold, fontSize: MyFonts.normal, @@ -157,14 +161,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 +262,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 +273,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: () { @@ -313,12 +331,12 @@ class _CartVCState extends BaseStatefulState { Future increaseItem(StoreItems storeItem) async { if (storeItem.isCombo) { addComboPopup(storeItem, false); - } else if (storeItem.modifiers!.isNotEmpty) { + } else if (storeItem.modifiers.isNotEmpty) { 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 +398,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 +424,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 +454,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..b8511da 100644 --- a/lib/application/views/create_order_module/HoldOrderVC.dart +++ b/lib/application/views/create_order_module/HoldOrderVC.dart @@ -1,20 +1,18 @@ -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: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'; class HoldOrderVC extends StatefulWidget { final DrawerWidgetSelect delegateDrawer; @@ -26,37 +24,31 @@ class HoldOrderVC extends StatefulWidget { } 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)), - ], - )), - ), + return Scaffold( + 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,194 +56,20 @@ 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, ); @@ -265,166 +83,118 @@ class _HoldOrderVCState extends BaseStatefulState { ); } } 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 Align( + alignment: Alignment.center, + child: Image.asset( + ThemeImage.emptyImage, + height: 128, + ), + ); + } + } 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/viewModels/CartViewModel.dart b/lib/application/views/create_order_module/viewModels/CartViewModel.dart index ff0bc78..41fcb7a 100644 --- a/lib/application/views/create_order_module/viewModels/CartViewModel.dart +++ b/lib/application/views/create_order_module/viewModels/CartViewModel.dart @@ -12,6 +12,7 @@ import 'package:wosull/application/model/Modifiers/GetModifiersModel.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; } @@ -73,10 +76,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 +95,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 +102,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 +124,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 +134,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 +145,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 +155,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 +165,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 +202,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 +293,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 +313,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 +327,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 +345,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 +358,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 +369,134 @@ 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/CreateOrderViewModel.dart b/lib/application/views/create_order_module/viewModels/CreateOrderViewModel.dart index abd473d..932b08d 100644 --- a/lib/application/views/create_order_module/viewModels/CreateOrderViewModel.dart +++ b/lib/application/views/create_order_module/viewModels/CreateOrderViewModel.dart @@ -48,9 +48,9 @@ class CreateOrderViewModel with ChangeNotifier { var subCategoryItems = []; late ItemSubCategory itemSubCategory; - final searchController = TextEditingController(); + var searchController = ''; - bool isInternetConnected = false; + //bool isConnected = false; late var selectedTable = StoreTable(); String tableName = ''; @@ -58,7 +58,7 @@ class CreateOrderViewModel with ChangeNotifier { //Store store = Store(name: ""); int categoryPosition = 0; int selectedSubCategoryPosition = 0; - int selectedService = 1; + int selectedService = 0; String selectedDeliveryPartner = ''; String selectedProductId = ""; @@ -80,6 +80,7 @@ class CreateOrderViewModel with ChangeNotifier { OrderModel get completedOrder => _newOrder; void disposeData() { + searchController = ''; categoryPosition = 0; itemCategories.clear(); filteredItems.clear(); @@ -133,11 +134,10 @@ class CreateOrderViewModel with ChangeNotifier { } void fetchData() async { - getSelectedService(); - await APIManager() .fetchData(Constants.GET_STORE_CATEGORY_LIST, getCategoryParam()) .then((value) { + getSelectedService(); final response = ItemCategoryResponse.fromJson(value); if (response.success && response.categories.isNotEmpty) { itemCategories.clear(); @@ -165,7 +165,14 @@ class CreateOrderViewModel with ChangeNotifier { 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,30 +186,30 @@ class CreateOrderViewModel with ChangeNotifier { Future getItems(String categoryID, String selectedProductId, bool loader, int subCategoryPosition, {String deliveryPartnerId = ''}) async { + 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 { @@ -237,13 +244,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, @@ -277,26 +312,32 @@ 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 { + if (!isConnected) { 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(); + searchedItems.addAll(objectbox.searchItems(searchValue)); + notifyListeners(); + } else { + Map data = { + 'store_id': sharedPrefs.storeId, + 'search_value': searchValue, + 'page': 1 + }; + await APIManager() + .fetchData(Constants.SEARCH_ALL_ITEMS, data) + .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(); + } } } - } - }).onError((error, stackTrace) {}); + }).onError((error, stackTrace) {}); + } } Future searchCombo(String searchValue) async { @@ -325,7 +366,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, @@ -373,19 +414,20 @@ class CreateOrderViewModel with ChangeNotifier { } void updateOrderStatus(String id, String status) async { - // Utils.progressDialogue(context); Map data = {}; data = { 'store_id': sharedPrefs.storeId, 'order_id': id, 'status': status, }; + + print(jsonEncode(data)); await APIManager() .fetchData(Constants.UPDATE_ORDER_STATUS, data) .then((value) { final response = SimpleResponseModel.fromJson(value); if (response.success) { - if (status == "cancelled") { + if (status == Constants.cancelled) { isCartShow = false; _cashierState = CashierState.cancelled; } else { @@ -400,15 +442,14 @@ class CreateOrderViewModel with ChangeNotifier { } 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; @@ -505,8 +546,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 +566,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,30 +622,39 @@ class CreateOrderViewModel with ChangeNotifier { int? timer, double? amount, double? totalAmount, - String? orderId]) async { + 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, + // 'orderId': orderId, 'order_type': services[selectedService].name!, '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 { data = { + 'payment_mode': paymentMode, + 'total_discount': totalDiscount, + 'discountId': discountId, + 'billing_counter_id': sharedPrefs.billingCounterId, '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, @@ -604,6 +664,7 @@ class CreateOrderViewModel with ChangeNotifier { } } else { data = { + 'billing_counter_id': sharedPrefs.billingCounterId, 'store_id': sharedPrefs.storeId, 'cart_id': sharedPrefs.cartID, 'order_type': services[selectedService].name!, @@ -612,7 +673,6 @@ class CreateOrderViewModel with ChangeNotifier { // 'orderId': CreateAndUpdateOrder.cartOrder.orderId!, }; } - await APIManager() .fetchData(Constants.CREATE_ORDER, data) .then((value) async { @@ -642,10 +702,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) { @@ -727,7 +784,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 +817,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 +836,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(); @@ -795,11 +852,13 @@ class CreateOrderViewModel with ChangeNotifier { newOrder.status! == Constants.ready) { _newOrder = newOrder; _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 isCartShow = true; CreateAndUpdateOrder.cartOrder.clearCart(); @@ -816,14 +875,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 +895,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 +929,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 +944,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 +976,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 +1021,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 +1054,77 @@ 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(); + } } 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..c98bf47 --- /dev/null +++ b/lib/application/views/create_order_module/viewModels/PaymentOptionViewModel.dart @@ -0,0 +1,228 @@ +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/network/APIManager.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; + + void disposeData() { + enable = false; + isCash = true; + isCard = false; + isCredit = false; + discountId = ''; + cashAmountController = ''; + balanceOrChangeController = ''; + discountAmountController = ''; + deliveryNoteController = ''; + } + + void setAmountValue(double cartAmount) { + subTotalAmount = cartAmount; + totalAmount = cartAmount; + } + + 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(String? data) { + if (data == null) { + selectedPaymentMethod = ''; + } else { + selectedPaymentMethod = data; + } + } +} 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..8c7bb0c 100644 --- a/lib/application/views/create_order_module/views/PrintInvoiceVC.dart +++ b/lib/application/views/create_order_module/views/PrintInvoiceVC.dart @@ -7,6 +7,7 @@ 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/widgets/CustomSimpleButton.dart'; @@ -65,8 +66,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: 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..3a70775 --- /dev/null +++ b/lib/application/views/create_order_module/views/PrintReceiptVC.dart @@ -0,0 +1,705 @@ +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/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, + 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(16), + 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(), + 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.logo), + 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: [ + Text( + 'Billed by: ${sharedPrefs.billingCounterName}', + style: ThemeText.textStyleMediumDJMono, + ), + Text( + '${viewModel.itemQuantity} Items : (${viewModel.allItemsQuantity} Qty)', + 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.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(), + 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.logo), + 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.uniqueId!.toString()}', + style: ThemeText.textStyleBOLDDJMono, + ), + Text( + 'Date : ${DataTimeFormat.getFormatDate(order.createdAt ?? '')}', + style: ThemeText.textStyleMediumDJMono, + ), + ], + ), + AppSpaces.verticalMedium, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Billed by: ${sharedPrefs.billingCounterName}', + style: ThemeText.textStyleMediumDJMono, + ), + Text( + '${viewModel.itemQuantity} Items : (${viewModel.allItemsQuantity} Qty)', + 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, + 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), + 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)}', + 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( + 'شكراً لزيارتكم وعشمنا منكم وفيكم', + 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() { + return Container( + margin: + EdgeInsets.fromLTRB(isPortrait ? 8 : 80, 0, isPortrait ? 8 : 80, 0), + child: Row( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + SizedBox( + width: 110, + child: CustomIconButton( + textColor: MyColors.white, + backgroundColor: MyColors.blueThemeColor, + onPressed: () {}, + icon: Icons.print, + heading: AppLocalizations.of(context)!.print_now, + ), + ), + AppSpaces.horizontalSmall, + SizedBox( + width: 140, + child: CustomIconButton( + textColor: MyColors.white, + backgroundColor: MyColors.blueThemeColor, + onPressed: () { + captureImage(); + }, + heading: AppLocalizations.of(context)!.download, + icon: Icons.download, + ), + ), + AppSpaces.horizontalSmall, + SizedBox( + width: 90, + child: 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, + ), + ), + ], + ), + ); + } + + 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, + ); + } + +// 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..ba93b72 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,12 @@ 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/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 +64,91 @@ class _TabBarHomeVCState extends BaseStatefulState { @override void initState() { - viewModel.getStoreDetails(); + context.read().getStoreDetails(); 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(), + ], + ), + ), + ); + }), + ))); + + // return WillPopScope( + // child: , + // onWillPop: () { + // viewModel.dispose(); + // return Future.value(false); + // }); } Widget getCategoryWidget() { - if (viewModel.isInternetConnected) { + if (isConnected) { return tabCategory(); } else { - print('aaaaaofflie'); return StreamBuilder>( stream: objectbox.getCategories(), builder: (context, snapshot) { @@ -182,13 +175,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 +196,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 +212,6 @@ class _TabBarHomeVCState extends BaseStatefulState { .subCategoryItems[viewModel.selectedSubCategoryPosition].id; return subItemList(viewModel.subCategoryItems); } else { - print('no data'); return const EmptyDataWidget(); } } else { @@ -233,7 +220,9 @@ class _TabBarHomeVCState extends BaseStatefulState { }, ); } else { - return Center(child: Container()); + return AppError( + error: 'No Sub-Category found for this Category', + ); } } @@ -243,11 +232,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 +256,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 +300,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,9 +322,11 @@ 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) {} } @@ -411,8 +415,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 +427,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 +456,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 +470,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, @@ -567,7 +559,7 @@ class _TabBarHomeVCState extends BaseStatefulState { children: [ SizedBox( height: viewModel.height - 155, - child: viewModel.isInternetConnected + child: isConnected ? getHoldItem(context) : getDbHoldItem(context), ) @@ -600,7 +592,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 +617,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 +670,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 +738,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 +759,7 @@ class _TabBarHomeVCState extends BaseStatefulState { ); if (result != null) { + await viewModel.checkLastSelectedService(); viewModel.setDineTable(result); } } @@ -776,9 +767,10 @@ 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); }); @@ -824,9 +816,7 @@ class _TabBarHomeVCState extends BaseStatefulState { getCartHoldBuilder(), ], )), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisSize: MainAxisSize.max, @@ -854,7 +844,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 +853,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 +919,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 +941,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 +973,7 @@ class _TabBarHomeVCState extends BaseStatefulState { Future addItem(StoreItems storeItem) async { if (storeItem.isCombo) { addComboPopup(storeItem, true); - } else if (storeItem.modifiers!.isNotEmpty) { + } else if (storeItem.modifiers.isNotEmpty) { showModifiers(storeItem, true); } else { showProgress(); @@ -979,12 +985,14 @@ class _TabBarHomeVCState extends BaseStatefulState { Future increaseItem(StoreItems storeItem) async { if (storeItem.isCombo) { addComboPopup(storeItem, false); - } else if (storeItem.modifiers!.isNotEmpty) { + } else if (storeItem.modifiers.isNotEmpty) { 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,7 +1014,7 @@ class _TabBarHomeVCState extends BaseStatefulState { Utils.progressDialogue(context); } - void _serviceTap(int i) { + Future _serviceTap(int i) async { if (viewModel.services[i].name .toString() .replaceAll(' ', '') @@ -1020,6 +1028,8 @@ class _TabBarHomeVCState extends BaseStatefulState { '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..e50d6d6 100644 --- a/lib/application/views/create_order_module/views/popups/CashOutVC.dart +++ b/lib/application/views/create_order_module/views/popups/CashOutVC.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(15.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..9ff16e7 --- /dev/null +++ b/lib/application/views/create_order_module/views/popups/CounterCloseVC.dart @@ -0,0 +1,88 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/theme/MyColors.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; + + @override + Widget build(BuildContext context) { + return 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 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( + children: [ + const CustomOptionalTitle(hint: 'Credit'), + AppSpaces.verticalSmall, + CustomTextFieldForm( + keyboardType: TextInputType.number, + onChanged: (value) {}, + hintText: '0.0'), + AppSpaces.verticalMedium, + const CustomOptionalTitle(hint: 'Cash'), + AppSpaces.verticalSmall, + CustomTextFieldForm( + keyboardType: TextInputType.number, + onChanged: (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, + onPressed: () async {}, + heading: 'Close', + ), + ), + ], + ), + ) + ], + ), + ), + ); + }), + )); + } +} 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..256d22b 100644 --- a/lib/application/views/create_order_module/views/popups/DeliveryPartnerPopUp.dart +++ b/lib/application/views/create_order_module/views/popups/DeliveryPartnerPopUp.dart @@ -106,17 +106,23 @@ 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); + print(viewModel.selectedType); return RadioGroup.builder( direction: Axis.vertical, horizontalAlignment: MainAxisAlignment.start, @@ -136,7 +142,6 @@ class _DeliveryPartnerPopUpState extends State { } 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..adba0a2 100644 --- a/lib/application/views/create_order_module/views/popups/DineInPopup.dart +++ b/lib/application/views/create_order_module/views/popups/DineInPopup.dart @@ -319,6 +319,8 @@ class _DineInPopupState extends State { for (var item in storeTables) { tablesSeats.add(item.noOfOccupants.toString()); } + + tablesSeats = tablesSeats.toSet().toList(); } tables.addAll(storeTables); filteredTables.addAll(storeTables); 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..b3dc9eb 100644 --- a/lib/application/views/create_order_module/views/popups/ItemModifiersPopUp.dart +++ b/lib/application/views/create_order_module/views/popups/ItemModifiersPopUp.dart @@ -8,6 +8,8 @@ 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/helpers/AppSpaces.dart'; +import 'package:wosull/widgets/CustomTextFieldForm.dart'; +import 'package:wosull/widgets/DialogHeader.dart'; class ItemModifiersPopUp extends StatefulWidget { late StoreItems item; @@ -24,7 +26,7 @@ class _ItemModifiersPopUpState extends State { List selectedModifier = []; List? selectedOption = []; - final noteController = TextEditingController(); + var noteController = ''; @override void initState() { @@ -69,39 +71,8 @@ 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( @@ -117,31 +88,11 @@ class _ItemModifiersPopUpState extends State { 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) { + noteController = value; + }, ), AppSpaces.verticalMedium, ListView.builder( @@ -422,7 +373,7 @@ class _ItemModifiersPopUpState extends State { onPressed: () { var result = [ selectedModifier, - noteController.text + noteController ]; Navigator.pop(context, result); }, 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..d91f6cd 100644 --- a/lib/application/views/create_order_module/views/popups/LogoutVC.dart +++ b/lib/application/views/create_order_module/views/popups/LogoutVC.dart @@ -23,6 +23,7 @@ class _LogoutVCState extends State { @override void initState() { + context.read().getCounterById(); super.initState(); } @@ -35,9 +36,9 @@ class _LogoutVCState extends State { @override Widget build(BuildContext context) { viewModel = context.watch(); - if (viewModel.isGettingData) { - viewModel.getCounterById(); - } + // if (viewModel.isGettingData) { + // viewModel.getCounterById(); + // } return Directionality( textDirection: TextDirection.ltr, child: Dialog( @@ -128,9 +129,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..bb34df9 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,24 @@ 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/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/MandatoryTitleText.dart'; class PaymentOptionPopUpVC extends StatefulWidget { double cartAmount = 0.0; @@ -32,32 +38,25 @@ 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() { + // TODO: implement dispose + viewModel.disposeData(); + super.dispose(); } @override Widget build(BuildContext context) { + viewModel = context.watch(); return Directionality( textDirection: TextDirection.ltr, child: Dialog( @@ -67,11 +66,11 @@ class _PaymentOptionPopUpVCState borderRadius: BorderRadius.circular(15.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 @@ -168,11 +143,7 @@ class _PaymentOptionPopUpVCState ), ), onTap: () { - setState(() { - isCash = true; - isCard = false; - isCredit = false; - }); + viewModel.setCashView(); }, )), Expanded( @@ -184,10 +155,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 @@ -209,10 +180,9 @@ class _PaymentOptionPopUpVCState const SizedBox( width: 2, ), - Text( - AppLocalizations.of(context)! - .card_machine, - style: const TextStyle( + const Text( + 'Credit Card', + style: TextStyle( fontSize: 10, color: MyColors.black, fontFamily: MyFonts.Medium), @@ -221,11 +191,7 @@ class _PaymentOptionPopUpVCState ), ), onTap: () { - setState(() { - isCash = false; - isCard = true; - isCredit = false; - }); + viewModel.setCreditCardView(); }, )), // Expanded( @@ -305,10 +271,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 @@ -345,11 +311,7 @@ class _PaymentOptionPopUpVCState ), ), onTap: () { - setState(() { - isCash = true; - isCard = false; - isCredit = false; - }); + viewModel.setCashView(); }, ), ), @@ -364,10 +326,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 @@ -390,8 +352,7 @@ class _PaymentOptionPopUpVCState width: 8, ), Text( - AppLocalizations.of(context)! - .card_machine, + 'Credit Card', style: const TextStyle( fontSize: MyFonts.H2, color: MyColors.black, @@ -402,11 +363,7 @@ class _PaymentOptionPopUpVCState ), ), onTap: () { - setState(() { - isCash = false; - isCard = true; - isCredit = false; - }); + viewModel.setCreditCardView(); }, ), ), @@ -489,170 +446,9 @@ 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), @@ -661,210 +457,51 @@ class _PaymentOptionPopUpVCState 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, + const Text( + 'Credit Card', + 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,7 +511,7 @@ class _PaymentOptionPopUpVCState Widget card() { return Visibility( - visible: isCash, + visible: viewModel.isCash, child: Card( child: Container( padding: const EdgeInsets.all(MyFonts.normal), @@ -885,60 +522,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 +548,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(), ], ), @@ -1025,131 +578,28 @@ 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'), - ), - ), - ), - ), - ), - ); - } 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) { - 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()); - }); + return SizedBox( + height: 48, + child: DiscountDropdown( + onChanged: (data) { + if (isConnected) { + viewModel.applyDiscount(sharedPrefs.cartID, data); + } else { + viewModel.calculateDiscount(data); + } + }, + 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 +611,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), - ), - const SizedBox( - height: 4, + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.discount_code, ), + AppSpaces.verticalSmall, getDiscounts(context), ], )), - 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 +659,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 +683,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 +707,267 @@ 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 - ]; + 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); Navigator.pop(context, 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 == "ready" + ? AppLocalizations.of(context)!.done + : AppLocalizations.of(context)!.send_to_kitchen, + ), + viewModel.isCash && widget.status != Constants.ready + ? AppSpaces.verticalMedium + : Container(), + viewModel.isCash && 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); + Navigator.pop(context, result); + }, + heading: AppLocalizations.of(context)!.completed, + ) + : Container(), ], ); } + Widget paymentMethod() { + return DropdownSearch( + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: const PopupProps.menu( + fit: FlexFit.loose, constraints: BoxConstraints(maxHeight: 250)), + items: Constants.paymentMethodForOrders, + itemAsString: (String u) => u, + onChanged: (String? 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), - ), - ), - ); - } - - 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), - ), - ), + return CustomTextFieldForm( + key: Key(viewModel.balanceOrChangeController), + hintText: 'Balance or Change', + initialValue: viewModel.balanceOrChangeController, + readOnly: true, + onChanged: (String value) {}, ); } 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), - ), - ), + return CustomTextFieldForm( + onChanged: (String value) { + viewModel.deliveryNoteController = value; + }, + hintText: 'Enter Delivery Note', ); } 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, - ), - borderRadius: BorderRadius.circular(8.0), - ), - ), + return CustomTextFieldForm( + initialValue: viewModel.totalAmount.toStringAsFixed(2), + readOnly: true, + hintText: 'Enter Card number', + onChanged: (String value) {}, ); } - 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"; - } - }); + Widget credit() { + return Visibility( + visible: viewModel.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), + ), + AppSpaces.verticalMedium, + 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), + ), + ), + ), + ), + ], + )) + ], + ), + 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: const TextStyle( + fontSize: MyFonts.bold, + color: MyColors.white, + fontFamily: MyFonts.Bold), + ), + ) + ], + ), + ), + )); } } 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..6de3d24 100644 --- a/lib/application/views/create_order_module/views/popups/RegisterCashVC.dart +++ b/lib/application/views/create_order_module/views/popups/RegisterCashVC.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(15.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/widgets/CartItemView.dart b/lib/application/views/create_order_module/widgets/CartItemView.dart index 1c95577..53a8844 100644 --- a/lib/application/views/create_order_module/widgets/CartItemView.dart +++ b/lib/application/views/create_order_module/widgets/CartItemView.dart @@ -46,8 +46,8 @@ 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( @@ -65,7 +65,7 @@ class CartItemView extends StatelessWidget { child: Align( alignment: Alignment.centerLeft, child: Text( - storeItems.name!, + storeItems.name, style: ThemeText.textStyleNormalMedium, ), )), @@ -235,7 +235,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..cef3f9b 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,40 @@ 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: Center( + 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 +146,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 +156,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 +173,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), diff --git a/lib/application/views/dashboard/HomeVC.dart b/lib/application/views/dashboard/HomeVC.dart index 158c2de..a242f33 100644 --- a/lib/application/views/dashboard/HomeVC.dart +++ b/lib/application/views/dashboard/HomeVC.dart @@ -8,8 +8,6 @@ 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/utils/AppLoader.dart'; import 'package:wosull/application/views/dashboard/viewModel/DashboardViewModel.dart'; import 'package:wosull/application/views/dashboard/widgets/AnimatedProgressBar.dart'; import 'package:wosull/application/views/dashboard/widgets/InvoiceDetailsView.dart'; @@ -29,6 +27,7 @@ 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 +44,365 @@ class _HomeVCState extends BaseStatefulState implements ReportsCVS { @override void initState() { + // WidgetsBinding.instance.addPostFrameCallback((timeStamp) { + // Provider.of(context, listen: false).getService(); + // }); + context.read().getService(false); super.initState(); } + @override + void dispose() { + viewModel.disposeData(); + super.dispose(); + } + @override void didChangeDependencies() {} @override Widget build(BuildContext context) { viewModel = context.watch(); - + // viewModel.getService(); + // viewModel = Provider.of(context); 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 + ? const Center( + child: CircularProgressIndicator(), + ) + : 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")), + ], + ), + const SizedBox(height: 8), + 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")), + ], + ), + const SizedBox(height: 8), + Row( + children: [ + Flexible( + child: AnimatedProgressBar( + heading: + AppLocalizations.of( + context)! .total_branches, - value: viewModel - .adminData - .totalBranches - ?.toStringAsFixed( - 2) ?? - "0")), - ], - ), - //upper part - - AppSpaces.verticalMedium, - TodaySaleGraph(), - AppSpaces.verticalMedium, - TodayPOSSales(), - AppSpaces.verticalMedium, - RevenueGraph( - data: viewModel.graphData - .totalIncomeExpense ?? - []), - AppSpaces.verticalMedium, - InvoiceStatusGraph( - 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), - ), - ], - ), - AppSpaces.verticalMedium, - Card( - shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.circular(12.0), + value: viewModel.adminData + .totalBranches + ?.toStringAsFixed( + 2) ?? + "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, - ) - ], - )), + ]) + : 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, + TodaySaleGraph( + todaySales: + viewModel.graphData.todaySales ?? [], + ), + AppSpaces.verticalMedium, + TodayPOSSales( + todaySales: + viewModel.graphData.todaySales ?? [], + ), + AppSpaces.verticalMedium, + RevenueGraph( + data: viewModel + .graphData.totalIncomeExpense ?? + []), + AppSpaces.verticalMedium, + InvoiceStatusGraph( + data: viewModel + .graphData.allInvoiceStatus ?? + []), + AppSpaces.verticalMedium, + POSStatusGraph( + data: viewModel.graphData.allPosStatus ?? + []), + AppSpaces.verticalMedium, + POSOrderCountDayWiseGraph( + data: viewModel + .graphData.posOrderCountDayWise ?? + [], + ), + AppSpaces.verticalMedium, + POSOrderValueDayWise( + data: viewModel.graphData.array ?? []), + AppSpaces.verticalMedium, + POSOrderCountTimeWiseGraph( + data: viewModel.graphData + .posOrderCountTodayTimewise ?? + [], + ), + AppSpaces.verticalMedium, + 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 +423,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 +450,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/viewModel/DashboardViewModel.dart b/lib/application/views/dashboard/viewModel/DashboardViewModel.dart index de6c1b0..61af6f9 100644 --- a/lib/application/views/dashboard/viewModel/DashboardViewModel.dart +++ b/lib/application/views/dashboard/viewModel/DashboardViewModel.dart @@ -19,34 +19,47 @@ class DashBoardViewModel with ChangeNotifier { 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(); + 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; } @@ -61,7 +74,6 @@ class DashBoardViewModel with ChangeNotifier { .getResponseAuth(Constants.GET_ADMIN_DASHBOARD_DATA, data) .then((value) { graphData = GraphData.fromJson(value); - print('lenth' + graphData.totalIncomeExpense!.length.toString()); }).onError((error, stackTrace) { setLoading(false); }); 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/RevenueGraph.dart b/lib/application/views/dashboard/widgets/RevenueGraph.dart index 15704b4..66a6a9d 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: 2, + child: PieChart( + PieChartData( + pieTouchData: PieTouchData( + touchCallback: + (FlTouchEvent event, pieTouchResponse) {}, + ), + borderData: FlBorderData( + show: false, + ), + sectionsSpace: 0, + 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..2689fac 100644 --- a/lib/application/views/dashboard/widgets/TodayPOSSales.dart +++ b/lib/application/views/dashboard/widgets/TodayPOSSales.dart @@ -1,6 +1,9 @@ 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'; @@ -10,8 +13,8 @@ class TodayPOSSales extends StatelessWidget { MyColors.blueThemeColor, MyColors.blueThemeColor, ]; - - TodayPOSSales({super.key}); + List todaySales = []; + TodayPOSSales({super.key, required this.todaySales}); @override Widget build(BuildContext context) { @@ -45,9 +48,13 @@ class TodayPOSSales extends StatelessWidget { top: 24, bottom: 12, ), - child: LineChart( - mainData(), - ), + child: todaySales.isNotEmpty + ? LineChart( + mainData(), + ) + : AppError( + error: 'No Sales Available', + ), ), ), ], @@ -62,22 +69,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,58 +84,8 @@ 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( - gridData: FlGridData( - show: true, - drawVerticalLine: true, - horizontalInterval: 1, - verticalInterval: 1, - getDrawingHorizontalLine: (value) { - return const FlLine( - color: MyColors.black, - strokeWidth: 1, - ); - }, - getDrawingVerticalLine: (value) { - return const FlLine( - color: MyColors.black, - strokeWidth: 1, - ); - }, - ), titlesData: FlTitlesData( show: true, rightTitles: const AxisTitles( @@ -154,34 +102,10 @@ 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), - ], + spots: getSpots(), isCurved: true, gradient: LinearGradient( colors: gradientColors, @@ -189,7 +113,7 @@ class TodayPOSSales extends StatelessWidget { barWidth: 5, isStrokeCapRound: true, dotData: const FlDotData( - show: false, + show: true, ), belowBarData: BarAreaData( show: true, @@ -203,4 +127,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..c224421 100644 --- a/lib/application/views/dashboard/widgets/TodaySaleGraph.dart +++ b/lib/application/views/dashboard/widgets/TodaySaleGraph.dart @@ -1,6 +1,9 @@ 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'; @@ -10,8 +13,9 @@ class TodaySaleGraph extends StatelessWidget { MyColors.blueThemeColor, 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,15 @@ 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) { + print(value.toInt()); + text = Text( + DataTimeFormat.getTimeFormat( + todaySales[value.toInt()].id!.createdAt!), + style: style); + } else { + text = Text('', style: style); } return SideTitleWidget( @@ -86,58 +87,8 @@ 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( - gridData: FlGridData( - show: true, - drawVerticalLine: true, - horizontalInterval: 1, - verticalInterval: 1, - getDrawingHorizontalLine: (value) { - return const FlLine( - color: MyColors.black, - strokeWidth: 1, - ); - }, - getDrawingVerticalLine: (value) { - return const FlLine( - color: MyColors.black, - strokeWidth: 1, - ); - }, - ), titlesData: FlTitlesData( show: true, rightTitles: const AxisTitles( @@ -154,34 +105,10 @@ 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), - ], + spots: getSpots(), isCurved: true, gradient: LinearGradient( colors: gradientColors, @@ -189,7 +116,7 @@ class TodaySaleGraph extends StatelessWidget { barWidth: 5, isStrokeCapRound: true, dotData: const FlDotData( - show: false, + show: true, ), belowBarData: BarAreaData( show: true, @@ -203,4 +130,14 @@ 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/viewModels/DiscountViewModel.dart b/lib/application/views/discountModule/viewModels/DiscountViewModel.dart index 18bd395..f6af84c 100644 --- a/lib/application/views/discountModule/viewModels/DiscountViewModel.dart +++ b/lib/application/views/discountModule/viewModels/DiscountViewModel.dart @@ -1,20 +1,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/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'; - class DiscountViewModel with ChangeNotifier { int _currentPageNumber = 1; DataState _dataState = DataState.uninitialized; - + int limit = 10; bool _didLastLoad = false; bool _isLoading = false; @@ -28,7 +23,8 @@ class DiscountViewModel 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) @@ -43,6 +39,7 @@ class DiscountViewModel with ChangeNotifier { Map data = { 'store_id': sharedPrefs.storeId, 'page': _currentPageNumber, + 'limit': this.limit }; try { @@ -60,7 +57,7 @@ class DiscountViewModel with ChangeNotifier { if (value.success!) { _filteredList.addAll(value.storeDiscount!); _dataList.addAll(value.storeDiscount!); - if (value.storeDiscount!.length < 10) { + if (value.storeDiscount!.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; @@ -136,40 +133,14 @@ class DiscountViewModel with ChangeNotifier { await APIManager() .getResponsePatch(Constants.UPDATE_STORE_DISCOUNT_STATUS, data) .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..7cc7d30 --- /dev/null +++ b/lib/application/views/discountModule/viewModels/NewDiscountViewModel.dart @@ -0,0 +1,305 @@ +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/converters/DataTimeFormat.dart'; +import 'package:wosull/application/model/discount/StoreDiscountModel.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/GetItemsByStoreId.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 NewDiscountViewModel with ChangeNotifier { + var items = [ + 'Percentage', + 'Amount', + ]; + + String selectedDiscountType = "Percentage"; + late StoreDiscount storeDiscount; + + var _crudOperation = CRUDOperationState.uninitialized; + + CRUDOperationState get crudOperation => _crudOperation; + + final types = [ + "Manual", + "Automatic", + ]; + String typesGroupValue = "Manual"; + String verticalGroupValue = ""; + + bool isLoading = false; + bool isGettingItems = false; + bool isTablet = true; + bool isPortrait = true; + + List filteredItems = []; + List data = []; + + disposeData() { + isLoading = false; + isGettingItems = false; + selectedDiscountType = items[0]; + typesGroupValue = types[0]; + verticalGroupValue = Constants.discountFilters[0]; + 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 = []; + } + } + + 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) { + storeDiscount.discountStartDate = + DataTimeFormat.formatDateFromPicket(pickedDate); + } else { + storeDiscount.discountEndDate = + DataTimeFormat.formatDateFromPicket(pickedDate); + } + + notifyListeners(); + }); + } + + Future isValidate() async { + if (storeDiscount.name == null) { + Utils.showMessage('Enter Discount Code'); + } else if (selectedDiscountType == items[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': selectedDiscountType == 'Percentage' ? '2' : '1', + '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 ?? '' + }; + + print(jsonEncode(data)); + await APIManager() + .fetchData(Constants.ADD_STORE_DISCOUNT, data) + .then((value) { + final response = SimpleResponseModel.fromJson(value); + 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)) { + filteredItems.clear(); + data.clear(); + } else if (verticalGroupValue == Constants.discountFilters.elementAt(2)) { + final response = await APIManager().fetchData( + Constants.GET_STORE_CATEGORY_LIST, Constants.getStorePayload()); + final itemsResponse = ItemCategoryResponse.fromJson(response); + if (itemsResponse.success && itemsResponse.categories.isNotEmpty) { + filteredItems.clear(); + data.clear(); + filteredItems.addAll(itemsResponse.categories); + data.addAll(itemsResponse.categories); + } + } else { + final response = await APIManager().fetchData( + Constants.GET_STORE_CATEGORY_LIST_ID, Constants.getStorePayload()); + final getItemsByStoreId = GetItemsByStoreId.fromJson(response); + if (getItemsByStoreId.success! && + getItemsByStoreId.categories!.isNotEmpty) { + filteredItems.clear(); + data.clear(); + filteredItems.addAll(getItemsByStoreId.categories!); + data.addAll(getItemsByStoreId.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..ee47827 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,42 @@ 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, + newDiscountButton(), + Flexible( + child: 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, newDiscountButton(), + AppSpaces.horizontalSmall, + getSearchBar(), + Flexible( + child: 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 +98,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 +121,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( + storeDiscount: discount, + ); + }, + ); + }, + onEdit: (discount) { + toDiscount(true, discount); + }), if (viewModel.dataState == DataState.moreFetching) AppLoader(), ], ); @@ -457,7 +154,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 +167,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 +184,7 @@ class _DiscountVCState extends BaseStatefulState { filterSearchResults(text); }, ), - )); + ); } Future filterSearchResults(String query) async { @@ -505,73 +201,36 @@ class _DiscountVCState extends BaseStatefulState { return SizedBox( width: 130, child: CustomSimpleButton( + height: 38, 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); - } + 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() { return Text( AppLocalizations.of(context)!.discount, 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..9e9244c 100644 --- a/lib/application/views/discountModule/views/NewDiscountVC.dart +++ b/lib/application/views/discountModule/views/NewDiscountVC.dart @@ -1,18 +1,30 @@ +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:wosull/application/model/converters/DataTimeFormat.dart'; +import 'package:provider/provider.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/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/MandatoryTitleText.dart'; +import 'package:wosull/widgets/SearchBox.dart'; class NewDiscountVC extends StatefulWidget { late bool isEdit; @@ -26,99 +38,34 @@ 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( 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, @@ -142,493 +89,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 +127,10 @@ class _NewDiscountVCState extends BaseStatefulState { ], ), ), - isPortrait + viewModel.isPortrait ? Container() - : const SizedBox( - width: 8, - ), - isPortrait + : AppSpaces.horizontalMedium, + viewModel.isPortrait ? Container() : Expanded( flex: 2, @@ -663,133 +151,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 +179,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 +201,10 @@ 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() { return Visibility( - visible: _verticalGroupValue != _status.elementAt(0), + visible: viewModel.verticalGroupValue != + Constants.discountFilters.elementAt(0), child: Container( height: 200, padding: const EdgeInsets.all(16), @@ -879,109 +223,53 @@ class _NewDiscountVCState extends BaseStatefulState { flex: 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) + color: viewModel.storeDiscount.products! + .contains(filteredItem.id) || + viewModel + .storeDiscount.categories! + .contains(filteredItem.id) ? MyColors.blueThemeColor : MyColors.fillColor2, border: Border.all( @@ -996,21 +284,20 @@ class _NewDiscountVCState extends BaseStatefulState { MainAxisAlignment.center, children: [ Text( - filteredItems[i].name, + filteredItem.name, maxLines: 1, style: TextStyle( fontSize: 11, fontFamily: MyFonts.DMREGULAR, - color: widget.storeDiscount + color: viewModel.storeDiscount .products! .contains( - filteredItems[i] + filteredItem .id) || - widget.storeDiscount + viewModel.storeDiscount .categories! .contains( - filteredItems[i] - .id) + filteredItem.id) ? MyColors.white : MyColors.textColorBlack, fontWeight: FontWeight.bold), @@ -1027,57 +314,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 +336,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: viewModel.types, itemBuilder: (item) => RadioButtonBuilder( item, ), @@ -1119,61 +358,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), + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.maximum_discount_limit, ), - 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.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 +391,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 +413,260 @@ 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: const PopupProps.menu( + fit: FlexFit.loose, constraints: BoxConstraints(maxHeight: 250)), + items: viewModel.items, + 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, + Visibility( + visible: viewModel.selectedDiscountType == viewModel.items[0], + child: 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 + ? viewModel.storeDiscount.discountEndDate! + : viewModel.storeDiscount.discountEndDate ?? 'dd/mm/yyyy', + onPressed: () { + viewModel.presentDatePicker(context, false); + }, + ); + } + + Widget getStartDateButton() { + return CustomTextButtonIcon( + backgroundColor: MyColors.backFillColor, + icon: Icons.calendar_month, + heading: widget.isEdit + ? viewModel.storeDiscount.discountStartDate! + : 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 + : AppLocalizations.of(context)!.discount_value, + ), + AppSpaces.verticalSmall, + CustomTextFieldForm( + hintText: viewModel.selectedDiscountType == 'Percentage' + ? 'Enter Discount Percentage' + : 'Enter Discount Value', + 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/widgets/DiscountListView.dart b/lib/application/views/discountModule/widgets/DiscountListView.dart new file mode 100644 index 0000000..42b4051 --- /dev/null +++ b/lib/application/views/discountModule/widgets/DiscountListView.dart @@ -0,0 +1,301 @@ +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/CustomSwitch.dart'; +import 'package:wosull/widgets/EmptyDataWidget.dart'; +import 'package:wosull/widgets/HeadingText.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() + : Container( + padding: const EdgeInsets.only(left: 8, right: 8), + height: 48, + color: MyColors.containerBackColor, + 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: 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"; + // } + // }); + onUpdate(discount, value); + // _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: + 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 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, discount), + ); + } +} diff --git a/lib/application/views/home/HomePage.dart b/lib/application/views/home/HomePage.dart index 2ad9341..d6642f5 100644 --- a/lib/application/views/home/HomePage.dart +++ b/lib/application/views/home/HomePage.dart @@ -4,12 +4,13 @@ import 'package:flutter_svg/svg.dart'; import 'package:internet_connection_checker/internet_connection_checker.dart'; import 'package:provider/provider.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/utils/AppLoader.dart'; import 'package:wosull/application/views/authModule/loginViews/CheckInPopUp.dart'; import 'package:wosull/application/views/authModule/loginViews/LoginVC.dart'; +import 'package:wosull/application/views/billingCounterDashboard/BillingCounterMainVC.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'; @@ -20,14 +21,16 @@ 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/ThemeImage.dart'; +import 'package:wosull/main.dart'; import 'package:wosull/widgets/CustomListTIle.dart'; -import 'package:wosull/widgets/IconButton.dart'; +import 'package:wosull/widgets/LanguageDropdown.dart'; +import 'package:wosull/widgets/ValueText.dart'; class DrawerItem { String title; @@ -64,10 +67,11 @@ class _HomePageState extends BaseStatefulState viewModel = context.watch(); 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,27 +90,24 @@ class _HomePageState extends BaseStatefulState mainAxisSize: MainAxisSize.min, children: [ getLangDropdown(), - const SizedBox( - width: 12, - ), - 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: 12, - ), + AppSpaces.horizontalMedium, + // 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, + // ), + // ), + getSyncButton(), + AppSpaces.horizontalMedium, SizedBox( width: 130, child: ElevatedButton.icon( @@ -135,9 +136,34 @@ class _HomePageState extends BaseStatefulState ), ), ), - const SizedBox( - width: 8, + AppSpaces.horizontalMedium, + 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: () {}, + label: Text( + 'Counter', + style: TextStyle( + fontSize: 13, + color: MyColors.blueThemeColor, + fontFamily: MyFonts.Medium), + ), + icon: ImageIcon( + color: MyColors.blueThemeColor, + const AssetImage('images/cashier.png'), + size: 18, + ), + ), ), + AppSpaces.horizontalMedium, SizedBox( width: 120, child: ElevatedButton.icon( @@ -166,9 +192,7 @@ class _HomePageState extends BaseStatefulState ), ), ), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, PopupMenuButton( padding: EdgeInsets.zero, child: Container( @@ -217,9 +241,7 @@ class _HomePageState extends BaseStatefulState onSelected: (String value) => actionPopUpItemSelected(value), ), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, ], )) : Expanded( @@ -228,27 +250,9 @@ 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, - ), + AppSpaces.horizontalMedium, + getSyncButton(), + AppSpaces.horizontalMedium, PopupMenuButton( padding: EdgeInsets.zero, child: Container( @@ -297,9 +301,7 @@ class _HomePageState extends BaseStatefulState onSelected: (String value) => actionPopUpItemSelected(value), ), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, ], )) ], @@ -328,19 +330,19 @@ class _HomePageState extends BaseStatefulState return [ PopupMenuItem( value: 'mystore', - child: Text(AppLocalizations.of(context)!.my_store), + child: ValueText(AppLocalizations.of(context)!.my_store), ), PopupMenuItem( value: 'register', - child: Text(AppLocalizations.of(context)!.register), + child: ValueText(AppLocalizations.of(context)!.register), ), - const PopupMenuItem( + PopupMenuItem( value: 'cashout', - child: Text('Cash Out'), + child: ValueText('Cash Out'), ), PopupMenuItem( value: 'logout', - child: Text(AppLocalizations.of(context)!.logout), + child: ValueText(AppLocalizations.of(context)!.logout), ), ]; } @@ -353,9 +355,26 @@ class _HomePageState extends BaseStatefulState showCashout(); } else if (value == 'logout') { logout(); + } else if (value == 'fetch') { + viewModel.syncData(); + } else if (value == 'upload') { + viewModel.uploadOrders(); } } + List> getSyncMenu() { + return [ + PopupMenuItem( + value: 'fetch', + child: ValueText('Fetch Data'), + ), + PopupMenuItem( + value: 'upload', + child: ValueText('Upload Order'), + ), + ]; + } + Future logout() async { final result = await showDialog( barrierColor: Colors.black26, @@ -372,7 +391,7 @@ class _HomePageState extends BaseStatefulState sharedPrefs.isLoggedIn = false; Navigator.pushReplacement( context, - MaterialPageRoute(builder: (context) => LoginVC()), + MaterialPageRoute(builder: (context) => const LoginVC()), ); } } @@ -447,49 +466,63 @@ class _HomePageState extends BaseStatefulState ), ), CustomListTile( + wasTaped: viewModel.isTaped[0], path: 'images/home_icon.svg', - title: AppLocalizations.of(context)!.dashboard, + title: 'Master Dashboard', onTap: () { - viewModel.onSelectItem(12); + viewModel.onSelectItem(0); }), CustomListTile( + wasTaped: viewModel.isTaped[1], + path: 'images/create-order.svg', + title: 'Billing Counter Dashboard', + onTap: () { + viewModel.onSelectItem(1); + }), + CustomListTile( + wasTaped: viewModel.isTaped[2], path: 'images/create-order.svg', title: AppLocalizations.of(context)!.create_order, onTap: () { - viewModel.onSelectItem(0); + viewModel.onSelectItem(2); }), CustomListTile( + wasTaped: viewModel.isTaped[3], path: 'images/inven.svg', title: AppLocalizations.of(context)!.inventory, onTap: () { - viewModel.onSelectItem(1); + viewModel.onSelectItem(3); }), CustomListTile( + wasTaped: viewModel.isTaped[4], path: 'images/dis.svg', title: AppLocalizations.of(context)!.discount, onTap: () { - viewModel.onSelectItem(2); + viewModel.onSelectItem(4); }), CustomListTile( + wasTaped: viewModel.isTaped[5], path: 'images/sales_order.svg', title: AppLocalizations.of(context)!.sales_and_orders, onTap: () { - viewModel.onSelectItem(7); + viewModel.onSelectItem(5); }), CustomListTile( + wasTaped: viewModel.isTaped[6], path: 'images/kitchen.svg', title: AppLocalizations.of(context)!.kitchen, onTap: () { viewModel.tableIndex = 0; - viewModel.onSelectItem(8); + viewModel.onSelectItem(6); }), Align( alignment: FractionalOffset.bottomCenter, child: CustomListTile( + wasTaped: viewModel.isTaped[7], path: 'images/setting.svg', title: AppLocalizations.of(context)!.settings, onTap: () { - viewModel.onSelectItem(14); + viewModel.onSelectItem(7); }), ) ], @@ -499,73 +532,108 @@ class _HomePageState extends BaseStatefulState @override void goToHome() { - viewModel.setSelectedDrawer(0); + viewModel.setSelectedDrawer(2); } @override void changeBottomNavigation(int index) { - if (viewModel.isCashier) { - viewModel.onItemTapped(1); - } + // if (viewModel.isCashier) { + // viewModel.onItemTapped(1); + // } else { + // + // } + 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( + dropdownValue: viewModel.dropdownValue, + onChange: (language) { + viewModel.dropdownValue = language!; + viewModel.setLanguage(language); + }); } _getDrawerItemWidget(int pos) { + print(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 SalesAndOrderMainVC( delegateDrawer: this, ); - case 8: + case 6: return KitchenMainVC( delegateDrawer: this, initialIndex: 0, ); + case 7: + return SettingsMainVC(delegateDrawer: this); + case 8: + return HomeVC(delegateDrawer: this); + case 9: + return CartVC(delegateDrawer: this); case 10: - return CartVC(); - 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, + child: Container( + padding: const EdgeInsets.only(left: 8, right: 8), + decoration: BoxDecoration( + borderRadius: const BorderRadius.all(Radius.circular(8)), + color: MyColors.backFillColor), + height: 44, + child: viewModel.isInSync + ? AppLoader() + : Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SizedBox( + width: 24, + height: 24, + child: Icon( + Icons.sync, + size: 14, + color: MyColors.blueThemeColor, + ), + ), + const Text( + 'Sync', + style: TextStyle( + fontSize: MyFonts.normalButton, + fontFamily: MyFonts.Medium, + color: MyColors.textColorBlack), + ), + ], + ), + ), + itemBuilder: (context) { + return getSyncMenu(); + }, + onSelected: (String value) => actionPopUpItemSelected(value), + ); + } } diff --git a/lib/application/views/home/HomePageViewModel.dart b/lib/application/views/home/HomePageViewModel.dart index 17f1c2c..fae9452 100644 --- a/lib/application/views/home/HomePageViewModel.dart +++ b/lib/application/views/home/HomePageViewModel.dart @@ -9,63 +9,76 @@ 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 = []; + // List cashierItems = []; var _appLocale; - late String currentDefaultSystemLocale; + //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, + ]; // 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(); + // setFlag(); sharedPrefs.setLocale(language.languageCode); } 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(); + // 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() { @@ -83,52 +96,60 @@ class HomePageViewModel with ChangeNotifier { ]; } - 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 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; + } } + // if (index == 12) { + // isCashier = false; + // currentIndex = 0; + // } + // currentIndex = index; setSelectedDrawer(index); Navigator.of(context).pop(); // close the drawer } void onItemTapped(int index) async { + print('index' + index.toString()); currentIndex = index; - if (index == 0) { - isCashier = false; - setSelectedDrawer(12); - } else if (index == 1) { - isCashier = true; - currentIndex = 0; + // isCashier = false; setSelectedDrawer(0); + } else if (index == 1) { + // isCashier = true; + // currentIndex = 1; + setSelectedDrawer(2); } else if (index == 2) { - setSelectedDrawer(10); + setSelectedDrawer(9); } else if (index == 3) { - setSelectedDrawer(11); + setSelectedDrawer(10); } } @@ -147,9 +168,23 @@ 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(); } } diff --git a/lib/application/views/inventorymodule/categoryviews/InventoryAddCategoryVC.dart b/lib/application/views/inventorymodule/categoryviews/InventoryAddCategoryVC.dart index 8ea8342..7b97b47 100644 --- a/lib/application/views/inventorymodule/categoryviews/InventoryAddCategoryVC.dart +++ b/lib/application/views/inventorymodule/categoryviews/InventoryAddCategoryVC.dart @@ -47,15 +47,16 @@ 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); - } + // if (widget.isEdit) { + // viewModel.setDataOnEdit(widget.item); + // } // else { // viewModel.setStoreIds(widget.stores); // } diff --git a/lib/application/views/inventorymodule/categoryviews/InventoryCategoriesModule.dart b/lib/application/views/inventorymodule/categoryviews/InventoryCategoriesModule.dart index f84ec20..a7fbf94 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 @@ -49,75 +50,32 @@ class _InventoryCategoriesModuleState // 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, - ), + AppSpaces.horizontalSmall, SizedBox( width: 120, child: CustomSimpleButton( @@ -130,72 +88,118 @@ 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, - ), - ), - ], + Flexible(child: PageLimitDropdown( + 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 + : 240, + height: 48, + child: SearchBox( + onEditingDone: (text) { + filterSearchResults(text); + }, + onChanged: (text) { + filterSearchResults(text); + }, + hint: AppLocalizations.of(context)!.search, + ), + ), + AppSpaces.horizontalSmall, + PageLimitDropdown( + 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(); + }); + 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); + } + }, + ), ), - ), - ); - })), - onWillPop: () { - categoryViewModel.dispose(); - return Future.value(false); - }); + ], + ), + ), + ); + })); } Widget categoryListViewWidget(List data) { @@ -223,7 +227,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/viewModels/CategoryViewModel.dart b/lib/application/views/inventorymodule/categoryviews/viewModels/CategoryViewModel.dart index 3419235..c6b1eb1 100644 --- a/lib/application/views/inventorymodule/categoryviews/viewModels/CategoryViewModel.dart +++ b/lib/application/views/inventorymodule/categoryviews/viewModels/CategoryViewModel.dart @@ -1,3 +1,5 @@ +import 'dart:convert'; + import 'package:flutter/material.dart'; import 'package:wosull/application/enum/DataState.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; @@ -12,7 +14,6 @@ import 'package:wosull/application/utils/Constants.dart'; class CategoryViewModel extends ChangeNotifier { int _currentPageNumber = 1; - //using this state to handle for get data and pagination DataState _dataState = DataState.uninitialized; @@ -35,7 +36,7 @@ class CategoryViewModel extends ChangeNotifier { List get dataList => _dataList; List get filteredList => _filteredList; - + int limit = 10; var wosulError = WosulError(message: ''); late ViewItemCategory category; @@ -46,7 +47,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,8 +63,9 @@ class CategoryViewModel extends ChangeNotifier { Map data = { 'store_id': sharedPrefs.storeId, 'page': _currentPageNumber, + 'limit': this.limit }; - + print(jsonEncode(data)); try { if (_didLastLoad) { _dataState = DataState.noMoreData; @@ -78,7 +81,7 @@ class CategoryViewModel extends ChangeNotifier { if (value.success) { _filteredList.addAll(value.categories); _dataList.addAll(value.categories); - if (value.categories.length < 10) { + if (value.categories.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; diff --git a/lib/application/views/inventorymodule/comboviews/ComboAddSizesVC.dart b/lib/application/views/inventorymodule/comboviews/ComboAddSizesVC.dart index df3b3eb..51242a6 100644 --- a/lib/application/views/inventorymodule/comboviews/ComboAddSizesVC.dart +++ b/lib/application/views/inventorymodule/comboviews/ComboAddSizesVC.dart @@ -1,44 +1,44 @@ 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); + 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( @@ -48,300 +48,139 @@ class _ComboAddSizesVCState extends BaseStatefulState { borderRadius: BorderRadius.circular(15.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', + 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( + isLoading: viewModel.isLoading, + 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( + 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/CreateComboGroupVC.dart b/lib/application/views/inventorymodule/comboviews/CreateComboGroupVC.dart index 24724e2..485f633 100644 --- a/lib/application/views/inventorymodule/comboviews/CreateComboGroupVC.dart +++ b/lib/application/views/inventorymodule/comboviews/CreateComboGroupVC.dart @@ -1,13 +1,16 @@ 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/CustomOptionalTitle.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 CreateComboGroupVC extends StatefulWidget { const CreateComboGroupVC({Key? key}) : super(key: key); @@ -17,22 +20,18 @@ 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( @@ -42,11 +41,11 @@ class _CreateComboGroupVCState extends BaseStatefulState { borderRadius: BorderRadius.circular(15.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,77 +54,27 @@ 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( + height: 48, decoration: BoxDecoration( borderRadius: const BorderRadius.all( Radius.circular( @@ -135,7 +84,6 @@ class _CreateComboGroupVCState extends BaseStatefulState { width: 1, color: MyColors.fillColorGray2), color: MyColors.containerBackColor, ), - height: 48, child: Row( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, @@ -144,8 +92,7 @@ class _CreateComboGroupVCState extends BaseStatefulState { child: Container( padding: const EdgeInsets.only(left: 4, right: 4), - height: 48, - decoration: BoxDecoration( + decoration: const BoxDecoration( border: Border( right: BorderSide( width: 1.0, @@ -154,21 +101,14 @@ class _CreateComboGroupVCState extends BaseStatefulState { ), 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), - ), + child: HeadingText( + AppLocalizations.of(context)! + .sub_group_name), ), )), Container( width: 80, - height: 48, - decoration: BoxDecoration( + decoration: const BoxDecoration( border: Border( right: BorderSide( width: 1.0, @@ -176,13 +116,8 @@ class _CreateComboGroupVCState extends BaseStatefulState { ), ), child: Center( - child: Text( + child: HeadingText( AppLocalizations.of(context)!.action, - style: TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.bold, - fontSize: MyFonts.normal, - color: MyColors.textColorBlack20), ), ), ) @@ -195,8 +130,7 @@ class _CreateComboGroupVCState extends BaseStatefulState { physics: const NeverScrollableScrollPhysics(), shrinkWrap: true, itemBuilder: (context, position) { - _subGroupNameController - .add(TextEditingController()); + // viewModel.subGroupNameController.add(''); return Container( decoration: BoxDecoration( borderRadius: const BorderRadius.all( @@ -207,13 +141,11 @@ class _CreateComboGroupVCState extends BaseStatefulState { 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( @@ -221,82 +153,59 @@ class _CreateComboGroupVCState extends BaseStatefulState { 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: CustomTextFieldForm( + height: 42, + 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, + child: Padding( + padding: + const EdgeInsets.only(right: 4), + child: Align( + alignment: Alignment.centerRight, + child: Container( + width: 32, + height: 32, + decoration: const BoxDecoration( + borderRadius: + BorderRadius.all( + Radius.circular(4)), color: - MyColors.textColorBlack, - ), - onPressed: () { - setState(() { - _subGroupNameController - .removeAt(position); - addComboGroup.subGroups! - .removeAt(position); - }); - }), + MyColors.fillColorGray2), + child: IconButton( + icon: const Icon( + size: 14, + Icons.close, + color: + MyColors.textColorBlack, + ), + onPressed: () { + viewModel + .removeGroup(position); + }), + ), ), )), ], ), ); }, - itemCount: addComboGroup.subGroups!.length, + itemCount: + viewModel.addComboGroup.subGroups!.length, ), Container( - padding: EdgeInsets.all(8), + padding: const EdgeInsets.all(8), decoration: BoxDecoration( borderRadius: const BorderRadius.all( Radius.circular( @@ -312,33 +221,14 @@ class _CreateComboGroupVCState extends BaseStatefulState { 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 +237,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 +261,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..bceaedd 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,47 @@ class _InventoryComboVCState extends BaseStatefulState { AppLocalizations.of(context)!.combos, style: ThemeText.textStylePageHeading, ), - const SizedBox( - width: 4, - ), + AppSpaces.horizontalSmall, SizedBox( width: 120, child: newComboGroup(), ), - const SizedBox( - width: 4, - ), + AppSpaces.horizontalSmall, SizedBox( width: 115, 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: [ + SizedBox( + width: 120, + child: addSizesButton(), + ), + Flexible(child: 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 +118,43 @@ 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 + : 240, + height: 48, + child: SearchBox( + onEditingDone: (text) { + // filterSearchResults(text); + }, + onChanged: (text) { + // filterSearchResults(text); + }, + hint: AppLocalizations.of(context)!.search, + ), + ), + Flexible(child: PageLimitDropdown( + onChange: (value) { + viewModel.fetch( + isRefresh: true, limit: int.parse(value!)); + }, + )) ], ), AppSpaces.verticalMedium, @@ -202,7 +207,7 @@ class _InventoryComboVCState extends BaseStatefulState { bool _scrollNotification() { if (!viewModel.isLoading && _controller.position.extentAfter < 300) { - viewModel.fetch(); + viewModel.fetch(limit: viewModel.limit); } return true; } @@ -256,40 +261,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 ComboAddSizesVC(); + }, + ); }, heading: AppLocalizations.of(context)!.add_sizes, ); @@ -300,7 +278,7 @@ class _InventoryComboVCState extends BaseStatefulState { textColor: MyColors.blueThemeColor, backGroundColor: MyColors.backColorBlue50, onPressed: () async { - getCategory(); + newCombo(); }, heading: AppLocalizations.of(context)!.new_combos, ); @@ -318,18 +296,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 +317,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..22d39d7 100644 --- a/lib/application/views/inventorymodule/comboviews/InventoryNewComboVC.dart +++ b/lib/application/views/inventorymodule/comboviews/InventoryNewComboVC.dart @@ -1,370 +1,151 @@ 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/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/ChildContainer.dart'; +import 'package:wosull/widgets/CustomSimpleButton.dart'; +import 'package:wosull/widgets/CustomTextFieldForm.dart'; +import 'package:wosull/widgets/HeadingContainer.dart'; +import 'package:wosull/widgets/ItemCategoryDropdown.dart'; +import 'package:wosull/widgets/MandatoryTitleText.dart'; +import 'package:wosull/widgets/PortraitContainer.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 super.initState(); - selectedItemCategory = widget.itemCategories[0]; - addCombo.comboProducts = List.empty(growable: true); - addCombo.comboProducts.add(ComboProducts()); - addCombo.categoryId = widget.itemCategories[0].id!; - loadSizes(); + context.read().initData(); } @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( + 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) { + 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 + ? 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 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 ItemCategoryDropdown( + selectedCategoryDropDown: viewModel.selectedItemCategory, + onChanged: (data) { + viewModel.setSelectedCategory(data); + }); } Widget getProductContainer() { @@ -383,16 +164,10 @@ class _InventoryNewComboVCState extends BaseStatefulState { children: [ const Text( 'Combo Products', - style: TextStyle( - fontSize: 16, - fontFamily: MyFonts.Bold, - color: Colors.black, - fontWeight: FontWeight.bold), - ), - const SizedBox( - height: 16, + style: ThemeText.textStylePageHeading, ), - isPortrait + AppSpaces.verticalLarge, + viewModel.isPortrait ? Container() : Container( decoration: BoxDecoration( @@ -408,151 +183,37 @@ class _InventoryNewComboVCState extends BaseStatefulState { crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ + Expanded(child: HeadingContainer(heading: 'Size')), 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(), - ), - ), + child: HeadingContainer( + heading: AppLocalizations.of(context)!.group, )), 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(), - ), - ), + child: HeadingContainer( + heading: AppLocalizations.of(context)!.sub_group, )), 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(), - ), - ), + child: HeadingContainer( + heading: 'Product', )), 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(), - ), - ), + child: HeadingContainer( + heading: AppLocalizations.of(context)!.measurement, )), - Container( - padding: const EdgeInsets.only(left: 4, right: 4), + HeadingContainer( 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(), - ), - ), + heading: AppLocalizations.of(context)!.quantity, ), - Container( - padding: const EdgeInsets.only(left: 4, right: 4), + HeadingContainer( 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(), - ), - ), + heading: AppLocalizations.of(context)!.price, ), - Container( + HeadingContainer( 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), - ), - ), + heading: '', ) ], ), @@ -563,22 +224,7 @@ class _InventoryNewComboVCState extends BaseStatefulState { 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) { + if (viewModel.isPortrait) { return Container( decoration: BoxDecoration( borderRadius: const BorderRadius.all(Radius.circular( @@ -598,17 +244,7 @@ class _InventoryNewComboVCState extends BaseStatefulState { 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: PortraitContainer( child: Align( alignment: Alignment.centerLeft, child: Text( @@ -618,71 +254,15 @@ class _InventoryNewComboVCState extends BaseStatefulState { ), )), 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'), - ), - ), - ), - ), - ), + child: PortraitContainer( + child: getSizesDropdown(position), )) ], ), 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: PortraitContainer( child: Align( alignment: Alignment.centerLeft, child: Text( @@ -692,69 +272,15 @@ class _InventoryNewComboVCState extends BaseStatefulState { ), )), 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'), - ), - ), - ), - ), - ), + child: PortraitContainer( + child: getComboGroupDropdown(position), )) ], ), 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: PortraitContainer( child: Align( alignment: Alignment.centerLeft, child: Text( @@ -764,69 +290,15 @@ class _InventoryNewComboVCState extends BaseStatefulState { ), )), 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'), - ), - ), - ), - ), - ), + child: PortraitContainer( + child: getSubGroupDropdown(position), )) ], ), 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: PortraitContainer( child: Align( alignment: Alignment.centerLeft, child: Text( @@ -836,85 +308,15 @@ class _InventoryNewComboVCState extends BaseStatefulState { ), )), 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'), - ), - ), - ), - ), - ), + child: PortraitContainer( + child: getProductDropdown(position), )) ], ), 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: PortraitContainer( child: Align( alignment: Alignment.centerLeft, child: Text( @@ -924,68 +326,15 @@ class _InventoryNewComboVCState extends BaseStatefulState { ), )), 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'), - ), - ), - ), - ), - ), + child: PortraitContainer( + child: getMeasurementDropdown(position), )) ], ), 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: PortraitContainer( child: Align( alignment: Alignment.centerLeft, child: Text( @@ -995,81 +344,15 @@ class _InventoryNewComboVCState extends BaseStatefulState { ), )), 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), - ), - ), - ), + child: PortraitContainer( + child: quantityTextField(position), )) ], ), 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: PortraitContainer( child: Align( alignment: Alignment.centerLeft, child: Text( @@ -1079,92 +362,14 @@ class _InventoryNewComboVCState extends BaseStatefulState { ), )), 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), - ), - ), - ), + child: PortraitContainer( + child: getPriceTextField(position), )) ], ), ], )), - 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(); - } - - 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); - }); - }), - ), - )), + getRemoveButton(position) ], ), ); @@ -1181,391 +386,46 @@ class _InventoryNewComboVCState extends BaseStatefulState { 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'), - ), - ), - ), - ), - ), + child: ChildContainer( + child: getSizesDropdown(position), )), 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'), - ), - ), - ), - ), - ), + child: ChildContainer( + child: getComboGroupDropdown(position), )), 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'), - ), - ), - ), - ), - ), + child: ChildContainer( + child: getSubGroupDropdown(position), )), 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'), - ), - ), - ), - ), - ), + child: ChildContainer( + child: getProductDropdown(position), )), 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'), - ), - ), - ), - ), - ), + child: ChildContainer( + child: getMeasurementDropdown(position), )), - Container( - padding: const EdgeInsets.all(4), + ChildContainer( 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(); - - 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), - ), - ), - ), + child: quantityTextField(position), ), ), - Container( - padding: const EdgeInsets.all(4), + ChildContainer( 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), - ), - ), - ), + child: getPriceTextField(position), ), ), - 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(); - } - - 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); - }); - }), - ), - )), + getRemoveButton(position) ], ), ); } }, - itemCount: addCombo.comboProducts.length, + itemCount: viewModel.addCombo.comboProducts.length, ), Container( padding: const EdgeInsets.all(8), @@ -1579,31 +439,7 @@ class _InventoryNewComboVCState extends BaseStatefulState { 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()); - }); - }), - ), - )) - ], + children: [getAddComboButton()], ), ), ], @@ -1611,94 +447,158 @@ class _InventoryNewComboVCState extends BaseStatefulState { ); } - 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 getSizesDropdown(int position) { + return DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: const PopupProps.menu( + fit: FlexFit.loose, constraints: BoxConstraints(maxHeight: 250)), + items: viewModel.comboSize, + itemAsString: (String u) => u, + onChanged: (String? data) { + viewModel.setSelectedSize(data, position); + }, + selectedItem: viewModel.selectedSizeValue[position], + dropdownDecoratorProps: MyColors.dropDownStyle(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 getComboGroupDropdown(int position) { + return DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: const PopupProps.menu( + fit: FlexFit.loose, constraints: BoxConstraints(maxHeight: 250)), + items: viewModel.comboGroups, + itemAsString: (ComboGroup u) => u.name!, + onChanged: (ComboGroup? data) { + viewModel.setSelectedComboGroup(data, position); + }, + selectedItem: viewModel.selectedGroup[position], + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), + ); } - 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 getSubGroupDropdown(int position) { + return DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: const PopupProps.menu( + fit: FlexFit.loose, constraints: BoxConstraints(maxHeight: 250)), + items: viewModel.subGroup, + itemAsString: (ComboSubGroup u) => u.name!, + onChanged: (ComboSubGroup? data) { + viewModel.setSelectedSubGroup(data, position); + }, + selectedItem: viewModel.selectedSubGroup[position], + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), + ); } - 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 getProductDropdown(int position) { + return DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: const PopupProps.menu( + fit: FlexFit.loose, constraints: BoxConstraints(maxHeight: 250)), + items: viewModel.comboProduct, + selectedItem: viewModel.selectedProduct[position], + itemAsString: (ProductItem u) => u.name!, + onChanged: (ProductItem? data) { + viewModel.onChangeProduct(data, position); + }, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), + ); + } - setState(() { - isLoadingFirst = false; - }); - } else { - setState(() { - isLoadingFirst = false; - }); - } - }).onError((error, stackTrace) { - setState(() { - isLoadingFirst = false; - }); - }); + Widget getMeasurementDropdown(int position) { + return DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: const PopupProps.menu( + fit: FlexFit.loose, constraints: BoxConstraints(maxHeight: 250)), + items: viewModel.comboMeasurement, + itemAsString: (ComboMeasurement u) => u.name!, + onChanged: (ComboMeasurement? data) { + viewModel.onChangeMeasurement(data, position); + }, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), + ); + } + + Widget quantityTextField(int position) { + return CustomTextFieldForm( + hintText: '0.0', + keyboardType: TextInputType.number, + initialValue: viewModel.quantityController[position], + onChanged: (value) { + viewModel.onChangeQuantity(value, position); + }, + ); + } + + Widget getPriceTextField(int position) { + return CustomTextFieldForm( + onChanged: (value) { + viewModel.priceController[position] = value; + }, + keyboardType: TextInputType.number, + hintText: '0.0', + initialValue: viewModel.priceController[position], + ); + } + + Widget getRemoveButton(int position) { + return 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: 14, + Icons.close, + color: MyColors.textColorBlack, + ), + onPressed: () { + viewModel.removeComboProduct(position); + }), + ), + )); + } + + Widget getAddComboButton() { + return 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: 14, + Icons.add, + color: MyColors.textColorBlack, + ), + onPressed: () { + viewModel.addNewCombo(); + }), + ), + )); + } + + void checkState() { + if (viewModel.crudOperation == CRUDOperationState.add) { + Navigator.pop(context, true); + } } } 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..50a7d1c --- /dev/null +++ b/lib/application/views/inventorymodule/comboviews/viewModels/AddComboGroupViewModel.dart @@ -0,0 +1,82 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/model/Combo/GetComboModel.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/helpers/Utils.dart'; + +class AddComboGroupViewModel with ChangeNotifier { + bool isPortrait = true; + bool _isLoading = false; + + bool get isLoading => _isLoading; + var addComboGroup = AddComboGroup(); + //List subGroupNameController = []; + var groupName = ''; + + var _crudOperation = CRUDOperationState.uninitialized; + + CRUDOperationState get crudOperation => _crudOperation; + + void init() { + addComboGroup.subGroups = []; + addComboGroup.subGroups!.add(ComboSubGroup(name: "")); + } + + void disposeData() { + // subGroupNameController.clear(); + _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 APIManager() + .fetchData(Constants.ADD_COMBO_GROUP, addComboGroup.toJson()) + .then((value) { + final response = SimpleResponseModel.fromJson(value); + 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) { + // subGroupNameController.removeAt(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..a0e29d8 --- /dev/null +++ b/lib/application/views/inventorymodule/comboviews/viewModels/AddComboSizeViewModel.dart @@ -0,0 +1,103 @@ +import 'package:flutter/cupertino.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/CRUDOperatoinState.dart'; +import 'package:wosull/application/utils/Constants.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; + + 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 APIManager() + .fetchData(Constants.ADD_COMBO_SIZES, comboSizes.toJson()) + .then((value) { + final response = SimpleResponseModel.fromJson(value); + 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 APIManager() + .fetchData(Constants.GET_COMBO_SIZES, Constants.getStorePayload()) + .then((value) { + final response = GetComboSizes.fromJson(value); + if (response.success!) { + if (response.comboSizes != null) { + for (var size in response.comboSizes!.sizes!) { + controller.add(size); + } + } + } + _crudOperation = CRUDOperationState.update; + notifyListeners(); + }).onError((error, stackTrace) { + print(stackTrace.toString()); + _crudOperation = CRUDOperationState.error; + }).timeout(const Duration(minutes: 1)); + } +} 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..d858272 --- /dev/null +++ b/lib/application/views/inventorymodule/comboviews/viewModels/AddNewComboViewModel.dart @@ -0,0 +1,284 @@ +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/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/network/APIManager.dart'; +import 'package:wosull/application/utils/CRUDOperatoinState.dart'; +import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/helpers/Utils.dart'; + +class AddNewComboViewModel with ChangeNotifier { + var isLoadingFirst = false; + var isLoadingData = false; + + bool isPortrait = true; + + var comboNameController = ''; + var comboTotalPriceController = ''; + + List comboProduct = []; + List comboGroups = []; + 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; + + void setLoading(bool value) { + isLoadingData = value; + notifyListeners(); + } + + void initData() { + addCombo.comboProducts = []; + emptyProduct(); + loadSizes(); + } + + void loadSizes() async { + await APIManager() + .fetchData(Constants.GET_COMBO_SIZES, Constants.getStorePayload()) + .then((value) { + final response = GetComboSizes.fromJson(value); + if (response.success!) { + comboSize.addAll(response.comboSizes!.sizes!); + loadGroups(); + } else { + setLoading(false); + } + }).onError((error, stackTrace) { + print('size' + error.toString()); + setLoading(false); + }); + } + + void loadGroups() async { + await APIManager() + .fetchData(Constants.GET_COMBO_GROUPS, Constants.getStorePayload()) + .then((value) { + final response = GetComboGroupModel.fromJson(value); + if (response.success!) { + comboGroups.addAll(response.comboGroup!); + loadMeasurement(); + } else { + setLoading(false); + } + }).onError((error, stackTrace) { + setLoading(false); + print(error.toString()); + }); + } + + void loadMeasurement() async { + await APIManager() + .fetchData(Constants.GET_MEASUREMENT, Constants.getStorePayload()) + .then((value) { + final response = GetComboMeasurementModel.fromJson(value); + if (response.success!) { + comboMeasurement.addAll(response.measurements!); + setLoading(false); + } else { + setLoading(false); + } + }).onError((error, stackTrace) { + setLoading(false); + }); + } + + void loadProduct() async { + ItemCategory itemCategory = selectedItemCategory; + Map data = { + 'store_id': sharedPrefs.storeId, + 'category_id': itemCategory.id, + }; + await APIManager() + .fetchData(Constants.GET_PRODUCT_ITEM_BY_CATEGORY, data) + .then((value) { + final response = GetComboProductItem.fromJson(value); + if (response.success!) { + comboProduct.clear(); + comboProduct.addAll(response.products!); + + setLoading(false); + } else { + setLoading(false); + } + }).onError((error, stackTrace) { + setLoading(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 APIManager() + .fetchData(Constants.NEW_COMBO, addCombo.toJson()) + .then((value) { + final response = SimpleResponseModel.fromJson(value); + 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..a91c8c0 100644 --- a/lib/application/views/inventorymodule/comboviews/viewModels/ComboViewModel.dart +++ b/lib/application/views/inventorymodule/comboviews/viewModels/ComboViewModel.dart @@ -1,3 +1,5 @@ +import 'dart:convert'; + import 'package:flutter/cupertino.dart'; import 'package:wosull/application/enum/DataState.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; @@ -9,10 +11,12 @@ class ComboViewModel with ChangeNotifier { 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 +25,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,8 +41,9 @@ class ComboViewModel with ChangeNotifier { Map data = { 'store_id': sharedPrefs.storeId, 'page': _currentPageNumber, + 'limit': this.limit }; - + print(jsonEncode(data)); try { if (_didLastLoad) { _dataState = DataState.noMoreData; @@ -51,7 +57,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; diff --git a/lib/application/views/inventorymodule/deliveryPartnerViews/InventoryDeliveryPartnerPriceVC.dart b/lib/application/views/inventorymodule/deliveryPartnerViews/InventoryDeliveryPartnerPriceVC.dart index c6b38e1..e058f85 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); @@ -52,18 +55,42 @@ class _InventoryDeliveryPartnerPriceVCState child: Column( children: [ isPortrait - ? Row( - mainAxisAlignment: MainAxisAlignment.start, + ? 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: 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 +101,30 @@ class _InventoryDeliveryPartnerPriceVCState .delivery_partner_price, style: ThemeText.textStylePageHeading, ), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalSmall, toNewDeliveryPrice(), + AppSpaces.horizontalSmall, + 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: PageLimitDropdown( + onChange: (value) { + viewModel.fetch( + isRefresh: true, limit: int.parse(value!)); + }, + )) ], ), AppSpaces.verticalMedium, @@ -139,7 +186,7 @@ class _InventoryDeliveryPartnerPriceVCState bool _scrollNotification() { if (!viewModel.isLoading && _controller.position.extentAfter < 300) { - viewModel.fetch(); + viewModel.fetch(limit: viewModel.limit); } return true; } @@ -209,7 +256,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/inventoryAddDeliveryPriceVC.dart b/lib/application/views/inventorymodule/deliveryPartnerViews/inventoryAddDeliveryPriceVC.dart index def890b..543aaaa 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/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,156 @@ 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(); - - InventoryViewModel viewModel = InventoryViewModel(); + var viewModel = NewDeliveryPartnerViewModel(); @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, + viewModel = context.watch(); + return Scaffold( + resizeToAvoidBottomInset: true, + appBar: AppBar( + leading: BackButton( + color: Colors.black, + onPressed: () { + Navigator.pop(context); + }, // <-- SEE HERE ), - 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), - ), - ), - ), - ), - ], + centerTitle: true, + title: Text( + viewModel.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) { + 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) { + setState(() { + if (value) { + viewModel.deliveryPartner.status = "Active"; + } else { + viewModel.deliveryPartner.status = "Inactive"; + } + }); + }, ), + ], + ), + 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/viewModels/DeliveryPartnerPriceViewModel.dart b/lib/application/views/inventorymodule/deliveryPartnerViews/viewModels/DeliveryPartnerPriceViewModel.dart index 29201ce..7d823d7 100644 --- a/lib/application/views/inventorymodule/deliveryPartnerViews/viewModels/DeliveryPartnerPriceViewModel.dart +++ b/lib/application/views/inventorymodule/deliveryPartnerViews/viewModels/DeliveryPartnerPriceViewModel.dart @@ -9,7 +9,7 @@ class DeliveryPartnerPriceViewModel with ChangeNotifier { int _currentPageNumber = 1; DataState _dataState = DataState.uninitialized; - + int limit = 10; bool _didLastLoad = false; bool _isLoading = false; @@ -28,6 +28,7 @@ class DeliveryPartnerPriceViewModel with ChangeNotifier { DeliveryPartner get selectedType => __typesGroupValue; void changeSelectedType(DeliveryPartner? value) { + print('value'); __typesGroupValue = value!; notifyListeners(); } @@ -49,7 +50,8 @@ class DeliveryPartnerPriceViewModel with ChangeNotifier { 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,6 +66,7 @@ class DeliveryPartnerPriceViewModel with ChangeNotifier { Map data = { 'store_id': sharedPrefs.storeId, 'page': _currentPageNumber, + 'limit': this.limit }; try { @@ -81,7 +84,7 @@ class DeliveryPartnerPriceViewModel with ChangeNotifier { if (value.success!) { _filteredList.addAll(value.deliveries!); _dataList.addAll(value.deliveries!); - if (value.deliveries!.length < 10) { + if (value.deliveries!.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; 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..8708ba1 --- /dev/null +++ b/lib/application/views/inventorymodule/deliveryPartnerViews/viewModels/NewDeliveryPartnerViewModel.dart @@ -0,0 +1,128 @@ +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 setLoading(bool value) { + _isLoading = value; + notifyListeners(); + } + + void initPartner(bool isEdit, DeliveryPartner deliveryPartner) { + this.isEdit = isEdit; + this.deliveryPartner = deliveryPartner; + if (isEdit) { + nameController = deliveryPartner.name; + arabicNameController = deliveryPartner.nameArabic; + } else { + deliveryPartner.status = "Active"; + } + } + + 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(); + } +} diff --git a/lib/application/views/inventorymodule/ingredientsViews/IngredientsVC.dart b/lib/application/views/inventorymodule/ingredientsViews/IngredientsVC.dart index 11c21b9..e82c688 100644 --- a/lib/application/views/inventorymodule/ingredientsViews/IngredientsVC.dart +++ b/lib/application/views/inventorymodule/ingredientsViews/IngredientsVC.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/converters/DataTimeFormat.dart'; import 'package:wosull/application/model/inventory/AddIngredientModel.dart'; @@ -10,12 +11,15 @@ 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/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/PageLimitDropDown.dart'; +import 'package:wosull/widgets/SearchBox.dart'; import 'package:wosull/widgets/ValueText.dart'; class IngredientsVC extends StatefulWidget { @@ -28,86 +32,116 @@ 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(12), + 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()); - }, - ), - ), - ], - ), - const SizedBox( - height: 8, + const Text( + 'Ingredient', + style: ThemeText.textStylePageHeading, ), - 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); - } + AppSpaces.horizontalSmall, + SizedBox( + width: 120, + child: CustomSimpleButton( + textColor: MyColors.blueThemeColor, + backGroundColor: MyColors.backColorBlue50, + heading: AppLocalizations.of(context)!.add_ingredient, + onPressed: () { + addUpdateIngredient(false, false, AddIngredient()); }, ), ), + AppSpaces.horizontalMedium, + isPortrait + ? Container() + : 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: PageLimitDropdown(onChange: (value) { + viewModel.fetch( + isRefresh: true, limit: int.parse(value!)); + })) ], ), - ), - ); - })), - onWillPop: () { - viewModel.dispose(); - return Future.value(false); - }); + isPortrait + ? SizedBox( + height: 48, + child: SearchBox( + onEditingDone: (text) { + // filterSearchResults(text); + }, + onChanged: (text) { + // filterSearchResults(text); + }, + hint: AppLocalizations.of(context)!.search, + ), + ) + : 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); + } + }, + ), + ), + ], + ), + ), + ); + })); } Widget showList(List data) { @@ -260,7 +294,7 @@ class _IngredientsVCState extends State { bool _scrollNotification() { if (!viewModel.isLoading && _controller.position.extentAfter < 300) { - viewModel.fetch(); + viewModel.fetch(limit: viewModel.limit); } return true; } diff --git a/lib/application/views/inventorymodule/ingredientsViews/viewModels/IngredientViewModel.dart b/lib/application/views/inventorymodule/ingredientsViews/viewModels/IngredientViewModel.dart index 39a4460..aa55c6e 100644 --- a/lib/application/views/inventorymodule/ingredientsViews/viewModels/IngredientViewModel.dart +++ b/lib/application/views/inventorymodule/ingredientsViews/viewModels/IngredientViewModel.dart @@ -10,7 +10,7 @@ class IngredientViewModel with ChangeNotifier { List _filteredList = []; List get filteredList => _filteredList; - + int limit = 10; bool _didLastLoad = false; bool _isLoading = false; @@ -26,7 +26,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,6 +42,7 @@ class IngredientViewModel with ChangeNotifier { Map data = { 'store_id': sharedPrefs.storeId, 'page': _currentPageNumber, + 'limit': this.limit }; try { @@ -56,7 +58,7 @@ class IngredientViewModel with ChangeNotifier { } if (value.success) { _filteredList.addAll(value.ingredient); - if (value.ingredient.length < 10) { + if (value.ingredient.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; diff --git a/lib/application/views/inventorymodule/measurementviews/InventoryAddMeasurementVC.dart b/lib/application/views/inventorymodule/measurementviews/InventoryAddMeasurementVC.dart index dd140a1..72b26de 100644 --- a/lib/application/views/inventorymodule/measurementviews/InventoryAddMeasurementVC.dart +++ b/lib/application/views/inventorymodule/measurementviews/InventoryAddMeasurementVC.dart @@ -10,6 +10,7 @@ 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'; @@ -36,7 +37,9 @@ class _InventoryAddMeasurementVCState @override void initState() { - viewModel.fillValueOnEdit(widget.isEdit, widget.measurement); + context + .read() + .fillValueOnEdit(widget.isEdit, widget.measurement); super.initState(); } @@ -151,25 +154,19 @@ class _InventoryAddMeasurementVCState 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'), - ), - ), - ), + return DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: const PopupProps.menu( + fit: FlexFit.loose, + constraints: BoxConstraints(maxHeight: 250)), + items: units, + itemAsString: (MeasurementUnit u) => u.name, + onChanged: (MeasurementUnit? data) { + viewModel.setMeasurementUnit(data); + }, + selectedItem: viewModel.dropdownValue, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), ); } else { return AppLoader(); diff --git a/lib/application/views/inventorymodule/measurementviews/InventoryMeasurementVC.dart b/lib/application/views/inventorymodule/measurementviews/InventoryMeasurementVC.dart index 88b9fcd..2379cd0 100644 --- a/lib/application/views/inventorymodule/measurementviews/InventoryMeasurementVC.dart +++ b/lib/application/views/inventorymodule/measurementviews/InventoryMeasurementVC.dart @@ -1,21 +1,27 @@ 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/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/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/PageLimitDropDown.dart'; +import 'package:wosull/widgets/SearchBox.dart'; import 'package:wosull/widgets/ValueText.dart'; class InventoryMeasurementVC extends StatefulWidget { @@ -35,49 +41,48 @@ class _InventoryMeasurementVCState @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, + ), + AppSpaces.horizontalMedium, + SizedBox( + width: 160, + child: CustomSimpleButton( + textColor: MyColors.blueThemeColor, + backGroundColor: MyColors.backColorBlue50, + onPressed: () { + addUpdateMeasurement( + false, Measurement()); + }, + heading: AppLocalizations.of(context)! + .add_measurements, + ), ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ SizedBox( width: 160, child: CustomSimpleButton( @@ -89,96 +94,128 @@ class _InventoryMeasurementVCState heading: '+ Add Measurement Unit', ), ), + Flexible(child: PageLimitDropdown( + onChange: (value) { + viewModel.fetch( + isRefresh: true, + limit: int.parse(value!)); + }, + )) ], - ) - : 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: 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', - ), - ), - ], - )), + 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', + ), + ), + 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, + ), + ), ], - ), - 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); - } - }, + )), + 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 const Center( + child: CircularProgressIndicator(), + ); + 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); + } + }, + ), ), - ), - ); - })), - onWillPop: () { - viewModel.dispose(); - return Future.value(false); - }); + ], + ), + ), + ); + })); } Widget showData(List data) { @@ -476,15 +513,14 @@ class _InventoryMeasurementVCState ) ], ), - if (viewModel.dataState == DataState.moreFetching) - const Center(child: CircularProgressIndicator()), + if (viewModel.dataState == DataState.moreFetching) AppLoader(), ], ); } bool _scrollNotification() { if (!viewModel.isLoading && _controller.position.extentAfter < 300) { - viewModel.fetch(); + viewModel.fetch(limit: viewModel.limit); } return true; } diff --git a/lib/application/views/inventorymodule/measurementviews/viewModels/AddMeasurementViewModel.dart b/lib/application/views/inventorymodule/measurementviews/viewModels/AddMeasurementViewModel.dart index e6a6175..0088f8a 100644 --- a/lib/application/views/inventorymodule/measurementviews/viewModels/AddMeasurementViewModel.dart +++ b/lib/application/views/inventorymodule/measurementviews/viewModels/AddMeasurementViewModel.dart @@ -75,20 +75,19 @@ class AddMeasurementViewModel with ChangeNotifier { var items = []; Map data = {}; await APIManager() - .fetchData(Constants.GET_INVENTORY_MEASUREMENTS_UNITS, data) + .getResponseAuth( + "${Constants.GET_INVENTORY_MEASUREMENTS_UNITS}/${sharedPrefs.storeId}", + 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()); - }); + }).onError((error, stackTrace) {}); dropdownValue ??= MeasurementUnit(name: 'Choose'); return items; } diff --git a/lib/application/views/inventorymodule/measurementviews/viewModels/MeasurementViewModel.dart b/lib/application/views/inventorymodule/measurementviews/viewModels/MeasurementViewModel.dart index c889a63..5b1e523 100644 --- a/lib/application/views/inventorymodule/measurementviews/viewModels/MeasurementViewModel.dart +++ b/lib/application/views/inventorymodule/measurementviews/viewModels/MeasurementViewModel.dart @@ -9,7 +9,7 @@ class MeasurementViewModel extends ChangeNotifier { bool _isLoading = false; bool get isLoading => _isLoading; - + int limit = 10; int _currentPageNumber = 1; DataState _dataState = DataState.uninitialized; @@ -21,7 +21,8 @@ class MeasurementViewModel extends 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,6 +37,7 @@ class MeasurementViewModel extends ChangeNotifier { Map data = { 'store_id': sharedPrefs.storeId, 'page': _currentPageNumber, + 'limit': this.limit }; try { @@ -51,7 +53,7 @@ class MeasurementViewModel extends ChangeNotifier { } if (value.success!) { _filteredList.addAll(value.measurements!); - if (value.measurements!.length < 10) { + if (value.measurements!.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; diff --git a/lib/application/views/inventorymodule/modifierviews/InventoryModifierVC.dart b/lib/application/views/inventorymodule/modifierviews/InventoryModifierVC.dart index a3edd4f..2fecb0b 100644 --- a/lib/application/views/inventorymodule/modifierviews/InventoryModifierVC.dart +++ b/lib/application/views/inventorymodule/modifierviews/InventoryModifierVC.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); @@ -62,6 +53,10 @@ class _InventoryModifierVCState extends BaseStatefulState { ), AppSpaces.horizontalSmall, newModifier(), + Flexible(child: PageLimitDropdown(onChange: (value) { + viewModel.fetch( + isRefresh: true, limit: int.parse(value!)); + })) ], ), AppSpaces.verticalMedium, @@ -125,7 +120,7 @@ class _InventoryModifierVCState 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/inventorymodule/modifierviews/InventoryNewModifierVC.dart b/lib/application/views/inventorymodule/modifierviews/InventoryNewModifierVC.dart index 4b1f26c..5bf2efb 100644 --- a/lib/application/views/inventorymodule/modifierviews/InventoryNewModifierVC.dart +++ b/lib/application/views/inventorymodule/modifierviews/InventoryNewModifierVC.dart @@ -36,6 +36,7 @@ class _InventoryNewModifierVCState @override void initState() { + context.read().initModifier(widget.isEdit, widget.modifier); super.initState(); } @@ -48,7 +49,6 @@ class _InventoryNewModifierVCState @override Widget build(BuildContext context) { viewModel = context.watch(); - viewModel.initModifier(widget.isEdit, widget.modifier); return Directionality( textDirection: TextDirection.ltr, child: Dialog( @@ -82,7 +82,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; }, @@ -299,7 +299,7 @@ class _InventoryNewModifierVCState AppLocalizations.of(context)! .name, initialValue: viewModel - .modifier.options![position].name, + .modifier.options[position].name, onChanged: (value) { viewModel.onChangeModifierOption( value, position); @@ -329,7 +329,7 @@ class _InventoryNewModifierVCState value, position); }, initialValue: viewModel.modifier - .options![position].arabicName, + .options[position].arabicName, ), ), )), @@ -352,7 +352,7 @@ class _InventoryNewModifierVCState value, position); }, initialValue: viewModel - .modifier.options![position].price + .modifier.options[position].price .toString(), hintText: AppLocalizations.of(context)! diff --git a/lib/application/views/inventorymodule/modifierviews/viewModels/ModiferViewModel.dart b/lib/application/views/inventorymodule/modifierviews/viewModels/ModiferViewModel.dart index fa5259b..fa5947a 100644 --- a/lib/application/views/inventorymodule/modifierviews/viewModels/ModiferViewModel.dart +++ b/lib/application/views/inventorymodule/modifierviews/viewModels/ModiferViewModel.dart @@ -9,7 +9,7 @@ class ModifierViewModel extends ChangeNotifier { bool _isLoading = false; bool get isLoading => _isLoading; - + int limit = 10; int _currentPageNumber = 1; DataState _dataState = DataState.uninitialized; @@ -29,7 +29,8 @@ class ModifierViewModel extends ChangeNotifier { 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,6 +45,7 @@ class ModifierViewModel extends ChangeNotifier { Map data = { 'store_id': sharedPrefs.storeId, 'page': _currentPageNumber, + 'limit': this.limit }; try { @@ -61,7 +63,7 @@ class ModifierViewModel extends ChangeNotifier { if (value.success!) { _filteredList.addAll(value.modifiers!); _dataList.addAll(value.modifiers!); - if (value.modifiers!.length < 10) { + if (value.modifiers!.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; diff --git a/lib/application/views/inventorymodule/modifierviews/viewModels/NewModifierVM.dart b/lib/application/views/inventorymodule/modifierviews/viewModels/NewModifierVM.dart index 7c272a0..db7ca4e 100644 --- a/lib/application/views/inventorymodule/modifierviews/viewModels/NewModifierVM.dart +++ b/lib/application/views/inventorymodule/modifierviews/viewModels/NewModifierVM.dart @@ -45,9 +45,9 @@ class NewModifierVM with ChangeNotifier { // } } else { // modifier.options = []; - if (modifier.options!.isEmpty) { + if (modifier.options.isEmpty) { print('here'); - modifier.options!.add( + modifier.options.add( ModifierOption(name: '', arabicName: '', price: 0), ); } @@ -69,15 +69,15 @@ 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) { + } 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) { + } 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) { + 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; @@ -111,22 +111,22 @@ 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(); } @@ -135,7 +135,7 @@ class NewModifierVM with ChangeNotifier { // controllersArabic.add(''); // controllersPrice.add(''); - modifier.options!.add(ModifierOption(name: '', arabicName: '')); + modifier.options.add(ModifierOption(name: '', arabicName: '')); notifyListeners(); } diff --git a/lib/application/views/inventorymodule/productviews/AddNewInventoryProductVC.dart b/lib/application/views/inventorymodule/productviews/AddNewInventoryProductVC.dart index a99474a..0b81cbf 100644 --- a/lib/application/views/inventorymodule/productviews/AddNewInventoryProductVC.dart +++ b/lib/application/views/inventorymodule/productviews/AddNewInventoryProductVC.dart @@ -68,837 +68,1221 @@ class _AddNewInventoryProductVCState extends State 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( + 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 SingleChildScrollView( - child: Container( - color: MyColors.white, - padding: const EdgeInsets.all(8), - child: Column( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), + return SingleChildScrollView( + child: Container( + color: MyColors.white, + padding: const EdgeInsets.all(8), + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: Padding( + padding: const EdgeInsets.all(15), + child: isPortrait + ? 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); + }, + ) + ], + ), + ) + ], + ) + : Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Expanded( + flex: 1, + child: Column( + 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, + ), + ), + ], + ), + ), + const SizedBox( + width: 12, ), - child: Padding( - padding: const EdgeInsets.all(15), - child: isPortrait - ? Column( - crossAxisAlignment: CrossAxisAlignment.start, + 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, + ), + ), + ], + )), + const SizedBox( + width: 12, + ), + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + MandatoryTitleText( + hint: AppLocalizations.of(context)! + .barcode), + const SizedBox( + height: 4, + ), + Row( children: [ - MandatoryTitleText( - hint: AppLocalizations.of(context)! - .item_name, + 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: 4, + ], + ), + 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); + }, + ) + ], + ), + ) + ], + )), + ], + ), + ), + ), + 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)! + .price_quantity_tax_additional_information, + style: ThemeText.textStyleHeadingCart, + ), + const SizedBox( + height: 12, + ), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: AppLocalizations.of(context)! + .sale_price_excl_tax), + AppSpaces.verticalSmall, 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); - }) - ], + readOnly: true, + initialValue: + viewModel.salePriceExclTax, + key: Key(viewModel.salePriceExclTax), + keyboardType: TextInputType.number, + onChanged: (value) {}, + hintText: + 'Enter Sale Price (Excl. Tax)', ), - const SizedBox( - height: 4, + ], + )), + AppSpaces.horizontalMedium, + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + const CustomOptionalTitle( + hint: 'Price (Incl. Tax)', ), + AppSpaces.verticalSmall, CustomTextFieldForm( - hintText: 'Enter Quantity', - readOnly: widget.isView || - viewModel - .storeItem.isUnlimitedQuantity, + initialValue: + viewModel.purchasePriceExclTax, + hintText: 'Enter Price (Incl. Tax)', + readOnly: widget.isView, keyboardType: TextInputType.number, onChanged: (value) { - viewModel.setQuantity(value); + viewModel.purchasePriceExclTax = + 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, - ), + ], + )), + AppSpaces.horizontalMedium, + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ CustomOptionalTitle( hint: AppLocalizations.of(context)! - .item_name_ar_optional, - ), - const SizedBox( - height: 4, + .stock_alert_quantity, ), + AppSpaces.verticalSmall, CustomTextFieldForm( + initialValue: + viewModel.stockAlertQuantity, + hintText: 'Enter Stock Alert Quantity', readOnly: widget.isView, + keyboardType: TextInputType.number, onChanged: (value) { - viewModel.productCode = value; + viewModel.stockAlertQuantity = 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, ), + ], + )), + ], + ), + const SizedBox( + height: 12, + ), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ 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, + hint: AppLocalizations.of(context)! + .discount, ), - MandatoryTitleText( - hint: - AppLocalizations.of(context)!.barcode, + AppSpaces.verticalSmall, + getDiscounts(context), + ], + )), + AppSpaces.horizontalMedium, + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: AppLocalizations.of(context)! + .supplier, ), - const SizedBox( - height: 4, + AppSpaces.verticalSmall, + getSupplierWidget(context), + ], + )), + ], + ), + const SizedBox( + height: 12, + ), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: AppLocalizations.of(context)! + .manufacturer_date, ), - 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', - ), + AppSpaces.verticalSmall, + Container( + height: 48, + padding: + const EdgeInsets.only(right: 8), + decoration: BoxDecoration( + border: Border.all( + color: Colors.transparent, + width: 1, ), - ], - ), - const SizedBox( - height: 8, - ), - MandatoryTitleText( - hint: AppLocalizations.of(context)! - .status), - const SizedBox( - height: 4, - ), - SizedBox( - height: 44, + color: MyColors.backFillColor, + borderRadius: + BorderRadius.circular(8.0), + ), child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + crossAxisAlignment: + CrossAxisAlignment.stretch, children: [ - const CustomOptionalTitle( - hint: 'Item In Stock', - ), - const SizedBox( - width: 6, - ), - CustomSwitch( - value: viewModel - .storeItem.isItemInStock, - onToggle: (value) { - viewModel - .setItemInStockStatus(value); - }, + 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, ) ], ), - ) + ), ], - ) - : Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.min, + )), + AppSpaces.horizontalMedium, + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, children: [ - Expanded( - flex: 1, - child: Column( + 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.start, + CrossAxisAlignment.stretch, 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, - ), - ), + 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, + ) ], ), ), - const SizedBox( - width: 12, - ), - 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, - ), - ), - ], - )), - const SizedBox( - width: 12, - ), - 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); - }, - ) - ], - ), - ) - ], - )), ], - ), + )), + ], ), - ), - const SizedBox( - height: 12, - ), - Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(4.0), + ], + ), + ), + ), + 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, + children: [ + Text( + AppLocalizations.of(context)! + .delivery_partner_price, + style: ThemeText.textStyleHeadingCart, ), - child: Container( - padding: const EdgeInsets.all(8), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, + const SizedBox( + height: 8, + ), + 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: [ - Text( - AppLocalizations.of(context)! - .price_quantity_tax_additional_information, - style: ThemeText.textStyleHeadingCart, - ), - const SizedBox( - height: 12, + 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( + AppLocalizations.of(context)! + .name), + ), ), - 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)', + 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), ), - AppSpaces.verticalSmall, - CustomTextFieldForm( - initialValue: - viewModel.purchasePriceExclTax, - hintText: 'Enter Price (Incl. Tax)', - readOnly: widget.isView, - keyboardType: TextInputType.number, - onChanged: (value) { - viewModel.purchasePriceExclTax = - value; - }, + ), + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + 'Delivery Partner Price(Exclusive of vat & Including vat)', ), - ], + ), )), - 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; - }, + Container( + width: 44, + height: 48, + decoration: const BoxDecoration( + border: Border( + right: BorderSide( + width: 1.0, + color: MyColors + .fillColorGray2), + ), + ), + child: Container(), + ) + ], + ), + ), + 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, + child: Row( + children: [ + Expanded( + child: Container( + height: 48, + decoration: const BoxDecoration( + border: Border( + right: BorderSide( + width: 1.0, + color: MyColors + .fillColorGray2), ), - ], - )), - ], - ), - const SizedBox( - height: 12, - ), - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - CustomOptionalTitle( - hint: AppLocalizations.of(context)! - .discount, + ), + child: Center( + child: Text( + '', + style: + MyColors.textStyleValue(), ), - AppSpaces.verticalSmall, - getDiscounts(context), - ], + ), )), - AppSpaces.horizontalMedium, - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - CustomOptionalTitle( - hint: AppLocalizations.of(context)! - .supplier, + 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, ), - AppSpaces.verticalSmall, - getSupplierWidget(context), - ], - )), - ], - ), - const SizedBox( - height: 12, + onPressed: () { + viewModel + .addNewDeliveryPartner(); + }), + ), ), - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - CustomOptionalTitle( - hint: AppLocalizations.of(context)! - .manufacturer_date, + ], + ), + ) + : 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), ), - 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, - ) - ], - ), + ), + child: Center( + child: Text( + '', + style: + MyColors.textStyleValue(), ), - ], + ), )), - AppSpaces.horizontalMedium, - Expanded( - child: Column( + 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(); + }), + ), + ), + ], + ), + ), + ], + ), + ), + ), + const SizedBox( + height: 12, + ), + Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(4.0), + ), + child: Container( + padding: const EdgeInsets.all(8), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Container( + padding: const EdgeInsets.all(8), + child: Column( crossAxisAlignment: - CrossAxisAlignment.start, + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, children: [ + Text( + AppLocalizations.of(context)! + .search_and_add_products, + style: ThemeText.textStyleHeadingCart, + ), + const SizedBox( + height: 12, + ), CustomOptionalTitle( hint: AppLocalizations.of(context)! - .expiry_date, + .search, ), - AppSpaces.verticalSmall, - Container( - height: 48, - padding: - const EdgeInsets.only(right: 8), - decoration: BoxDecoration( - border: Border.all( - color: Colors.transparent, - width: 1, + const SizedBox( + height: 4, + ), + getIngredientsWidget(context), + const SizedBox( + height: 4, + ), + CustomOptionalTitle( + hint: AppLocalizations.of(context)! + .choose_ingredients), + const SizedBox( + height: 12, + ), + ], + ), + )), + 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, + ), ), - 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, - ) - ], ), + 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, ), ], - )), - ], - ), - ], - ), - ), - ), - const SizedBox( - height: 12, - ), - Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(4.0), + ), + )), + ], ), - child: Container( - width: double.infinity, + isPortrait + ? Container( padding: const EdgeInsets.all(8), child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + 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)! - .delivery_partner_price, - style: ThemeText.textStyleHeadingCart, - ), - const SizedBox( - height: 8, + .option_enable_product_invoice, + style: ThemeText.textStyleHeading, ), - 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: [ - Container( + ], + ), + ) + : Container(), + Visibility( + visible: viewModel + .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, + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + Expanded( + child: Container( padding: - const EdgeInsets.only(left: 8), + const EdgeInsets.only( + left: 4, right: 4), height: 48, - width: 250, - decoration: const BoxDecoration( + decoration: + const BoxDecoration( border: Border( right: BorderSide( width: 1.0, @@ -907,18 +1291,23 @@ class _AddNewInventoryProductVCState extends State ), ), child: Align( - alignment: Alignment.centerLeft, + alignment: + Alignment.centerLeft, child: HeadingText( - AppLocalizations.of(context)! - .name), + AppLocalizations.of( + context)! + .name_description, + ), ), - ), - Expanded( - child: Container( - padding: const EdgeInsets.only( + )), + Expanded( + child: Container( + padding: + const EdgeInsets.only( left: 4, right: 4), height: 48, - decoration: const BoxDecoration( + decoration: + const BoxDecoration( border: Border( right: BorderSide( width: 1.0, @@ -927,16 +1316,20 @@ class _AddNewInventoryProductVCState extends State ), ), child: Align( - alignment: Alignment.centerLeft, + alignment: + Alignment.centerLeft, child: HeadingText( - 'Delivery Partner Price(Exclusive of vat & Including vat)', - ), + 'Purchase Price of 1 Unit'), ), )), - Container( - width: 44, + Expanded( + child: Container( + padding: + const EdgeInsets.only( + left: 4, right: 4), height: 48, - decoration: const BoxDecoration( + decoration: + const BoxDecoration( border: Border( right: BorderSide( width: 1.0, @@ -944,33 +1337,21 @@ class _AddNewInventoryProductVCState extends State .fillColorGray2), ), ), - child: Container(), - ) - ], - ), - ), - getListViewDeliveryPartner(), - isPortrait - ? Container( - margin: - const EdgeInsets.fromLTRB(8, 0, 0, 8), - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular( - 1.0) // <--- border radius here + child: Align( + alignment: + Alignment.centerLeft, + child: HeadingText( + 'Sale Price of 1 Unit'), ), - border: Border.all( - width: 1, - color: MyColors.fillColorGray2), - color: Colors.white, - ), - height: 48, - child: Row( - children: [ - Expanded( - child: Container( + )), + Expanded( + child: Container( + padding: + const EdgeInsets.only( + left: 4, right: 4), height: 48, - decoration: const BoxDecoration( + decoration: + const BoxDecoration( border: Border( right: BorderSide( width: 1.0, @@ -978,61 +1359,21 @@ class _AddNewInventoryProductVCState extends State .fillColorGray2), ), ), - child: Center( - child: Text( - '', - style: - MyColors.textStyleValue(), - ), + child: Align( + alignment: + Alignment.centerLeft, + child: HeadingText( + 'Sale Price of 1 Unit'), ), )), - 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(); - }), - ), - ), - ], - ), - ) - : 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( + Expanded( + child: Container( + padding: + const EdgeInsets.only( + left: 4, right: 4), height: 48, - decoration: const BoxDecoration( + decoration: + const BoxDecoration( border: Border( right: BorderSide( width: 1.0, @@ -1040,423 +1381,103 @@ class _AddNewInventoryProductVCState extends State .fillColorGray2), ), ), - child: Center( - child: Text( - '', - style: - MyColors.textStyleValue(), - ), + child: Align( + alignment: + Alignment.centerLeft, + child: HeadingText( + 'Measuring Unit'), ), )), - 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(); - }), - ), + Container( + width: 48, + height: 48, + decoration: + const BoxDecoration( + border: Border( + right: BorderSide( + width: 1.0, + color: MyColors + .fillColorGray2), ), - ], - ), - ), - ], - ), - ), - ), - const SizedBox( - height: 12, - ), - Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(4.0), - ), - child: Container( - padding: const EdgeInsets.all(8), - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - 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: ThemeText.textStyleHeadingCart, - ), - const SizedBox( - height: 12, - ), - CustomOptionalTitle( - hint: AppLocalizations.of(context)! - .search, - ), - const SizedBox( - height: 4, - ), - getIngredientsWidget(context), - const SizedBox( - height: 4, - ), - CustomOptionalTitle( - hint: AppLocalizations.of(context)! - .choose_ingredients), - const SizedBox( - height: 12, ), - ], - ), - )), - 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, - ), - ], - ), - )), - ], - ), - 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, + child: Center( + child: HeadingText( + '', ), - Text( - AppLocalizations.of(context)! - .option_enable_product_invoice, - style: ThemeText.textStyleHeading, + ), + ) + ], + ), + ), + 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 ), - ], - ), - ) - : Container(), - Visibility( - visible: viewModel - .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, - 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: HeadingText( - 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'), - ), - )), - 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.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'), - ), - )), - Container( - width: 48, - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: HeadingText( - '', - ), - ), - ) - ], - ), - ), - 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( + 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 - .only( - left: 4, - right: 4), - height: 48, + const EdgeInsets + .all(4), decoration: - const BoxDecoration( + const BoxDecoration( border: Border( right: BorderSide( - width: 1.0, + width: + 1.0, color: MyColors .fillColorGray2), ), @@ -1464,23 +1485,31 @@ class _AddNewInventoryProductVCState extends State child: Align( alignment: Alignment .centerLeft, - child: HeadingText( - AppLocalizations.of( - context)! - .name_description), + child: ValueText(viewModel + .storeItem + .ingredients![ + position] + .name), ), - )), - Expanded( + ), + ) + ], + ), + Row( + children: [ + Expanded( child: Container( padding: - const EdgeInsets - .all(4), + const EdgeInsets + .only( + left: 4, + right: 4), + height: 48, decoration: - const BoxDecoration( + const BoxDecoration( border: Border( right: BorderSide( - width: - 1.0, + width: 1.0, color: MyColors .fillColorGray2), ), @@ -1488,31 +1517,21 @@ class _AddNewInventoryProductVCState extends State child: Align( alignment: Alignment .centerLeft, - child: ValueText(viewModel - .storeItem - .ingredients![ - position] - .name), + child: HeadingText( + 'Purchase Price of 1 Unit'), ), - ), - ) - ], - ), - Row( - children: [ - Expanded( - child: Container( + )), + Expanded( + child: Container( padding: - const EdgeInsets - .only( - left: 4, - right: 4), - height: 48, + const EdgeInsets + .all(4), decoration: - const BoxDecoration( + const BoxDecoration( border: Border( right: BorderSide( - width: 1.0, + width: + 1.0, color: MyColors .fillColorGray2), ), @@ -1520,21 +1539,35 @@ class _AddNewInventoryProductVCState extends State child: Align( alignment: Alignment .centerLeft, - child: HeadingText( - 'Purchase Price of 1 Unit'), + child: + ValueText( + viewModel + .storeItem + .ingredients![ + position] + .purchasePrice! + .toString(), + ), ), - )), - Expanded( + ), + ) + ], + ), + Row( + children: [ + Expanded( child: Container( padding: - const EdgeInsets - .all(4), + const EdgeInsets + .only( + left: 4, + right: 4), + height: 48, decoration: - const BoxDecoration( + const BoxDecoration( border: Border( right: BorderSide( - width: - 1.0, + width: 1.0, color: MyColors .fillColorGray2), ), @@ -1542,35 +1575,21 @@ class _AddNewInventoryProductVCState extends State child: Align( alignment: Alignment .centerLeft, - child: - ValueText( - viewModel - .storeItem - .ingredients![ - position] - .purchasePrice! - .toString(), - ), + child: HeadingText( + 'Sale Price of 1 Unit'), ), - ), - ) - ], - ), - Row( - children: [ - Expanded( - child: Container( + )), + Expanded( + child: Container( padding: - const EdgeInsets - .only( - left: 4, - right: 4), - height: 48, + const EdgeInsets + .all(4), decoration: - const BoxDecoration( + const BoxDecoration( border: Border( right: BorderSide( - width: 1.0, + width: + 1.0, color: MyColors .fillColorGray2), ), @@ -1578,21 +1597,32 @@ class _AddNewInventoryProductVCState extends State child: Align( alignment: Alignment .centerLeft, - child: HeadingText( - 'Sale Price of 1 Unit'), + child: ValueText(viewModel + .storeItem + .ingredients![ + position] + .salePrice! + .toString()), ), - )), - Expanded( + ), + ) + ], + ), + Row( + children: [ + Expanded( child: Container( padding: - const EdgeInsets - .all(4), + const EdgeInsets + .only( + left: 4, + right: 4), + height: 48, decoration: - const BoxDecoration( + const BoxDecoration( border: Border( right: BorderSide( - width: - 1.0, + width: 1.0, color: MyColors .fillColorGray2), ), @@ -1600,594 +1630,556 @@ class _AddNewInventoryProductVCState extends State child: Align( alignment: Alignment .centerLeft, - child: ValueText(viewModel - .storeItem - .ingredients![ - position] - .salePrice! - .toString()), + child: HeadingText( + 'Sale Price of 1 Unit'), ), - ), - ) - ], - ), - Row( - children: [ - Expanded( - child: Container( + )), + Expanded( + child: Container( padding: - const EdgeInsets - .only( - left: 4, - right: 4), + const EdgeInsets + .all(4), + width: 100, height: 48, decoration: - const BoxDecoration( + const BoxDecoration( border: Border( right: BorderSide( - width: 1.0, + width: + 1.0, color: MyColors .fillColorGray2), ), ), - child: Align( - alignment: Alignment - .centerLeft, - child: HeadingText( - 'Sale Price of 1 Unit'), + 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( + ), + ) + ], + ), + Row( + children: [ + Expanded( child: Container( padding: - const EdgeInsets - .all(4), - width: 100, + const EdgeInsets + .only( + left: 4, + right: 4), height: 48, decoration: - const BoxDecoration( + const BoxDecoration( border: Border( right: BorderSide( - width: - 1.0, + width: 1.0, color: MyColors .fillColorGray2), ), ), - child: Center( + child: Align( + alignment: Alignment + .centerLeft, 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', + HeadingText( + 'Measuring Unit', ), ), - ), - ) - ], - ), - 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), + )), + 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: - 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 + getMeasurementUnit( + context, + position), + )) + ], ), - 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), + ], + )), + 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, ), - ), - child: Align( - alignment: Alignment - .centerLeft, - child: Text( + onPressed: () { viewModel - .storeItem - .ingredients![ - position] - .name, - style: const TextStyle( - fontSize: 11, - fontFamily: MyFonts - .DMREGULAR, - color: MyColors - .textColorBlack), - ), - ), - ), + .removeUnit( + position); + }), ), - 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), - ), - ), - ), + )), + ], + ), + ); + } 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), ), - 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), - ), - ), - ), + ), + 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), - 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: 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), ), - Expanded( - child: Container( - padding: - const EdgeInsets.all(4), - 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); - }); - }), + ), + 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, ), - )), - ], - ), - ); - } - }, - itemCount: viewModel - .storeItem.ingredients!.length, - ), - ], - )) - ], - ), - ), - ), - 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, - ), - ), - ], - ), - ), - ), - 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, + onPressed: () { + setState(() { + viewModel + .unitsController + .removeAt( + position); + viewModel + .storeItem + .ingredients! + .removeAt( + position); + }); + }), + ), + )), + ], ), - 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(), - ], - ), - ), - ), + ); + } + }, + itemCount: viewModel + .storeItem.ingredients!.length, ), ], + )) + ], + ), + ), + ), + 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, + ), ), - const SizedBox( - height: 12, + ], + ), + ), + ), + 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, + ), + ), + ], + ), + ), ), - Card( + ), + Expanded( + child: 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: [ - CustomOptionalTitle( - hint: AppLocalizations.of(context)!.modifiers, - ), - const SizedBox( - height: 12, - ), - getModifierWidget(), - ], - )), + 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(), + ], + ), + ), ), - Visibility( - visible: !widget.isView, - child: SizedBox( - width: 140, - child: CustomSimpleButton( - textColor: MyColors.white, - isLoading: viewModel.isLoadingData, - backGroundColor: MyColors.blueThemeColor, - onPressed: () { - viewModel.isValidate(context, widget.isEdit); - }, - heading: widget.isEdit - ? "Update" - : AppLocalizations.of(context)!.add_product, - ), - )), - ], + ), + ], + ), + 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: [ + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.modifiers, + ), + const SizedBox( + height: 12, + ), + getModifierWidget(), + ], + )), ), - ); - }), + Visibility( + visible: !widget.isView, + child: SizedBox( + width: 140, + child: CustomSimpleButton( + textColor: MyColors.white, + isLoading: viewModel.isLoadingData, + backGroundColor: MyColors.blueThemeColor, + onPressed: () { + viewModel.isValidate(context, widget.isEdit); + }, + heading: widget.isEdit + ? "Update" + : AppLocalizations.of(context)!.add_product, + ), + )), + ], + ), ), - ), - onWillPop: () { - viewModel.dispose(); - return Future.value(false); - }); + ); + }), + ); } Widget getDeliveryPartner(BuildContext context, int position) { diff --git a/lib/application/views/inventorymodule/productviews/InventoryProductVC.dart b/lib/application/views/inventorymodule/productviews/InventoryProductVC.dart index c5be937..43850c0 100644 --- a/lib/application/views/inventorymodule/productviews/InventoryProductVC.dart +++ b/lib/application/views/inventorymodule/productviews/InventoryProductVC.dart @@ -3,6 +3,7 @@ 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'; @@ -14,6 +15,8 @@ import 'package:wosull/application/views/inventorymodule/productviews/AddNewInve import 'package:wosull/application/views/inventorymodule/productviews/viewModels/ProductViewModel.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/ThemeDropDown.dart'; import 'package:wosull/helpers/ThemeImage.dart'; import 'package:wosull/helpers/ThemeText.dart'; import 'package:wosull/helpers/Utils.dart'; @@ -21,6 +24,7 @@ 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'; @@ -37,63 +41,50 @@ 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); - } - }, - ), - ), - ), - ); - }))), - ); + 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: 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) { @@ -103,35 +94,6 @@ class _InventoryProductVCState extends BaseStatefulState { children: [ isPortrait ? Column( - children: [ - Row( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.start, - 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(), - ), - ], - ), - ], - ) - ], - ) - : Row( children: [ Row( mainAxisAlignment: MainAxisAlignment.start, @@ -140,25 +102,80 @@ class _InventoryProductVCState extends BaseStatefulState { 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.verticalMedium, + Row( + children: [ + Flexible( + 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( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)!.our_products, + style: ThemeText.textStylePageHeading, + ), + AppSpaces.horizontalSmall, + SizedBox( + 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: PageLimitDropdown(onChange: (value) { + viewModel.fetch( + isRefresh: true, limit: int.parse(value!)); + })) ], ), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, viewModel.isLoading ? AppLoader() : data.isEmpty @@ -262,14 +279,13 @@ class _InventoryProductVCState extends BaseStatefulState { 2, 2, 2, 2), // Border radius child: ClipOval( - child: item - .imageUrl! + child: item.imageUrl .isEmpty ? Image.asset( ThemeImage .wosulLogo) : Image.network( - item.imageUrl!)), + item.imageUrl)), ), ), ), @@ -330,7 +346,7 @@ class _InventoryProductVCState extends BaseStatefulState { MainAxisAlignment .start, children: [ - ValueText(item.name!), + ValueText(item.name), const SizedBox( height: 8, ), @@ -340,7 +356,7 @@ class _InventoryProductVCState extends BaseStatefulState { const SizedBox( height: 8, ), - ValueText(item.price! + ValueText(item.price .toString()), const SizedBox( height: 4, @@ -355,11 +371,11 @@ class _InventoryProductVCState extends BaseStatefulState { children: [ CustomSwitch( value: item - .isItemInStock!, + .isItemInStock, onToggle: (value) { _update( - item.id!, + item.itemId, value); }, ) @@ -370,7 +386,7 @@ class _InventoryProductVCState extends BaseStatefulState { ), ValueText(DataTimeFormat .getFormatDate(item - .updatedAt!)), + .updatedAt)), ], )), ], @@ -414,42 +430,41 @@ class _InventoryProductVCState extends BaseStatefulState { 2), // Border radius child: ClipOval( child: item - .imageUrl!.isEmpty + .imageUrl.isEmpty ? Image.asset( ThemeImage .wosulLogo) : Image.network( - item.imageUrl!)), + item.imageUrl)), ), ), ), )), - Expanded( - child: ValueText(item.name!)), + Expanded(child: ValueText(item.name)), Expanded( child: ValueText(viewModel .selectedCategoryDropDown .name)), Expanded( child: ValueText( - item.price!.toString())), + item.price.toString())), Expanded( child: Align( alignment: Alignment.centerLeft, child: CustomSwitch( - value: item.isItemInStock!, + value: item.isItemInStock, onToggle: (value) { setState(() { item.isItemInStock = value; }); - _update(item.id!, value); + _update(item.itemId, value); }, ), )), Expanded( child: ValueText( DataTimeFormat.getFormatDate( - item.updatedAt!))), + item.updatedAt))), Expanded( child: Padding( padding: const EdgeInsets.all(4), @@ -483,7 +498,7 @@ class _InventoryProductVCState extends BaseStatefulState { bool _scrollNotification() { if (!viewModel.isLoading && _controller.position.extentAfter < 300) { - viewModel.fetch(); + viewModel.fetch(limit: viewModel.limit); } return true; } @@ -534,7 +549,7 @@ class _InventoryProductVCState extends BaseStatefulState { if (!mounted) return; bool isDelete = result; if (isDelete) { - _delete(storeItems.id!); + _delete(storeItems.itemId); } } else { Navigator.push( @@ -561,35 +576,22 @@ 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 DropdownSearch( + selectedItem: viewModel.selectedCategoryDropDown, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: const PopupProps.menu( + fit: FlexFit.loose, + constraints: BoxConstraints(maxHeight: 300), ), + clearButtonProps: ThemeDropDown.clearButton, + items: viewModel.categories, + itemAsString: (ItemCategory u) => u.name, + onChanged: (ItemCategory? data) { + if (data != null) { + viewModel.getNewData(data); + } + }, + dropdownDecoratorProps: MyColors.dropDownStyle(fillColor: MyColors.white), ); } diff --git a/lib/application/views/inventorymodule/productviews/viewModels/AddProductViewModel.dart b/lib/application/views/inventorymodule/productviews/viewModels/AddProductViewModel.dart index e9c4bb1..1473b5e 100644 --- a/lib/application/views/inventorymodule/productviews/viewModels/AddProductViewModel.dart +++ b/lib/application/views/inventorymodule/productviews/viewModels/AddProductViewModel.dart @@ -252,7 +252,7 @@ class AddProductViewModel with ChangeNotifier { Future updateProduct(BuildContext context) 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); diff --git a/lib/application/views/inventorymodule/productviews/viewModels/ProductViewModel.dart b/lib/application/views/inventorymodule/productviews/viewModels/ProductViewModel.dart index 9fdcac7..f70fc85 100644 --- a/lib/application/views/inventorymodule/productviews/viewModels/ProductViewModel.dart +++ b/lib/application/views/inventorymodule/productviews/viewModels/ProductViewModel.dart @@ -13,7 +13,7 @@ class ProductViewModel with ChangeNotifier { bool _isFirstLoadRunning = true; bool get isFirstLoadRunning => _isFirstLoadRunning; - + int limit = 10; String selectedCategoryId = ""; List _dataList = []; @@ -99,7 +99,8 @@ class ProductViewModel with ChangeNotifier { } } - 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,6 +118,7 @@ class ProductViewModel with ChangeNotifier { 'product_id': productId, 'category_id': selectedCategoryId, 'page': _currentPageNumber, + 'limit': this.limit }; try { @@ -131,10 +133,10 @@ class ProductViewModel with ChangeNotifier { _filteredList.clear(); _dataList.clear(); } - if (value.success!) { - _filteredList.addAll(value.storeItems!); - _dataList.addAll(value.storeItems!); - if (value.storeItems!.length < 10) { + if (value.success) { + _filteredList.addAll(value.storeItems); + _dataList.addAll(value.storeItems); + if (value.storeItems.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; @@ -199,8 +201,8 @@ class ProductViewModel with ChangeNotifier { .getResponsePatch(Constants.DELETE_PRODUCT, data) .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; @@ -219,9 +221,9 @@ class ProductViewModel with ChangeNotifier { .getResponsePatch(Constants.UPDATE_PRODUCT_STATUS, data) .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 { diff --git a/lib/application/views/inventorymodule/stockTransferViews/InventoryStockTransferVC.dart b/lib/application/views/inventorymodule/stockTransferViews/InventoryStockTransferVC.dart index 935e059..047acdf 100644 --- a/lib/application/views/inventorymodule/stockTransferViews/InventoryStockTransferVC.dart +++ b/lib/application/views/inventorymodule/stockTransferViews/InventoryStockTransferVC.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/StockTransfer/StockTransferDetailsModel.dart'; import 'package:wosull/application/theme/MyColors.dart'; @@ -14,6 +15,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 +51,79 @@ 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, + getNewStockTransferBtn(), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Flexible( + child: SearchBox( + onEditingDone: (text) { + // filterSearchResults(text); + }, + onChanged: (text) { + // filterSearchResults(text); + }, + hint: AppLocalizations.of(context)!.search, + ), + ), + AppSpaces.horizontalSmall, + PageLimitDropdown(onChange: (value) { + viewModel.fetch( + isRefresh: true, + limit: int.parse(value!)); + }) + ], + ), + ], + ) + : Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)!.stock_transfers, + style: ThemeText.textStylePageHeading, + ), + AppSpaces.horizontalSmall, + getNewStockTransferBtn(), + AppSpaces.horizontalSmall, + 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: PageLimitDropdown(onChange: (value) { + viewModel.fetch( + isRefresh: true, limit: int.parse(value!)); + })) + ], + ), AppSpaces.verticalMedium, ChangeNotifierProvider( create: (context) => viewModel, @@ -123,7 +183,7 @@ class _InventoryStockTransferVCState bool _scrollNotification() { if (!viewModel.isLoading && _controller.position.extentAfter < 300) { - viewModel.fetch(); + viewModel.fetch(limit: viewModel.limit); } return true; } @@ -176,7 +236,7 @@ class _InventoryStockTransferVCState Widget getNewStockTransferBtn() { return SizedBox( - width: 180, + width: 140, child: CustomSimpleButton( height: 38, heading: AppLocalizations.of(context)!.new_stock_transfer, diff --git a/lib/application/views/inventorymodule/stockTransferViews/viewModels/StockTransferViewModel.dart b/lib/application/views/inventorymodule/stockTransferViews/viewModels/StockTransferViewModel.dart index 66513b8..a549b14 100644 --- a/lib/application/views/inventorymodule/stockTransferViews/viewModels/StockTransferViewModel.dart +++ b/lib/application/views/inventorymodule/stockTransferViews/viewModels/StockTransferViewModel.dart @@ -12,7 +12,7 @@ class StockTransferViewModel with ChangeNotifier { bool _isLoading = false; bool get isLoading => _isLoading; - + int limit = 10; int _currentPageNumber = 1; DataState _dataState = DataState.uninitialized; @@ -24,7 +24,8 @@ class StockTransferViewModel 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) @@ -39,6 +40,7 @@ class StockTransferViewModel with ChangeNotifier { Map data = { 'store_id': sharedPrefs.storeId, 'page': _currentPageNumber, + 'limit': this.limit }; try { @@ -54,7 +56,7 @@ class StockTransferViewModel with ChangeNotifier { } if (value.success) { _filteredList.addAll(value.stockTransfers); - if (value.stockTransfers.length < 10) { + if (value.stockTransfers.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; diff --git a/lib/application/views/inventorymodule/subCategoryViews/InventorySubCategoryVC.dart b/lib/application/views/inventorymodule/subCategoryViews/InventorySubCategoryVC.dart index b5f1fa9..70c8cc6 100644 --- a/lib/application/views/inventorymodule/subCategoryViews/InventorySubCategoryVC.dart +++ b/lib/application/views/inventorymodule/subCategoryViews/InventorySubCategoryVC.dart @@ -1,24 +1,20 @@ -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/ItemSubCategoryResponse.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'; import 'package:wosull/helpers/AppSpaces.dart'; -import 'package:wosull/helpers/ThemeDropDown.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/ItemCategoryDropdown.dart'; import 'package:wosull/widgets/MandatoryTitleText.dart'; -import '../../../model/inventory/category/ItemCategory.dart'; - class InventorySubCategoryVC extends StatefulWidget { ItemSubCategory subCategory; bool isEdit = false; @@ -45,14 +41,16 @@ class _InventorySubCategoryVCState @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( @@ -92,8 +90,8 @@ class _InventorySubCategoryVCState MandatoryTitleText( hint: AppLocalizations.of(context)!.category), - AppSpaces.horizontalSmall, - getCategoryWidget(context), + AppSpaces.verticalSmall, + getCategoryWidget(), const SizedBox( height: 8, ), @@ -272,38 +270,15 @@ 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 ItemCategoryDropdown( + isEdit: widget.isEdit, + categoryId: viewModel.categoryId, + onChanged: (data) { + viewModel.setCategory(data); + }, + selectedCategoryDropDown: viewModel.selectedCategory, + ); } Future addUpdateSubCategory() async { diff --git a/lib/application/views/inventorymodule/subCategoryViews/SubCategoryVC.dart b/lib/application/views/inventorymodule/subCategoryViews/SubCategoryVC.dart index 09012eb..dd6294b 100644 --- a/lib/application/views/inventorymodule/subCategoryViews/SubCategoryVC.dart +++ b/lib/application/views/inventorymodule/subCategoryViews/SubCategoryVC.dart @@ -1,7 +1,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'; @@ -18,6 +18,9 @@ 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/ItemCategoryDropdown.dart'; +import 'package:wosull/widgets/PageLimitDropDown.dart'; +import 'package:wosull/widgets/SearchBox.dart'; class SubCategoryVC extends StatefulWidget { const SubCategoryVC({super.key}); @@ -34,100 +37,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( 'Sub Categories', style: ThemeText.textStylePageHeading, ), - AppSpaces.horizontalSmall, - SizedBox( - width: 150, child: getCategoriesDropdown()), - AppSpaces.horizontalSmall, + const SizedBox( + width: 4, + ), + Flexible(child: getCategoriesDropdown()), + ], + ), + AppSpaces.verticalSmall, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ 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: [ + const Text( + 'Sub Categories', + style: ThemeText.textStylePageHeading, + ), + AppSpaces.horizontalSmall, + SizedBox( + width: 150, child: getCategoriesDropdown()), + AppSpaces.horizontalSmall, + SizedBox( + width: 140, + child: addSubCategoryButton(), + ), + 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, + 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.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); + } + }, + ), + ) + ], + ), + ), + ); + })); } Widget showList(List data) { @@ -164,49 +208,42 @@ 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(); - } - }, + return SizedBox( + height: 38, + child: ItemCategoryDropdown( + fillColor: MyColors.white, + onChanged: (data) { + viewModel.fetchCategories(isRefresh: true, category: data); + }), ); } + // Widget getCategoriesDropdown() { + // return FutureBuilder( + // future: viewModel.getCategory(), + // builder: (context, snapshot) { + // if (snapshot.hasData) { + // var itemsData = snapshot.data ?? []; + // return SizedBox( + // height: 38, + // child: ItemCategoryDropdown( + // fillColor: MyColors.white, + // items: itemsData, + // onChanged: (data) { + // viewModel.fetchCategories(isRefresh: true, category: data); + // }, + // selectedCategoryDropDown: viewModel.selectedCategoryDropDown), + // ); + // } else { + // return AppLoader(); + // } + // }, + // ); + // } + bool _scrollNotification() { if (!viewModel.isLoading && _controller.position.extentAfter < 300) { - viewModel.fetchCategories(); + viewModel.fetchCategories(limit: viewModel.limit); } return true; } diff --git a/lib/application/views/inventorymodule/subCategoryViews/viewModels/AddSubCategoryViewModel.dart b/lib/application/views/inventorymodule/subCategoryViews/viewModels/AddSubCategoryViewModel.dart index 3ef83b4..4e5fed2 100644 --- a/lib/application/views/inventorymodule/subCategoryViews/viewModels/AddSubCategoryViewModel.dart +++ b/lib/application/views/inventorymodule/subCategoryViews/viewModels/AddSubCategoryViewModel.dart @@ -92,6 +92,8 @@ class AddSubCategoryViewModel with ChangeNotifier { nameController = subCategory.name; arabicController = subCategory.arabicName; } + + getStores(); } Future addCategory() async { diff --git a/lib/application/views/inventorymodule/subCategoryViews/viewModels/SubCategoryViewModel.dart b/lib/application/views/inventorymodule/subCategoryViews/viewModels/SubCategoryViewModel.dart index d48dba6..d9e4b92 100644 --- a/lib/application/views/inventorymodule/subCategoryViews/viewModels/SubCategoryViewModel.dart +++ b/lib/application/views/inventorymodule/subCategoryViews/viewModels/SubCategoryViewModel.dart @@ -1,5 +1,3 @@ -import 'dart:convert'; - import 'package:flutter/cupertino.dart'; import 'package:wosull/application/enum/DataState.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; @@ -18,11 +16,11 @@ class SubCategoryViewModel with ChangeNotifier { int _currentPageNumber = 1; bool _isFirstLoadRunning = true; - + int limit = 10; bool get isFirstLoadRunning => _isFirstLoadRunning; String productId = ""; - late ItemCategory selectedCategoryDropDown; + // late ItemCategory selectedCategoryDropDown; //using this state to handle for get data and pagination DataState _dataState = DataState.uninitialized; @@ -62,22 +60,24 @@ class SubCategoryViewModel with ChangeNotifier { itemCategoryResponse.categories.isNotEmpty) { categories.addAll(itemCategoryResponse.categories); } - selectedCategoryDropDown = ItemCategory( - name: "Choose", - id: '', - isVisibleInStore: false, - createdAt: '', - updatedAt: '', - description: '', - arabicName: '', - store_id: [], - image_url: '', - ); + // selectedCategoryDropDown = ItemCategory( + // name: "Choose", + // id: '', + // isVisibleInStore: false, + // createdAt: '', + // updatedAt: '', + // description: '', + // arabicName: '', + // store_id: [], + // image_url: '', + // ); }).onError((error, stackTrace) {}); return categories; } - 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,15 +95,16 @@ 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; @@ -111,7 +112,6 @@ class SubCategoryViewModel with ChangeNotifier { await APIManager() .fetchData(Constants.GET_SUBCATEGORIES_URL, data) .then((result) { - print(jsonEncode(result)); final value = ItemSubCategoriesResponse.fromJson(result); if (_dataState == DataState.refreshing) { _filteredList.clear(); @@ -120,7 +120,7 @@ class SubCategoryViewModel with ChangeNotifier { if (value.success) { _filteredList.addAll(value.categories); _dataList.addAll(value.categories); - if (value.categories.length < 10) { + if (value.categories.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; @@ -129,17 +129,14 @@ 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(); @@ -176,7 +173,6 @@ class SubCategoryViewModel with ChangeNotifier { await APIManager() .getResponseAuth('${Constants.GET_SUB_CATEGORY_BY_ID}$id') .then((response) { - print(response); final value = SubCategoryResponse.fromJson(response); if (value.success) { category = value.subCategory; diff --git a/lib/application/views/inventorymodule/viewmodel/ProductViewModel.dart b/lib/application/views/inventorymodule/viewmodel/ProductViewModel.dart index 2abc403..da963e3 100644 --- a/lib/application/views/inventorymodule/viewmodel/ProductViewModel.dart +++ b/lib/application/views/inventorymodule/viewmodel/ProductViewModel.dart @@ -11,13 +11,14 @@ class ProductViewModel with ChangeNotifier { DataState _dataState = DataState.uninitialized; bool _didLastLoad = false; - + int limit = 10; DataState get dataState => _dataState; List _dataList = []; List get dataList => _dataList; - fetchReportsProducts({bool isRefresh = false}) async { + fetchReportsProducts({bool isRefresh = false, int limit = 10}) async { + this.limit = limit; if (!isRefresh) { _dataState = (_dataState == DataState.uninitialized) ? DataState.initialFetching @@ -31,7 +32,7 @@ class ProductViewModel with ChangeNotifier { 'store_id': sharedPrefs.storeId, 'page': _currentPageNumber, 'is_export': false, - 'limit': 10 + 'limit': this.limit }; try { if (_didLastLoad) { @@ -46,7 +47,7 @@ class ProductViewModel with ChangeNotifier { } if (value.success!) { _dataList.addAll(value.storeItems!); - if (value.storeItems!.length < 10) { + if (value.storeItems!.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; diff --git a/lib/application/views/kitchenmodule/viewModel/KitchenViewModel.dart b/lib/application/views/kitchenmodule/viewModel/KitchenViewModel.dart index 2df316f..0f41afc 100644 --- a/lib/application/views/kitchenmodule/viewModel/KitchenViewModel.dart +++ b/lib/application/views/kitchenmodule/viewModel/KitchenViewModel.dart @@ -12,6 +12,7 @@ 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/main.dart'; class KitchenViewModel with ChangeNotifier { int _currentPageNumber = 1; @@ -111,7 +112,7 @@ class KitchenViewModel with ChangeNotifier { .fetchData(Constants.UPDATE_ORDER_STATUS, data) .then((result) { final response = SimpleResponseModel.fromJson(result); - if (response.success!) { + if (response.success) { _filteredList.removeWhere((element) => element.id! == id); _dataList.removeWhere((element) => element.id! == id); notifyListeners(); @@ -148,7 +149,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 +177,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(); @@ -189,21 +190,19 @@ class KitchenViewModel with ChangeNotifier { 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); + // Future.delayed(const Duration(milliseconds: 500), () { + // notifyListeners(); // Here you can write your code + // }); + } } diff --git a/lib/application/views/kitchenmodule/viewModel/TablesViewModel.dart b/lib/application/views/kitchenmodule/viewModel/TablesViewModel.dart index 7f2688c..2ce2920 100644 --- a/lib/application/views/kitchenmodule/viewModel/TablesViewModel.dart +++ b/lib/application/views/kitchenmodule/viewModel/TablesViewModel.dart @@ -8,6 +8,7 @@ import 'package:wosull/application/utils/Constants.dart'; class TablesViewModel with ChangeNotifier { int _currentPageNumber = 1; DataState _dataState = DataState.uninitialized; + int limit = 10; bool _didLastLoad = false; bool _isLoading = false; @@ -22,7 +23,8 @@ class TablesViewModel 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,7 +38,8 @@ class TablesViewModel with ChangeNotifier { notifyListeners(); Map data = { 'store_id': sharedPrefs.storeId, - 'page': _currentPageNumber + 'page': _currentPageNumber, + 'limit': this.limit }; try { @@ -54,7 +57,7 @@ class TablesViewModel with ChangeNotifier { if (value.success) { _filteredList.addAll(value.storeTables); _dataList.addAll(value.storeTables); - if (value.storeTables.length < 10) { + if (value.storeTables.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; diff --git a/lib/application/views/kitchenmodule/views/KitchenMainTableVC.dart b/lib/application/views/kitchenmodule/views/KitchenMainTableVC.dart index b1b8011..b34ad39 100644 --- a/lib/application/views/kitchenmodule/views/KitchenMainTableVC.dart +++ b/lib/application/views/kitchenmodule/views/KitchenMainTableVC.dart @@ -1,14 +1,14 @@ 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'; class KitchenMainTableVC extends StatefulWidget { final DrawerWidgetSelect delegateDrawer; - KitchenMainTableVC({Key? key, required this.delegateDrawer}) + const KitchenMainTableVC({Key? key, required this.delegateDrawer}) : super(key: key); @override diff --git a/lib/application/views/kitchenmodule/views/kitchen/KitchenViewVC.dart b/lib/application/views/kitchenmodule/views/kitchen/KitchenViewVC.dart index c61496b..44fc037 100644 --- a/lib/application/views/kitchenmodule/views/kitchen/KitchenViewVC.dart +++ b/lib/application/views/kitchenmodule/views/kitchen/KitchenViewVC.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/widgets/KitchenListView.dart b/lib/application/views/kitchenmodule/views/kitchen/widgets/KitchenListView.dart index 33041d7..fa53735 100644 --- a/lib/application/views/kitchenmodule/views/kitchen/widgets/KitchenListView.dart +++ b/lib/application/views/kitchenmodule/views/kitchen/widgets/KitchenListView.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( 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/KitchenOfflineListView.dart b/lib/application/views/kitchenmodule/views/kitchen/widgets/offline/KitchenOfflineListView.dart index 8c7426c..bb0962a 100644 --- a/lib/application/views/kitchenmodule/views/kitchen/widgets/offline/KitchenOfflineListView.dart +++ b/lib/application/views/kitchenmodule/views/kitchen/widgets/offline/KitchenOfflineListView.dart @@ -1,7 +1,10 @@ +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'; @@ -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( @@ -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/KitchenTableVC.dart b/lib/application/views/kitchenmodule/views/table/KitchenTableVC.dart index 9380d12..f4f245e 100644 --- a/lib/application/views/kitchenmodule/views/table/KitchenTableVC.dart +++ b/lib/application/views/kitchenmodule/views/table/KitchenTableVC.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,15 @@ class _KitchenTableVCState extends BaseStatefulState { AppLocalizations.of(context)!.new_table, ), ), + Flexible( + child: PageLimitDropdown(onChange: (value) { + viewModel.fetch( + isRefresh: true, + limit: int.parse(value!)); + })) ], ), - const SizedBox( - height: 4, - ), + AppSpaces.verticalSmall, SizedBox( height: 48, child: SearchBox( @@ -118,9 +121,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 +147,7 @@ class _KitchenTableVCState extends BaseStatefulState { }, ), ), - ], - )), - Expanded( - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ + AppSpaces.horizontalSmall, SizedBox( width: 240, height: 48, @@ -168,6 +164,11 @@ class _KitchenTableVCState extends BaseStatefulState { ), ], )), + Flexible( + child: PageLimitDropdown(onChange: (value) { + viewModel.fetch( + isRefresh: true, limit: int.parse(value!)); + })) ], ), AppSpaces.verticalMedium, @@ -230,7 +231,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/salesandordermodule/viewModel/QuotationViewModel.dart b/lib/application/views/salesandordermodule/viewModel/QuotationViewModel.dart index 4725d74..8f43428 100644 --- a/lib/application/views/salesandordermodule/viewModel/QuotationViewModel.dart +++ b/lib/application/views/salesandordermodule/viewModel/QuotationViewModel.dart @@ -9,7 +9,7 @@ class QuotationViewModel with ChangeNotifier { int _currentPageNumber = 1; String filterValue = 'All'; DataState _dataState = DataState.uninitialized; - + int limit = 10; bool _didLastLoad = false; bool _isLoading = false; @@ -23,7 +23,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,6 +41,7 @@ class QuotationViewModel with ChangeNotifier { 'store_id': sharedPrefs.storeId, 'page': _currentPageNumber, 'quotation_status': filterValue, + 'limit': this.limit }; try { @@ -57,7 +59,7 @@ class QuotationViewModel 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; diff --git a/lib/application/views/salesandordermodule/views/AddInvoiceAndPrintVC.dart b/lib/application/views/salesandordermodule/views/AddInvoiceAndPrintVC.dart index 8421853..4c5930b 100644 --- a/lib/application/views/salesandordermodule/views/AddInvoiceAndPrintVC.dart +++ b/lib/application/views/salesandordermodule/views/AddInvoiceAndPrintVC.dart @@ -11,6 +11,7 @@ import 'package:wosull/application/views/salesandordermodule/views/invoiceModule 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/IconButton.dart'; import 'package:wosull/widgets/QRCodeGenerate.dart'; @@ -25,15 +26,8 @@ class AddInvoiceAndPrintVC extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( 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(), diff --git a/lib/application/views/salesandordermodule/views/ReturnInvoiceVC.dart b/lib/application/views/salesandordermodule/views/ReturnInvoiceVC.dart index 19f0689..eb23bb5 100644 --- a/lib/application/views/salesandordermodule/views/ReturnInvoiceVC.dart +++ b/lib/application/views/salesandordermodule/views/ReturnInvoiceVC.dart @@ -1,19 +1,29 @@ -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/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/ValueText.dart'; class ReturnInvoiceVC extends StatefulWidget { StoreInvoice storeInvoice; @@ -27,45 +37,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,12 +67,10 @@ 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( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(4.0), @@ -93,206 +84,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,1120 +140,244 @@ 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 (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), - ), + if (viewModel.isPortrait) { + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + returnCheckBoxWidget(position), + Expanded( + flex: 2, + child: Container( + decoration: BoxDecoration( + borderRadius: const BorderRadius + .all( + Radius.circular( + 1.0) // <--- border radius here + ), + border: Border.all( + width: 1, + 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( - widget - .storeInvoice - .products[ - position] - .amount! - .toStringAsFixed( - 2) ?? - 0.toString(), - style: const TextStyle( - fontFamily: - MyFonts.Bold, - fontWeight: - FontWeight - .bold, - fontSize: 11, - color: MyColors - .textColorBlack20), - ), - ), + ), + ], + )), + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + 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: Center( + child: ValueText(widget + .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: ValueText( + 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: [ 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( - getTotalProductsPrice(), - style: MyColors.textStyleValue(), - ), - ), + heading: + 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: () { - 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, - )); - }); - }), - ), - ), + getAddButtonWidget(), ], ), ) - : 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( + HeadingContainer( 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, - )); - }); - }), - ), + heading: + viewModel.getTotalProductsPrice(), ), + getAddButtonWidget(), ], ), ), - const SizedBox( - height: 20, - ), + AppSpaces.verticalLarge, Row( children: [ const Expanded(child: Text('')), @@ -1428,11 +389,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 +397,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.textStyleAmountHeading, ), )), ], @@ -1464,11 +417,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 +425,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.textStyleAmountHeading, ), )), ], @@ -1501,11 +446,7 @@ 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.textStyleAmountHeading, ), )), AppSpaces.horizontalMedium, @@ -1513,13 +454,9 @@ 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.textStyleAmountHeading, ), )), ], @@ -1530,18 +467,12 @@ 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, @@ -1549,51 +480,27 @@ class _ReturnInvoiceVCState extends BaseStatefulState { 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 + child: CustomSimpleButton( + textColor: MyColors.white, + backGroundColor: MyColors.blueThemeColor, + onPressed: () async { + await viewModel.update(); + checkState(); + }, + heading: viewModel.isReturn ? 'Return whole order' - : "Damage whole order", - style: const TextStyle( - fontSize: MyFonts.normalButton, - color: MyColors.white, - fontFamily: MyFonts.Bold), - ), - )), - const SizedBox( - width: 12, - ), + : "Damage whole order")), + AppSpaces.horizontalMedium, 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: CustomSimpleButton( + textColor: MyColors.white, + backGroundColor: MyColors.blueThemeColor, + onPressed: () async { + await viewModel.returnInvoice(); + checkState(); }, - child: Text( - AppLocalizations.of(context)!.save, - style: const TextStyle( - fontSize: MyFonts.normalButton, - color: MyColors.white, - fontFamily: MyFonts.Bold), - ), + heading: AppLocalizations.of(context)!.save, ), ) ], @@ -1605,156 +512,25 @@ 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()); - }); - } - } - - Future _update() async { - setState(() { - isLoadingData = true; - }); - - Map data = { - 'invoiceId': widget.storeInvoice.id!, - 'status': widget.isReturn ? 'Return' : 'Damage' - }; - final response = - await viewModel.getResponsePatch(Constants.UPDATE_INVOICE, data); - setState(() { - isLoadingData = false; - }); - - if (response.success!) { + void checkState() { + if (viewModel.crudOperation == CRUDOperationState.update) { Navigator.pop(context, true); } } - 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); - } - }); - } - - 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); - } - - 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); - } - - 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); - } - - 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; - - return tax; - } - - 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!; - }); + getItemsWidget(int position) { + return TransparentBorderContainer( + height: 48, + backgroundColor: MyColors.backFillColor, + child: CustomTextButtonIcon( + onPressed: () { + showSheet(position); + }, + heading: viewModel.selectedProduct[position].isEmpty + ? 'Choose' + : viewModel.selectedProduct[position], + icon: Icons.arrow_drop_down), + ); } void showSheet(int index) async { @@ -1768,33 +544,78 @@ class _ReturnInvoiceVCState extends BaseStatefulState { 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(); - // }); + viewModel.updateProduct(result, index); } catch (e) { print(e); } } - void onCheck(int position, bool isChecked) { - widget.storeInvoice.products[position].isChecked = isChecked; + getRemoveButtonWidget(int position) { + return CustomRemoveItemButton(onPressed: () { + viewModel.onRemoveItem(position); + }); + } - if (isChecked) { - returnDamageOrder.details.add(widget.storeInvoice.products[position]); - } else { - returnDamageOrder.details.removeWhere((element) => - element.itemId! == widget.storeInvoice.products[position].itemId!); - } + 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); + }, + ), + ); + } + + getQuantityWidget(int position) { + return Center( + child: CustomTextFieldForm( + keyboardType: TextInputType.number, + initialValue: viewModel.quantityControllers[position], + onChanged: (value) { + viewModel.onChangeQuantity(position, value); + }, + hintText: '', + ), + ); + } + + getUnitPriceWidget(int position) { + return Center( + child: CustomTextFieldForm( + onChanged: (String value) {}, + hintText: '', + ), + ); + } + + getDescriptionWidget(int position) { + return TransparentBorderContainer( + backgroundColor: MyColors.disableColor, + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + viewModel.storeInvoice.products[position].description ?? "", + ), + ), + ); + } + + getPriceWidget(int position) { + return TransparentBorderContainer( + backgroundColor: MyColors.disableColor, + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText(viewModel.storeInvoice.products[position].price! + .toStringAsFixed(2)), + ), + ); + } + + getAddButtonWidget() { + return CustomAddButton(onPressed: () { + viewModel.onAddNewProduct(); + }); } } diff --git a/lib/application/views/salesandordermodule/views/invoiceModule/InvoicesVC.dart b/lib/application/views/salesandordermodule/views/invoiceModule/InvoicesVC.dart index b2cb8b0..4650b5c 100644 --- a/lib/application/views/salesandordermodule/views/invoiceModule/InvoicesVC.dart +++ b/lib/application/views/salesandordermodule/views/invoiceModule/InvoicesVC.dart @@ -4,26 +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/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/application/views/salesandordermodule/views/invoiceModule/viewModels/InvoiceViewModel.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/EmptyDataWidget.dart'; -import 'package:wosull/widgets/ValueText.dart'; +import 'package:wosull/widgets/PageLimitDropDown.dart'; +import 'package:wosull/widgets/SearchBox.dart'; class InvoicesVC extends StatefulWidget { const InvoicesVC({Key? key}) : super(key: key); @@ -59,62 +57,138 @@ class _InvoicesVCState extends BaseStatefulState { 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, + isPortrait + ? Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)!.invoices, + style: ThemeText.textStylePageHeading, + ), + AppSpaces.horizontalSmall, + SizedBox( + height: 38, + width: 160, + child: DropdownSearch( + dropdownButtonProps: + ThemeDropDown.dropdownButtonProps, + popupProps: const PopupProps.menu( + constraints: + 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), + ), + ), + AppSpaces.horizontalSmall, + Flexible( + child: CustomSimpleButton( + textColor: MyColors.blueThemeColor, + backGroundColor: MyColors.backColorBlue50, + onPressed: () { + toNewInvoice( + false, StoreInvoice(products: [])); + }, + heading: AppLocalizations.of(context)! + .new_invoices, + ), + ), + ], + ), + AppSpaces.verticalSmall, + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Flexible( + child: SearchBox( + onEditingDone: (text) {}, + onChanged: (text) {}, + hint: AppLocalizations.of(context)!.search, + ), + ), + AppSpaces.horizontalSmall, + PageLimitDropdown(onChange: (value) { + viewModel.fetch( + isRefresh: true, + limit: int.parse(value!)); + }) + ], + ), + ], + ) + : Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)!.invoices, + style: ThemeText.textStylePageHeading, + ), + AppSpaces.horizontalSmall, + SizedBox( + height: 38, + width: 160, + child: DropdownSearch( + dropdownButtonProps: + ThemeDropDown.dropdownButtonProps, + popupProps: const PopupProps.menu( + constraints: 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), + ), + ), + AppSpaces.horizontalSmall, + SizedBox( + width: 120, + child: CustomSimpleButton( + textColor: MyColors.blueThemeColor, + backGroundColor: MyColors.backColorBlue50, + onPressed: () { + toNewInvoice( + false, StoreInvoice(products: [])); + // newInvoice(false, StoreInvoice(products: [])); + }, + heading: + AppLocalizations.of(context)!.new_invoices, + ), + ), + AppSpaces.horizontalSmall, + SizedBox( + width: SizerUtil.deviceType == DeviceType.mobile + ? 200 + : 240, + height: 48, + child: SearchBox( + onEditingDone: (text) {}, + onChanged: (text) {}, + hint: AppLocalizations.of(context)!.search, + ), + ), + Flexible( + child: PageLimitDropdown(onChange: (value) { + viewModel.fetch( + isRefresh: true, limit: int.parse(value!)); + })) + ], ), - ), - ], - ), AppSpaces.verticalLarge, ChangeNotifierProvider( create: (context) => viewModel, @@ -152,634 +226,27 @@ class _InvoicesVCState extends BaseStatefulState { 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, - ), - ], - ), + 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(), ], ); @@ -787,7 +254,7 @@ class _InvoicesVCState extends BaseStatefulState { bool _scrollNotification() { if (!viewModel.isLoading && _controller.position.extentAfter < 300) { - viewModel.fetch(); + viewModel.fetch(limit: viewModel.limit); } return true; } @@ -804,78 +271,44 @@ class _InvoicesVCState extends BaseStatefulState { 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!)), - ); + 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); } } - 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); + 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!); } } + void onPrint(String invoiceId) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => AddInvoiceAndPrintVC(id: invoiceId)), + ); + } + void toNewInvoice(bool isEdit, StoreInvoice invoice) async { final result = await Navigator.push( context, diff --git a/lib/application/views/salesandordermodule/views/invoiceModule/NewInvoiceVC.dart b/lib/application/views/salesandordermodule/views/invoiceModule/NewInvoiceVC.dart index 936a864..02245b9 100644 --- a/lib/application/views/salesandordermodule/views/invoiceModule/NewInvoiceVC.dart +++ b/lib/application/views/salesandordermodule/views/invoiceModule/NewInvoiceVC.dart @@ -1,33 +1,35 @@ -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:provider/provider.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/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/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/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 '../../../../model/customers/GetStoreCustomer.dart'; import '../../../../model/discount/StoreDiscountModel.dart'; @@ -47,144 +49,33 @@ class NewInvoiceVC extends StatefulWidget { } 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', - ]; + var viewModel = NewInvoiceViewModel(); @override void initState() { - // TODO: implement initState + context + .read() + .initData(widget.isEdit, widget.storeInvoice); 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) { + viewModel = context.watch(); return Scaffold( resizeToAvoidBottomInset: true, - appBar: AppBar( - leading: BackButton( - color: Colors.black, - onPressed: () { - Navigator.pop(context); - }, // <-- SEE HERE - ), - centerTitle: true, - title: Text( - widget.isEdit + appBar: CustomAppBar( + heading: widget.isEdit ? AppLocalizations.of(context)!.edit_invoice - : AppLocalizations.of(context)!.add_invoice, - style: ThemeText.textStylePopUpHeading, - ), - backgroundColor: MyColors.white, - elevation: 5, - ), + : AppLocalizations.of(context)!.add_invoice), 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(4), - child: isLoadingFirst + child: viewModel.isLoadingFirst ? const Center( child: CircularProgressIndicator(), ) @@ -216,7 +107,7 @@ class _NewInvoiceVCState extends BaseStatefulState { getInvoiceDate(), AppSpaces.verticalLarge, getDefaultStatus(), - isPortrait + viewModel.isPortrait ? Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -241,10 +132,10 @@ class _NewInvoiceVCState extends BaseStatefulState { ], ), ), - isPortrait + viewModel.isPortrait ? Container() : AppSpaces.horizontalMedium, - isPortrait + viewModel.isPortrait ? Container() : Expanded( flex: 2, @@ -269,12 +160,7 @@ class _NewInvoiceVCState extends BaseStatefulState { AppSpaces.verticalLarge, getInvoiceDueDate(), AppSpaces.verticalLarge, - CustomOptionalTitle( - hint: AppLocalizations - .of(context)! - .currency), - AppSpaces.verticalSmall, - getSelectedCurrencyDropdown() + getSelectedCurrencyWidget() ], )), AppSpaces.horizontalMedium, @@ -298,36 +184,7 @@ class _NewInvoiceVCState extends BaseStatefulState { ], ), 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), - ), + getStockUpdateOptionWidget() ], ), ), @@ -349,7 +206,8 @@ class _NewInvoiceVCState extends BaseStatefulState { CustomTextFieldForm( height: 100, maxLines: 5, - initialValue: addInvoice.terms ?? '', + initialValue: + viewModel.addInvoice.terms ?? '', onChanged: (value) {}, hintText: AppLocalizations.of(context)!.terms) ], @@ -370,29 +228,12 @@ class _NewInvoiceVCState 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.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.backFillColor, - ), - height: 48, + : BorderContainer( child: Row( children: [ HeadingContainer( @@ -475,7 +316,7 @@ class _NewInvoiceVCState extends BaseStatefulState { physics: const NeverScrollableScrollPhysics(), shrinkWrap: true, itemBuilder: (c, position) { - if (isPortrait) { + if (viewModel.isPortrait) { return Container( padding: const EdgeInsets.fromLTRB(8, 0, 0, 8), @@ -506,429 +347,111 @@ class _NewInvoiceVCState 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( 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( child: Align( alignment: Alignment .centerLeft, - child: Text( + child: HeadingText( 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), - ), - ), + PortraitContainer( 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( 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( 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( 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( 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( 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( + 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( 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), ), ), ), @@ -943,142 +466,23 @@ class _NewInvoiceVCState 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: 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), - ), - ), + getItemsWidget( + position), + PortraitContainer( 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( 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( child: Center( child: getProductPrice( @@ -1093,93 +497,15 @@ class _NewInvoiceVCState extends BaseStatefulState { 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), - ), - ), + PortraitContainer( + child: + getSingleItemTaxWidget( + 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] - .amount! - .toStringAsFixed( - 2) ?? - 0.toString(), - style: const TextStyle( - fontFamily: - MyFonts - .Bold, - fontWeight: - FontWeight - .bold, - fontSize: 11, - color: MyColors - .textColorBlack20), - ), - ), + PortraitContainer( + child: + getSingleItemAmountWidget( + position), ), ], )), @@ -1204,112 +530,27 @@ class _NewInvoiceVCState extends BaseStatefulState { ), child: Row( children: [ - Container( + ChildContainer( 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, - ) - ], - ), - ), + child: getItemsWidget(position), ), - Container( - padding: const EdgeInsets.all(4), - height: 48, + 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( 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, + ChildContainer( width: 80, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), child: Center( child: getProductPrice(position), ), @@ -1326,51 +567,15 @@ class _NewInvoiceVCState extends BaseStatefulState { Expanded( child: getMeasurementWidget( context, position)), - Container( + ChildContainer( 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(), - ), - ), + child: getSingleItemTaxWidget( + position), ), - Container( + ChildContainer( 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(), - ), - ), + child: getSingleItemAmountWidget( + position), ), getRemoveProductButton(position) ], @@ -1378,36 +583,16 @@ class _NewInvoiceVCState extends BaseStatefulState { ); } }, - itemCount: addInvoice.products.length, + itemCount: viewModel.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, + viewModel.isPortrait + ? BorderContainer( + backgroundColor: MyColors.white, child: Row( children: [ Expanded( - child: Container( + child: PortraitContainer( height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), child: Center( child: Text( '', @@ -1417,262 +602,62 @@ class _NewInvoiceVCState extends BaseStatefulState { ), )), Expanded( - child: Container( + child: ChildContainer( height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), child: Center( child: Text( - getTotalProductsPrice(), + viewModel + .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(); - }), - ), - ), + getAddItemButtonWidget() ], ), ) - : 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( + 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( - '', - 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: '', )), 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: '', ), + getAddItemButtonWidget() ], ), ), @@ -1689,26 +674,17 @@ class _NewInvoiceVCState 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, ), )), ], @@ -1726,27 +702,18 @@ class _NewInvoiceVCState 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, ), )), ], @@ -1766,27 +733,20 @@ class _NewInvoiceVCState 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.textStyleImageHeading, ), )), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, 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), + viewModel.addInvoice.totalAmount + ?.toStringAsFixed(2) ?? + '0.0', + style: + ThemeText.textStyleImageHeading, ), )), ], @@ -1798,14 +758,12 @@ class _NewInvoiceVCState extends BaseStatefulState { ), ), AppSpaces.verticalLarge, - isLoadingData - ? const Row( + viewModel.isLoadingData + ? Row( crossAxisAlignment: CrossAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end, children: [ - Center( - child: CircularProgressIndicator(), - ) + AppLoader(), ], ) : Row( @@ -1820,7 +778,7 @@ class _NewInvoiceVCState extends BaseStatefulState { height: 38, heading: 'Add Service', onPressed: () { - onAddService(); + viewModel.onAddService(); }, )), AppSpaces.horizontalMedium, @@ -1835,8 +793,9 @@ class _NewInvoiceVCState extends BaseStatefulState { .edit_invoice : AppLocalizations.of(context)! .add_invoice, - onPressed: () { - isValidate(false); + onPressed: () async { + await viewModel.isValidate(false); + checkState(); }, )), AppSpaces.horizontalMedium, @@ -1848,8 +807,9 @@ class _NewInvoiceVCState extends BaseStatefulState { height: 38, heading: AppLocalizations.of(context)! .add_invoice_and_print, - onPressed: () { - isValidate(true); + onPressed: () async { + await viewModel.isValidate(true); + checkState(); }, ), ) @@ -1863,66 +823,41 @@ class _NewInvoiceVCState extends BaseStatefulState { ); } - 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); + void checkState() { + if (viewModel.crudOperation == CRUDOperationState.view) { + Navigator.pop(context, true); + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => AddInvoiceAndPrintVC( + id: 'response.invoice!.id!', + )), + ); + } else if (viewModel.crudOperation == CRUDOperationState.add) { + Navigator.pop(context, true); } } Widget getMeasurementWidget(BuildContext context, int position) { return FutureBuilder( - future: getMeasurement(), + 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( - 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'), - ), - ), - ), + return ChildContainer( + child: DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: const PopupProps.menu( + fit: FlexFit.loose, + constraints: BoxConstraints(maxHeight: 250)), + selectedItem: viewModel.selectedMeasurement[position], + items: itemsList, + itemAsString: (Measurement u) => u.name!, + onChanged: (Measurement? data) { + viewModel.setMeasurement(data, position); + }, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), ), ); } else { @@ -1931,64 +866,28 @@ class _NewInvoiceVCState extends BaseStatefulState { }); } - 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(), + future: viewModel.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'), - ), - ), - ), + return ChildContainer( + child: DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: const PopupProps.menu( + fit: FlexFit.loose, + constraints: BoxConstraints(maxHeight: 250)), + selectedItem: viewModel.selectedTax[position], + items: itemsList, + itemAsString: (VAT u) { + return u.value!; + }, + onChanged: (VAT? data) { + viewModel.setVat(data, position); + }, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), ), ); } else { @@ -1997,57 +896,27 @@ class _NewInvoiceVCState extends BaseStatefulState { }); } - 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(), + future: viewModel.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'), - ), - ), - ), + return DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: const PopupProps.menu( + fit: FlexFit.loose, + constraints: BoxConstraints(maxHeight: 250)), + selectedItem: viewModel.selectedCustomerCompany, + items: itemsList, + itemAsString: (StoreCustomer u) { + return u.name!; + }, + onChanged: (StoreCustomer? data) { + viewModel.changeCustomer(data); + }, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), ); } else { return AppLoader(); @@ -2055,78 +924,34 @@ class _NewInvoiceVCState extends BaseStatefulState { }); } - 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'), - ), - ), - ), + return ChildContainer( + child: DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: const PopupProps.menu( + fit: FlexFit.loose, constraints: 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.dropDownStyle(hint: 'Choose'), ), ); } Widget getDiscounts(BuildContext context, int position) { - if (addInvoice.products[position].discountType == null) { + if (viewModel.addInvoice.products[position].discountType == null) { return Container( height: 42, ); - } else if (addInvoice.products[position].discountType! == + } else if (viewModel.addInvoice.products[position].discountType! == Constants.discountTypes[0]) { return autoDiscount(position); - } else if (addInvoice.products[position].discountType! == + } else if (viewModel.addInvoice.products[position].discountType! == Constants.discountTypes[1]) { return manualDiscount(position); } else { @@ -2145,14 +970,11 @@ class _NewInvoiceVCState extends BaseStatefulState { ), ), child: CustomTextFieldForm( - initialValue: - addInvoice.products[position].discountPercentage?.toString() ?? '', + initialValue: viewModel.addInvoice.products[position].discountPercentage + ?.toString() ?? + '', onChanged: (String value) { - if (value.isNotEmpty) { - addDiscount(double.parse(value), position); - } else { - resetDiscount(position); - } + viewModel.onChangeManualDiscount(value, position); }, hintText: '', ), @@ -2161,45 +983,25 @@ class _NewInvoiceVCState extends BaseStatefulState { Widget autoDiscount(int position) { return FutureBuilder( - future: getDiscount(), + future: viewModel.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'), - ), - ), - ), + return ChildContainer( + child: DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: const PopupProps.menu( + fit: FlexFit.loose, + constraints: BoxConstraints(maxHeight: 250)), + selectedItem: viewModel.selectedDiscount[position], + items: itemsList, + itemAsString: (StoreDiscount u) => u.name ?? '', + onChanged: (StoreDiscount? data) { + viewModel.onChangeAutoDiscount(data, position); + // calculateDiscount(data, position); + }, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), ), ); } else { @@ -2208,20 +1010,6 @@ class _NewInvoiceVCState extends BaseStatefulState { }); } - 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, @@ -2233,53 +1021,10 @@ class _NewInvoiceVCState extends BaseStatefulState { 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!; - }); + viewModel.updateProduct(result, index); } 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: [ @@ -2287,31 +1032,18 @@ class _NewInvoiceVCState 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: 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'), - ), - ), - ), - ), + DropdownSearch( + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + selectedItem: viewModel.addInvoice.status ?? 'Choose', + popupProps: const PopupProps.menu( + fit: FlexFit.loose, constraints: BoxConstraints(maxHeight: 250)), + items: Constants.statusTypes, + itemAsString: (String u) => u, + onChanged: (String? data) { + viewModel.addInvoice.status = data!; + }, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), + ) ], ); } @@ -2334,13 +1066,14 @@ class _NewInvoiceVCState extends BaseStatefulState { height: 48, backgroundColor: MyColors.backFillColor, icon: Icons.calendar_month, - heading: addInvoice.invoiceDate == null + heading: viewModel.addInvoice.invoiceDate == null ? 'dd/mm/yyyy' - : (addInvoice.invoiceDate!.contains("T") - ? DataTimeFormat.getFormatDateString(addInvoice.invoiceDate!) + : (viewModel.addInvoice.invoiceDate!.contains("T") + ? DataTimeFormat.getFormatDateString( + viewModel.addInvoice.invoiceDate!) : 'dd/mm/yyyy'), onPressed: () { - _presentDatePicker(true); + viewModel.presentDatePicker(context, true); }, ); } @@ -2363,13 +1096,14 @@ class _NewInvoiceVCState extends BaseStatefulState { height: 48, backgroundColor: MyColors.backFillColor, icon: Icons.calendar_month, - heading: addInvoice.invoiceDueDate == null + heading: viewModel.addInvoice.invoiceDueDate == null ? 'dd/mm/yyyy' - : (addInvoice.invoiceDueDate!.contains("T") - ? DataTimeFormat.getFormatDateString(addInvoice.invoiceDueDate!) + : (viewModel.addInvoice.invoiceDueDate!.contains("T") + ? DataTimeFormat.getFormatDateString( + viewModel.addInvoice.invoiceDueDate!) : 'dd/mm/yyyy'), onPressed: () { - _presentDatePicker(false); + viewModel.presentDatePicker(context, false); }, ); } @@ -2384,196 +1118,16 @@ class _NewInvoiceVCState extends BaseStatefulState { AppSpaces.verticalSmall, CustomTextFieldForm( readOnly: true, - key: Key(addInvoice.invoiceReference.toString()), - initialValue: addInvoice.invoiceReference.toString(), + key: Key(viewModel.addInvoice.invoiceReference.toString()), + initialValue: viewModel.addInvoice.invoiceReference.toString(), onChanged: (value) { - addInvoice.invoiceReference = value; + viewModel.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: [ @@ -2581,35 +1135,20 @@ class _NewInvoiceVCState extends BaseStatefulState { 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'), - ), - ), + DropdownSearch( + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + selectedItem: viewModel.selectedInvoiceFor ?? "Choose", + popupProps: const PopupProps.menu( + fit: FlexFit.loose, + constraints: BoxConstraints(maxHeight: 100), ), - ), + items: Constants.chooseInvoiceForTypes, + itemAsString: (String u) => u, + onChanged: (String? data) { + viewModel.onChangeInvoiceFor(data); + }, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), + ) ], ); } @@ -2618,7 +1157,7 @@ class _NewInvoiceVCState extends BaseStatefulState { return Column( children: [ MandatoryTitleText( - hint: 'Choose $selectedInvoiceFor', + hint: 'Choose ${viewModel.selectedInvoiceFor}', ), AppSpaces.verticalSmall, getCompanyWidget(context) @@ -2628,35 +1167,24 @@ class _NewInvoiceVCState extends BaseStatefulState { getSelectedCurrencyDropdown() { return FutureBuilder( - future: getCurrency(), + future: viewModel.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'), - ), - ), + return DropdownSearch( + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + selectedItem: viewModel.selectedCurrency, + popupProps: const PopupProps.menu( + fit: FlexFit.loose, + constraints: BoxConstraints(maxHeight: 200), ), + items: currency, + itemAsString: (Currency u) => u.name!, + onChanged: (Currency? data) { + viewModel.addInvoice.currencyId = data!; + }, + dropdownDecoratorProps: + MyColors.dropDownStyle(hint: 'Choose Currency'), ); } else { return AppLoader(); @@ -2673,8 +1201,8 @@ class _NewInvoiceVCState extends BaseStatefulState { AppSpaces.verticalSmall, CustomTextFieldForm( readOnly: true, - key: Key((addInvoice.invoiceNumber ?? 0).toString()), - initialValue: (addInvoice.invoiceNumber ?? 0).toString(), + key: Key((viewModel.addInvoice.invoiceNumber ?? 0).toString()), + initialValue: (viewModel.addInvoice.invoiceNumber ?? 0).toString(), onChanged: (String value) {}, hintText: 'Enter Invoice Number', ), @@ -2691,9 +1219,9 @@ class _NewInvoiceVCState extends BaseStatefulState { ), AppSpaces.verticalSmall, CustomTextFieldForm( - initialValue: (addInvoice.vatNumber ?? ""), + initialValue: (viewModel.addInvoice.vatNumber ?? ""), onChanged: (String value) { - addInvoice.vatNumber = value; + viewModel.addInvoice.vatNumber = value; }, hintText: 'Enter VAT Number', ), @@ -2703,10 +1231,10 @@ class _NewInvoiceVCState extends BaseStatefulState { getProductDescription(int position) { return CustomTextFieldForm( - key: Key(addInvoice.products[position].description ?? ''), - initialValue: addInvoice.products[position].description ?? '', + key: Key(viewModel.addInvoice.products[position].description ?? ''), + initialValue: viewModel.addInvoice.products[position].description ?? '', onChanged: (String value) { - addInvoice.products[position].description = value; + viewModel.addInvoice.products[position].description = value; }, hintText: '', ); @@ -2715,11 +1243,13 @@ class _NewInvoiceVCState extends BaseStatefulState { getProductQuantity(int position) { return CustomTextFieldForm( keyboardType: TextInputType.number, - key: Key((addInvoice.products[position].totalQuantity ?? '0').toString()), + key: Key((viewModel.addInvoice.products[position].totalQuantity ?? '0') + .toString()), initialValue: - (addInvoice.products[position].totalQuantity ?? '0').toString(), + (viewModel.addInvoice.products[position].totalQuantity ?? '0') + .toString(), onChanged: (String value) { - onChangeQuantity(position, value); + viewModel.onChangeQuantity(position, value); }, hintText: '', ); @@ -2727,17 +1257,13 @@ class _NewInvoiceVCState extends BaseStatefulState { getProductPrice(int position) { return CustomTextFieldForm( - key: Key((addInvoice.products[position].price ?? '0').toString()), + key: Key( + (viewModel.addInvoice.products[position].price ?? '0').toString()), keyboardType: TextInputType.number, - initialValue: (addInvoice.products[position].price ?? '0').toString(), + initialValue: + (viewModel.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); - } + viewModel.onChangeItemPrice(value, position); }, hintText: '', ); @@ -2761,85 +1287,99 @@ class _NewInvoiceVCState extends BaseStatefulState { color: MyColors.textColorBlack, ), onPressed: () { - onRemoveItem(position); + viewModel.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) {}); + getSelectedCurrencyWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle(hint: AppLocalizations.of(context)!.currency), + AppSpaces.verticalSmall, + getSelectedCurrencyDropdown() + ], + ); + } - return currencies; + 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, + ), + ], + ); } - void setDiscountType(int position, String? data) { - setState(() { - resetDiscount(position); - if (data != null) { - addInvoice.products[position].discountType = data; - } else { - addInvoice.products[position].discountType = ''; - } - }); + getAddItemButtonWidget() { + return 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.onAddService(); + }), + ), + ); } - void calculateDiscount(StoreDiscount? data, int position) { - setState(() { - if (data != null) { - addDiscount(double.parse(data.discountPercentage!), position); - } else { - resetDiscount(position); - } - }); + getItemsWidget(int position) { + return TransparentBorderContainer( + height: 48, + backgroundColor: MyColors.backFillColor, + child: CustomTextButtonIcon( + onPressed: () { + showSheet(position); + }, + heading: viewModel.selectedProduct[position].isEmpty + ? 'Choose' + : viewModel.selectedProduct[position], + icon: Icons.arrow_drop_down), + ); } - 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!; - } - }); + getSingleItemTaxWidget(int position) { + return Center( + child: ValueText( + viewModel.addInvoice.products[position].tax!.toStringAsFixed(2) ?? + 0.toString(), + ), + ); } - 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; - }); + getSingleItemAmountWidget(int position) { + return Center( + child: ValueText( + viewModel.addInvoice.products[position].amount!.toStringAsFixed(2)), + ); } } diff --git a/lib/application/views/salesandordermodule/viewModel/InvoiceViewModel.dart b/lib/application/views/salesandordermodule/views/invoiceModule/viewModels/InvoiceViewModel.dart similarity index 94% rename from lib/application/views/salesandordermodule/viewModel/InvoiceViewModel.dart rename to lib/application/views/salesandordermodule/views/invoiceModule/viewModels/InvoiceViewModel.dart index 64fd238..ee1a739 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,8 @@ class InvoiceViewModel 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) { @@ -43,6 +44,7 @@ class InvoiceViewModel with ChangeNotifier { 'store_id': sharedPrefs.storeId, 'page': _currentPageNumber, 'invoice_status': filterValue, + 'limit': this.limit }; print(jsonEncode(data)); try { @@ -60,7 +62,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; 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..5ea61c9 --- /dev/null +++ b/lib/application/views/salesandordermodule/views/invoiceModule/viewModels/NewInvoiceViewModel.dart @@ -0,0 +1,535 @@ +import 'dart:math'; + +import 'package:flutter/material.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/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/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; + + //var selectedSupplier; + 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]; + + 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) { + print(error.toString()); + isLoadingFirst = false; + notifyListeners(); + }); + } + + Future initData(bool isEdit, StoreInvoice storeInvoice) async { + if (isEdit) { + // addInvoice = storeInvoice; + isLoadingFirst = true; + await getInvoiceById(storeInvoice.id ?? ''); + } else { + addEmptyService(); + getRandomNumber(); + getRandomInvoiceRef(); + } + } + + 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.status == null) { + Utils.showMessage('Select Status'); + } 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 { + 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> 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> 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; + } + + 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; + // 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; + // } + 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 ?? ''); + 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 { + 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; + } + + Future> getCompany() async { + var items = []; + await APIManager() + .fetchData(Constants.GET_STORE_CUSTOMER, Constants.getStorePayload()) + .then((value) { + final response = GetStoreCustomer.fromJson(value); + if (response.success!) { + items.addAll(response.topOrders!); + selectedCustomerCompany ??= StoreCustomer(name: "Choose", id: ""); + } + }).onError((error, stackTrace) {}); + + return items; + } + + 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; + } +} 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..f8d8f8a --- /dev/null +++ b/lib/application/views/salesandordermodule/views/invoiceModule/viewModels/ReturnDamageInvoiceViewModel.dart @@ -0,0 +1,226 @@ +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!); + } + } + + 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/invoiceModule/widgets/InvoiceListView.dart b/lib/application/views/salesandordermodule/views/invoiceModule/widgets/InvoiceListView.dart new file mode 100644 index 0000000..368f7b7 --- /dev/null +++ b/lib/application/views/salesandordermodule/views/invoiceModule/widgets/InvoiceListView.dart @@ -0,0 +1,523 @@ +import 'package:flutter/material.dart'; +import 'package:sizer/sizer.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/EmptyDataWidget.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() + : Container( + padding: const EdgeInsets.only(left: 8, right: 8), + height: 50, + color: MyColors.containerBackColor, + 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.centerLeft, + 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(), + ), + )) + ], + ), + 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!), + )) + ], + ), + 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.supplier!.name ?? "", + ), + )) + ], + ), + 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!)), + )) + ], + ), + 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!), + ), + )) + ], + ), + 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)), + )) + ], + ), + 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: Container( + padding: const EdgeInsets.only(left: 8, right: 8), + height: 56, + color: MyColors.containerBackColor, + 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: 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 PopupMenuButton( + icon: const Icon(Icons.more_vert), + itemBuilder: (c) { + 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).print_or_download, + ), + ), + PopupMenuItem( + value: 'delete', + child: ValueText( + lang(context).delete, + ), + ) + ]; + }, + onSelected: (String value) => actionPopUpItemSelected(value, invoice), + ); + } +} diff --git a/lib/application/views/salesandordermodule/views/ordersModule/OrderVC.dart b/lib/application/views/salesandordermodule/views/ordersModule/OrderVC.dart index 5520b98..e2a789b 100644 --- a/lib/application/views/salesandordermodule/views/ordersModule/OrderVC.dart +++ b/lib/application/views/salesandordermodule/views/ordersModule/OrderVC.dart @@ -1,6 +1,8 @@ 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/interfaces/DrawerWidgetSelect.dart'; import 'package:wosull/application/model/cart/GetHoldOrderModel.dart'; import 'package:wosull/application/model/invoice/StoreInvoice.dart'; @@ -12,7 +14,10 @@ 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/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeDropDown.dart'; import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/widgets/PageLimitDropDown.dart'; +import 'package:wosull/widgets/SearchBox.dart'; class OrderVC extends StatefulWidget { const OrderVC({super.key}); @@ -23,6 +28,7 @@ class OrderVC extends StatefulWidget { class _OrderVCState extends State implements TransactionCVS { bool isPortrait = false; + var viewModel = OrderViewModel(); @override @@ -32,68 +38,81 @@ class _OrderVCState extends State implements TransactionCVS { backgroundColor: MyColors.fillColor, body: OrientationBuilder(builder: (c, orientation) { isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; - return SingleChildScrollView( - child: Container( - padding: const EdgeInsets.all(12), - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - const Text( - 'Order', - style: ThemeText.textStylePageHeading, - ), - const SizedBox( - width: 4, + return Container( + padding: const EdgeInsets.all(12), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + const Text( + 'Order', + style: ThemeText.textStylePageHeading, + ), + AppSpaces.horizontalSmall, + SizedBox( + height: 38, + width: 160, + child: DropdownSearch( + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: const PopupProps.menu( + fit: FlexFit.loose, + constraints: BoxConstraints(maxHeight: 170)), + clearButtonProps: ThemeDropDown.clearButton, + items: Constants.orderStatus, + itemAsString: (String u) => u, + onChanged: (String? data) { + if (data != null) { + viewModel.setSelectedFilter(data); + } else { + viewModel.setSelectedFilter('All'); + } + }, + dropdownDecoratorProps: MyColors.dropDownStyle( + hint: Constants.orderStatus[0], + fillColor: MyColors.white), ), - 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'); - } - }, - dropdownDecoratorProps: MyColors.dropDownStyle( - hint: Constants.orderStatus[0]), - ), + ), + AppSpaces.horizontalSmall, + isPortrait + ? Container() + : SizedBox( + width: SizerUtil.deviceType == DeviceType.mobile + ? 200 + : 240, + height: 48, + child: SearchBox( + onEditingDone: (text) {}, + onChanged: (text) {}, + hint: AppLocalizations.of(context)!.search, ), ), + Flexible(child: PageLimitDropdown(onChange: (value) { + viewModel.setLimit(int.parse(value!)); + })) + ], + ), + isPortrait + ? SizedBox( + height: 48, + child: SearchBox( + onEditingDone: (text) {}, + onChanged: (text) {}, + hint: AppLocalizations.of(context)!.search, ), - ), - ], - ), - AppSpaces.verticalLarge, - CashierTransactionsVC( - context: context, - delegate: this, - isOrder: true, - filter: viewModel.selectedFilter.toLowerCase(), - ) - ], - ), + ) + : Container(), + AppSpaces.verticalLarge, + Expanded( + child: CashierTransactionsVC( + context: context, + delegate: this, + isPortrait: isPortrait, + limit: viewModel.limit, + isOrder: true, + filter: viewModel.selectedFilter.toLowerCase(), + )) + ], ), ); }), @@ -114,9 +133,7 @@ class _OrderVCState extends State implements TransactionCVS { } @override - void editOnNewInvoice(StoreInvoice invoice) { - // TODO: implement editOnNewInvoice - } + void editOnNewInvoice(StoreInvoice invoice) {} @override void printDownloadInvoice(StoreInvoice 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..83dc78c 100644 --- a/lib/application/views/salesandordermodule/views/ordersModule/viewModel/OrderViewModel.dart +++ b/lib/application/views/salesandordermodule/views/ordersModule/viewModel/OrderViewModel.dart @@ -2,9 +2,14 @@ import 'package:flutter/cupertino.dart'; class OrderViewModel with ChangeNotifier { String selectedFilter = 'All'; - + int limit = 10; void setSelectedFilter(String filter) { selectedFilter = filter; notifyListeners(); } + + void setLimit(int parse) { + limit = parse; + notifyListeners(); + } } diff --git a/lib/application/views/salesandordermodule/views/quotataionModule/NewQuotationsVC.dart b/lib/application/views/salesandordermodule/views/quotataionModule/NewQuotationsVC.dart index 54e9176..1cc067c 100644 --- a/lib/application/views/salesandordermodule/views/quotataionModule/NewQuotationsVC.dart +++ b/lib/application/views/salesandordermodule/views/quotataionModule/NewQuotationsVC.dart @@ -23,6 +23,7 @@ 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 'package:wosull/widgets/TransprentBorderContainer.dart'; import '../../../../model/SimpleResponsModel.dart'; import '../../../../model/StockTransfer/ProductItemCategoryModel.dart'; @@ -912,26 +913,11 @@ class _NewQuotationsVCState extends BaseStatefulState { MainAxisAlignment .start, children: [ - Container( + TransparentBorderContainer( 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), - ), + backgroundColor: + MyColors + .backFillColor, child: CustomTextButtonIcon( onPressed: @@ -1821,8 +1807,7 @@ class _NewQuotationsVCState extends BaseStatefulState { height: 48, width: double.infinity, child: DropdownSearch( - dropdownButtonProps: const DropdownButtonProps( - iconSize: 14, padding: EdgeInsets.zero), + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, // selectedItem: selectedDiscount[position], popupProps: const PopupProps.menu( fit: FlexFit.tight, @@ -1902,6 +1887,7 @@ class _NewQuotationsVCState extends BaseStatefulState { height: isPortrait ? 42 : 48, width: double.infinity, child: DropdownSearch( + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, selectedItem: selectedDiscount[position], popupProps: const PopupProps.menu(), clearButtonProps: ThemeDropDown.clearButton, @@ -1971,6 +1957,7 @@ class _NewQuotationsVCState extends BaseStatefulState { height: 48, width: double.infinity, child: DropdownSearch( + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, selectedItem: selectedMeasurement[position], popupProps: const PopupProps.menu(), clearButtonProps: ThemeDropDown.clearButton, @@ -2034,6 +2021,7 @@ class _NewQuotationsVCState extends BaseStatefulState { height: 48, width: double.infinity, child: DropdownSearch( + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, selectedItem: selectedTax[position], popupProps: const PopupProps.menu(), clearButtonProps: ThemeDropDown.clearButton, @@ -2092,6 +2080,7 @@ class _NewQuotationsVCState extends BaseStatefulState { height: 48, width: double.infinity, child: DropdownSearch( + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, selectedItem: selectedCustomerCompany, popupProps: const PopupProps.menu(), clearButtonProps: ThemeDropDown.clearButton, @@ -2235,6 +2224,7 @@ class _NewQuotationsVCState extends BaseStatefulState { height: 48, width: double.infinity, child: DropdownSearch( + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, selectedItem: selectedQuotationFor ?? "Choose", popupProps: const PopupProps.menu( constraints: BoxConstraints(maxHeight: 100), @@ -2287,6 +2277,7 @@ class _NewQuotationsVCState extends BaseStatefulState { height: 48, width: double.infinity, child: DropdownSearch( + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, selectedItem: selectedCurrency, popupProps: const PopupProps.menu( constraints: BoxConstraints(maxHeight: 200), @@ -2434,6 +2425,7 @@ class _NewQuotationsVCState extends BaseStatefulState { height: 48, width: double.infinity, child: DropdownSearch( + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, selectedItem: addQuotation.status ?? 'Choose', popupProps: const PopupProps.menu( constraints: BoxConstraints(maxHeight: 200), diff --git a/lib/application/views/salesandordermodule/views/quotataionModule/QuotationsVC.dart b/lib/application/views/salesandordermodule/views/quotataionModule/QuotationsVC.dart index 75c9698..6050d47 100644 --- a/lib/application/views/salesandordermodule/views/quotataionModule/QuotationsVC.dart +++ b/lib/application/views/salesandordermodule/views/quotataionModule/QuotationsVC.dart @@ -17,9 +17,12 @@ import 'package:wosull/application/views/salesandordermodule/viewModel/Quotation import 'package:wosull/application/views/salesandordermodule/views/quotataionModule/NewQuotationsVC.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/PageLimitDropDown.dart'; +import 'package:wosull/widgets/SearchBox.dart'; import 'package:wosull/widgets/ValueText.dart'; class QuotationsVC extends StatefulWidget { @@ -56,61 +59,139 @@ 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: DropdownSearch( + dropdownButtonProps: + ThemeDropDown.dropdownButtonProps, + 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: + MyColors.dropDownStyle( + hint: 'All', + fillColor: MyColors.white), + ), + ), + AppSpaces.horizontalSmall, + Flexible( + child: CustomSimpleButton( + textColor: MyColors.blueThemeColor, + backGroundColor: MyColors.backColorBlue50, + heading: AppLocalizations.of(context)! + .new_quotations, + onPressed: () { + newInvoice(false, + QuotationInvoice(products: [])); + }, + ), + ), + ], + ), + AppSpaces.verticalSmall, + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Flexible( + child: SearchBox( + onEditingDone: (text) {}, + onChanged: (text) {}, + hint: AppLocalizations.of(context)!.search, + ), + ), + AppSpaces.horizontalSmall, + PageLimitDropdown(onChange: (value) { + viewModel.fetch( + isRefresh: true, + limit: int.parse(value!)); + }) + ], + ), + ], + ) + : Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)!.quotations, + style: ThemeText.textStylePageHeading, + ), + AppSpaces.horizontalSmall, + SizedBox( + height: 38, + width: 160, + child: DropdownSearch( + dropdownButtonProps: + ThemeDropDown.dropdownButtonProps, + popupProps: const PopupProps.menu( + constraints: 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), + ), + ), + AppSpaces.horizontalSmall, + SizedBox( + width: 140, + child: CustomSimpleButton( + textColor: MyColors.blueThemeColor, + backGroundColor: MyColors.backColorBlue50, + heading: AppLocalizations.of(context)! + .new_quotations, + onPressed: () { + newInvoice( + false, QuotationInvoice(products: [])); + }, + ), + ), + AppSpaces.horizontalSmall, + SizedBox( + width: SizerUtil.deviceType == DeviceType.mobile + ? 200 + : 240, + height: 48, + child: SearchBox( + onEditingDone: (text) {}, + onChanged: (text) {}, + hint: AppLocalizations.of(context)!.search, + ), + ), + Flexible( + child: PageLimitDropdown(onChange: (value) { + viewModel.fetch( + isRefresh: true, limit: int.parse(value!)); + })) + ], ), - ), - ], - ), AppSpaces.verticalMedium, ChangeNotifierProvider( create: (context) => viewModel, @@ -756,7 +837,7 @@ class _QuotationsVCState 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/settings/ReportsVC.dart b/lib/application/views/settings/ReportsVC.dart index d994533..5cc3f42 100644 --- a/lib/application/views/settings/ReportsVC.dart +++ b/lib/application/views/settings/ReportsVC.dart @@ -22,6 +22,7 @@ import 'package:wosull/application/views/settings/reportsViews/ReportsQuotationV 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 'reportsViews/POSCompleteVC.dart'; import 'reportsViews/ReportsProductsVC.dart'; @@ -38,7 +39,9 @@ class _ReportsVCState extends BaseStatefulState final viewModel = InventoryViewModel(); bool isPortrait = true; bool isLoading = true; - bool _isLoadMoreRunning = false; + + int limit = 10; + List cvsData = []; List completedOrders = []; List returnOrder = []; @@ -78,226 +81,74 @@ class _ReportsVCState extends BaseStatefulState child: Column( children: [ isPortrait - ? Column( + ? Row( + mainAxisAlignment: MainAxisAlignment.start, children: [ - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Text( - AppLocalizations.of(context)!.pos_sales, - style: ThemeText.textStylePageHeading, - ), - const SizedBox( - width: 4, - ), - Flexible( - child: getReportsTypeButton(), - ) - ], + Text( + AppLocalizations.of(context)!.pos_sales, + style: ThemeText.textStylePageHeading, ), - 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, - ), - ), - ) - ], + AppSpaces.horizontalSmall, + Flexible( + child: getReportsTypeButton(), ), + Flexible( + child: PageLimitDropdown(onChange: (value) { + limit = int.parse(value!); + })) ], ) : 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'), - ), - ), + Text( + AppLocalizations.of(context)!.pos_sales, + style: ThemeText.textStylePageHeading, + ), + AppSpaces.horizontalSmall, + 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), ), - ), - ), - ), - ], - )), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - SizedBox( - width: 100, - child: ElevatedButton.icon( - style: ElevatedButton.styleFrom( - elevation: 0, - shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.circular(8.0), + 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'), ), - 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), - ), - )), ), ), - ], + ), ), + Flexible( + child: PageLimitDropdown(onChange: (value) { + limit = int.parse(value!); + })) ], ), AppSpaces.verticalMedium, @@ -351,36 +202,43 @@ class _ReportsVCState extends BaseStatefulState Widget getReportsType() { if (selectedReport == items[0]) { return BestSupplierVC( + limit: limit, context: context, delegate: this, ); } else if (selectedReport == items[1]) { return POSComplete( + limit: limit, context: context, delegate: this, ); } else if (selectedReport == items[2]) { return POSReturnOrderVC( + limit: limit, context: context, delegate: this, ); } else if (selectedReport == items[3]) { return ReportsInvoiceVC( + limit: limit, context: context, delegate: this, ); } else if (selectedReport == items[4]) { return ReportsQuotationVC( + limit: limit, context: context, delegate: this, ); } else if (selectedReport == items[5]) { return ReportsCategoryVC( + limit: limit, context: context, delegate: this, ); } else if (selectedReport == items[6]) { return ReportsProductsVC( + limit: limit, context: context, delegate: this, ); diff --git a/lib/application/views/settings/reportsViews/BestSuppliersVC.dart b/lib/application/views/settings/reportsViews/BestSuppliersVC.dart index 9fc5f99..cfad5df 100644 --- a/lib/application/views/settings/reportsViews/BestSuppliersVC.dart +++ b/lib/application/views/settings/reportsViews/BestSuppliersVC.dart @@ -15,8 +15,13 @@ import 'package:wosull/widgets/ValueText.dart'; class BestSupplierVC extends StatelessWidget { final ReportsCVS delegate; BuildContext context; + int limit = 10; - BestSupplierVC({super.key, required this.delegate, required this.context}); + BestSupplierVC( + {super.key, + required this.delegate, + required this.context, + this.limit = 10}); late ScrollController _controller; final viewModel = BestSupplierViewModel(); @@ -37,7 +42,7 @@ class BestSupplierVC extends StatelessWidget { switch (controller.dataState) { case DataState.uninitialized: Future(() { - controller.fetch(); + controller.fetch(limit: limit); }); return showData(controller.data, true); case DataState.initialFetching: @@ -223,7 +228,7 @@ class BestSupplierVC extends StatelessWidget { bool _scrollNotification() { if (!viewModel.isLoading && _controller.position.extentAfter < 300) { - viewModel.fetch(); + viewModel.fetch(limit: limit); } return true; } diff --git a/lib/application/views/settings/reportsViews/POSCompleteVC.dart b/lib/application/views/settings/reportsViews/POSCompleteVC.dart index a9faf95..37e44c9 100644 --- a/lib/application/views/settings/reportsViews/POSCompleteVC.dart +++ b/lib/application/views/settings/reportsViews/POSCompleteVC.dart @@ -18,11 +18,16 @@ 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}); + POSComplete( + {super.key, + required this.delegate, + required this.context, + this.limit = 10}); @override Widget build(BuildContext context) { @@ -39,7 +44,7 @@ class POSComplete extends StatelessWidget { switch (controller.dataState) { case DataState.uninitialized: Future(() { - controller.fetch(); + controller.fetch(limit: limit); }); return showData(controller.data); case DataState.initialFetching: @@ -225,7 +230,7 @@ class POSComplete extends StatelessWidget { bool _scrollNotification() { if (!viewModel.isLoading && _controller.position.extentAfter < 300) { - viewModel.fetch(); + viewModel.fetch(limit: limit); } return true; } diff --git a/lib/application/views/settings/reportsViews/POSReturnOrderVC.dart b/lib/application/views/settings/reportsViews/POSReturnOrderVC.dart index 455c2c1..1f83c51 100644 --- a/lib/application/views/settings/reportsViews/POSReturnOrderVC.dart +++ b/lib/application/views/settings/reportsViews/POSReturnOrderVC.dart @@ -17,11 +17,15 @@ 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}); + POSReturnOrderVC( + {super.key, + required this.delegate, + required this.context, + this.limit = 10}); @override Widget build(BuildContext context) { @@ -38,7 +42,7 @@ class POSReturnOrderVC extends StatelessWidget { switch (controller.dataState) { case DataState.uninitialized: Future(() { - controller.fetch(); + controller.fetch(limit: limit); }); return showData(controller.data); case DataState.initialFetching: @@ -222,7 +226,7 @@ class POSReturnOrderVC extends StatelessWidget { bool _scrollNotification() { if (!viewModel.isLoading && _controller.position.extentAfter < 300) { - viewModel.fetch(); + viewModel.fetch(limit: viewModel.limit); } return true; } diff --git a/lib/application/views/settings/reportsViews/ReportsCategoryVC.dart b/lib/application/views/settings/reportsViews/ReportsCategoryVC.dart index 3a258ee..7a34215 100644 --- a/lib/application/views/settings/reportsViews/ReportsCategoryVC.dart +++ b/lib/application/views/settings/reportsViews/ReportsCategoryVC.dart @@ -13,8 +13,13 @@ import '../../../../widgets/EmptyDataWidget.dart'; class ReportsCategoryVC extends StatefulWidget { final ReportsCVS delegate; BuildContext context; + int limit = 10; - ReportsCategoryVC({super.key, required this.delegate, required this.context}); + ReportsCategoryVC( + {super.key, + required this.delegate, + required this.context, + this.limit = 10}); @override State createState() => _ReportsCategoryVCState(); @@ -53,7 +58,7 @@ class _ReportsCategoryVCState extends State { switch (controller.dataState) { case DataState.uninitialized: Future(() { - controller.fetchCategories(); + controller.fetchCategories(limit: widget.limit); }); return categoryListViewWidget(controller.dataList, true); case DataState.initialFetching: @@ -292,7 +297,7 @@ class _ReportsCategoryVCState extends State { bool _scrollNotification() { if (!_isLoading && _controller.position.extentAfter < 300) { _isLoading = true; - categoryViewModel.fetchCategories(); + categoryViewModel.fetchCategories(limit: categoryViewModel.limit); } return true; } diff --git a/lib/application/views/settings/reportsViews/ReportsInvoiceVC.dart b/lib/application/views/settings/reportsViews/ReportsInvoiceVC.dart index 3de8d8f..0710a73 100644 --- a/lib/application/views/settings/reportsViews/ReportsInvoiceVC.dart +++ b/lib/application/views/settings/reportsViews/ReportsInvoiceVC.dart @@ -18,8 +18,13 @@ class ReportsInvoiceVC extends StatelessWidget { final ReportsCVS delegate; BuildContext context; + int limit = 10; - ReportsInvoiceVC({super.key, required this.delegate, required this.context}); + ReportsInvoiceVC( + {super.key, + required this.delegate, + required this.context, + this.limit = 10}); @override Widget build(BuildContext context) { @@ -36,7 +41,7 @@ class ReportsInvoiceVC extends StatelessWidget { switch (controller.dataState) { case DataState.uninitialized: Future(() { - controller.fetchInvoices(); + controller.fetchInvoices(limit: limit); }); return showList(controller.invoiceList); case DataState.initialFetching: @@ -454,7 +459,7 @@ class ReportsInvoiceVC extends StatelessWidget { bool _scrollNotification() { if (!viewModel.isLoading && _controller.position.extentAfter < 300) { - viewModel.fetchInvoices(); + viewModel.fetchInvoices(limit: viewModel.limit); } return true; } diff --git a/lib/application/views/settings/reportsViews/ReportsProductsVC.dart b/lib/application/views/settings/reportsViews/ReportsProductsVC.dart index 870486e..308b4e5 100644 --- a/lib/application/views/settings/reportsViews/ReportsProductsVC.dart +++ b/lib/application/views/settings/reportsViews/ReportsProductsVC.dart @@ -12,7 +12,13 @@ class ReportsProductsVC extends StatefulWidget { final ReportsCVS delegate; BuildContext context; - ReportsProductsVC({super.key, required this.delegate, required this.context}); + int limit = 10; + + ReportsProductsVC( + {super.key, + required this.delegate, + required this.context, + this.limit = 10}); @override State createState() => _ReportsProductsVCState(); @@ -51,7 +57,7 @@ class _ReportsProductsVCState extends State { switch (controller.dataState) { case DataState.uninitialized: Future(() { - controller.fetchReportsProducts(); + controller.fetchReportsProducts(limit: widget.limit); }); return showList(controller.dataList, true); case DataState.initialFetching: @@ -300,7 +306,7 @@ class _ReportsProductsVCState extends State { bool _scrollNotification() { if (!_isLoading && _controller.position.extentAfter < 300) { _isLoading = true; - viewModel.fetchReportsProducts(); + viewModel.fetchReportsProducts(limit: viewModel.limit); } return true; } diff --git a/lib/application/views/settings/reportsViews/ReportsQuotationVC.dart b/lib/application/views/settings/reportsViews/ReportsQuotationVC.dart index e715444..e2bcb76 100644 --- a/lib/application/views/settings/reportsViews/ReportsQuotationVC.dart +++ b/lib/application/views/settings/reportsViews/ReportsQuotationVC.dart @@ -13,9 +13,13 @@ import 'package:wosull/widgets/EmptyDataWidget.dart'; class ReportsQuotationVC extends StatefulWidget { final ReportsCVS delegate; BuildContext context; + int limit = 10; ReportsQuotationVC( - {super.key, required this.delegate, required this.context}); + {super.key, + required this.delegate, + required this.context, + this.limit = 10}); @override State createState() => _ReportsQuotationVCState(); @@ -27,6 +31,7 @@ class _ReportsQuotationVCState extends State { late ScrollController _controller; late DataState _dataState; final viewModel = ReportsViewModel(); + @override void initState() { _controller = ScrollController()..addListener(_scrollNotification); @@ -53,7 +58,7 @@ class _ReportsQuotationVCState extends State { switch (controller.dataState) { case DataState.uninitialized: Future(() { - controller.fetchQuotations(); + controller.fetchQuotations(limit: widget.limit); }); return showList(controller.quotationList, true); case DataState.initialFetching: @@ -507,7 +512,7 @@ class _ReportsQuotationVCState extends State { bool _scrollNotification() { if (!_isLoading && _controller.position.extentAfter < 300) { _isLoading = true; - viewModel.fetchQuotations(); + viewModel.fetchQuotations(limit: viewModel.limit); } return true; } diff --git a/lib/application/views/settings/viewModels/BestSupplierViewModel.dart b/lib/application/views/settings/viewModels/BestSupplierViewModel.dart index 0a150ac..f08ef9e 100644 --- a/lib/application/views/settings/viewModels/BestSupplierViewModel.dart +++ b/lib/application/views/settings/viewModels/BestSupplierViewModel.dart @@ -11,7 +11,7 @@ class BestSupplierViewModel with ChangeNotifier { DataState _dataState = DataState.uninitialized; bool _didLastLoad = false; bool _isLoading = false; - + int limit = 10; bool get isLoading => _isLoading; DataState get dataState => _dataState; @@ -28,7 +28,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 +41,7 @@ class BestSupplierViewModel with ChangeNotifier { } notifyListeners(); Map data = { - 'limit': 50, + 'limit': this.limit, 'page': _currentPageNumber, }; @@ -59,7 +60,7 @@ class BestSupplierViewModel with ChangeNotifier { } if (value.success!) { _data.addAll(value.topOrders!); - if (value.topOrders!.length < 50) { + if (value.topOrders!.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; @@ -72,16 +73,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..79d6ca7 100644 --- a/lib/application/views/settings/viewModels/POSCompleteViewModel.dart +++ b/lib/application/views/settings/viewModels/POSCompleteViewModel.dart @@ -10,7 +10,7 @@ class POSCompleteViewModel with ChangeNotifier { DataState _dataState = DataState.uninitialized; bool _didLastLoad = false; bool _isLoading = false; - + int limit = 10; bool get isLoading => _isLoading; DataState get dataState => _dataState; @@ -18,7 +18,8 @@ class POSCompleteViewModel with ChangeNotifier { 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) @@ -33,6 +34,7 @@ class POSCompleteViewModel with ChangeNotifier { Map data = { 'store_id': sharedPrefs.storeId, 'page': _currentPageNumber, + 'limit': this.limit }; try { @@ -48,7 +50,7 @@ class POSCompleteViewModel with ChangeNotifier { } if (value.success!) { _data.addAll(value.topOrders!); - if (value.topOrders!.length < 10) { + if (value.topOrders!.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..14013cf 100644 --- a/lib/application/views/settings/viewModels/POSReturnOrderViewModel.dart +++ b/lib/application/views/settings/viewModels/POSReturnOrderViewModel.dart @@ -10,14 +10,17 @@ class POSReturnOrderViewModel with ChangeNotifier { 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,6 +35,7 @@ class POSReturnOrderViewModel with ChangeNotifier { Map data = { 'store_id': sharedPrefs.storeId, 'page': _currentPageNumber, + 'limit': this.limit }; try { @@ -47,7 +51,7 @@ class POSReturnOrderViewModel with ChangeNotifier { } if (value.success!) { _data.addAll(value.orderModel!); - if (value.orderModel!.length < 10) { + if (value.orderModel!.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; diff --git a/lib/application/views/settings/viewModels/ReportsInvoiceViewModel.dart b/lib/application/views/settings/viewModels/ReportsInvoiceViewModel.dart index 10446bb..486d5d7 100644 --- a/lib/application/views/settings/viewModels/ReportsInvoiceViewModel.dart +++ b/lib/application/views/settings/viewModels/ReportsInvoiceViewModel.dart @@ -10,8 +10,9 @@ class ReportsInvoiceViewModel with ChangeNotifier { int _currentPageNumber = 1; DataState _dataState = DataState.uninitialized; bool _didLastLoad = false; - + int limit = 10; bool _isLoading = false; + bool get isLoading => _isLoading; DataState get dataState => _dataState; @@ -20,7 +21,8 @@ class ReportsInvoiceViewModel with ChangeNotifier { List get invoiceList => _invoiceList; - fetchInvoices({bool isRefresh = false}) async { + fetchInvoices({bool isRefresh = false, int limit = 10}) async { + this.limit = limit; if (!isRefresh) { _dataState = (_dataState == DataState.uninitialized) ? DataState.initialFetching @@ -33,6 +35,7 @@ class ReportsInvoiceViewModel with ChangeNotifier { Map data = { 'store_id': sharedPrefs.storeId, 'page': _currentPageNumber, + 'limit': this.limit }; try { if (_didLastLoad) { @@ -47,7 +50,7 @@ class ReportsInvoiceViewModel 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; diff --git a/lib/application/views/settings/viewModels/ReportsViewModel.dart b/lib/application/views/settings/viewModels/ReportsViewModel.dart index b29603c..1d84530 100644 --- a/lib/application/views/settings/viewModels/ReportsViewModel.dart +++ b/lib/application/views/settings/viewModels/ReportsViewModel.dart @@ -13,7 +13,7 @@ class ReportsViewModel with ChangeNotifier { 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 +21,8 @@ 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; if (!isRefresh) { _dataState = (_dataState == DataState.uninitialized) ? DataState.initialFetching @@ -34,6 +35,7 @@ class ReportsViewModel with ChangeNotifier { Map data = { 'store_id': sharedPrefs.storeId, 'page': _currentPageNumber, + 'limit': this.limit }; try { if (_didLastLoad) { @@ -48,7 +50,7 @@ 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; @@ -67,7 +69,8 @@ class ReportsViewModel with ChangeNotifier { } } - 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 +84,7 @@ class ReportsViewModel with ChangeNotifier { 'store_id': sharedPrefs.storeId, 'page': _currentPageNumber, 'quotation_status': 'All', + 'limit': this.limit }; try { if (_didLastLoad) { @@ -96,7 +100,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/transactions/CashierTransactionsVC.dart b/lib/application/views/transactions/CashierTransactionsVC.dart index 3daf49d..72bdcd5 100644 --- a/lib/application/views/transactions/CashierTransactionsVC.dart +++ b/lib/application/views/transactions/CashierTransactionsVC.dart @@ -1,31 +1,30 @@ 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/enum/DataState.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/AppError.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/application/views/transactions/viewmodels/CashierTransactionViewModel.dart'; +import 'package:wosull/application/views/transactions/widgets/CashierOrderListView.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; + int limit = 10; + bool isPortrait = false; CashierTransactionsVC( {super.key, required this.delegate, required this.context, + required this.isPortrait, this.filter, + this.limit = 10, this.isOrder}); @override @@ -35,457 +34,92 @@ class CashierTransactionsVC extends StatefulWidget { 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; + final viewModel = CashierTransactionViewModel(); @override void initState() { + _controller = ScrollController()..addListener(_scrollNotification); 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; + 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); } - 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'), + 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); + }, ), - ]; - } else { - return [ - PopupMenuItem( - value: 'return', - child: ValueText('Return'), - ), - PopupMenuItem( - value: 'damage', - child: ValueText('Damage'), - ), - PopupMenuItem( - value: 'view', - child: ValueText('View'), - ), - ]; - } + if (viewModel.dataState == DataState.moreFetching) AppLoader(), + ], + ); } - Future deleteOrder(String? id) async { - Map data = { - 'orderId': id!, - }; + bool _scrollNotification() { + if (!viewModel.isLoading && _controller.position.extentAfter < 300) { + viewModel.fetch(limit: viewModel.limit, filter: widget.filter ?? 'all'); + } + return true; + } - await APIManager() - .getResponsePatch(Constants.DELETE_ORDER, data) - .then((value) { - if (value.success) { - setState(() { - posOrders.removeWhere((element) => element.id == id); - }); - } - }).onError((error, stackTrace) {}); + void viewOrder(CashierOrder order) { + showDialog( + barrierColor: Colors.black26, + context: context, + builder: (context) { + return ViewPOSReturnVC( + orderDetails: order.cart!.orderDetails!, + ); + }, + ); } } diff --git a/lib/application/views/transactions/EditOrderVC.dart b/lib/application/views/transactions/EditOrderVC.dart index ebe11ce..66183cf 100644 --- a/lib/application/views/transactions/EditOrderVC.dart +++ b/lib/application/views/transactions/EditOrderVC.dart @@ -1,27 +1,32 @@ -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:provider/provider.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/utils/AppLoader.dart'; +import 'package:wosull/application/utils/CRUDOperatoinState.dart'; import 'package:wosull/application/views/inventorymodule/productviews/SearchProductVC.dart'; -import 'package:wosull/helpers/Utils.dart'; -import 'package:wosull/objectbox.g.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/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/HeadingContainer.dart'; +import 'package:wosull/widgets/HeadingText.dart'; +import 'package:wosull/widgets/PortraitContainer.dart'; +import 'package:wosull/widgets/ValueText.dart'; class EditOrderVC extends StatefulWidget { CashierOrder cashierOrder; @@ -33,2391 +38,557 @@ class EditOrderVC extends StatefulWidget { } 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; + var viewModel = EditOrderViewModel(); @override void initState() { + context.read().initData(widget.cashierOrder); 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 + 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: 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), + viewModel = context.watch(); + return Scaffold( + resizeToAvoidBottomInset: true, + appBar: CustomAppBar( + heading: AppLocalizations.of(context)!.edit_order, + ), + body: OrientationBuilder(builder: (c, orientation) { + viewModel.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: [ + 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() + ], + )), + ], + ), + ], + )), + ], + ), + ], ), - 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'), - ), - ), - ), + ), + ), + AppSpaces.verticalLarge, + 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: ThemeText.textStylePageHeading, + ), + 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, + 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, ), - 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, + HeadingContainer( + width: 84, + heading: AppLocalizations.of(context)! + .total_amount, ), - 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() + HeadingContainer( + width: 44, + heading: '', + ) ], ), ), - 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( + 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 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: [ - 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, + 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, ), - 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, + PortraitContainer( + width: double.infinity, + child: Align( + alignment: Alignment + .centerLeft, + child: HeadingText( + AppLocalizations.of( + context)! + .item_note, ), - 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, + PortraitContainer( + width: double.infinity, + child: Align( + alignment: Alignment + .centerLeft, + child: HeadingText( + AppLocalizations.of( + context)! + .quantity, ), - 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, + PortraitContainer( + width: double.infinity, + child: Align( + alignment: Alignment + .centerLeft, + child: HeadingText( + AppLocalizations.of( + context)! + .total_cost_price, ), - 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), - ), + PortraitContainer( + width: double.infinity, + child: Align( + alignment: Alignment + .centerLeft, + child: HeadingText( + AppLocalizations.of( + context)! + .total_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), - ), - ), - 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), - ), - ), - ), - ), + ), + ], + )), + 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), ), - 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(), - ), - ), + ), + PortraitContainer( + width: double.infinity, + child: Center( + child: + getItemQuantityWidget( + position, i), ), - ], - )), - ], - ), - )), - 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), + PortraitContainer( + width: double.infinity, + child: Center( + child: + getItemCostPriceWidget( + position, i), ), ), - )), - 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(), + PortraitContainer( + width: double.infinity, + child: + getItemPriceWidget( + item), + ), + ], + )), + ], ), + )), + getRemoveItemButton(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: 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( + '', ), ), - 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(); - }), ), + getRemoveItemButton(position, i), + ], + ), + ); + } + }, + itemCount: orderDetails.items!.length, + ); + }, + itemCount: + widget.cashierOrder.cart!.orderDetails!.length, + ), + viewModel.isPortrait + ? Container( + margin: const EdgeInsets.fromLTRB(8, 0, 0, 8), + decoration: BoxDecoration( + borderRadius: const BorderRadius.all( + Radius.circular( + 1.0) // <--- border radius here ), - ], - ), - ) - : 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(), - ), - ), + border: Border.all( + width: 1, color: MyColors.fillColorGray2), + color: Colors.white, + ), + height: 48, + child: Row( + children: [ + Expanded( + child: ChildContainer( + child: Center( + child: HeadingText( + AppLocalizations.of(context)! + .total_amount), ), - 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(), - ), + )), + Expanded( + child: ChildContainer( + child: Center( + child: HeadingText( + viewModel.getItemsPriceWithModifier(), ), ), - 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(); - }), - ), + )), + getAddItemButton() + ], + ), + ) + : 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: '', + )), + HeadingContainer( + width: 84, + heading: viewModel.getItemsPriceOnly(), + ), + HeadingContainer( + width: 84, + heading: + viewModel.getItemsPriceWithModifier(), + ), + getAddItemButton() + ], ), - const SizedBox( - height: 20, - ), - ], - ), + ), + AppSpaces.verticalLarge, + ], ), ), - 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), - ), - )), - ], - ) - ], - ), + ), + AppSpaces.verticalLarge, + 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, + )), + ], + ) + ], ), - ); - }), - ), + ), + ); + }), ); } - 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, @@ -2428,340 +599,325 @@ class _EditOrderVCState extends State { ); 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(); - }); + if (result != null) { + viewModel.updateItem(parent, child, result); + } } Widget getOrderTypeWidget() { return FutureBuilder( - future: getService(), + future: viewModel.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'), - ), - ), - ), - ), + return DropdownSearch( + selectedItem: viewModel.selectedOrderType, + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: const PopupProps.menu( + fit: FlexFit.loose, + constraints: BoxConstraints(maxHeight: 250)), + items: itemsList, + itemAsString: (StoreServiceModel u) => u.name!, + onChanged: (StoreServiceModel? data) { + viewModel.setSelectedOrderType(data); + }, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), ); } else { - return const Center(child: CircularProgressIndicator()); + return AppLoader(); } }); } - 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(), + future: viewModel.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'), - ), - ), - ), - ), + return DropdownSearch( + selectedItem: viewModel.selectedTable ?? + StoreTable(id: '', tableName: 'N/A', noOfOccupants: 0), + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: const PopupProps.menu( + fit: FlexFit.loose, + constraints: 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 const Center(child: CircularProgressIndicator()); + return AppLoader(); } }); } - 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(), + future: viewModel.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'), - ), - ), - ), - ), + return DropdownSearch( + selectedItem: viewModel.selectedStore, + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: const PopupProps.menu( + fit: FlexFit.loose, + constraints: BoxConstraints(maxHeight: 250)), + items: itemsList, + itemAsString: (WosulStore u) => u.name, + onChanged: (WosulStore? data) { + viewModel.setSelectedStore(data); + }, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), ); } else { - return const Center(child: CircularProgressIndicator()); + return AppLoader(); } }); } - 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 DropdownSearch( + selectedItem: viewModel.selectedPaymentMode ?? "Choose", + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: const PopupProps.menu( + fit: FlexFit.loose, constraints: BoxConstraints(maxHeight: 250)), + items: viewModel.items, + itemAsString: (String u) => u, + onChanged: (String? data) { + viewModel.setSelectedPaymentMode(data); + }, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), + ); } - 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'), - ), - ), + Widget getStatusDropdown() { + return DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: const PopupProps.menu( + fit: FlexFit.loose, constraints: 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) {}, + ) + ], ); } - 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); + getAmountWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.amount, + ), + AppSpaces.verticalSmall, + CustomTextFieldForm( + keyboardType: TextInputType.number, + hintText: 'Enter Amount', + initialValue: viewModel.cashierOrder.amount?.toString() ?? '', + onChanged: (String value) { + viewModel.updateOrderAmount(value); + }, + ) + ], + ); } - 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); - } - } + 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) {}, + ) + ], + ); + } - return price.toStringAsFixed(2); + 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, + ], + )); } - void removeItemFromCart(int parentPosition, int child) { - setState(() { - //remove specif child + Widget getDeliveryNotesWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.delivery_note, + ), + AppSpaces.verticalSmall, + CustomTextFieldForm( + hintText: 'Enter Delivery Note', + initialValue: viewModel.cashierOrder.deliveryNotes ?? '', + onChanged: (String value) { + viewModel.updateDeliveryNotes(value); + }, + ), + ], + ); + } - widget.cashierOrder.returnOrderDetails! - .add(widget.cashierOrder.cart!.orderDetails![parentPosition]); + getPaymentModeWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.payment_mode, + ), + AppSpaces.verticalSmall, + getSelectedPaymentMode(), + ], + ); + } - 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(); - }); + getShowProductsWidget(StoreItems item, int position, int i) { + return CustomTextButtonIcon( + icon: Icons.arrow_drop_down, + heading: item.name.isEmpty ? 'Choose' : item.name, + onPressed: () { + showSheet(position, i); + }, + ); } - 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"; - } - } + getItemNotesWidget(int position, int i) { + return CustomTextFieldForm( + hintText: 'Enter item note', + initialValue: viewModel.itemNotesController[position][i], + onChanged: (value) { + viewModel.updateItemNote(position, i, value); + }, + ); + } + + getItemQuantityWidget(int position, int i) { + return CustomTextFieldForm( + 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( + 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(); + }), + ), + ); + } - itemNotesController[i].add(TextEditingController(text: text)); - itemQuantityController[i] - .add(TextEditingController(text: item.quantity.toString())); - itemCostPriceController[i] - .add(TextEditingController(text: item.price.toString())); - } + 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/ReturnTransactionInvoiceVC.dart index 408bbd7..79c33c3 100644 --- a/lib/application/views/transactions/ReturnTransactionInvoiceVC.dart +++ b/lib/application/views/transactions/ReturnTransactionInvoiceVC.dart @@ -18,11 +18,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 +44,7 @@ class _ReturnTransactionInvoiceVCState 'Damage' ]; - InventoryViewModel viewModel = InventoryViewModel(); + var viewModel = InventoryViewModel(); List filteredInvoices = []; @@ -837,7 +840,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 +852,7 @@ class _ReturnTransactionInvoiceVCState final response = await viewModel.getResponsePatch(Constants.UPDATE_INVOICE, data); - if (response.success!) { + if (response.success) { setState(() {}); } } @@ -869,12 +872,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 +913,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 +921,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/TransactionDamageInvoiceVC.dart b/lib/application/views/transactions/TransactionDamageInvoiceVC.dart index ce57493..e56a092 100644 --- a/lib/application/views/transactions/TransactionDamageInvoiceVC.dart +++ b/lib/application/views/transactions/TransactionDamageInvoiceVC.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 = InventoryViewModel(); 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/TransactionInvoicesVC.dart b/lib/application/views/transactions/TransactionInvoicesVC.dart index a7a1f06..0ab0f47 100644 --- a/lib/application/views/transactions/TransactionInvoicesVC.dart +++ b/lib/application/views/transactions/TransactionInvoicesVC.dart @@ -19,9 +19,11 @@ 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}); @@ -838,7 +840,7 @@ class _TransactionInvoicesVCState final response = await viewModel.getResponsePatch(Constants.DELETE_NVOICE, data); - if (response.success!) { + if (response.success) { setState(() { filteredInvoices.removeWhere((element) => element.id! == id); }); @@ -850,7 +852,7 @@ class _TransactionInvoicesVCState final response = await viewModel.getResponsePatch(Constants.UPDATE_INVOICE, data); - if (response.success!) { + if (response.success) { setState(() {}); } } @@ -870,12 +872,13 @@ class _TransactionInvoicesVCState '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(() { @@ -910,6 +913,7 @@ class _TransactionInvoicesVCState 'store_id': sharedPrefs.storeId, 'page': _page, 'invoice_status': widget.filter, + 'limit': widget.limit }; await viewModel.getData(Constants.GET_INVOICE, data).then((response) { @@ -917,7 +921,7 @@ class _TransactionInvoicesVCState 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/TransactionPOSReturnVC.dart b/lib/application/views/transactions/TransactionPOSReturnVC.dart index d231ed2..e4394b9 100644 --- a/lib/application/views/transactions/TransactionPOSReturnVC.dart +++ b/lib/application/views/transactions/TransactionPOSReturnVC.dart @@ -14,8 +14,12 @@ import 'package:wosull/widgets/EmptyDataWidget.dart'; class TransactionPOSReturnVC extends StatefulWidget { TransactionCVS delegate; BuildContext context; + int limit; TransactionPOSReturnVC( - {super.key, required this.delegate, required this.context}); + {super.key, + required this.delegate, + required this.context, + this.limit = 10}); @override State createState() => _TransactionPOSReturnVCState(); @@ -397,6 +401,7 @@ class _TransactionPOSReturnVCState Map data = { 'store_id': sharedPrefs.storeId, 'page': _pageForPOS, + 'limit': widget.limit }; await viewModel @@ -407,7 +412,7 @@ class _TransactionPOSReturnVCState orders.addAll(response.orderModel!); // widget.delegate.posReturnCVS(orders); } - if (response.orderModel!.length < 10) { + if (response.orderModel!.length < widget.limit) { __hasNextPageForPOS = false; } @@ -436,6 +441,7 @@ class _TransactionPOSReturnVCState Map data = { 'store_id': sharedPrefs.storeId, 'page': _pageForPOS, + 'limit': widget.limit }; await viewModel .getData(Constants.GET_CASHIER_ORDER_HISTORY, data) @@ -443,7 +449,7 @@ class _TransactionPOSReturnVCState final value = GetReturnOrderModel.fromJson(response); if (value.success!) { if (value.orderModel!.isNotEmpty) { - if (value.orderModel!.length < 10) { + if (value.orderModel!.length < widget.limit) { __hasNextPageForPOS = false; } setState(() { diff --git a/lib/application/views/transactions/TransactionQuotationVC.dart b/lib/application/views/transactions/TransactionQuotationVC.dart index 3f688c7..6ceeafc 100644 --- a/lib/application/views/transactions/TransactionQuotationVC.dart +++ b/lib/application/views/transactions/TransactionQuotationVC.dart @@ -9,6 +9,7 @@ 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'; @@ -17,9 +18,13 @@ 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); @@ -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/TransactionVC.dart b/lib/application/views/transactions/TransactionVC.dart index 5ad7b5f..699da54 100644 --- a/lib/application/views/transactions/TransactionVC.dart +++ b/lib/application/views/transactions/TransactionVC.dart @@ -5,7 +5,6 @@ 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/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'; @@ -16,7 +15,10 @@ import 'package:wosull/application/views/transactions/TransactionPOSReturnVC.dar import 'package:wosull/application/views/transactions/TransactionQuotationVC.dart'; import 'package:wosull/application/views/transactions/return/ReturnPOS.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/PageLimitDropDown.dart'; import '../../model/cart/GetHoldOrderModel.dart'; import '../../model/reports/CashierOrderHistory.dart'; @@ -31,6 +33,7 @@ class TransactionVC extends StatefulWidget { class _TransactionVCState extends BaseStatefulState implements TransactionCVS { + int limit = 10; bool isPortrait = false; var items = [ 'Cashier', @@ -69,50 +72,33 @@ 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: 120, + child: DropdownSearch( + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + selectedItem: selectedReport, + popupProps: const PopupProps.menu( + constraints: BoxConstraints(maxHeight: 200), ), + items: items, + itemAsString: (String u) => u, + onChanged: (String? data) { + setState(() { + selectedReport = data!; + }); + }, + dropdownDecoratorProps: MyColors.dropDownStyle( + hint: 'Choose', fillColor: MyColors.white), ), ), + Flexible(child: PageLimitDropdown(onChange: (value) { + limit = int.parse(value!); + })) ], ), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, Expanded(child: getReportsType()) ], ), @@ -122,34 +108,41 @@ class _TransactionVCState extends BaseStatefulState Widget getReportsType() { if (selectedReport == items[0]) { return CashierTransactionsVC( + limit: limit, + isPortrait: isPortrait, context: context, isOrder: false, delegate: this, ); } else if (selectedReport == items[1]) { return TransactionPOSReturnVC( + limit: limit, context: context, delegate: this, ); } else if (selectedReport == items[2]) { return TransactionInvoicesVC( + limit: limit, filter: 'All', context: context, delegate: this, ); } else if (selectedReport == items[3]) { return TransactionQuotationVC( + limit: limit, context: context, delegate: this, ); } else if (selectedReport == items[4]) { return ReturnTransactionInvoiceVC( + limit: limit, filter: 'Return', context: context, delegate: this, ); } else if (selectedReport == items[5]) { return TransactionDamageInvoiceVC( + limit: limit, filter: 'Damage', context: context, delegate: this, diff --git a/lib/application/views/transactions/ViewPOSReturnVC.dart b/lib/application/views/transactions/ViewPOSReturnVC.dart index 624f830..9a9b2ab 100644 --- a/lib/application/views/transactions/ViewPOSReturnVC.dart +++ b/lib/application/views/transactions/ViewPOSReturnVC.dart @@ -2,7 +2,12 @@ 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; @@ -38,9 +43,7 @@ class _ViewPOSReturnVCState extends State { mainAxisSize: MainAxisSize.min, children: [ DialogHeader(title: 'Order Details'), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, Container( padding: const EdgeInsets.fromLTRB(8, 8, 8, 16), child: Column( @@ -52,116 +55,34 @@ class _ViewPOSReturnVCState extends State { ), border: Border.all( width: 1, color: MyColors.fillColorGray2), - color: MyColors.fillColor, + color: MyColors.containerBackColor, ), 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(), - ), - ), + child: HeadingContainer( + heading: 'Name', )), 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(), - ), - ), + child: HeadingContainer( + heading: 'Item Note', )), 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(), - ), - ), + child: HeadingContainer( + heading: 'Quantity', )), 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(), - ), - ), + child: HeadingContainer( + heading: 'Total Cost Price', )), 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(), - ), - ), + child: HeadingContainer( + heading: 'Total Price', )), - Container( + HeadingContainer( 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(), - ), - ), + heading: 'Total Amount', ), ], ), @@ -195,122 +116,47 @@ class _ViewPOSReturnVCState extends State { 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(), - ), - ), + 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: ChildContainer( child: Center( - child: Text( - getItemNote(item), - style: MyColors.textStyleValue(), - ), + child: ValueText(getItemNote(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: ChildContainer( child: Center( - child: Text( - item.quantity.toString(), - style: MyColors.textStyleValue(), - ), + child: + ValueText(item.quantity.toString()), ), )), Expanded( - child: Container( - padding: const EdgeInsets.all(4), - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), + child: ChildContainer( child: Center( - child: Text( + child: ValueText( (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: ChildContainer( child: Center( - child: Text( - (item.price * item.quantity) + child: ValueText( + (item.price * item.quantity!) .toStringAsFixed(2), - style: MyColors.textStyleValue(), ), ), )), - Container( + ChildContainer( width: 84, - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), child: Center( - child: Text( + child: ValueText( '', - style: MyColors.textStyleValue(), ), ), ), @@ -338,108 +184,30 @@ class _ViewPOSReturnVCState extends State { 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: '', )), 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( - 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( - 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( - 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: '', )), - Container( + ChildContainer( width: 84, - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), child: Center( - child: Text( + child: HeadingText( getItemsPriceWithModifier(), - style: MyColors.textStyleHeading(), ), ), ), @@ -461,7 +229,7 @@ class _ViewPOSReturnVCState extends State { double price = 0.0; for (var order in widget.orderDetails!) { for (var item in order.items!) { - price += (item.quantity * item.price); + price += (item.quantity! * item.price); if (item.selectedModifiers!.isNotEmpty) { for (var modi in item.selectedModifiers!) { price += modi.price; @@ -476,7 +244,7 @@ class _ViewPOSReturnVCState extends State { double price = 0.0; for (var order in widget.orderDetails!) { for (var item in order.items!) { - price += (item.quantity * item.price); + price += (item.quantity! * item.price); } } diff --git a/lib/application/views/transactions/return/ReturnPOS.dart b/lib/application/views/transactions/return/ReturnPOS.dart index f80a007..96a0a69 100644 --- a/lib/application/views/transactions/return/ReturnPOS.dart +++ b/lib/application/views/transactions/return/ReturnPOS.dart @@ -10,10 +10,15 @@ import 'package:wosull/application/views/transactions/return/ReturnReasonPopUp.d 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/ChildContainer.dart'; +import 'package:wosull/widgets/CustomAppBar.dart'; import 'package:wosull/widgets/CustomCheckBox.dart'; import 'package:wosull/widgets/CustomSimpleButton.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/ValueText.dart'; class ReturnPOS extends StatefulWidget { @@ -29,6 +34,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 +49,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 = @@ -87,7 +83,7 @@ class _ReturnPOSState extends State { Text( AppLocalizations.of(context)! .search_and_add_products, - style: ThemeText.textStylePopUpHeading, + style: ThemeText.textStylePageHeading, ), AppSpaces.verticalMedium, viewModel.isPortrait @@ -106,117 +102,35 @@ class _ReturnPOSState extends State { height: 48, 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, ), ], ), @@ -267,28 +181,10 @@ class _ReturnPOSState extends State { MainAxisAlignment .start, children: [ - Container( - padding: - const EdgeInsets - .all(4), + PortraitContainer( + width: + double.infinity, 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, @@ -298,32 +194,10 @@ class _ReturnPOSState extends State { .name_or_barcode), ), ), - Container( - padding: - const EdgeInsets - .all(4), + PortraitContainer( + width: + double.infinity, 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, @@ -333,28 +207,10 @@ class _ReturnPOSState extends State { .description), ), ), - Container( - padding: - const EdgeInsets - .all(4), + PortraitContainer( + width: + double.infinity, 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, @@ -365,28 +221,10 @@ class _ReturnPOSState extends State { ), ), ), - Container( - padding: - const EdgeInsets - .all(4), + PortraitContainer( + width: + double.infinity, 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, @@ -396,32 +234,10 @@ class _ReturnPOSState extends State { .unit_price), ), ), - Container( - padding: - const EdgeInsets - .all(4), + PortraitContainer( + width: + double.infinity, 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, @@ -436,33 +252,11 @@ class _ReturnPOSState extends State { )), Expanded( child: Column( - crossAxisAlignment: - CrossAxisAlignment - .start, - mainAxisAlignment: - MainAxisAlignment - .start, children: [ - Container( + PortraitContainer( + width: + double.infinity, 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), - ), child: Center( child: Align( alignment: Alignment @@ -472,71 +266,29 @@ class _ReturnPOSState extends State { ), ), ), - Container( - padding: - const EdgeInsets - .all(4), + PortraitContainer( height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), + width: + double.infinity, child: Center( child: ValueText(item .description), ), ), - Container( - padding: - const EdgeInsets - .all(4), + PortraitContainer( height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), + width: + double.infinity, child: getQuantityWidget( parent, child, item), ), - Container( - padding: - const EdgeInsets - .all(4), + PortraitContainer( height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - top: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), + width: + double.infinity, child: Center( child: ValueText( item.price @@ -545,28 +297,10 @@ class _ReturnPOSState extends State { ), ), ), - Container( - padding: - const EdgeInsets - .all(4), + PortraitContainer( 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), - ), - ), + width: + double.infinity, child: Center( child: ValueText( viewModel @@ -611,19 +345,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,29 +359,8 @@ 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: ChildContainer( + child: TransparentBorderContainer( child: Expanded( child: Align( alignment: @@ -669,27 +371,10 @@ class _ReturnPOSState extends State { ), )), 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: ChildContainer( + child: TransparentBorderContainer( + backgroundColor: + MyColors.disableColor, child: Align( alignment: Alignment.centerLeft, child: ValueText( @@ -699,43 +384,16 @@ class _ReturnPOSState extends State { ), )), 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: ChildContainer( + child: TransparentBorderContainer( + backgroundColor: + MyColors.disableColor, child: Align( alignment: Alignment.centerLeft, child: ValueText( @@ -744,19 +402,8 @@ class _ReturnPOSState extends State { ), ), )), - 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: ValueText( @@ -793,38 +440,14 @@ class _ReturnPOSState extends State { 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( - 'Grand Total', - style: MyColors.textStyleValue(), - ), - ), + child: HeadingContainer( + heading: 'Grand Total', )), Expanded( - child: Container( + child: HeadingContainer( height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: Text( + heading: viewModel.getTotalProductsPrice(), - style: MyColors.textStyleValue(), - ), - ), )), ], ), @@ -844,91 +467,30 @@ class _ReturnPOSState extends State { height: 48, 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: HeadingContainer( + heading: 'Grand Total', )), - Container( + HeadingContainer( width: 84, - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: Text( + heading: viewModel.getTotalProductsPrice(), - style: MyColors.textStyleHeading(), - ), - ), ), ], ), @@ -1061,9 +623,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: '', ), diff --git a/lib/application/views/transactions/return/ReturnReasonPopUp.dart b/lib/application/views/transactions/return/ReturnReasonPopUp.dart index 5ca4990..c263785 100644 --- a/lib/application/views/transactions/return/ReturnReasonPopUp.dart +++ b/lib/application/views/transactions/return/ReturnReasonPopUp.dart @@ -3,6 +3,7 @@ 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'; @@ -93,57 +94,40 @@ 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: const PopupProps.menu( + fit: FlexFit.loose, 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: const PopupProps.menu( + 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..94b1fa5 --- /dev/null +++ b/lib/application/views/transactions/viewmodels/CashierTransactionViewModel.dart @@ -0,0 +1,102 @@ +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/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; + + 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 + }; + print(jsonEncode(data)); + 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) { + print(stackTrace.toString()); + _dataState = DataState.error; + }); + } + _isLoading = false; + notifyListeners(); + } catch (e) { + print(e.toString()); + _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..cdb1252 100644 --- a/lib/application/views/transactions/viewmodels/ReturnPOSOrderVM.dart +++ b/lib/application/views/transactions/viewmodels/ReturnPOSOrderVM.dart @@ -75,7 +75,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 +83,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 +104,7 @@ class ReturnPOSOrderVM with ChangeNotifier { cashierOrder!.cart!.orderDetails![parent].items![child].quantity = int.parse(value); } + notifyListeners(); } Future returnWholeOrder(result, bool isReturn) async { @@ -158,12 +159,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 +177,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/widgets/CashierOrderListView.dart b/lib/application/views/transactions/widgets/CashierOrderListView.dart new file mode 100644 index 0000000..f1ff979 --- /dev/null +++ b/lib/application/views/transactions/widgets/CashierOrderListView.dart @@ -0,0 +1,317 @@ +import 'package:flutter/material.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/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/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: [ + AppSpaces.verticalMedium, + 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), + ], + )), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + ValueText( + posOrders[position] + .referenceNo! + .toString(), + ), + AppSpaces.verticalMedium, + ValueText( + posOrders[position].transactionId ?? '', + ), + ValueText( + posOrders[position] + .uniqueId! + .toString(), + ), + AppSpaces.verticalMedium, + ValueText( + posOrders[position].storeId!.name ?? '', + ), + AppSpaces.verticalMedium, + ValueText( + posOrders[position].status ?? '', + ), + AppSpaces.verticalMedium, + ValueText( + DataTimeFormat.getFormatDate( + posOrders[position].createdAt ?? + ''), + ), + AppSpaces.verticalMedium, + ValueText(DataTimeFormat.getFormatDate( + posOrders[position].updatedAt ?? '')), + ], + )), + ], + ), + )), + 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: 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: PopupMenuButton( + icon: const Icon(Icons.more_vert), + itemBuilder: (c) { + return getPopUpMenuButton(); + }, + onSelected: (String value) => + actionPopUpItemSelected( + value, posOrders[position]), + ), + ), + ), + ) + ], + ), + ), + ); + } + }, + itemCount: posOrders.length, + ) + ], + ); + } + + List> getPopUpMenuButton() { + if (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'), + ), + ]; + } + } + + 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); + } + } +} diff --git a/lib/application/views/transactions/widgets/EditOrderViewModel.dart b/lib/application/views/transactions/widgets/EditOrderViewModel.dart new file mode 100644 index 0000000..57282ea --- /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/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/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/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/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..0866764 100644 --- a/lib/helpers/ThemeDropDown.dart +++ b/lib/helpers/ThemeDropDown.dart @@ -10,4 +10,13 @@ abstract class ThemeDropDown { color: MyColors.black, isVisible: true, ); + + static const PopupProps popupProps = PopupProps.menu( + fit: FlexFit.loose, + constraints: BoxConstraints(maxHeight: 300), + ); + + static const DropdownButtonProps dropdownButtonProps = DropdownButtonProps( + padding: EdgeInsets.only(left: 0, right: 4), + constraints: BoxConstraints(maxHeight: 38)); } diff --git a/lib/helpers/ThemeText.dart b/lib/helpers/ThemeText.dart index 1193af1..a0a8c2c 100644 --- a/lib/helpers/ThemeText.dart +++ b/lib/helpers/ThemeText.dart @@ -3,6 +3,27 @@ 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, @@ -85,12 +106,19 @@ abstract class ThemeText { 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.black); + color: MyColors.textColorBlack20); static const TextStyle textStyleValue = TextStyle( fontStyle: FontStyle.normal, @@ -157,13 +185,23 @@ abstract class ThemeText { 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( fontWeight: FontWeight.bold, fontSize: MyFonts.normal, fontFamily: MyFonts.Bold, color: MyColors.white); + + static const TextStyle textStyleAmountHeading = TextStyle( + fontFamily: MyFonts.Bold, + fontWeight: FontWeight.bold, + fontSize: MyFonts.normalButton, + color: MyColors.textColorBlack); + + static const TextStyle textStyleAmountValue = TextStyle( + fontFamily: MyFonts.Bold, + fontWeight: FontWeight.bold, + fontSize: MyFonts.normalButton, + color: MyColors.textColorBlack20); } diff --git a/lib/main.dart b/lib/main.dart index 4a456ec..0345e31 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -15,6 +15,14 @@ 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: @@ -27,5 +35,4 @@ Future main() async { break; } }); - runApp(const MyApp()); } diff --git a/lib/objectbox-model.json b/lib/objectbox-model.json index b8e704f..79bf2ae 100644 --- a/lib/objectbox-model.json +++ b/lib/objectbox-model.json @@ -4,168 +4,168 @@ "_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": "32:4971480019915069043", "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 } @@ -173,63 +173,63 @@ "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,48 +237,194 @@ "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": "8:5336083002345932458", "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 } @@ -286,63 +432,63 @@ "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 +496,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,123 +555,152 @@ "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": "7:5534011194632221070", "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 } @@ -533,23 +708,63 @@ "relations": [] }, { - "id": "8:1495441327752723255", - "lastPropertyId": "3:7196896965463181090", + "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": "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 +772,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 +916,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 +1155,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": "12:5672312728119666494", "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..7ecffc6 100644 --- a/lib/objectbox.g.dart +++ b/lib/objectbox.g.dart @@ -32,168 +32,168 @@ 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(32, 4971480019915069043), 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) @@ -201,63 +201,63 @@ final _entities = [ 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,48 +265,193 @@ 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(8, 5336083002345932458), 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) @@ -314,63 +459,63 @@ final _entities = [ 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 +523,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,121 +582,150 @@ 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(7, 5534011194632221070), 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) @@ -559,23 +733,62 @@ final _entities = [ relations: [], backlinks: []), ModelEntity( - id: const IdUid(8, 1495441327752723255), + 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(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 +796,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 +940,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), + 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(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)), - 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(9, 4265877760756686195), + name: 'deliveryPartners', + targetId: const IdUid(7, 6854003909814618353)), ModelRelation( - id: const IdUid(8, 4922321800841909780), + 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 +1175,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 +1257,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(12, 5672312728119666494), 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); @@ -1532,8 +1547,156 @@ ModelDefinition getObjectBoxModel() { return object; }), - DeliveryPartner: EntityDefinition( + CreateAndUpdateOrder: EntityDefinition( model: _entities[2], + toOneRelations: (CreateAndUpdateOrder object) => [], + toManyRelations: (CreateAndUpdateOrder object) => {}, + 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 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, 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, @@ -1595,7 +1758,7 @@ ModelDefinition getObjectBoxModel() { return object; }), ItemCategory: EntityDefinition( - model: _entities[3], + model: _entities[4], toOneRelations: (ItemCategory object) => [], toManyRelations: (ItemCategory object) => {}, getId: (ItemCategory object) => object.obid, @@ -1675,7 +1838,7 @@ ModelDefinition getObjectBoxModel() { return object; }), ItemSubCategory: EntityDefinition( - model: _entities[4], + model: _entities[5], toOneRelations: (ItemSubCategory object) => [], toManyRelations: (ItemSubCategory object) => {}, getId: (ItemSubCategory object) => object.odid, @@ -1742,12 +1905,46 @@ ModelDefinition getObjectBoxModel() { return object; }), - Modifier: EntityDefinition( - model: _entities[5], - toOneRelations: (Modifier object) => [], - toManyRelations: (Modifier object) => { - RelInfo.toMany(9, object.obid): object.options, - RelInfo.toMany(10, object.obid): object.selected + 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[7], + toOneRelations: (Modifier object) => [], + toManyRelations: (Modifier object) => { + 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 +1964,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 +1987,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,15 +2015,15 @@ 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) => {}, getId: (ModifierOption object) => object.obid, @@ -1875,8 +2072,56 @@ ModelDefinition getObjectBoxModel() { 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, @@ -1911,7 +2156,7 @@ ModelDefinition getObjectBoxModel() { return object; }), StoreDiscount: EntityDefinition( - model: _entities[8], + model: _entities[11], toOneRelations: (StoreDiscount object) => [], toManyRelations: (StoreDiscount object) => {}, getId: (StoreDiscount object) => object.obid, @@ -1968,7 +2213,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 +2231,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 +2263,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 +2292,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 +2318,7 @@ ModelDefinition getObjectBoxModel() { value: valueParam, type: typeParam, storeId: storeIdParam, + isUserUsed: isUserUsedParam, categories: categoriesParam, products: productsParam, status: statusParam, @@ -2093,24 +2342,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 +2382,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 +2394,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 +2405,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 +2415,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 +2454,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 +2512,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 +2551,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 +2605,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,228 +2663,8 @@ 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; - }) - }; + }) + }; return ModelDefinition(model, bindings); } @@ -2824,721 +2847,720 @@ class ComboProduct_ { 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 [CreateAndUpdateOrder.orderStatus] + static final orderStatus = + QueryStringProperty(_entities[2].properties[14]); + + /// see [CreateAndUpdateOrder.paymentStatus] + static final paymentStatus = + QueryBooleanProperty(_entities[2].properties[15]); + + /// see [CreateAndUpdateOrder.paymentMode] + static final paymentMode = + QueryStringProperty(_entities[2].properties[16]); + + /// see [CreateAndUpdateOrder.amount] + static final amount = + QueryDoubleProperty(_entities[2].properties[17]); + + /// see [CreateAndUpdateOrder.totalAmount] + static final totalAmount = + QueryDoubleProperty(_entities[2].properties[18]); + + /// see [CreateAndUpdateOrder.totalDiscount] + static final totalDiscount = + QueryDoubleProperty(_entities[2].properties[19]); + + /// see [CreateAndUpdateOrder.discountId] + static final discountId = + QueryStringProperty(_entities[2].properties[20]); + + /// see [CreateAndUpdateOrder.cardNumber] + static final cardNumber = + QueryIntegerProperty(_entities[2].properties[21]); + + /// see [CreateAndUpdateOrder.changeBalanceAmount] + static final changeBalanceAmount = + QueryDoubleProperty(_entities[2].properties[22]); + + /// see [CreateAndUpdateOrder.timer] + static final timer = + QueryIntegerProperty(_entities[2].properties[23]); + + /// see [CreateAndUpdateOrder.orderNumber] + static final orderNumber = + QueryIntegerProperty(_entities[2].properties[24]); + + /// see [CreateAndUpdateOrder.deliveryNotes] + static final deliveryNotes = + QueryStringProperty(_entities[2].properties[25]); + + /// 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]); } /// [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]); +} + +/// [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..92c5369 --- /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: 42, + height: 42, + decoration: BoxDecoration( + borderRadius: const BorderRadius.all(Radius.circular(4)), + color: MyColors.backFillColor), + child: child, + ); + } +} 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/ChildContainer.dart b/lib/widgets/ChildContainer.dart new file mode 100644 index 0000000..c338a6a --- /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 = 48}); + + @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( + child: child, + alignment: Alignment.centerLeft, + ), + ); + } +} diff --git a/lib/widgets/CustomAddButton.dart b/lib/widgets/CustomAddButton.dart new file mode 100644 index 0000000..5f1441c --- /dev/null +++ b/lib/widgets/CustomAddButton.dart @@ -0,0 +1,29 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/theme/MyColors.dart'; + +class CustomAddButton extends StatelessWidget { + final void Function() onPressed; + + const CustomAddButton({super.key, required this.onPressed}); + + @override + Widget build(BuildContext context) { + 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: 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..62fc8cd 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,7 +13,7 @@ class CustomCheckBox extends StatelessWidget { @override Widget build(BuildContext context) { - return Row(mainAxisAlignment: MainAxisAlignment.center, children: [ + return Row(mainAxisAlignment: MainAxisAlignment.end, children: [ SizedBox( height: 20, width: 20, @@ -28,6 +29,7 @@ class CustomCheckBox extends StatelessWidget { ), ), ), + AppSpaces.horizontalSmall, Text( heading ?? '', style: ThemeText.textStyleHeading, 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/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/CustomTextButtonIcon.dart b/lib/widgets/CustomTextButtonIcon.dart index 650aef8..213def8 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; @@ -21,40 +21,48 @@ class CustomTextButtonIcon extends StatelessWidget { @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, + 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: const 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/CustomTextFieldForm.dart b/lib/widgets/CustomTextFieldForm.dart index 5c4ff24..c324dab 100644 --- a/lib/widgets/CustomTextFieldForm.dart +++ b/lib/widgets/CustomTextFieldForm.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 CustomTextFieldForm extends StatelessWidget { CustomTextFieldForm( @@ -25,37 +25,40 @@ 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( + // style: ThemeText.textStyleValue, + textAlignVertical: TextAlignVertical.center, + readOnly: readOnly, + keyboardType: keyboardType, + initialValue: initialValue, + maxLines: maxLines, + style: const TextStyle( + fontFamily: MyFonts.DMREGULAR, + fontSize: MyFonts.normal, + color: MyColors.black), + decoration: InputDecoration( + constraints: BoxConstraints(maxHeight: height), + + fillColor: readOnly ? MyColors.disableColor : MyColors.backFillColor, + filled: true, + border: InputBorder.none, + // labelStyle: ThemeText.labelStyleTextField, + // hintStyle: ThemeText.labelStyleTextField, + hintText: hintText, + isDense: 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), ), - onChanged: onChanged, ), + onChanged: onChanged, ); } } diff --git a/lib/widgets/CustomTextFieldPassword.dart b/lib/widgets/CustomTextFieldPassword.dart index 77e27fa..2b663c9 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: const 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/DiscountDropdown.dart b/lib/widgets/DiscountDropdown.dart new file mode 100644 index 0000000..451cafd --- /dev/null +++ b/lib/widgets/DiscountDropdown.dart @@ -0,0 +1,86 @@ +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'; + +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( + height: 42, + width: double.infinity, + child: DropdownSearch( + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: const PopupProps.menu( + fit: FlexFit.loose, constraints: 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/ItemCategoryDropdown.dart b/lib/widgets/ItemCategoryDropdown.dart new file mode 100644 index 0000000..089c4ab --- /dev/null +++ b/lib/widgets/ItemCategoryDropdown.dart @@ -0,0 +1,96 @@ +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'; + +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 = ''; + + 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( + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: const PopupProps.menu( + fit: FlexFit.loose, + constraints: BoxConstraints(maxHeight: 300), + ), + clearButtonProps: ThemeDropDown.clearButton, + selectedItem: selectedCategoryDropDown, + items: itemsList, + itemAsString: (ItemCategory u) => u.name, + onChanged: onChanged, + dropdownDecoratorProps: + MyColors.dropDownStyle(fillColor: fillColor), + ); + } else { + return AppLoader(); + } + }); + } + + 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); + 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..d7ddc23 --- /dev/null +++ b/lib/widgets/LanguageDropdown.dart @@ -0,0 +1,32 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/language/AppLanguage.dart'; +import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/widgets/HeadingText.dart'; + +class LanguageDropdown extends StatelessWidget { + AppLanguage dropdownValue = AppLanguage.languages().first; + final void Function(AppLanguage? language) onChange; + + LanguageDropdown( + {super.key, required this.dropdownValue, required this.onChange}); + + @override + Widget build(BuildContext context) { + return DropdownButton( + value: dropdownValue, + iconSize: 12, + style: ThemeText.textStyleHeading, + onChanged: onChange, + underline: DropdownButtonHideUnderline(child: Container()), + items: AppLanguage.languages() + .map>( + (e) => DropdownMenuItem( + value: e, + child: HeadingText( + e.name, + )), + ) + .toList(), + ); + } +} 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/PageLimitDropDown.dart b/lib/widgets/PageLimitDropDown.dart new file mode 100644 index 0000000..e67780f --- /dev/null +++ b/lib/widgets/PageLimitDropDown.dart @@ -0,0 +1,46 @@ +import 'package:dropdown_search/dropdown_search.dart'; +import 'package:flutter/material.dart'; +import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeText.dart'; + +class PageLimitDropdown extends StatelessWidget { + final void Function(String? language) onChange; + + const PageLimitDropdown({super.key, required this.onChange}); + + @override + Widget build(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Text( + 'Show', + style: ThemeText.textStyleValue, + ), + AppSpaces.horizontalSmall, + SizedBox( + width: 100, + child: DropdownSearch( + popupProps: const PopupProps.menu( + constraints: BoxConstraints(maxHeight: 220)), + items: Constants.pageLimits, + itemAsString: (String u) => u, + onChanged: onChange, + dropdownDecoratorProps: const DropDownDecoratorProps( + baseStyle: ThemeText.textStyleValue, + textAlignVertical: TextAlignVertical.center, + dropdownSearchDecoration: InputDecoration( + labelStyle: ThemeText.textStyleValue, + hintStyle: ThemeText.textStyleValue, + border: InputBorder.none, + hintText: 'Page Limit', + ), + ), + ), + ), + ], + ); + } +} diff --git a/lib/widgets/PortraitContainer.dart b/lib/widgets/PortraitContainer.dart new file mode 100644 index 0000000..a76007a --- /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 = 48}); + + @override + Widget build(BuildContext context) { + return Container( + width: width, + height: 48, + 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/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/pubspec.lock b/pubspec.lock index e0373fb..d591f62 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -17,6 +17,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: @@ -41,6 +57,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 +109,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 +141,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 +173,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 +213,10 @@ 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" crypto: dependency: transitive description: @@ -213,18 +245,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: @@ -293,42 +325,42 @@ 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_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 +418,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 +431,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 +549,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 +569,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 +585,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: @@ -705,26 +745,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 +809,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 +873,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 +897,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 +913,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: @@ -941,62 +997,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: @@ -1174,26 +1238,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 +1268,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..ee8b481 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -66,6 +66,9 @@ 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 dev_dependencies: flutter_test: sdk: flutter @@ -123,6 +126,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: From 68e42846a0546557bf3c7e3cb62b5b5792465f0e Mon Sep 17 00:00:00 2001 From: waqasYeepeey Date: Tue, 26 Sep 2023 19:07:50 +0500 Subject: [PATCH 02/11] 'modifier and modifier options changes' --- lib/application/MyApp.dart | 3 + .../SearchComboItemModel.dart | 2 +- .../model/CreateAndUpdateOrder.dart | 2 +- .../GetMeasurementCategory.dart | 0 .../InventoryMeasurementModel.dart | 0 .../MeasurementUnitModel.dart | 0 .../model/Measurement/MeasuringUnit.dart | 18 + .../model/Modifiers/GetModifiersModel.dart | 131 +- lib/application/model/Modifiers/Modifier.dart | 85 + .../model/Modifiers/ModifierOption.dart | 45 + .../ProductItemCategoryModel.dart | 4 +- .../model/createOrder/CashierCart.dart | 6 +- lib/application/model/ingredients/Add.dart | 9 + .../AddIngredient.dart} | 93 +- .../model/ingredients/AddIngredientModel.dart | 26 + .../model/ingredients/AddProdcutModel.dart | 25 + .../model/ingredients/AddProductItem.dart | 11 + .../model/ingredients/GetIngredientModel.dart | 16 + .../model/modifierOptions/ModifierId.dart | 13 + .../model/modifierOptions/ModifierOption.dart | 62 + .../ModifierOptionsResponse.dart | 19 + .../model/store/StoreItemsResponse.dart | 5 +- lib/application/utils/Constants.dart | 8 + .../viewModels/CartViewModel.dart | 2 +- .../viewModels/CreateOrderViewModel.dart | 4 +- .../views/popups/ItemModifiersPopUp.dart | 3 +- .../InventoryModuleMainVC.dart | 9 +- .../AddProductIngredientVC.dart | 4 +- .../ingredientsViews/IngredientsVC.dart | 2 +- .../viewModels/IngredientViewModel.dart | 3 +- .../InventoryAddMeasurementVC.dart | 4 +- .../InventoryMeasurementVC.dart | 2 +- .../ViewInventoryMeasurementVC.dart | 2 +- .../viewModels/AddMeasurementViewModel.dart | 4 +- .../viewModels/MeasurementViewModel.dart | 2 +- .../viewModels/ModifierOptionsViewModel.dart | 106 + .../NewModifierOptionViewModel.dart | 186 + .../modiferOption/views/ModiferOptionVC.dart | 190 ++ .../views/NewModifierOptionVC.dart | 436 +++ .../widgets/ModifierOptionsListView.dart | 261 ++ .../modifierviews/InventoryModifierVC.dart | 2 +- .../modifierviews/InventoryNewModifierVC.dart | 306 +- .../ViewInventoryModifiersVC.dart | 34 +- .../viewModels/ModiferViewModel.dart | 1 + .../viewModels/NewModifierVM.dart | 44 +- .../widgets/ModifierListView.dart | 2 +- .../AddNewInventoryProductVC.dart | 3032 ++++++++--------- .../viewModels/AddIngredientViewModel.dart | 5 +- .../viewModels/AddProductViewModel.dart | 9 +- .../viewModel/KitchenViewModel.dart | 2 +- .../views/invoiceModule/NewInvoiceVC.dart | 2 +- .../viewModels/NewInvoiceViewModel.dart | 2 +- .../quotataionModule/NewQuotationsVC.dart | 2 +- lib/objectbox.g.dart | 5 +- lib/widgets/ChildContainer.dart | 4 +- 55 files changed, 3020 insertions(+), 2235 deletions(-) rename lib/application/model/{inventory => Combo}/SearchComboItemModel.dart (95%) rename lib/application/model/{inventory => Measurement}/GetMeasurementCategory.dart (100%) rename lib/application/model/{inventory => Measurement}/InventoryMeasurementModel.dart (100%) rename lib/application/model/{inventory => Measurement}/MeasurementUnitModel.dart (100%) create mode 100644 lib/application/model/Measurement/MeasuringUnit.dart create mode 100644 lib/application/model/Modifiers/Modifier.dart create mode 100644 lib/application/model/Modifiers/ModifierOption.dart create mode 100644 lib/application/model/ingredients/Add.dart rename lib/application/model/{inventory/AddIngredientModel.dart => ingredients/AddIngredient.dart} (80%) create mode 100644 lib/application/model/ingredients/AddIngredientModel.dart create mode 100644 lib/application/model/ingredients/AddProdcutModel.dart create mode 100644 lib/application/model/ingredients/AddProductItem.dart create mode 100644 lib/application/model/ingredients/GetIngredientModel.dart create mode 100644 lib/application/model/modifierOptions/ModifierId.dart create mode 100644 lib/application/model/modifierOptions/ModifierOption.dart create mode 100644 lib/application/model/modifierOptions/ModifierOptionsResponse.dart create mode 100644 lib/application/views/inventorymodule/modiferOption/viewModels/ModifierOptionsViewModel.dart create mode 100644 lib/application/views/inventorymodule/modiferOption/viewModels/NewModifierOptionViewModel.dart create mode 100644 lib/application/views/inventorymodule/modiferOption/views/ModiferOptionVC.dart create mode 100644 lib/application/views/inventorymodule/modiferOption/views/NewModifierOptionVC.dart create mode 100644 lib/application/views/inventorymodule/modiferOption/widgets/ModifierOptionsListView.dart diff --git a/lib/application/MyApp.dart b/lib/application/MyApp.dart index c6a0194..4729f5d 100644 --- a/lib/application/MyApp.dart +++ b/lib/application/MyApp.dart @@ -37,6 +37,7 @@ 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'; @@ -49,6 +50,8 @@ class MyApp extends StatelessWidget { Widget build(BuildContext context) { return MultiProvider( providers: [ + ChangeNotifierProvider( + create: (context) => NewModifierOptionViewModel()), ChangeNotifierProvider( create: (context) => InvoiceViewModel()), ChangeNotifierProvider( 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 9eed3d5..c4e948f 100644 --- a/lib/application/model/CreateAndUpdateOrder.dart +++ b/lib/application/model/CreateAndUpdateOrder.dart @@ -1,12 +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() 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/inventory/InventoryMeasurementModel.dart b/lib/application/model/Measurement/InventoryMeasurementModel.dart similarity index 100% rename from lib/application/model/inventory/InventoryMeasurementModel.dart rename to lib/application/model/Measurement/InventoryMeasurementModel.dart 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..43b923f --- /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 = "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'] ?? '', + 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..f0b6aca --- /dev/null +++ b/lib/application/model/Modifiers/ModifierOption.dart @@ -0,0 +1,45 @@ +import 'package:objectbox/objectbox.dart'; +import 'package:wosull/helpers/Utils.dart'; + +@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/StockTransfer/ProductItemCategoryModel.dart b/lib/application/model/StockTransfer/ProductItemCategoryModel.dart index 33adcb1..7a65ece 100644 --- a/lib/application/model/StockTransfer/ProductItemCategoryModel.dart +++ b/lib/application/model/StockTransfer/ProductItemCategoryModel.dart @@ -1,8 +1,8 @@ +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; 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/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 80% rename from lib/application/model/inventory/AddIngredientModel.dart rename to lib/application/model/ingredients/AddIngredient.dart index bedf83e..d0fe7b9 100644 --- a/lib/application/model/inventory/AddIngredientModel.dart +++ b/lib/application/model/ingredients/AddIngredient.dart @@ -1,92 +1,5 @@ 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'; @Entity() class AddIngredient { @@ -141,7 +54,7 @@ class AddIngredient { String expiryDate; String createdAt; String updatedAt; - + String quantity; String measuringUnit; bool checked; @@ -151,6 +64,7 @@ class AddIngredient { {this.name = '', this.description = '', this.value = '', + this.quantity = '', this.purchasePrice, this.salePrice, this.defaultSalePrice, @@ -211,6 +125,7 @@ class AddIngredient { 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'] ?? '', 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..0e8fa25 --- /dev/null +++ b/lib/application/model/ingredients/GetIngredientModel.dart @@ -0,0 +1,16 @@ +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: List.from(json['ingrediant']) + .map((i) => AddIngredient.fromJson(i)) + .toList()); + } +} 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..05ba7e4 --- /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 = false, + 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/store/StoreItemsResponse.dart b/lib/application/model/store/StoreItemsResponse.dart index 9c27735..f29331d 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; diff --git a/lib/application/utils/Constants.dart b/lib/application/utils/Constants.dart index c7aa586..9ff2e2b 100644 --- a/lib/application/utils/Constants.dart +++ b/lib/application/utils/Constants.dart @@ -63,6 +63,8 @@ class Constants { static const UPDATE_MEASUREMENT_STATUS = 'api/store/update_measurement_status'; + static const getMeasuringUnit = 'api/store/get_measuring_unit'; + //stock transfer static const GET_STOCK_TRANSFER = 'api/store/get_stock_transfer'; @@ -88,6 +90,12 @@ 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 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'; diff --git a/lib/application/views/create_order_module/viewModels/CartViewModel.dart b/lib/application/views/create_order_module/viewModels/CartViewModel.dart index 41fcb7a..02986f6 100644 --- a/lib/application/views/create_order_module/viewModels/CartViewModel.dart +++ b/lib/application/views/create_order_module/viewModels/CartViewModel.dart @@ -8,7 +8,7 @@ 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'; diff --git a/lib/application/views/create_order_module/viewModels/CreateOrderViewModel.dart b/lib/application/views/create_order_module/viewModels/CreateOrderViewModel.dart index 932b08d..83b7ae6 100644 --- a/lib/application/views/create_order_module/viewModels/CreateOrderViewModel.dart +++ b/lib/application/views/create_order_module/viewModels/CreateOrderViewModel.dart @@ -7,15 +7,15 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; 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/Combo/SearchComboItemModel.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/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'; 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 b3dc9eb..205b9bf 100644 --- a/lib/application/views/create_order_module/views/popups/ItemModifiersPopUp.dart +++ b/lib/application/views/create_order_module/views/popups/ItemModifiersPopUp.dart @@ -3,7 +3,8 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:objectbox/objectbox.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/Modifiers/Modifier.dart'; +import 'package:wosull/application/model/Modifiers/ModifierOption.dart'; import 'package:wosull/application/model/store/StoreItemsResponse.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/theme/MyFonts.dart'; diff --git a/lib/application/views/inventorymodule/InventoryModuleMainVC.dart b/lib/application/views/inventorymodule/InventoryModuleMainVC.dart index 70777d6..2262349 100644 --- a/lib/application/views/inventorymodule/InventoryModuleMainVC.dart +++ b/lib/application/views/inventorymodule/InventoryModuleMainVC.dart @@ -6,6 +6,7 @@ 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/stockTransferViews/InventoryStockTransferVC.dart'; @@ -28,7 +29,7 @@ class _InventoryModuleMainVCState extends State { @override Widget build(BuildContext context) { return DefaultTabController( - length: 9, + length: 10, child: Scaffold( body: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -117,13 +118,16 @@ class _InventoryModuleMainVCState extends State { Tab( text: AppLocalizations.of(context)!.measurements, ), + const Tab( + text: 'Modifier Options', + ), Tab( text: AppLocalizations.of(context)!.modifiers, ), Tab( text: AppLocalizations.of(context)!.product, ), - Tab( + const Tab( text: 'Ingredient', ), Tab( @@ -147,6 +151,7 @@ class _InventoryModuleMainVCState extends State { InventoryCategoriesModule(), SubCategoryVC(), InventoryMeasurementVC(), + ModifierOptionVC(), InventoryModifierVC(), InventoryProductVC(), IngredientsVC(), diff --git a/lib/application/views/inventorymodule/ingredientsViews/AddProductIngredientVC.dart b/lib/application/views/inventorymodule/ingredientsViews/AddProductIngredientVC.dart index 95ae3e4..bcd393b 100644 --- a/lib/application/views/inventorymodule/ingredientsViews/AddProductIngredientVC.dart +++ b/lib/application/views/inventorymodule/ingredientsViews/AddProductIngredientVC.dart @@ -2,10 +2,10 @@ 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/GetMeasurementCategory.dart'; import 'package:wosull/application/model/brands/GetBrandsModel.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'; diff --git a/lib/application/views/inventorymodule/ingredientsViews/IngredientsVC.dart b/lib/application/views/inventorymodule/ingredientsViews/IngredientsVC.dart index e82c688..e5b4638 100644 --- a/lib/application/views/inventorymodule/ingredientsViews/IngredientsVC.dart +++ b/lib/application/views/inventorymodule/ingredientsViews/IngredientsVC.dart @@ -4,7 +4,7 @@ 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'; diff --git a/lib/application/views/inventorymodule/ingredientsViews/viewModels/IngredientViewModel.dart b/lib/application/views/inventorymodule/ingredientsViews/viewModels/IngredientViewModel.dart index aa55c6e..d687f6a 100644 --- a/lib/application/views/inventorymodule/ingredientsViews/viewModels/IngredientViewModel.dart +++ b/lib/application/views/inventorymodule/ingredientsViews/viewModels/IngredientViewModel.dart @@ -1,7 +1,8 @@ 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/model/ingredients/AddIngredient.dart'; +import 'package:wosull/application/model/ingredients/GetIngredientModel.dart'; import 'package:wosull/application/network/APIManager.dart'; import 'package:wosull/application/utils/CRUDOperatoinState.dart'; import 'package:wosull/application/utils/Constants.dart'; diff --git a/lib/application/views/inventorymodule/measurementviews/InventoryAddMeasurementVC.dart b/lib/application/views/inventorymodule/measurementviews/InventoryAddMeasurementVC.dart index 72b26de..f71e291 100644 --- a/lib/application/views/inventorymodule/measurementviews/InventoryAddMeasurementVC.dart +++ b/lib/application/views/inventorymodule/measurementviews/InventoryAddMeasurementVC.dart @@ -2,8 +2,8 @@ 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'; diff --git a/lib/application/views/inventorymodule/measurementviews/InventoryMeasurementVC.dart b/lib/application/views/inventorymodule/measurementviews/InventoryMeasurementVC.dart index 2379cd0..fe30410 100644 --- a/lib/application/views/inventorymodule/measurementviews/InventoryMeasurementVC.dart +++ b/lib/application/views/inventorymodule/measurementviews/InventoryMeasurementVC.dart @@ -3,8 +3,8 @@ 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/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/utils/AppError.dart'; import 'package:wosull/application/utils/AppLoader.dart'; diff --git a/lib/application/views/inventorymodule/measurementviews/ViewInventoryMeasurementVC.dart b/lib/application/views/inventorymodule/measurementviews/ViewInventoryMeasurementVC.dart index 356718a..789d79e 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'; diff --git a/lib/application/views/inventorymodule/measurementviews/viewModels/AddMeasurementViewModel.dart b/lib/application/views/inventorymodule/measurementviews/viewModels/AddMeasurementViewModel.dart index 0088f8a..9370c0b 100644 --- a/lib/application/views/inventorymodule/measurementviews/viewModels/AddMeasurementViewModel.dart +++ b/lib/application/views/inventorymodule/measurementviews/viewModels/AddMeasurementViewModel.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/application/model/Measurement/InventoryMeasurementModel.dart'; +import 'package:wosull/application/model/Measurement/MeasurementUnitModel.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/utils/CRUDOperatoinState.dart'; import 'package:wosull/application/utils/Constants.dart'; diff --git a/lib/application/views/inventorymodule/measurementviews/viewModels/MeasurementViewModel.dart b/lib/application/views/inventorymodule/measurementviews/viewModels/MeasurementViewModel.dart index 5b1e523..54fc06d 100644 --- a/lib/application/views/inventorymodule/measurementviews/viewModels/MeasurementViewModel.dart +++ b/lib/application/views/inventorymodule/measurementviews/viewModels/MeasurementViewModel.dart @@ -1,7 +1,7 @@ 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'; 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..a070ee6 --- /dev/null +++ b/lib/application/views/inventorymodule/modiferOption/viewModels/ModifierOptionsViewModel.dart @@ -0,0 +1,106 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/enum/DataState.dart'; +import 'package:wosull/application/localdb/SharedPrefs.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 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; + + 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 APIManager() + .getResponseAuth( + Constants.getModifierOptions + sharedPrefs.storeId, data) + .then((result) { + final value = ModifierOptionsResponse.fromJson(result); + if (_dataState == DataState.refreshing) { + _filteredList.clear(); + } + if (value.status!) { + _filteredList.addAll(value.modifierOptions!); + if (value.modifierOptions!.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 { + Map data = {'modifier_option_id': id}; + await APIManager() + .getResponsePatch(Constants.deleteModifierOption, data) + .then((result) { + filteredList.removeWhere((element) => element.id! == id); + notifyListeners(); + }).onError((error, stackTrace) { + notifyListeners(); + }); + } + + Future update(String id, bool value) async { + Map data = {'modifier_option_id': id, 'status': value}; + await APIManager() + .getResponsePatch(Constants.updateModifierOption, data) + .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..cef376f --- /dev/null +++ b/lib/application/views/inventorymodule/modiferOption/viewModels/NewModifierOptionViewModel.dart @@ -0,0 +1,186 @@ +import 'package:flutter/material.dart'; +import 'package:objectbox/objectbox.dart'; +import 'package:wosull/application/localdb/SharedPrefs.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/ingredients/AddIngredient.dart'; +import 'package:wosull/application/model/ingredients/GetIngredientModel.dart'; +import 'package:wosull/application/model/modifierOptions/ModifierId.dart'; +import 'package:wosull/application/model/modifierOptions/ModifierOption.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 NewModifierOptionViewModel with ChangeNotifier { + bool _isLoading = false; + + bool get isLoading => _isLoading; + var modifierOption = ModifierOption(); + var selectedMeasurementUnits = []; + bool isEdit = false; + dynamic selectedModifier; + + var _crudOperation = CRUDOperationState.uninitialized; + + CRUDOperationState get crudOperation => _crudOperation; + + void setState(CRUDOperationState state) { + _crudOperation = state; + } + + void init(bool isEdit, ModifierOption modifierOption) { + 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 = []; + } + } + + 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 APIManager() + .fetchData(Constants.addModifierOptions, modifierOption.toJson()) + .then((value) { + final response = SimpleResponseModel.fromJson(value); + Utils.showMessage(response.message); + if (response.success) { + setState(CRUDOperationState.add); + } else { + setState(CRUDOperationState.error); + } + setLoading(false); + }).onError((error, stackTrace) { + setState(CRUDOperationState.error); + print(stackTrace.toString()); + setLoading(false); + }); + } + + void setLoading(bool value) { + _isLoading = value; + notifyListeners(); + } + + void setStatus(bool value) { + modifierOption.status = value; + notifyListeners(); + } + + 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> 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; + } + + 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..1c8a503 --- /dev/null +++ b/lib/application/views/inventorymodule/modiferOption/views/ModiferOptionVC.dart @@ -0,0 +1,190 @@ +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: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + const Text( + 'Modifier Options', + style: ThemeText.textStylePageHeading, + ), + AppSpaces.horizontalSmall, + newModifier(), + Flexible(child: 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 SizedBox( + width: 170, + child: 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..8a797e3 --- /dev/null +++ b/lib/application/views/inventorymodule/modiferOption/views/NewModifierOptionVC.dart @@ -0,0 +1,436 @@ +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/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'; + +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 + 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), + ), + 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(16), + 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 FutureBuilder( + future: viewModel.getModifiers(), + builder: (c, s) { + if (s.hasData) { + var itemsList = s.data ?? []; + return DropdownSearch( + enabled: !widget.isView, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: const PopupProps.menu( + fit: FlexFit.loose, + constraints: BoxConstraints(maxHeight: 300), + ), + clearButtonProps: ThemeDropDown.clearButton, + selectedItem: viewModel.selectedModifier, + items: itemsList, + itemAsString: (Modifier u) => u.name, + onChanged: (options) { + viewModel.onSelectModifier(options); + }, + dropdownDecoratorProps: + MyColors.dropDownStyle(hint: 'Choose Modifier'), + ); + } else { + return AppLoader(); + } + }); + } + + 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: const PopupProps.menu( + fit: FlexFit.loose, + constraints: 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 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: 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: getMeasurementUnit(position), + )) + ], + ), + ], + )), + getRemoveButton(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: 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: const PopupProps.menu( + fit: FlexFit.loose, + constraints: BoxConstraints(maxHeight: 300), + ), + clearButtonProps: ThemeDropDown.clearButton, + items: itemsList, + itemAsString: (MeasurementUnit u) => u.name, + onChanged: (MeasurementUnit? data) { + viewModel.setMeasurementUnit(position, data); + }, + dropdownDecoratorProps: + MyColors.dropDownStyle(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..77e07d1 --- /dev/null +++ b/lib/application/views/inventorymodule/modiferOption/widgets/ModifierOptionsListView.dart @@ -0,0 +1,261 @@ +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/CustomSwitch.dart'; +import 'package:wosull/widgets/EmptyDataWidget.dart'; +import 'package:wosull/widgets/HeadingText.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() + : Container( + padding: const EdgeInsets.only(left: 8, right: 8), + height: 48, + color: MyColors.containerBackColor, + 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!)), + ], + )), + ], + ), + )), + 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), + ) + ], + ), + ), + ); + } 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(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: 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), + ), + ), + ), + )) + ], + ), + ), + ); + } + }, + itemCount: data.length, + ) + ], + ); + } + + Future actionPopUpItemSelected( + String value, ModifierOption item) async { + if (value == 'edit') { + onEdit(item); + } else if (value == 'delete') { + onDelete(item); + } else { + onView(item); + } + } +} diff --git a/lib/application/views/inventorymodule/modifierviews/InventoryModifierVC.dart b/lib/application/views/inventorymodule/modifierviews/InventoryModifierVC.dart index 2fecb0b..b7b2f27 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'; diff --git a/lib/application/views/inventorymodule/modifierviews/InventoryNewModifierVC.dart b/lib/application/views/inventorymodule/modifierviews/InventoryNewModifierVC.dart index 5bf2efb..4c3c519 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'; @@ -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..abb7a8c 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'; @@ -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), diff --git a/lib/application/views/inventorymodule/modifierviews/viewModels/ModiferViewModel.dart b/lib/application/views/inventorymodule/modifierviews/viewModels/ModiferViewModel.dart index fa5947a..eb9b73d 100644 --- a/lib/application/views/inventorymodule/modifierviews/viewModels/ModiferViewModel.dart +++ b/lib/application/views/inventorymodule/modifierviews/viewModels/ModiferViewModel.dart @@ -2,6 +2,7 @@ import 'package:flutter/cupertino.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/model/Modifiers/Modifier.dart'; import 'package:wosull/application/network/APIManager.dart'; import 'package:wosull/application/utils/Constants.dart'; diff --git a/lib/application/views/inventorymodule/modifierviews/viewModels/NewModifierVM.dart b/lib/application/views/inventorymodule/modifierviews/viewModels/NewModifierVM.dart index db7ca4e..29a8b20 100644 --- a/lib/application/views/inventorymodule/modifierviews/viewModels/NewModifierVM.dart +++ b/lib/application/views/inventorymodule/modifierviews/viewModels/NewModifierVM.dart @@ -2,7 +2,8 @@ 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/Modifiers/Modifier.dart'; +import 'package:wosull/application/model/Modifiers/ModifierOption.dart'; import 'package:wosull/application/model/SimpleResponsModel.dart'; import 'package:wosull/application/network/APIManager.dart'; import 'package:wosull/application/utils/CRUDOperatoinState.dart'; @@ -14,10 +15,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: [])); @@ -37,24 +34,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,25 +48,8 @@ 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(); } } diff --git a/lib/application/views/inventorymodule/modifierviews/widgets/ModifierListView.dart b/lib/application/views/inventorymodule/modifierviews/widgets/ModifierListView.dart index 29ae03d..bca59b5 100644 --- a/lib/application/views/inventorymodule/modifierviews/widgets/ModifierListView.dart +++ b/lib/application/views/inventorymodule/modifierviews/widgets/ModifierListView.dart @@ -1,5 +1,5 @@ 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'; diff --git a/lib/application/views/inventorymodule/productviews/AddNewInventoryProductVC.dart b/lib/application/views/inventorymodule/productviews/AddNewInventoryProductVC.dart index 0b81cbf..49d4412 100644 --- a/lib/application/views/inventorymodule/productviews/AddNewInventoryProductVC.dart +++ b/lib/application/views/inventorymodule/productviews/AddNewInventoryProductVC.dart @@ -3,10 +3,10 @@ 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/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/Measurement/MeasurementUnitModel.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'; @@ -86,8 +86,7 @@ class _AddNewInventoryProductVCState extends State elevation: 5, ), body: OrientationBuilder(builder: (c, orientation) { - isPortrait = - MediaQuery.of(context).orientation == Orientation.portrait; + isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; return SingleChildScrollView( child: Container( @@ -104,472 +103,436 @@ class _AddNewInventoryProductVCState extends State padding: const EdgeInsets.all(15), child: isPortrait ? 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, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + MandatoryTitleText( + hint: AppLocalizations.of(context)!.item_name, ), - ), - 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(); - } + const SizedBox( + height: 4, + ), + CustomTextFieldForm( + initialValue: viewModel.nameController, + readOnly: widget.isView, + hintText: 'Enter Item name', + onChanged: (String value) { + viewModel.nameController = value; }, - 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( + height: 8, ), + MandatoryTitleText( + hint: AppLocalizations.of(context)!.category, + ), + const SizedBox( + height: 8, + ), + getCategoryWidget(context), const SizedBox( - width: 6, + height: 8, ), - CustomSwitch( - value: viewModel - .storeItem.isItemInStock, - onToggle: (value) { - viewModel - .setItemInStockStatus(value); + 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); }, - ) - ], - ), - ) - ], - ) - : Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - Expanded( - flex: 1, - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ + ), + const SizedBox( + height: 8, + ), MandatoryTitleText( - hint: - AppLocalizations.of(context)! - .item_name), + 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( - initialValue: - viewModel.nameController, + readOnly: widget.isView, onChanged: (value) { - viewModel.nameController = value; + viewModel.productCode = value; }, - readOnly: widget.isView, - hintText: 'Enter Item name', + hintText: 'Enter Item Name in Arabic', ), const SizedBox( height: 8, ), - MandatoryTitleText( - hint: - AppLocalizations.of(context)! - .category), + const MandatoryTitleText( + hint: 'Default Price (Incl. Tax)'), const SizedBox( height: 4, ), - getCategoryWidget(context), + CustomTextFieldForm( + hintText: 'Enter Price (Incl. Tax)', + readOnly: widget.isView, + keyboardType: TextInputType.number, + onChanged: (value) { + viewModel.setPrice(value); + }), const SizedBox( height: 8, ), - MandatoryTitleText( - hint: - AppLocalizations.of(context)! - .description), + CustomOptionalTitle( + hint: AppLocalizations.of(context)! + .description_ar), const SizedBox( height: 4, ), SizedBox( height: 100, child: CustomTextFieldForm( - initialValue: viewModel - .descriptionController, - hintText: 'Description', + hintText: 'Enter Description in Arabic', + readOnly: widget.isView, onChanged: (value) { - viewModel - .descriptionController = - value; + viewModel.descriptionArabic = value; }, - readOnly: widget.isView, maxLines: 5, - keyboardType: - TextInputType.multiline, + keyboardType: TextInputType.multiline, ), ), - ], - ), - ), - const SizedBox( - width: 12, - ), - 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', + 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.descriptionArabic = - value; + viewModel.barCodeController = value; }, - maxLines: 5, - keyboardType: - TextInputType.multiline, + )), + 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( - width: 12, - ), - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - MandatoryTitleText( - hint: AppLocalizations.of(context)! - .barcode), - const SizedBox( - height: 4, - ), - Row( + ], + ), + const SizedBox( + height: 8, + ), + MandatoryTitleText( + hint: AppLocalizations.of(context)!.status), + const SizedBox( + height: 4, + ), + SizedBox( + height: 44, + child: 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 CustomOptionalTitle( + hint: 'Item In Stock', + ), + const SizedBox( + width: 6, ), + CustomSwitch( + value: viewModel.storeItem.isItemInStock, + onToggle: (value) { + viewModel.setItemInStockStatus(value); + }, + ) ], ), - const SizedBox( - height: 8, - ), - Row( + ) + ], + ) + : Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Expanded( + flex: 1, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Expanded( - child: MandatoryTitleText( - hint: AppLocalizations.of( - context)! - .quantity, + 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, ), ), - 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( + ), + const SizedBox( + width: 12, + ), + 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, + ), + ), + ], + )), + const SizedBox( + width: 12, + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + MandatoryTitleText( + hint: AppLocalizations.of(context)! + .barcode), + const SizedBox( + height: 4, + ), + Row( children: [ - const CustomOptionalTitle( - hint: 'Item In Stock', + 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( - width: 6, + ], + ), + const SizedBox( + height: 8, + ), + Row( + children: [ + Expanded( + child: MandatoryTitleText( + hint: AppLocalizations.of(context)! + .quantity, + ), ), - CustomSwitch( - value: viewModel - .storeItem.isItemInStock, - onToggle: (value) { - viewModel - .setItemInStockStatus( - value); - }, - ) + 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); + }, + ) + ], + ), + ) + ], + )), + ], + ), ), ), const SizedBox( @@ -598,71 +561,63 @@ class _AddNewInventoryProductVCState extends State 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)', - ), - ], - )), + 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; - }, - ), - ], - )), + 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; + }, + ), + ], + )), 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; - }, - ), - ], - )), + 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; + }, + ), + ], + )), ], ), const SizedBox( @@ -673,31 +628,27 @@ class _AddNewInventoryProductVCState extends State children: [ Expanded( child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - CustomOptionalTitle( - hint: AppLocalizations.of(context)! - .discount, - ), - AppSpaces.verticalSmall, - getDiscounts(context), - ], - )), + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.discount, + ), + AppSpaces.verticalSmall, + getDiscounts(context), + ], + )), AppSpaces.horizontalMedium, Expanded( child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - CustomOptionalTitle( - hint: AppLocalizations.of(context)! - .supplier, - ), - AppSpaces.verticalSmall, - getSupplierWidget(context), - ], - )), + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.supplier, + ), + AppSpaces.verticalSmall, + getSupplierWidget(context), + ], + )), ], ), const SizedBox( @@ -708,145 +659,129 @@ class _AddNewInventoryProductVCState extends State children: [ Expanded( child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - CustomOptionalTitle( - hint: AppLocalizations.of(context)! - .manufacturer_date, + 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, ), - 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: + color: MyColors.backFillColor, + borderRadius: BorderRadius.circular(8.0), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: + 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, - ) - ], - ), - ), - ], - )), + 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, + ) + ], + ), + ), + ], + )), AppSpaces.horizontalMedium, Expanded( child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - CustomOptionalTitle( - hint: AppLocalizations.of(context)! - .expiry_date, + 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, ), - 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: + color: MyColors.backFillColor, + borderRadius: BorderRadius.circular(8.0), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: + 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, - ) - ], - ), - ), - ], - )), + 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, + ) + ], + ), + ), + ], + )), ], ), ], @@ -867,8 +802,7 @@ class _AddNewInventoryProductVCState extends State crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - AppLocalizations.of(context)! - .delivery_partner_price, + AppLocalizations.of(context)!.delivery_partner_price, style: ThemeText.textStyleHeadingCart, ), const SizedBox( @@ -877,201 +811,179 @@ class _AddNewInventoryProductVCState extends State 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: [ - 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( - AppLocalizations.of(context)! - .name), + decoration: BoxDecoration( + borderRadius: const BorderRadius.all( + Radius.circular( + 1.0) // <--- border radius here + ), + border: Border.all( + width: 1, color: MyColors.fillColorGray2), + color: MyColors.containerBackColor, ), - ), - 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), + height: 48, + 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( - 'Delivery Partner Price(Exclusive of vat & Including vat)', + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + AppLocalizations.of(context)!.name), ), ), - )), - 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: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + 'Delivery Partner Price(Exclusive of vat & Including vat)', + ), + ), + )), + Container( + width: 44, + height: 48, + decoration: const BoxDecoration( + border: Border( + right: BorderSide( + width: 1.0, + color: MyColors.fillColorGray2), + ), + ), + child: Container(), + ) + ], ), - child: Container(), - ) - ], - ), - ), + ), 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, - child: Row( - children: [ - Expanded( - child: Container( - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), + margin: const EdgeInsets.fromLTRB(8, 0, 0, 8), + decoration: BoxDecoration( + borderRadius: const BorderRadius.all( + Radius.circular( + 1.0) // <--- border radius here ), - ), - child: Center( - child: Text( - '', - style: - MyColors.textStyleValue(), + 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), + ), ), - ), - )), - 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, + child: Center( + child: Text( + '', + style: MyColors.textStyleValue(), + ), ), - onPressed: () { - viewModel - .addNewDeliveryPartner(); - }), + )), + 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(); + }), + ), + ), + ], ), - ), - ], - ), - ) + ) : 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), + margin: const EdgeInsets.fromLTRB(0, 0, 0, 8), + decoration: BoxDecoration( + borderRadius: const BorderRadius.all( + Radius.circular( + 1.0) // <--- border radius here ), - ), - child: Center( - child: Text( - '', - style: - MyColors.textStyleValue(), + 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), + ), ), - ), - )), - 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, + child: Center( + child: Text( + '', + style: MyColors.textStyleValue(), + ), ), - onPressed: () { - viewModel - .addNewDeliveryPartner(); - }), + )), + 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(); + }), + ), + ), + ], ), ), - ], - ), - ), ], ), ), @@ -1093,642 +1005,594 @@ class _AddNewInventoryProductVCState extends State children: [ Expanded( 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: ThemeText.textStyleHeadingCart, - ), - const SizedBox( - height: 12, - ), - CustomOptionalTitle( - hint: AppLocalizations.of(context)! - .search, - ), - const SizedBox( - height: 4, - ), - getIngredientsWidget(context), - const SizedBox( - height: 4, - ), - CustomOptionalTitle( - hint: AppLocalizations.of(context)! - .choose_ingredients), - const SizedBox( - height: 12, - ), - ], + padding: const EdgeInsets.all(8), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)! + .search_and_add_products, + style: ThemeText.textStyleHeadingCart, + ), + const SizedBox( + height: 12, + ), + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.search, + ), + const SizedBox( + height: 4, + ), + getIngredientsWidget(context), + const SizedBox( + height: 4, + ), + CustomOptionalTitle( + hint: AppLocalizations.of(context)! + .choose_ingredients), + const SizedBox( + height: 12, ), - )), + ], + ), + )), 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, + 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, + ), + ], + ), + )), + ], + ), + 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 - .textStylePopUpHeading, - textAlign: TextAlign.center, - ) - ]), - const SizedBox( - height: 4, ), Text( AppLocalizations.of(context)! - .option_enable_product_invoice, - style: - ThemeText.textStyleHeading, - ), - ], - ), - )), - ], - ), - 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, + .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, + ), + ], ), - 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, - ), - ], - ), - ) + ) : Container(), Visibility( - visible: viewModel - .storeItem.ingredients!.isNotEmpty, + visible: viewModel.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, - 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), + decoration: BoxDecoration( + borderRadius: const BorderRadius.all( + Radius.circular( + 1.0) // <--- border radius here ), - ), - child: Align( - alignment: - Alignment.centerLeft, - child: HeadingText( - AppLocalizations.of( - context)! - .name_description, + border: Border.all( + width: 1, + color: MyColors.fillColorGray2), + color: MyColors.backFillColor, + ), + 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), + ), ), - ), - )), - 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, + ), ), - ), - 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), + )), + 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.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'), ), - ), - child: Align( - alignment: - Alignment.centerLeft, - child: HeadingText( - '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), + )), + 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'), - ), - )), - Container( - width: 48, - height: 48, - decoration: - const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: HeadingText( - '', - ), + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + '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( + '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'), + ), + )), + Container( + width: 48, + height: 48, + decoration: const BoxDecoration( + border: Border( + right: BorderSide( + width: 1.0, + color: MyColors + .fillColorGray2), + ), + ), + child: Center( + child: HeadingText( + '', + ), + ), + ) + ], ), - ) - ], - ), - ), + ), ListView.builder( padding: EdgeInsets.zero, scrollDirection: Axis.vertical, - physics: - const NeverScrollableScrollPhysics(), + physics: const NeverScrollableScrollPhysics(), shrinkWrap: true, itemBuilder: (c, position) { if (isPortrait) { return Container( decoration: BoxDecoration( - borderRadius: const BorderRadius - .all( + borderRadius: const BorderRadius.all( Radius.circular( 1.0) // <--- border radius here - ), + ), border: Border.all( width: 1, - color: MyColors - .fillColorGray2), + color: MyColors.fillColorGray2), color: MyColors.white, ), child: Row( mainAxisAlignment: - MainAxisAlignment.start, + MainAxisAlignment.start, crossAxisAlignment: - CrossAxisAlignment.start, + CrossAxisAlignment.start, children: [ Expanded( child: Column( + children: [ + Row( 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: + 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: + decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: - 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: Alignment - .centerLeft, - child: ValueText(viewModel + border: Border( + right: BorderSide( + width: 1.0, + color: MyColors + .fillColorGray2), + ), + ), + child: Align( + alignment: Alignment + .centerLeft, + child: ValueText( + viewModel .storeItem - .ingredients![ - position] + .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: + ), + ), + ) + ], + ), + 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: + 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(), - ), - ), + 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: + ), + ), + ) + ], + ), + 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: + decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: - 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Align( - alignment: Alignment - .centerLeft, - child: ValueText(viewModel + border: Border( + right: BorderSide( + width: 1.0, + color: MyColors + .fillColorGray2), + ), + ), + child: Align( + alignment: Alignment + .centerLeft, + child: ValueText( + viewModel .storeItem - .ingredients![ - position] + .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: + ), + ), + ) + ], + ), + 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: + width: 100, + height: 48, + decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: - 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: + 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 + readOnly: + widget.isView, + onChanged: (value) { + viewModel.unitsController[ + position] = + value; + if (value + .isNotEmpty) { + viewModel .storeItem - .ingredients![ - position] - .defaultSalePrice = int.parse(value); - } - }, - hintText: - '0.0', - ), - ), + .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), - )) - ], - ), + ), + ), + ) ], - )), + ), + 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, @@ -1738,10 +1602,10 @@ class _AddNewInventoryProductVCState extends State height: 32, decoration: BoxDecoration( borderRadius: - const BorderRadius - .all( - Radius.circular( - 4)), + const BorderRadius + .all( + Radius.circular( + 4)), color: MyColors .backFillColor), child: IconButton( @@ -1752,8 +1616,7 @@ class _AddNewInventoryProductVCState extends State .textColorBlack, ), onPressed: () { - viewModel - .removeUnit( + viewModel.removeUnit( position); }), ), @@ -1764,15 +1627,13 @@ class _AddNewInventoryProductVCState extends State } else { return Container( decoration: BoxDecoration( - borderRadius: const BorderRadius - .all( + borderRadius: const BorderRadius.all( Radius.circular( 1.0) // <--- border radius here - ), + ), border: Border.all( width: 1, - color: MyColors - .fillColorGray2), + color: MyColors.fillColorGray2), color: MyColors.white, ), child: Row( @@ -1780,10 +1641,8 @@ class _AddNewInventoryProductVCState extends State Expanded( child: Container( padding: - const EdgeInsets.all( - 4), - decoration: - const BoxDecoration( + const EdgeInsets.all(4), + decoration: const BoxDecoration( border: Border( right: BorderSide( width: 1.0, @@ -1792,18 +1651,17 @@ class _AddNewInventoryProductVCState extends State ), ), child: Align( - alignment: Alignment - .centerLeft, + alignment: + Alignment.centerLeft, child: Text( viewModel .storeItem - .ingredients![ - position] + .ingredients[position] .name, style: const TextStyle( fontSize: 11, - fontFamily: MyFonts - .DMREGULAR, + fontFamily: + MyFonts.DMREGULAR, color: MyColors .textColorBlack), ), @@ -1813,10 +1671,8 @@ class _AddNewInventoryProductVCState extends State Expanded( child: Container( padding: - const EdgeInsets.all( - 4), - decoration: - const BoxDecoration( + const EdgeInsets.all(4), + decoration: const BoxDecoration( border: Border( right: BorderSide( width: 1.0, @@ -1825,19 +1681,18 @@ class _AddNewInventoryProductVCState extends State ), ), child: Align( - alignment: Alignment - .centerLeft, + alignment: + Alignment.centerLeft, child: Text( viewModel .storeItem - .ingredients![ - position] + .ingredients[position] .purchasePrice! .toString(), style: const TextStyle( fontSize: 11, - fontFamily: MyFonts - .DMREGULAR, + fontFamily: + MyFonts.DMREGULAR, color: MyColors .textColorBlack), ), @@ -1847,10 +1702,8 @@ class _AddNewInventoryProductVCState extends State Expanded( child: Container( padding: - const EdgeInsets.all( - 4), - decoration: - const BoxDecoration( + const EdgeInsets.all(4), + decoration: const BoxDecoration( border: Border( right: BorderSide( width: 1.0, @@ -1859,19 +1712,18 @@ class _AddNewInventoryProductVCState extends State ), ), child: Align( - alignment: Alignment - .centerLeft, + alignment: + Alignment.centerLeft, child: Text( viewModel .storeItem - .ingredients![ - position] + .ingredients[position] .salePrice! .toString(), style: const TextStyle( fontSize: 11, - fontFamily: MyFonts - .DMREGULAR, + fontFamily: + MyFonts.DMREGULAR, color: MyColors .textColorBlack), ), @@ -1881,12 +1733,10 @@ class _AddNewInventoryProductVCState extends State Expanded( child: Container( padding: - const EdgeInsets.all( - 4), + const EdgeInsets.all(4), width: 100, height: 48, - decoration: - const BoxDecoration( + decoration: const BoxDecoration( border: Border( right: BorderSide( width: 1.0, @@ -1895,23 +1745,18 @@ class _AddNewInventoryProductVCState extends State ), ), child: Center( - child: - CustomTextFieldForm( - readOnly: - widget.isView, + child: CustomTextFieldForm( + readOnly: widget.isView, onChanged: (value) { viewModel.unitsController[ - position] = - value; - if (value - .isNotEmpty) { + position] = value; + if (value.isNotEmpty) { viewModel - .storeItem - .ingredients![ - position] - .defaultSalePrice = - int.parse( - value); + .storeItem + .ingredients[ + position] + .defaultSalePrice = + int.parse(value); } }, hintText: '0.0', @@ -1921,20 +1766,18 @@ class _AddNewInventoryProductVCState extends State ), 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), - )), + 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, @@ -1944,10 +1787,10 @@ class _AddNewInventoryProductVCState extends State height: 32, decoration: BoxDecoration( borderRadius: - const BorderRadius - .all( - Radius.circular( - 4)), + const BorderRadius + .all( + Radius.circular( + 4)), color: MyColors .backFillColor), child: IconButton( @@ -1962,12 +1805,11 @@ class _AddNewInventoryProductVCState extends State viewModel .unitsController .removeAt( - position); - viewModel - .storeItem - .ingredients! + position); + viewModel.storeItem + .ingredients .removeAt( - position); + position); }); }), ), @@ -1977,8 +1819,8 @@ class _AddNewInventoryProductVCState extends State ); } }, - itemCount: viewModel - .storeItem.ingredients!.length, + itemCount: + viewModel.storeItem.ingredients.length, ), ], )) @@ -1988,152 +1830,142 @@ class _AddNewInventoryProductVCState extends State ), 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, + 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, + ), + ), + ], + ), ), - AlertDialogForPicture( - viewModel.storeItem.imageUrl, - viewModel.imageFile, - this), - const SizedBox( - height: 8, + ), + const SizedBox( + height: 12, + ), + Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(4.0), ), - Center( - child: Text( - AppLocalizations.of(context)! - .image_information_txt, - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normal, - color: MyColors.textColorGray), - textAlign: TextAlign.center, + 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(), + ], ), ), - ], - ), - ), - ), - 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, + 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, + Expanded( + child: Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(4.0), ), - getChooseMeasurement(), - ], + 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(), + ], + ), + ), + ), ), - ), + ], ), - ), - ], - ), const SizedBox( height: 12, ), @@ -2209,7 +2041,7 @@ class _AddNewInventoryProductVCState extends State isVisible: true, ), items: itemsList, - itemAsString: (DeliveryPartner u) => u.name!, + itemAsString: (DeliveryPartner u) => u.name, onChanged: (DeliveryPartner? partner) { viewModel.editDeliveryPartner(position, partner); }, @@ -2249,7 +2081,7 @@ class _AddNewInventoryProductVCState extends State isVisible: true, ), items: itemsList, - itemAsString: (MeasurementUnit u) => u.name!, + itemAsString: (MeasurementUnit u) => u.name, onChanged: (MeasurementUnit? data) { viewModel.setMeasurementUnit(position, data); }, @@ -2496,7 +2328,7 @@ class _AddNewInventoryProductVCState extends State direction: Axis.horizontal, spacing: 4, // space between items children: itemsList[i] - .options! + .options .map((e) => Container( padding: const EdgeInsets.all(3), decoration: BoxDecoration( @@ -2739,7 +2571,7 @@ class _AddNewInventoryProductVCState extends State } }, itemCount: viewModel.storeItem.deliveryPartners != null - ? viewModel.storeItem.deliveryPartners!.length + ? viewModel.storeItem.deliveryPartners.length : 0, ); } @@ -2787,9 +2619,9 @@ class _AddNewInventoryProductVCState extends State borderRadius: BorderRadius.circular(8.0), ), child: CustomTextFieldForm( - key: Key(viewModel.storeItem.deliveryPartners![position].price + key: Key(viewModel.storeItem.deliveryPartners[position].price .toStringAsFixed(2)), - initialValue: viewModel.storeItem.deliveryPartners![position].price + initialValue: viewModel.storeItem.deliveryPartners[position].price .toStringAsFixed(2), hintText: '', onChanged: (String value) { diff --git a/lib/application/views/inventorymodule/productviews/viewModels/AddIngredientViewModel.dart b/lib/application/views/inventorymodule/productviews/viewModels/AddIngredientViewModel.dart index e0f6b3c..bda4992 100644 --- a/lib/application/views/inventorymodule/productviews/viewModels/AddIngredientViewModel.dart +++ b/lib/application/views/inventorymodule/productviews/viewModels/AddIngredientViewModel.dart @@ -1,11 +1,12 @@ import 'package:flutter/material.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/application/model/Measurement/GetMeasurementCategory.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/ingredients/AddIngredient.dart'; +import 'package:wosull/application/model/ingredients/AddIngredientModel.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'; diff --git a/lib/application/views/inventorymodule/productviews/viewModels/AddProductViewModel.dart b/lib/application/views/inventorymodule/productviews/viewModels/AddProductViewModel.dart index 1473b5e..da196ea 100644 --- a/lib/application/views/inventorymodule/productviews/viewModels/AddProductViewModel.dart +++ b/lib/application/views/inventorymodule/productviews/viewModels/AddProductViewModel.dart @@ -10,13 +10,16 @@ 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/Measurement/InventoryMeasurementModel.dart'; +import 'package:wosull/application/model/Measurement/MeasurementUnitModel.dart'; import 'package:wosull/application/model/Modifiers/GetModifiersModel.dart'; +import 'package:wosull/application/model/Modifiers/Modifier.dart'; import 'package:wosull/application/model/Products/ItemProductModel.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/ingredients/AddProdcutModel.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/store/GetStoreSupplier.dart'; diff --git a/lib/application/views/kitchenmodule/viewModel/KitchenViewModel.dart b/lib/application/views/kitchenmodule/viewModel/KitchenViewModel.dart index 0f41afc..38e12dc 100644 --- a/lib/application/views/kitchenmodule/viewModel/KitchenViewModel.dart +++ b/lib/application/views/kitchenmodule/viewModel/KitchenViewModel.dart @@ -6,7 +6,7 @@ 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/Modifiers/ModifierOption.dart'; import 'package:wosull/application/model/SimpleResponsModel.dart'; import 'package:wosull/application/model/cart/GetHoldOrderModel.dart'; import 'package:wosull/application/model/createOrder/OrderDetails.dart'; diff --git a/lib/application/views/salesandordermodule/views/invoiceModule/NewInvoiceVC.dart b/lib/application/views/salesandordermodule/views/invoiceModule/NewInvoiceVC.dart index 02245b9..b1424cd 100644 --- a/lib/application/views/salesandordermodule/views/invoiceModule/NewInvoiceVC.dart +++ b/lib/application/views/salesandordermodule/views/invoiceModule/NewInvoiceVC.dart @@ -2,9 +2,9 @@ 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/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/theme/MyColors.dart'; diff --git a/lib/application/views/salesandordermodule/views/invoiceModule/viewModels/NewInvoiceViewModel.dart b/lib/application/views/salesandordermodule/views/invoiceModule/viewModels/NewInvoiceViewModel.dart index 5ea61c9..a589594 100644 --- a/lib/application/views/salesandordermodule/views/invoiceModule/viewModels/NewInvoiceViewModel.dart +++ b/lib/application/views/salesandordermodule/views/invoiceModule/viewModels/NewInvoiceViewModel.dart @@ -1,12 +1,12 @@ 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/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'; diff --git a/lib/application/views/salesandordermodule/views/quotataionModule/NewQuotationsVC.dart b/lib/application/views/salesandordermodule/views/quotataionModule/NewQuotationsVC.dart index 1cc067c..7addb17 100644 --- a/lib/application/views/salesandordermodule/views/quotataionModule/NewQuotationsVC.dart +++ b/lib/application/views/salesandordermodule/views/quotataionModule/NewQuotationsVC.dart @@ -6,6 +6,7 @@ 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/Measurement/InventoryMeasurementModel.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'; @@ -30,7 +31,6 @@ 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 { diff --git a/lib/objectbox.g.dart b/lib/objectbox.g.dart index 7ecffc6..c77c3da 100644 --- a/lib/objectbox.g.dart +++ b/lib/objectbox.g.dart @@ -18,10 +18,11 @@ 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/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'; diff --git a/lib/widgets/ChildContainer.dart b/lib/widgets/ChildContainer.dart index c338a6a..f30dea1 100644 --- a/lib/widgets/ChildContainer.dart +++ b/lib/widgets/ChildContainer.dart @@ -7,7 +7,7 @@ class ChildContainer extends StatelessWidget { double? height; ChildContainer( - {super.key, required this.child, this.width = 44, this.height = 48}); + {super.key, required this.child, this.width = 44, this.height = 58}); @override Widget build(BuildContext context) { @@ -21,8 +21,8 @@ class ChildContainer extends StatelessWidget { ), ), child: Align( - child: child, alignment: Alignment.centerLeft, + child: child, ), ); } From 303bff88d505c20cec600de520fcea158a427994 Mon Sep 17 00:00:00 2001 From: waqasYeepeey Date: Wed, 27 Sep 2023 12:27:20 +0500 Subject: [PATCH 03/11] 'stock return vc' --- .../model/ReturnStock/ReturnStock.dart | 89 ++++++ .../model/ReturnStock/ReturnStockCharges.dart | 14 + .../ReturnStock/ReturnStockResponse.dart | 21 ++ lib/application/utils/Constants.dart | 2 + .../BillingCounterMainVC.dart | 15 +- .../discountModule/DiscoountModuleMainVC.dart | 13 +- .../InventoryModuleMainVC.dart | 20 +- .../viewmodels/StockReturnViewModel.dart | 94 +++++++ .../stockReturn/views/NewStockReturnVC.dart | 0 .../stockReturn/views/StockReturnVC.dart | 149 ++++++++++ .../widgets/StockReturnListView.dart | 257 ++++++++++++++++++ .../views/KitchenMainTableVC.dart | 13 +- .../kitchenmodule/views/KitchenMainVC.dart | 13 +- .../SalesAndOrderMainVC.dart | 111 ++------ .../views/settings/SettingsMainVC.dart | 13 +- lib/helpers/ThemeText.dart | 12 + lib/widgets/BackButtonWidget.dart | 39 +++ lib/widgets/BackHeaderContainer.dart | 16 ++ lib/widgets/BackTabBarContainer.dart | 51 ++++ lib/widgets/CustomTabBar.dart | 22 ++ 20 files changed, 814 insertions(+), 150 deletions(-) create mode 100644 lib/application/model/ReturnStock/ReturnStock.dart create mode 100644 lib/application/model/ReturnStock/ReturnStockCharges.dart create mode 100644 lib/application/model/ReturnStock/ReturnStockResponse.dart create mode 100644 lib/application/views/inventorymodule/stockReturn/viewmodels/StockReturnViewModel.dart create mode 100644 lib/application/views/inventorymodule/stockReturn/views/NewStockReturnVC.dart create mode 100644 lib/application/views/inventorymodule/stockReturn/views/StockReturnVC.dart create mode 100644 lib/application/views/inventorymodule/stockReturn/widgets/StockReturnListView.dart create mode 100644 lib/widgets/BackButtonWidget.dart create mode 100644 lib/widgets/BackHeaderContainer.dart create mode 100644 lib/widgets/BackTabBarContainer.dart create mode 100644 lib/widgets/CustomTabBar.dart diff --git a/lib/application/model/ReturnStock/ReturnStock.dart b/lib/application/model/ReturnStock/ReturnStock.dart new file mode 100644 index 0000000..da498b1 --- /dev/null +++ b/lib/application/model/ReturnStock/ReturnStock.dart @@ -0,0 +1,89 @@ +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({ + required this.id, + required this.storeId, + required this.supplierId, + required this.stockReference, + required this.currency, + required this.taxOption, + required this.stockReturnDate, + required this.products, + required this.charges, + required this.discountType, + required this.notes, + required this.shippingCharges, + required this.packingCharges, + required this.totalDiscountAmount, + required this.totalVat, + required this.totalAmount, + required this.totalExcludingVat, + required this.totalTaxableAmount, + required this.isDeleted, + required this.createdAt, + required this.updatedAt, + required 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(), + 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); + } +} diff --git a/lib/application/model/ReturnStock/ReturnStockCharges.dart b/lib/application/model/ReturnStock/ReturnStockCharges.dart new file mode 100644 index 0000000..a653136 --- /dev/null +++ b/lib/application/model/ReturnStock/ReturnStockCharges.dart @@ -0,0 +1,14 @@ +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'] ?? ''); + } +} 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/utils/Constants.dart b/lib/application/utils/Constants.dart index 9ff2e2b..ec94b10 100644 --- a/lib/application/utils/Constants.dart +++ b/lib/application/utils/Constants.dart @@ -96,6 +96,8 @@ class Constants { 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 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'; diff --git a/lib/application/views/billingCounterDashboard/BillingCounterMainVC.dart b/lib/application/views/billingCounterDashboard/BillingCounterMainVC.dart index ff1ceff..0bc007f 100644 --- a/lib/application/views/billingCounterDashboard/BillingCounterMainVC.dart +++ b/lib/application/views/billingCounterDashboard/BillingCounterMainVC.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/billingCounterDashboard/BillingCounterDashBoard.dart'; +import 'package:wosull/helpers/ThemeText.dart'; class BillingCounterMainVC extends StatefulWidget { final DrawerWidgetSelect delegateDrawer; @@ -82,20 +83,12 @@ class _BillingCounterMainVCState 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: [ + tabs: const [ Tab( text: 'Billing Counter Dashboard', ), 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/inventorymodule/InventoryModuleMainVC.dart b/lib/application/views/inventorymodule/InventoryModuleMainVC.dart index 2262349..a0fc5d1 100644 --- a/lib/application/views/inventorymodule/InventoryModuleMainVC.dart +++ b/lib/application/views/inventorymodule/InventoryModuleMainVC.dart @@ -9,8 +9,10 @@ import 'package:wosull/application/views/inventorymodule/measurementviews/Invent 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/helpers/ThemeText.dart'; import 'categoryviews/InventoryCategoriesModule.dart'; import 'deliveryPartnerViews/InventoryDeliveryPartnerPriceVC.dart'; @@ -29,7 +31,7 @@ class _InventoryModuleMainVCState extends State { @override Widget build(BuildContext context) { return DefaultTabController( - length: 10, + length: 11, child: Scaffold( body: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -95,17 +97,9 @@ class _InventoryModuleMainVCState extends State { Flexible( child: 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: [ @@ -130,6 +124,9 @@ class _InventoryModuleMainVCState extends State { const Tab( text: 'Ingredient', ), + const Tab( + text: 'Stock Return', + ), Tab( text: AppLocalizations.of(context)!.stock_transfer, ), @@ -155,6 +152,7 @@ class _InventoryModuleMainVCState extends State { InventoryModifierVC(), InventoryProductVC(), IngredientsVC(), + StockReturnVC(), InventoryStockTransferVC(), InventoryComboVC(), InventoryDeliveryPartnerPriceVC(), diff --git a/lib/application/views/inventorymodule/stockReturn/viewmodels/StockReturnViewModel.dart b/lib/application/views/inventorymodule/stockReturn/viewmodels/StockReturnViewModel.dart new file mode 100644 index 0000000..f73b083 --- /dev/null +++ b/lib/application/views/inventorymodule/stockReturn/viewmodels/StockReturnViewModel.dart @@ -0,0 +1,94 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/enum/DataState.dart'; +import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/application/model/ReturnStock/ReturnStock.dart'; +import 'package:wosull/application/model/ReturnStock/ReturnStockResponse.dart'; +import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/utils/Constants.dart'; + +class StockReturnViewModel 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; + + 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 = { + 'store_id': sharedPrefs.storeId, + 'page': _currentPageNumber, + //'limit': this.limit + }; + + try { + if (_didLastLoad) { + _dataState = DataState.noMoreData; + } else { + await APIManager() + .fetchData(Constants.getReturnStock, data) + .then((result) { + final value = ReturnStockResponse.fromJson(result); + if (_dataState == DataState.refreshing) { + _filteredList.clear(); + } + if (value.success) { + _filteredList.addAll(value.returnStock); + if (value.returnStock.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 { + Map data = {'modifier_option_id': id}; + await APIManager() + .getResponsePatch(Constants.deleteModifierOption, data) + .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..e69de29 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..42937e2 --- /dev/null +++ b/lib/application/views/inventorymodule/stockReturn/views/StockReturnVC.dart @@ -0,0 +1,149 @@ +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/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: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + const Text( + 'Stock Return', + style: ThemeText.textStylePageHeading, + ), + AppSpaces.horizontalSmall, + newModifier(), + Flexible(child: 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) {}, + onView: (stock) {}, + onEdit: (stock) {}), + 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 newModifier() { + return SizedBox( + width: 150, + child: CustomSimpleButton( + heading: '+ New Stock Return', + textColor: MyColors.blueThemeColor, + backGroundColor: MyColors.backColorBlue50, + height: 38, + onPressed: () {}, + ), + ); + } +} 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..d66f203 --- /dev/null +++ b/lib/application/views/inventorymodule/stockReturn/widgets/StockReturnListView.dart @@ -0,0 +1,257 @@ +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/EmptyDataWidget.dart'; +import 'package:wosull/widgets/HeadingText.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() + : Container( + padding: const EdgeInsets.only(left: 8, right: 8), + height: 48, + color: MyColors.containerBackColor, + 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( + 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(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)), + ], + )), + ], + ), + )), + 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, stock), + ) + ], + ), + ), + ); + } else { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: Container( + padding: const EdgeInsets.only(left: 8, right: 8), + height: 48, + color: MyColors.containerBackColor, + 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: 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, stock), + ), + ), + ), + )) + ], + ), + ), + ); + } + }, + itemCount: data.length, + ) + ], + ); + } + + Future actionPopUpItemSelected(String value, ReturnStock item) async { + if (value == 'edit') { + onEdit(item); + } else if (value == 'delete') { + onDelete(item); + } else { + onView(item); + } + } +} diff --git a/lib/application/views/kitchenmodule/views/KitchenMainTableVC.dart b/lib/application/views/kitchenmodule/views/KitchenMainTableVC.dart index b34ad39..9a74c0d 100644 --- a/lib/application/views/kitchenmodule/views/KitchenMainTableVC.dart +++ b/lib/application/views/kitchenmodule/views/KitchenMainTableVC.dart @@ -4,6 +4,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 KitchenMainTableVC extends StatefulWidget { final DrawerWidgetSelect delegateDrawer; @@ -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/salesandordermodule/SalesAndOrderMainVC.dart b/lib/application/views/salesandordermodule/SalesAndOrderMainVC.dart index 64f2316..af5785f 100644 --- a/lib/application/views/salesandordermodule/SalesAndOrderMainVC.dart +++ b/lib/application/views/salesandordermodule/SalesAndOrderMainVC.dart @@ -2,11 +2,11 @@ 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/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; @@ -35,97 +35,32 @@ 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( + const Expanded( child: TabBarView( children: [ OrderVC(), - const InvoicesVC(), - const QuotationsVC(), - const TransactionVC() + InvoicesVC(), + QuotationsVC(), + TransactionVC() ], )) ], diff --git a/lib/application/views/settings/SettingsMainVC.dart b/lib/application/views/settings/SettingsMainVC.dart index 1359a84..d53e136 100644 --- a/lib/application/views/settings/SettingsMainVC.dart +++ b/lib/application/views/settings/SettingsMainVC.dart @@ -3,6 +3,7 @@ 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/helpers/ThemeText.dart'; import 'ReportsVC.dart'; @@ -84,17 +85,9 @@ 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: [ diff --git a/lib/helpers/ThemeText.dart b/lib/helpers/ThemeText.dart index a0a8c2c..0ca8188 100644 --- a/lib/helpers/ThemeText.dart +++ b/lib/helpers/ThemeText.dart @@ -204,4 +204,16 @@ abstract class ThemeText { fontWeight: FontWeight.bold, fontSize: MyFonts.normalButton, color: MyColors.textColorBlack20); + + static TextStyle tabLabelStyle = TextStyle( + fontSize: MyFonts.normalButton, + fontWeight: FontWeight.w500, + fontFamily: MyFonts.Bold, + color: MyColors.blueThemeColor); + + static TextStyle unSelectedTabLabelStyle = const TextStyle( + fontSize: MyFonts.normalButton, + fontWeight: FontWeight.w500, + fontFamily: MyFonts.Medium, + color: MyColors.textColorBlack); } diff --git a/lib/widgets/BackButtonWidget.dart b/lib/widgets/BackButtonWidget.dart new file mode 100644 index 0000000..4f815f5 --- /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: 16, + 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/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, + ); + } +} From b5276b287684c9fb69371d9b5b201795714ad15f Mon Sep 17 00:00:00 2001 From: waqasYeepeey Date: Thu, 28 Sep 2023 19:59:24 +0500 Subject: [PATCH 04/11] 'produxt chaanges' --- lib/application/MyApp.dart | 3 + .../ViewModel/InventoryViewModel.dart | 81 +- .../model/Products/AddProduct.dart | 218 ++ .../model/Products/GetProductResponse.dart | 28 + .../model/Products/ProductById.dart | 14 + lib/application/model/Products/ProductId.dart | 24 + .../model/Products/SearchProductResponse.dart | 18 + .../model/ReturnStock/ReturnStock.dart | 111 +- .../model/ReturnStock/ReturnStockCharges.dart | 7 + .../ProductItemCategoryModel.dart | 14 +- .../model/store/StoreItemsResponse.dart | 103 - lib/application/theme/MyColors.dart | 2 +- lib/application/utils/Constants.dart | 10 + .../views/NewModifierOptionVC.dart | 10 +- .../AddNewInventoryProductVC.dart | 3466 ++++++----------- .../productviews/InventoryProductVC.dart | 678 +--- .../productviews/SearchProductVC.dart | 18 +- .../viewModels/AddProductViewModel.dart | 483 ++- .../viewModels/ProductViewModel.dart | 60 +- .../productviews/views/ProductListView.dart | 308 ++ .../viewmodels/NewStockReturnViewModel.dart | 474 +++ .../stockReturn/views/NewStockReturnVC.dart | 1148 ++++++ .../stockReturn/views/StockReturnVC.dart | 35 +- .../widgets/StockReturnListView.dart | 22 +- .../views/invoiceModule/NewInvoiceVC.dart | 94 +- .../quotataionModule/NewQuotationsVC.dart | 2 +- lib/helpers/ThemeDropDown.dart | 21 + lib/helpers/ThemeText.dart | 2 +- lib/objectbox-model.json | 7 +- lib/objectbox.g.dart | 33 +- lib/widgets/CustomAddButton.dart | 18 +- lib/widgets/ItemCategoryDropdown.dart | 10 +- lib/widgets/WrapHeightContainer.dart | 22 + 33 files changed, 4168 insertions(+), 3376 deletions(-) create mode 100644 lib/application/model/Products/AddProduct.dart create mode 100644 lib/application/model/Products/GetProductResponse.dart create mode 100644 lib/application/model/Products/ProductById.dart create mode 100644 lib/application/model/Products/ProductId.dart create mode 100644 lib/application/model/Products/SearchProductResponse.dart create mode 100644 lib/application/views/inventorymodule/productviews/views/ProductListView.dart create mode 100644 lib/application/views/inventorymodule/stockReturn/viewmodels/NewStockReturnViewModel.dart create mode 100644 lib/widgets/WrapHeightContainer.dart diff --git a/lib/application/MyApp.dart b/lib/application/MyApp.dart index 4729f5d..808fd3d 100644 --- a/lib/application/MyApp.dart +++ b/lib/application/MyApp.dart @@ -25,6 +25,7 @@ import 'package:wosull/application/views/inventorymodule/measurementviews/viewMo 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'; @@ -50,6 +51,8 @@ class MyApp extends StatelessWidget { Widget build(BuildContext context) { return MultiProvider( providers: [ + ChangeNotifierProvider( + create: (context) => NewStockReturnViewModel()), ChangeNotifierProvider( create: (context) => NewModifierOptionViewModel()), ChangeNotifierProvider( diff --git a/lib/application/ViewModel/InventoryViewModel.dart b/lib/application/ViewModel/InventoryViewModel.dart index add1d11..4a1f6d4 100644 --- a/lib/application/ViewModel/InventoryViewModel.dart +++ b/lib/application/ViewModel/InventoryViewModel.dart @@ -1,13 +1,24 @@ -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/model/store/GetStoreSupplier.dart'; +import 'package:wosull/application/model/store/StoreInvoicesModel.dart'; +import 'package:wosull/application/network/APIManager.dart'; import 'package:wosull/application/repo/AuthRepository.dart'; import 'package:wosull/application/utils/Constants.dart'; class InventoryViewModel { + 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() @@ -18,70 +29,26 @@ class InventoryViewModel { } } - 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( + Future> getProductSearchStores( Map data) async { try { dynamic response = await AuthRepository() .postResponseAuth(Constants.SEARCH_ITEM_STORE, data); - return ProductItemCategoryModel.fromJson(response); + final value = ProductItemCategoryModel.fromJson(response); + return value.categories; } catch (e) { - return ProductItemCategoryModel(); + return []; } } - 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 { + Future> getAllProducts() 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); + dynamic response = await AuthRepository().postResponseAuth( + Constants.SEARCH_ITEM_STORE, Constants.getStorePayload()); + final value = ProductItemCategoryModel.fromJson(response); + return value.categories; } catch (e) { - return SimpleResponseModel(); + return []; } } diff --git a/lib/application/model/Products/AddProduct.dart b/lib/application/model/Products/AddProduct.dart new file mode 100644 index 0000000..1eeed88 --- /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 = 0.0, + this.uniqueId = 0, + this.measurementUnit = '', + this.uniqueIdForStoreData = '', + this.quantity, + this.imageUrl = '', + this.updatedAt = '', + this.totalItemPrice = 0.0, + this.isItemInStock = false, + this.description = '', + this.descriptionArabic = '', + this.purchasePrice = 0.0, + this.stockAlertQuantity = 0, + this.itemPriceWithOutOffer = 0, + this.totalAddedQuantity = 0, + this.noteForItem, + this.totalUsedQuantity = 0, + this.salePriceExclusiveTax = 0, + 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'] = 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; + 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'] = 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; + } +} 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/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 index da498b1..cc11474 100644 --- a/lib/application/model/ReturnStock/ReturnStock.dart +++ b/lib/application/model/ReturnStock/ReturnStock.dart @@ -1,54 +1,55 @@ +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; + 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({ - required this.id, - required this.storeId, - required this.supplierId, - required this.stockReference, - required this.currency, - required this.taxOption, - required this.stockReturnDate, - required this.products, - required this.charges, - required this.discountType, - required this.notes, - required this.shippingCharges, - required this.packingCharges, - required this.totalDiscountAmount, - required this.totalVat, - required this.totalAmount, - required this.totalExcludingVat, - required this.totalTaxableAmount, - required this.isDeleted, - required this.createdAt, - required this.updatedAt, - required this.uniqueId, + 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) { @@ -57,7 +58,7 @@ class ReturnStock { storeId: json['store_id'] ?? '', supplierId: json['supplier_id'] != null ? Supplier.fromJson(json['supplier_id']) - : Supplier(), + : Supplier(id: '', name: ''), stockReference: json['stock_reference'] ?? '', currency: json['currency'] ?? '', taxOption: json['tax_option'] ?? '', @@ -86,4 +87,24 @@ class ReturnStock { updatedAt: json['updatedAt'] ?? '', uniqueId: json['unique_id'] ?? 0); } + + Map toJson() { + final Map data = {}; + data['store_id'] = sharedPrefs.storeId; + data['invoiceId'] = id ?? ''; + data['supplier_id'] = supplierId!.id ?? ''; + data['stock_return_date'] = stockReturnDate; + data['currency'] = currency; + data['notes'] = notes; + 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'] = totalExcludingVat; + data['total_taxable_amount'] = totalTaxableAmount; + data['total_vat'] = totalVat; + + return data; + } } diff --git a/lib/application/model/ReturnStock/ReturnStockCharges.dart b/lib/application/model/ReturnStock/ReturnStockCharges.dart index a653136..f19572c 100644 --- a/lib/application/model/ReturnStock/ReturnStockCharges.dart +++ b/lib/application/model/ReturnStock/ReturnStockCharges.dart @@ -11,4 +11,11 @@ class ReturnStockCharges { 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/StockTransfer/ProductItemCategoryModel.dart b/lib/application/model/StockTransfer/ProductItemCategoryModel.dart index 7a65ece..5e06307 100644 --- a/lib/application/model/StockTransfer/ProductItemCategoryModel.dart +++ b/lib/application/model/StockTransfer/ProductItemCategoryModel.dart @@ -5,17 +5,19 @@ import 'package:wosull/helpers/Utils.dart'; import '../Combo/GetComboModel.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() + : []); } } diff --git a/lib/application/model/store/StoreItemsResponse.dart b/lib/application/model/store/StoreItemsResponse.dart index f29331d..0e0c1bc 100644 --- a/lib/application/model/store/StoreItemsResponse.dart +++ b/lib/application/model/store/StoreItemsResponse.dart @@ -35,23 +35,6 @@ 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(assignable: true) @@ -107,8 +90,6 @@ class StoreItems { var deliveryPartners = ToMany(); var comboProduct = ToMany(); - ProductId productIdUpdate = ProductId(); - StoreItems( {this.name = '', this.itemId = '', @@ -268,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; - 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'] = itemId; - 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/theme/MyColors.dart b/lib/application/theme/MyColors.dart index 7b033d8..269edc1 100644 --- a/lib/application/theme/MyColors.dart +++ b/lib/application/theme/MyColors.dart @@ -118,7 +118,7 @@ class MyColors { fillColor: fillColor, filled: true, labelStyle: ThemeText.textStyleValue, - hintStyle: ThemeText.hintStyleTextField, + hintStyle: ThemeText.textStyleValue, isDense: true, contentPadding: const EdgeInsets.only(left: 8), // Added enabledBorder: OutlineInputBorder( diff --git a/lib/application/utils/Constants.dart b/lib/application/utils/Constants.dart index ec94b10..f1e08f4 100644 --- a/lib/application/utils/Constants.dart +++ b/lib/application/utils/Constants.dart @@ -97,6 +97,7 @@ class Constants { 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'; @@ -278,6 +279,11 @@ class Constants { 'Closed Counter', ]; + static const currencies = [ + 'SAR', + 'AED', + ]; + static const paymentMethod = [ 'Cash', ]; @@ -297,6 +303,10 @@ class Constants { 'Company', ]; + static const taxOptions = [ + 'VAT', + ]; + static const statusTypes = [ 'Open', 'Paid Partially', diff --git a/lib/application/views/inventorymodule/modiferOption/views/NewModifierOptionVC.dart b/lib/application/views/inventorymodule/modiferOption/views/NewModifierOptionVC.dart index 8a797e3..cb4fd8d 100644 --- a/lib/application/views/inventorymodule/modiferOption/views/NewModifierOptionVC.dart +++ b/lib/application/views/inventorymodule/modiferOption/views/NewModifierOptionVC.dart @@ -24,6 +24,7 @@ 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; @@ -265,14 +266,7 @@ class _NewModifierOptionVCState extends State { 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, - ), + return WrapHeightContainer( child: Row( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, diff --git a/lib/application/views/inventorymodule/productviews/AddNewInventoryProductVC.dart b/lib/application/views/inventorymodule/productviews/AddNewInventoryProductVC.dart index 49d4412..035cc23 100644 --- a/lib/application/views/inventorymodule/productviews/AddNewInventoryProductVC.dart +++ b/lib/application/views/inventorymodule/productviews/AddNewInventoryProductVC.dart @@ -4,41 +4,47 @@ 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/discount/StoreDiscountModel.dart'; import 'package:wosull/application/model/ingredients/AddIngredient.dart'; -import 'package:wosull/application/model/Measurement/MeasurementUnitModel.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/productviews/viewModels/AddProductViewModel.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/CustomTextFieldForm.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,2037 +65,466 @@ 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 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 ? "Edit Product" : 'Add Product', - style: ThemeText.mediumHeader, - ), - backgroundColor: MyColors.white, - elevation: 5, + 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( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - child: Padding( - padding: const EdgeInsets.all(15), - child: isPortrait - ? Column( + child: (widget.isEdit || widget.isView) && viewModel.isLoadingFirst + ? AppLoader() + : Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Card( + elevation: 5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: Padding( + padding: const EdgeInsets.all(15), + child: isPortrait + ? Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + 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( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Expanded( + flex: 1, + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + getItemName(), + AppSpaces.verticalMedium, + getCategory(), + AppSpaces.verticalMedium, + getDescriptionWidget() + ], + ), + ), + AppSpaces.horizontalMedium, + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + getArabicNameWidget(), + AppSpaces.verticalMedium, + getDefaultPriceWidget(), + AppSpaces.verticalMedium, + getArabicDescriptionWidget() + ], + )), + AppSpaces.horizontalMedium, + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + getBarCodeWidget(), + AppSpaces.verticalMedium, + getQuantityWidget(), + AppSpaces.verticalMedium, + getItemInStockWidget() + ], + )), + ], + ), + ), + ), + AppSpaces.verticalLarge, + Card( + elevation: 5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(4.0), + ), + child: Container( + padding: const EdgeInsets.all(15), + child: Column( crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.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, + Text( + AppLocalizations.of(context)! + .price_quantity_tax_additional_information, + style: ThemeText.textStyleHeadingCart, ), + AppSpaces.verticalLarge, Row( + crossAxisAlignment: CrossAxisAlignment.start, children: [ + Expanded(child: getSalePriceExclTax()), + AppSpaces.horizontalMedium, + Expanded(child: getPriceIncludeTax()), + AppSpaces.horizontalMedium, Expanded( - child: MandatoryTitleText( - hint: AppLocalizations.of(context)! - .quantity, - ), - ), - CustomCheckBox( - heading: 'Unlimited Quantity', - value: viewModel - .storeItem.isUnlimitedQuantity, - onChange: (value) { - viewModel.setIsUnlimitedQuantity(value); - }) + child: getStockAlertQuantityWidget()), ], ), - 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, - ), + AppSpaces.verticalLarge, Row( + crossAxisAlignment: CrossAxisAlignment.start, 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', - ), - ), + Expanded(child: getDiscountWidget()), + AppSpaces.horizontalMedium, + Expanded(child: getSupplier()), ], ), - const SizedBox( - height: 8, - ), - MandatoryTitleText( - hint: AppLocalizations.of(context)!.status), - const SizedBox( - height: 4, + AppSpaces.verticalLarge, + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded(child: getManufactureDate()), + AppSpaces.horizontalMedium, + Expanded(child: getExpireDate()), + ], ), - 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); - }, - ) - ], - ), - ) ], - ) - : Row( + ), + ), + ), + AppSpaces.verticalLarge, + Card( + elevation: 5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(4.0), + ), + child: Container( + width: double.infinity, + padding: const EdgeInsets.all(15), + child: Column( crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.min, children: [ - Expanded( - flex: 1, - child: Column( - 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, + Text( + AppLocalizations.of(context)! + .delivery_partner_price, + style: ThemeText.textStyleHeadingCart, + ), + AppSpaces.verticalMedium, + isPortrait + ? Container() + : BorderContainer( + child: Row( + children: [ + HeadingContainer( + height: 48, + width: 250, + heading: + AppLocalizations.of(context)! + .name), + Expanded( + child: HeadingContainer( + heading: + 'Delivery Partner Price(Exclusive of vat & Including vat)', + )), + ChildContainer( + width: 44, + child: Container(), + ) + ], ), ), - ], - ), - ), - const SizedBox( - width: 12, - ), - 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, + getListViewDeliveryPartner(), + isPortrait + ? BorderContainer( + backgroundColor: Colors.transparent, + child: Row( + children: [ + Expanded( + child: HeadingContainer( + height: 48, + heading: '', + )), + getAddDeliveryPartnerButton() + ], + ), + ) + : BorderContainer( + backgroundColor: Colors.transparent, + child: Row( + children: [ + Expanded( + child: HeadingContainer( + heading: '', + )), + getAddDeliveryPartnerButton() + ], + ), ), - ), - ], - )), - const SizedBox( - width: 12, - ), - Expanded( - child: Column( + ], + ), + ), + ), + AppSpaces.verticalLarge, + Card( + elevation: 5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(4.0), + ), + child: Container( + padding: const EdgeInsets.all(15), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, 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( + Expanded( + child: Container( + padding: const EdgeInsets.all(8), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, children: [ - const CustomOptionalTitle( - hint: 'Item In Stock', + Text( + AppLocalizations.of(context)! + .search_and_add_products, + style: ThemeText.textStyleHeadingCart, ), - const SizedBox( - width: 6, + AppSpaces.verticalLarge, + CustomOptionalTitle( + hint: AppLocalizations.of(context)! + .search, ), - CustomSwitch( - value: - viewModel.storeItem.isItemInStock, - onToggle: (value) { - viewModel - .setItemInStockStatus(value); - }, - ) + AppSpaces.verticalSmall, + getIngredientsWidget(context), + AppSpaces.verticalSmall, + CustomOptionalTitle( + hint: AppLocalizations.of(context)! + .choose_ingredients), + AppSpaces.verticalLarge, ], ), - ) + )), + isPortrait + ? Container() + : Expanded( + child: getProductAsIngredientCost()), ], - )), + ), + isPortrait + ? getProductAsIngredientCost() + : Container(), + Visibility( + visible: viewModel + .storeItem.ingredients.isNotEmpty, + child: Column( + children: [ + 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: + 'Purchase Price of 1 Unit', + )), + Expanded( + child: HeadingContainer( + heading: + 'Sale Price of 1 Unit', + )), + Expanded( + child: HeadingContainer( + heading: 'Measuring Unit', + )), + HeadingContainer( + width: 48, + heading: '', + ) + ], + ), + ), + getIngredientsList() + ], + )) ], ), - ), - ), - 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)! - .price_quantity_tax_additional_information, - style: ThemeText.textStyleHeadingCart, - ), - const SizedBox( - height: 12, ), - 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; - }, - ), - ], - )), - AppSpaces.horizontalMedium, - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + ), + AppSpaces.verticalLarge, + isPortrait + ? Column( 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; - }, - ), + getItemImageCard(), + AppSpaces.verticalLarge, + getMeasurementCard() ], - )), - ], - ), - const SizedBox( - height: 12, - ), - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: Column( + ) + : Row( + mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ - CustomOptionalTitle( - hint: AppLocalizations.of(context)!.discount, + Expanded( + child: getItemImageCard(), ), - AppSpaces.verticalSmall, - getDiscounts(context), - ], - )), - AppSpaces.horizontalMedium, - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - CustomOptionalTitle( - hint: AppLocalizations.of(context)!.supplier, + Expanded( + child: getMeasurementCard(), ), - AppSpaces.verticalSmall, - getSupplierWidget(context), ], - )), - ], - ), - const SizedBox( - height: 12, + ), + AppSpaces.verticalLarge, + Card( + elevation: 5, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(4.0), ), - 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, - ) - ], - ), - ), - ], - )), - AppSpaces.horizontalMedium, - Expanded( - child: Column( + child: Container( + width: double.infinity, + padding: const EdgeInsets.all(15), + child: Column( crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.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, - ) - ], - ), + Text( + style: ThemeText.textStyleHeadingCart, + AppLocalizations.of(context)!.modifiers, ), + AppSpaces.verticalLarge, + getModifierWidget(), ], )), - ], - ), - ], - ), - ), - ), - const SizedBox( - height: 12, - ), - Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(4.0), + ), + AppSpaces.verticalLarge, + Visibility( + visible: !widget.isView, + child: SizedBox( + width: 140, + child: CustomSimpleButton( + textColor: MyColors.white, + isLoading: viewModel.isLoadingData, + backGroundColor: MyColors.blueThemeColor, + onPressed: () async { + await viewModel.isValidate( + context, widget.isEdit); + checkState(); + }, + heading: widget.isEdit + ? "Update" + : AppLocalizations.of(context)!.add_product, + ), + )), + ], ), - child: Container( - width: double.infinity, - padding: const EdgeInsets.all(8), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - AppLocalizations.of(context)!.delivery_partner_price, - style: ThemeText.textStyleHeadingCart, - ), - const SizedBox( - height: 8, - ), - 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: [ - 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( - 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( - 'Delivery Partner Price(Exclusive of vat & Including vat)', - ), - ), - )), - Container( - width: 44, - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Container(), - ) - ], - ), - ), - 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, - 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(), - ), - ), - )), - 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(); - }), - ), - ), - ], - ), - ) - : 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(), - ), - ), - )), - 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(); - }), - ), - ), - ], - ), - ), - ], - ), - ), - ), - const SizedBox( - height: 12, - ), - Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(4.0), - ), - child: Container( - padding: const EdgeInsets.all(8), - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - 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: ThemeText.textStyleHeadingCart, - ), - const SizedBox( - height: 12, - ), - CustomOptionalTitle( - hint: AppLocalizations.of(context)!.search, - ), - const SizedBox( - height: 4, - ), - getIngredientsWidget(context), - const SizedBox( - height: 4, - ), - CustomOptionalTitle( - hint: AppLocalizations.of(context)! - .choose_ingredients), - const SizedBox( - height: 12, - ), - ], - ), - )), - 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, - ), - ], - ), - )), - ], - ), - 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, - ), - ], - ), - ) - : Container(), - Visibility( - visible: viewModel.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, - 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: HeadingText( - 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'), - ), - )), - 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.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'), - ), - )), - Container( - width: 48, - height: 48, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors - .fillColorGray2), - ), - ), - child: Center( - child: HeadingText( - '', - ), - ), - ) - ], - ), - ), - 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, - ), - ], - )) - ], - ), - ), - ), - 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, - ), - ), - ], - ), - ), - ), - 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(), - ], - ), - ), - ), - ), - ], - ), - 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: [ - CustomOptionalTitle( - hint: AppLocalizations.of(context)!.modifiers, - ), - const SizedBox( - height: 12, - ), - getModifierWidget(), - ], - )), - ), - Visibility( - visible: !widget.isView, - child: SizedBox( - width: 140, - child: CustomSimpleButton( - textColor: MyColors.white, - isLoading: viewModel.isLoadingData, - backGroundColor: MyColors.blueThemeColor, - onPressed: () { - viewModel.isValidate(context, widget.isEdit); - }, - heading: widget.isEdit - ? "Update" - : AppLocalizations.of(context)!.add_product, - ), - )), - ], - ), ), ); }), ); } - Widget getDeliveryPartner(BuildContext context, int position) { + void checkState() { + if (viewModel.crudOperation == CRUDOperationState.add || + viewModel.crudOperation == CRUDOperationState.update) { + Navigator.pop(context, true); + } + } + + 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( + 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.dropDownStyle(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( + 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.dropDownStyle(hint: 'Choose')); } else { return AppLoader(); } @@ -2102,35 +537,21 @@ class _AddNewInventoryProductVCState extends State 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( + 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(); @@ -2138,35 +559,27 @@ 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( + 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(); @@ -2180,38 +593,21 @@ 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( - 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( + 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(); @@ -2225,37 +621,20 @@ 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( + 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(); @@ -2278,6 +657,7 @@ class _AddNewInventoryProductVCState extends State gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: isPortrait ? 3 : 6, crossAxisSpacing: 0, + mainAxisExtent: 60, mainAxisSpacing: 0, ), itemBuilder: (c, i) { @@ -2320,36 +700,34 @@ class _AddNewInventoryProductVCState extends State ), ), ), - 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(), + // ), ], )) ], @@ -2371,56 +749,65 @@ 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( + 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( + 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(); @@ -2446,9 +833,7 @@ 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, @@ -2464,65 +849,23 @@ class _AddNewInventoryProductVCState extends State Expanded( child: Column( children: [ - Container( - padding: const EdgeInsets.all(4), + PortraitContainer( + width: double.infinity, 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( + child: HeadingText( AppLocalizations.of(context)!.name, - style: const TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.bold, - fontSize: 11, - color: MyColors.textColorBlack20), ), ), ), - Container( - padding: const EdgeInsets.all(4), + PortraitContainer( + width: double.infinity, 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( + child: Align( alignment: Alignment.centerLeft, - child: Text( + child: HeadingText( 'Delivery Partner Price', - style: TextStyle( - fontFamily: MyFonts.Bold, - fontWeight: FontWeight.bold, - fontSize: 11, - color: MyColors.textColorBlack20), ), ), ) @@ -2533,7 +876,7 @@ class _AddNewInventoryProductVCState extends State crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ - getDeliveryPartner(context, position), + getDeliveryPartner(position), deliveryPartnerPrice(position) ], )), @@ -2545,21 +888,13 @@ class _AddNewInventoryProductVCState extends State ), ); } 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), @@ -2577,58 +912,691 @@ class _AddNewInventoryProductVCState extends State } 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, + return CustomRemoveItemButton( + onPressed: () { + viewModel.removeDeliveryPartner(position); + }, + ); + } + + Widget deliveryPartnerPrice(int position) { + return ChildContainer( + width: double.infinity, + child: 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, + ), + 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: [ + MandatoryTitleText(hint: AppLocalizations.of(context)!.category), + AppSpaces.verticalSmall, + getCategoryWidget(), + ], + ); + } + + 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, + Row( + children: [ + Expanded( + child: CustomTextFieldForm( + hintText: 'Enter Barcode', + readOnly: widget.isView, + key: Key(viewModel.storeItem.uniqueIdForStoreData.toString()), + initialValue: viewModel.storeItem.uniqueIdForStoreData.toString(), + onChanged: (value) { + viewModel.storeItem.uniqueIdForStoreData = value; + }, + )), + SizedBox( + width: 100, + child: CustomSimpleButton( + height: 48, + backGroundColor: MyColors.backColorBlue50, + textColor: MyColors.blueThemeColor, + onPressed: () { + if (!widget.isView) { + viewModel.generateCode(); + } + }, + heading: 'Generate', + ), + ), + ], + ), + ], + ); + } + + 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, + ), + ], + ); + } + + 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.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.storeItem.purchasePrice = double.parse(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.storeItem.stockAlertQuantity = int.parse(value); + }, + ), + ], + ); + } + + getDiscountWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.discount, + ), + AppSpaces.verticalSmall, + getDiscounts(context), + ], + ); + } + + getSupplier() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomOptionalTitle( + hint: AppLocalizations.of(context)!.supplier, + ), + AppSpaces.verticalSmall, + getSupplierWidget(context), + ], + ); + } + + getManufactureDate() { + return 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, + ) + ], + ), + ), + ], + ); + } + + getExpireDate() { + return 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.removeDeliveryPartner(position); - }), + 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, + ) + ], ), - )); + ), + ], + ); } - Widget deliveryPartnerPrice(int position) { + getAddDeliveryPartnerButton() { + return CustomAddButton(onPressed: () { + viewModel.addNewDeliveryPartner(); + }); + } + + getProductAsIngredientCost() { return Container( - decoration: const BoxDecoration( - border: Border( - right: BorderSide(width: 1.0, color: MyColors.fillColorGray2), - ), + 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, + ), + ], ), - height: 48, - padding: const EdgeInsets.all(4), + ); + } + + getItemImageCard() { + return Card( + elevation: 5, child: Container( - decoration: BoxDecoration( - border: Border.all( - color: Colors.transparent, - width: 1, - ), - color: MyColors.backFillColor, - borderRadius: BorderRadius.circular(8.0), + 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: const TextStyle( + fontFamily: MyFonts.DMREGULAR, + fontSize: MyFonts.normal, + color: MyColors.textColorGray), + textAlign: TextAlign.center, + ), + ), + ], ), - child: 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); - }, + ), + ); + } + + 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: ValueText(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: ValueText( + 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, + height: 48, + 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 43850c0..473013f 100644 --- a/lib/application/views/inventorymodule/productviews/InventoryProductVC.dart +++ b/lib/application/views/inventorymodule/productviews/InventoryProductVC.dart @@ -1,32 +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/AppSpaces.dart'; -import 'package:wosull/helpers/ThemeDropDown.dart'; -import 'package:wosull/helpers/ThemeImage.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); @@ -54,48 +46,54 @@ class _InventoryProductVCState extends BaseStatefulState { 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( + child: Column( + children: [ + isPortrait + ? Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)!.our_products, + style: ThemeText.textStylePageHeading, + ), + AppSpaces.horizontalSmall, + SizedBox( + height: 38, + width: 150, + child: getCategoriesDropdown()), + AppSpaces.horizontalSmall, + SizedBox( + width: 120, + child: addProductButton(), + ), + ], + ), + AppSpaces.verticalMedium, + Row( + children: [ + Flexible( + 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( mainAxisAlignment: MainAxisAlignment.start, children: [ Text( @@ -112,12 +110,12 @@ class _InventoryProductVCState extends BaseStatefulState { width: 120, child: addProductButton(), ), - ], - ), - AppSpaces.verticalMedium, - Row( - children: [ - Flexible( + AppSpaces.horizontalMedium, + SizedBox( + width: SizerUtil.deviceType == DeviceType.mobile + ? 200 + : 240, + height: 48, child: SearchBox( onEditingDone: (text) { // filterSearchResults(text); @@ -128,372 +126,68 @@ class _InventoryProductVCState extends BaseStatefulState { hint: AppLocalizations.of(context)!.search, ), ), - PageLimitDropdown(onChange: (value) { + Flexible( + child: PageLimitDropdown(onChange: (value) { viewModel.fetch( isRefresh: true, limit: int.parse(value!)); - }) + })) ], - ) - ], - ) - : Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Text( - AppLocalizations.of(context)!.our_products, - style: ThemeText.textStylePageHeading, ), - AppSpaces.horizontalSmall, - SizedBox( - 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: 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); + } + }, ), - AppSpaces.verticalMedium, - 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.itemId, - 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.itemId, 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() { @@ -506,62 +200,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.itemId); - } - } 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); } } @@ -576,23 +256,13 @@ class _InventoryProductVCState extends BaseStatefulState { } Widget getCategoriesDropdown() { - return DropdownSearch( - selectedItem: viewModel.selectedCategoryDropDown, - dropdownButtonProps: ThemeDropDown.dropdownButtonProps, - popupProps: const PopupProps.menu( - fit: FlexFit.loose, - constraints: BoxConstraints(maxHeight: 300), - ), - clearButtonProps: ThemeDropDown.clearButton, - items: viewModel.categories, - itemAsString: (ItemCategory u) => u.name, - onChanged: (ItemCategory? data) { - if (data != null) { - viewModel.getNewData(data); - } - }, - dropdownDecoratorProps: MyColors.dropDownStyle(fillColor: MyColors.white), - ); + return ItemCategoryDropdown( + fillColor: MyColors.white, + onChanged: (data) { + if (data != null) { + viewModel.getNewData(data); + } + }); } Widget addProductButton() { @@ -601,28 +271,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(true, true, ''); }, ); } @@ -638,33 +287,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..8e1b08d 100644 --- a/lib/application/views/inventorymodule/productviews/SearchProductVC.dart +++ b/lib/application/views/inventorymodule/productviews/SearchProductVC.dart @@ -1,5 +1,3 @@ -import 'dart:convert'; - import 'package:flutter/material.dart'; import 'package:wosull/application/ViewModel/InventoryViewModel.dart'; import 'package:wosull/application/localdb/SharedPrefs.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 @@ -163,15 +161,13 @@ class _SearchProductVCState extends State { '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/viewModels/AddProductViewModel.dart b/lib/application/views/inventorymodule/productviews/viewModels/AddProductViewModel.dart index da196ea..616510c 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'; @@ -12,9 +11,13 @@ import 'package:wosull/application/model/DeliveryPartner/GetDeliveryPartner.dart import 'package:wosull/application/model/DeliveryPartner/ItemsDeliveryPartner.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/Products/AddProduct.dart'; import 'package:wosull/application/model/Products/ItemProductModel.dart'; +import 'package:wosull/application/model/Products/ProductById.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/ingredients/AddIngredient.dart'; @@ -24,30 +27,23 @@ 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/utils/CRUDOperatoinState.dart'; import 'package:wosull/application/utils/Constants.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 = []; + // List unitsController = []; List selectedMod = []; List selectedPartners = []; + List selectedIngredientsMeasurement = []; dynamic selectedCategory; dynamic selectedDiscount; dynamic selectedSupplier; + dynamic selectedMeasurement; + dynamic selectedMeasurementUnit; var isLoadingData = false; File? imageFile; @@ -56,49 +52,45 @@ 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()); } 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) { @@ -106,17 +98,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(); @@ -124,57 +116,54 @@ 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(); + // 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(); + } else { + storeItem = AddProduct( + isUnlimitedQuantity: false, + modifiers: ToMany(items: []), + ingredients: ToMany(items: []), + selectedModifiers: ToMany(items: []), + deliveryPartners: ToMany(items: []), + ); } } @@ -229,71 +218,36 @@ class AddProductViewModel with ChangeNotifier { }); } - 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.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; - } - - 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())); + ItemCategory selected = selectedCategory; + productId.categoryId = selected.id; + productId.productId = await getSubProducts(selected.id); + storeItem.productId = productId; await APIManager() .getResponsePatch( @@ -301,80 +255,54 @@ class AddProductViewModel with ChangeNotifier { .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; - } + storeItem.productIdSt = await getSubProducts(storeItem.productIdSt); - 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); 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(); }); @@ -386,7 +314,7 @@ class AddProductViewModel with ChangeNotifier { 'store_id': sharedPrefs.storeId, 'category_id': categoryID, }; - print(jsonEncode(data)); + await APIManager() .fetchData(Constants.ITEM_GET_PRODUCT_LIST_BY_CATEGORY, data) .then((value) { @@ -399,7 +327,6 @@ class AddProductViewModel with ChangeNotifier { Utils.showMessage('Product not found against selected category'); } }).onError((error, stackTrace) { - print('getSubProducts'); isLoadingData = false; notifyListeners(); }); @@ -407,7 +334,7 @@ class AddProductViewModel with ChangeNotifier { 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', @@ -429,25 +356,27 @@ 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 respStr = await streamedResponse.stream.bytesToString(); + 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); + // barCodeController = number; + storeItem.uniqueIdForStoreData = number; notifyListeners(); } @@ -458,7 +387,9 @@ class AddProductViewModel with ChangeNotifier { Future> getIngredients() async { var items = []; - await APIManager().getResponseAuth(Constants.GET_INGREDIENTS).then((value) { + await APIManager() + .getResponseAuth("${Constants.GET_INGREDIENTS}/${sharedPrefs.storeId}") + .then((value) { final response = GetIngredientModel.fromJson(value); if (response.success) { items.addAll(response.ingredient); @@ -473,21 +404,18 @@ class AddProductViewModel with ChangeNotifier { 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; - } - } + 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; } } - }) - .onError((error, stackTrace) {}) - .timeout(const Duration(minutes: 1)); + } + } + }).onError((error, stackTrace) {}); return items; } @@ -499,49 +427,47 @@ class AddProductViewModel with ChangeNotifier { .fetchData(Constants.GET_STORE_SUPPLIER, Constants.getStorePayload()) .then((value) { final response = GetStoreSupplier.fromJson(value); + if (response.success!) { items.addAll(response.suppliers!); - print(storeItem.supplier); 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 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 (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!; + storeItem.productIdSt = selectedCategory.id!; } - } else { + selectedCategory ??= items[0]; - storeItem.productId = selectedCategory.id!; } - } + }).onError((error, stackTrace) {}); + return items; } @@ -555,6 +481,12 @@ class AddProductViewModel with ChangeNotifier { final response = ProductMeasurementModel.fromJson(value); if (response.success!) { items.addAll(response.measurements!); + if (isEdit) { + final name = items + .singleWhere((element) => element.name == storeItem.measurement) + .name; + selectedMeasurement = Measurement(id: '', name: name ?? ''); + } } }).onError((error, stackTrace) {}); @@ -579,20 +511,29 @@ class AddProductViewModel with ChangeNotifier { return items; } - Future> getMeasurements() async { + Future> getMeasurements(bool isIngredient) async { var items = []; await APIManager() - .fetchData(Constants.GET_INVENTORY_MEASUREMENTS_UNITS, - Constants.getStorePayload()) + .getResponseAuth( + Constants.getMeasuringUnit, Constants.getStorePayload()) .then((value) { - final response = MeasurementUnitModel.fromJson(value); - if (response.success) { - items.addAll(response.measurementUnits); + final response = MeasuringUnit.fromJson(value); + if (response.success) { + items.addAll(response.measurementUnits); + if (isEdit && !isIngredient) { + final name = items + .singleWhere((element) => element.name == storeItem.measurement) + .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; } @@ -619,9 +560,13 @@ class AddProductViewModel with ChangeNotifier { 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(); @@ -638,7 +583,7 @@ class AddProductViewModel with ChangeNotifier { void setSelectedCategory(ItemCategory? data) { if (data != null) { selectedCategory = data; - storeItem.productId = data.id; + storeItem.productIdSt = data.id; } } @@ -650,19 +595,21 @@ class AddProductViewModel with ChangeNotifier { void setIngredient(AddIngredient? data) { if (data != null) { - unitsController.add(data.defaultSalePrice.toString()); - storeItem.ingredients!.add(data); + // unitsController.add(data.defaultSalePrice.toString()); + 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(); @@ -670,26 +617,30 @@ 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); + // unitsController.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; - + // salePriceIncludeTax = value; + storeItem.price = double.parse(value); int percentage = 15; double tax = (double.parse(value) * percentage) / 100; - salePriceExclTax = (double.parse(value) - tax).toStringAsFixed(2); + // salePriceExclTax = (double.parse(value) - tax).toStringAsFixed(2); + + storeItem.salePriceExclusiveTax = (double.parse(value) - tax); } notifyListeners(); @@ -697,13 +648,59 @@ class AddProductViewModel with ChangeNotifier { void setIsUnlimitedQuantity(bool? value) { storeItem.isUnlimitedQuantity = value ?? false; - print(storeItem.isUnlimitedQuantity); + // print(storeItem.isUnlimitedQuantity); notifyListeners(); } void setQuantity(String value) { storeItem.totalAddedQuantity = int.parse(value); - quantityController = value; - print(storeItem.totalAddedQuantity); + // quantityController = value; + // print(storeItem.totalAddedQuantity); + } + + Future getProductById(String itemId) async { + await APIManager() + .getResponseAuth("${Constants.GET_PRODUCT_BY_ID}/$itemId") + .then((value) { + final response = ProductById.fromJson(value); + + 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)); + } + // for (var item in storeItem.ingredients) { + // unitsController.add(item.defaultSalePrice!.toString()); + // } + isLoadingFirst = false; + } + }).onError((error, stackTrace) { + isLoadingFirst = false; + }); + } + + void removeIngredient(int position) { + //unitsController.removeAt(position); + storeItem.ingredients.removeAt(position); + notifyListeners(); + } + + void updateIngredientUnitPrice(int position, String value) { + if (value.isNotEmpty) { + storeItem.ingredients[position].price = int.parse(value); + } + } + + void setMeasurementUnitProduct(MeasurementUnit? data) { + if (data != null) { + selectedMeasurementUnit = data; + storeItem.measurementUnit = data.name!; + } else { + storeItem.measurementUnit = ''; + } } } diff --git a/lib/application/views/inventorymodule/productviews/viewModels/ProductViewModel.dart b/lib/application/views/inventorymodule/productviews/viewModels/ProductViewModel.dart index f70fc85..aa211ec 100644 --- a/lib/application/views/inventorymodule/productviews/viewModels/ProductViewModel.dart +++ b/lib/application/views/inventorymodule/productviews/viewModels/ProductViewModel.dart @@ -1,7 +1,11 @@ +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/Products/GetProductResponse.dart'; import 'package:wosull/application/model/Products/ItemProductModel.dart'; +import 'package:wosull/application/model/Products/SearchProductResponse.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'; @@ -10,11 +14,11 @@ import 'package:wosull/application/utils/CRUDOperatoinState.dart'; import 'package:wosull/application/utils/Constants.dart'; class ProductViewModel with ChangeNotifier { - bool _isFirstLoadRunning = true; + bool _isFirstLoadRunning = false; bool get isFirstLoadRunning => _isFirstLoadRunning; int limit = 10; - String selectedCategoryId = ""; + String selectedCategoryId = "All"; List _dataList = []; List _filteredList = []; @@ -30,11 +34,11 @@ class ProductViewModel with ChangeNotifier { DataState get dataState => _dataState; bool _didLastLoad = false; - bool _isLoading = false; + bool _isLoading = true; bool get isLoading => _isLoading; String productId = ""; - late ItemCategory selectedCategoryDropDown; + String selectedCategoryName = 'All'; List categories = []; CRUDOperationState _crudOperationState = CRUDOperationState.uninitialized; @@ -50,34 +54,34 @@ class ProductViewModel with ChangeNotifier { categories.addAll(itemCategoryResponse.categories); if (categories.isNotEmpty) { selectedCategoryId = categories.first.id ?? ''; - selectedCategoryDropDown = categories.first; + // selectedCategoryDropDown = categories.first; _isFirstLoadRunning = false; getSubProducts(selectedCategoryId); } } else { selectedCategoryId = ""; - selectedCategoryDropDown = ItemCategory( - name: "Choose", - id: '', - isVisibleInStore: false, - createdAt: '', - updatedAt: '', - description: '', - arabicName: '', - store_id: [], - image_url: '', - ); + // selectedCategoryDropDown = ItemCategory( + // name: "Choose", + // id: '', + // isVisibleInStore: false, + // createdAt: '', + // updatedAt: '', + // description: '', + // arabicName: '', + // store_id: [], + // image_url: '', + // ); _isLoading = false; _isFirstLoadRunning = false; } } void getSubProducts(String categoryID, {bool isRefresh = false}) async { - _isLoading = true; - if (isRefresh) { - _isLoading = true; - } - notifyListeners(); + // _isLoading = true; + // if (isRefresh) { + // _isLoading = true; + // } + // notifyListeners(); Map data = { 'store_id': sharedPrefs.storeId, 'category_id': categoryID, @@ -120,7 +124,7 @@ class ProductViewModel with ChangeNotifier { 'page': _currentPageNumber, 'limit': this.limit }; - + print(jsonEncode(data)); try { if (_didLastLoad) { _dataState = DataState.noMoreData; @@ -128,7 +132,7 @@ class ProductViewModel with ChangeNotifier { await APIManager() .fetchData(Constants.GET_ITEMS_URL, data) .then((result) { - final value = StoreItemsResponse.fromJson(result); + final value = GetProductResponse.fromJson(result); if (_dataState == DataState.refreshing) { _filteredList.clear(); _dataList.clear(); @@ -147,6 +151,7 @@ class ProductViewModel with ChangeNotifier { _isLoading = false; notifyListeners(); }).onError((error, stackTrace) { + print(stackTrace.toString()); _dataState = DataState.error; _isLoading = false; notifyListeners(); @@ -237,8 +242,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..7badd87 --- /dev/null +++ b/lib/application/views/inventorymodule/productviews/views/ProductListView.dart @@ -0,0 +1,308 @@ +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/Utils.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'; + +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() + : Container( + padding: const EdgeInsets.only(left: 8, right: 8), + height: 48, + color: MyColors.containerBackColor, + 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: 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(lang(context).name), + const SizedBox( + height: 8, + ), + HeadingText(lang(context).category), + const SizedBox( + height: 8, + ), + HeadingText(lang(context).price), + const SizedBox( + height: 8, + ), + HeadingText(lang(context).status), + const SizedBox( + height: 8, + ), + HeadingText(lang(context).updated_on), + ], + )), + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.end, + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + ValueText(item.name), + AppSpaces.verticalMedium, + ValueText(selectedCategoryName), + AppSpaces.verticalMedium, + ValueText(item.price.toString()), + AppSpaces.verticalMedium, + Row( + mainAxisAlignment: + MainAxisAlignment.end, + crossAxisAlignment: + CrossAxisAlignment.end, + children: [ + CustomSwitch( + value: item.isItemInStock, + onToggle: (value) { + onUpdate(item, value); + }, + ) + ], + ), + AppSpaces.verticalMedium, + ValueText( + DataTimeFormat.getFormatDate( + item.updatedAt)), + ], + )), + ], + ) + ], + ), + )), + getPopUpBuilder(context, 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(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); + } + } + + PopupMenuButton getPopUpBuilder( + BuildContext context, StoreItems item) { + return PopupMenuButton( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + 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, item), + ); + } +} 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..6f83991 --- /dev/null +++ b/lib/application/views/inventorymodule/stockReturn/viewmodels/NewStockReturnViewModel.dart @@ -0,0 +1,474 @@ +import 'package:flutter/material.dart'; +import 'package:wosull/application/ViewModel/InventoryViewModel.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/SimpleResponsModel.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/network/APIManager.dart'; +import 'package:wosull/application/utils/CRUDOperatoinState.dart'; +import 'package:wosull/application/utils/Constants.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 var stockReturn; + var returnCharge = ReturnStockCharges(amount: '', name: ''); + var fetchDataHelper = InventoryViewModel(); + + bool _isLoading = false; + + bool get isLoading => _isLoading; + + var _crudOperation = CRUDOperationState.uninitialized; + + CRUDOperationState get crudOperation => _crudOperation; + + 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 { + addEmptyService(); + stockReturn.products = []; + stockReturn.charges = []; + } + + 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 APIManager() + .fetchData(Constants.addStockReturn, stockReturn.toJson()) + .then((value) { + final response = SimpleResponseModel.fromJson(value); + 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()); + 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 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> 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> 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> 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/inventorymodule/stockReturn/views/NewStockReturnVC.dart b/lib/application/views/inventorymodule/stockReturn/views/NewStockReturnVC.dart index e69de29..1d19c6d 100644 --- a/lib/application/views/inventorymodule/stockReturn/views/NewStockReturnVC.dart +++ b/lib/application/views/inventorymodule/stockReturn/views/NewStockReturnVC.dart @@ -0,0 +1,1148 @@ +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/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/CustomTextButtonIcon.dart'; +import 'package:wosull/widgets/CustomTextFieldForm.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'; + +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 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( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + flex: 2, + child: Container( + 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)! + .quantity, + ), + ), + ), + 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)! + .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( + '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: 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: 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: [ + 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: [ + 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: [ + const Expanded(child: Text('')), + Expanded( + child: Row( + children: [ + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: Text( + AppLocalizations.of(context)!.total_amount, + style: ThemeText.textStyleAmountValue, + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: Text( + viewModel.getTotalProductsPrice(), + style: ThemeText.textStyleAmountValue, + ), + )), + 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( + 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.dropDownStyle(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( + 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.dropDownStyle(hint: 'Choose'), + ); + } else { + return AppLoader(); + } + }); + } + + Widget getDiscountsTypes(int position) { + return DropdownSearch( + enabled: !widget.isView, + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + 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.dropDownStyle(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 Container( + padding: const EdgeInsets.all(4), + decoration: const BoxDecoration( + border: Border( + right: BorderSide(width: 1.0, color: MyColors.fillColorGray2), + ), + ), + child: 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( + 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.dropDownStyle(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( + 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.dropDownStyle(hint: 'Choose'), + ); + } + + getSingleItemTaxWidget(int position) { + return Center( + child: ValueText( + viewModel.stockReturn.products![position].tax!.toStringAsFixed(2)), + ); + } + + getSingleItemAmountWidget(int position) { + return Center( + child: ValueText( + 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: viewModel.stockReturn.stockReturnDate ?? 'dd/mm/yyyy', + 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( + 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( + 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.dropDownStyle(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( + 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: [ + const Expanded(child: Text('')), + Expanded( + child: Row( + children: [ + Expanded( + child: CustomTextFieldForm( + height: 42, + key: Key(viewModel.returnCharge.name), + initialValue: viewModel.returnCharge.name, + onChanged: (String value) { + viewModel.returnCharge.name = value; + }, + hintText: 'Charge', + )), + AppSpaces.horizontalMedium, + Expanded( + child: CustomTextFieldForm( + keyboardType: TextInputType.number, + height: 42, + key: Key(viewModel.returnCharge.amount), + 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: [ + const Expanded(child: Text('')), + Expanded( + child: Row( + children: [ + Expanded( + child: CustomTextFieldForm( + readOnly: widget.isView, + height: 42, + initialValue: viewModel.stockReturn.charges![position].name, + onChanged: (String value) { + viewModel.stockReturn.charges![position].name = value; + }, + hintText: 'Charge', + )), + AppSpaces.horizontalMedium, + Expanded( + child: CustomTextFieldForm( + height: 42, + 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 index 42937e2..9679176 100644 --- a/lib/application/views/inventorymodule/stockReturn/views/StockReturnVC.dart +++ b/lib/application/views/inventorymodule/stockReturn/views/StockReturnVC.dart @@ -5,6 +5,7 @@ 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'; @@ -97,9 +98,15 @@ class _StockReturnVCState extends BaseStatefulState { StockReturnListView( data: data, isPortrait: isPortrait, - onDelete: (stock) {}, - onView: (stock) {}, - onEdit: (stock) {}), + onDelete: (stock) { + showDeletePopUp(stock); + }, + onView: (stock) { + openStockReturn(true, stock, true); + }, + onEdit: (stock) { + openStockReturn(true, stock, false); + }), if (viewModel.dataState == DataState.moreFetching) AppLoader(), ], ); @@ -124,7 +131,7 @@ class _StockReturnVCState extends BaseStatefulState { if (!mounted) return; bool isDelete = result; if (isDelete) { - _delete(stock.id); + _delete(stock.id!); } } @@ -142,8 +149,26 @@ class _StockReturnVCState extends BaseStatefulState { textColor: MyColors.blueThemeColor, backGroundColor: MyColors.backColorBlue50, height: 38, - onPressed: () {}, + 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 index d66f203..daf6167 100644 --- a/lib/application/views/inventorymodule/stockReturn/widgets/StockReturnListView.dart +++ b/lib/application/views/inventorymodule/stockReturn/widgets/StockReturnListView.dart @@ -121,19 +121,19 @@ class StockReturnListView extends StatelessWidget { children: [ ValueText(stock.uniqueId.toString()), AppSpaces.verticalMedium, - ValueText(stock.supplierId.name ?? ''), + ValueText(stock.supplierId!.name ?? ''), AppSpaces.verticalMedium, ValueText(DataTimeFormat.getFormatDate( - stock.stockReturnDate)), + stock.stockReturnDate!)), AppSpaces.verticalMedium, - ValueText( - stock.totalAmount.toStringAsFixed(2)), + ValueText(stock.totalAmount! + .toStringAsFixed(2)), AppSpaces.verticalMedium, ValueText(DataTimeFormat.getFormatDate( - stock.createdAt)), + stock.createdAt!)), AppSpaces.verticalMedium, ValueText(DataTimeFormat.getFormatDate( - stock.updatedAt)), + stock.updatedAt!)), ], )), ], @@ -184,19 +184,19 @@ class StockReturnListView extends StatelessWidget { Expanded( child: ValueText(stock.uniqueId.toString())), Expanded( - child: ValueText(stock.supplierId.name ?? '')), + child: ValueText(stock.supplierId!.name ?? '')), Expanded( child: ValueText(DataTimeFormat.getFormatDate( - stock.stockReturnDate))), + stock.stockReturnDate!))), Expanded( child: ValueText( - stock.totalAmount.toStringAsFixed(2))), + stock.totalAmount!.toStringAsFixed(2))), Expanded( child: ValueText(DataTimeFormat.getFormatDate( - stock.createdAt))), + stock.createdAt!))), Expanded( child: ValueText(DataTimeFormat.getFormatDate( - stock.updatedAt))), + stock.updatedAt!))), Expanded( child: Padding( padding: const EdgeInsets.all(4), diff --git a/lib/application/views/salesandordermodule/views/invoiceModule/NewInvoiceVC.dart b/lib/application/views/salesandordermodule/views/invoiceModule/NewInvoiceVC.dart index b1424cd..4fdd900 100644 --- a/lib/application/views/salesandordermodule/views/invoiceModule/NewInvoiceVC.dart +++ b/lib/application/views/salesandordermodule/views/invoiceModule/NewInvoiceVC.dart @@ -18,8 +18,10 @@ 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/CustomTextButtonIcon.dart'; @@ -63,6 +65,7 @@ class _NewInvoiceVCState extends BaseStatefulState { Widget build(BuildContext context) { viewModel = context.watch(); return Scaffold( + backgroundColor: MyColors.fillColor, resizeToAvoidBottomInset: true, appBar: CustomAppBar( heading: widget.isEdit @@ -320,7 +323,16 @@ class _NewInvoiceVCState extends BaseStatefulState { return Container( padding: const EdgeInsets.fromLTRB(8, 0, 0, 8), - color: MyColors.containerBackColor, + 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( crossAxisAlignment: CrossAxisAlignment.start, @@ -490,13 +502,11 @@ class _NewInvoiceVCState extends BaseStatefulState { ), ), getDiscountsTypes( - context, position), - getDiscounts( - context, position), - getTaxWidget( - context, position), + position), + getDiscounts(position), + getTaxWidget(position), getMeasurementWidget( - context, position), + position), PortraitContainer( child: getSingleItemTaxWidget( @@ -556,17 +566,15 @@ class _NewInvoiceVCState extends BaseStatefulState { ), ), Expanded( - child: getDiscountsTypes( - context, position)), + child: + getDiscountsTypes(position)), Expanded( - child: getDiscounts( - context, position)), + child: getDiscounts(position)), Expanded( - child: getTaxWidget( - context, position)), + child: getTaxWidget(position)), Expanded( child: getMeasurementWidget( - context, position)), + position)), ChildContainer( width: 44, child: getSingleItemTaxWidget( @@ -838,7 +846,7 @@ class _NewInvoiceVCState extends BaseStatefulState { } } - Widget getMeasurementWidget(BuildContext context, int position) { + Widget getMeasurementWidget(int position) { return FutureBuilder( future: viewModel.getMeasurement(), builder: (c, s) { @@ -866,7 +874,7 @@ class _NewInvoiceVCState extends BaseStatefulState { }); } - Widget getTaxWidget(BuildContext context, int position) { + Widget getTaxWidget(int position) { return FutureBuilder( future: viewModel.getTax(), builder: (c, s) { @@ -896,7 +904,7 @@ class _NewInvoiceVCState extends BaseStatefulState { }); } - Widget getCompanyWidget(BuildContext context) { + Widget getCompanyWidget() { return FutureBuilder( future: viewModel.getCompany(), builder: (c, s) { @@ -924,7 +932,7 @@ class _NewInvoiceVCState extends BaseStatefulState { }); } - Widget getDiscountsTypes(BuildContext context, int position) { + Widget getDiscountsTypes(int position) { return ChildContainer( child: DropdownSearch( clearButtonProps: ThemeDropDown.clearButton, @@ -943,7 +951,7 @@ class _NewInvoiceVCState extends BaseStatefulState { ); } - Widget getDiscounts(BuildContext context, int position) { + Widget getDiscounts(int position) { if (viewModel.addInvoice.products[position].discountType == null) { return Container( height: 42, @@ -1160,7 +1168,7 @@ class _NewInvoiceVCState extends BaseStatefulState { hint: 'Choose ${viewModel.selectedInvoiceFor}', ), AppSpaces.verticalSmall, - getCompanyWidget(context) + getCompanyWidget() ], ); } @@ -1270,27 +1278,9 @@ class _NewInvoiceVCState extends BaseStatefulState { } 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: () { - viewModel.onRemoveItem(position); - }), - ), - )); + return CustomRemoveItemButton(onPressed: () { + viewModel.onRemoveItem(position); + }); } getSelectedCurrencyWidget() { @@ -1331,25 +1321,9 @@ class _NewInvoiceVCState extends BaseStatefulState { } getAddItemButtonWidget() { - return 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.onAddService(); - }), - ), - ); + return CustomAddButton(onPressed: () { + viewModel.onAddService(); + }); } getItemsWidget(int position) { diff --git a/lib/application/views/salesandordermodule/views/quotataionModule/NewQuotationsVC.dart b/lib/application/views/salesandordermodule/views/quotataionModule/NewQuotationsVC.dart index 7addb17..a886f5c 100644 --- a/lib/application/views/salesandordermodule/views/quotataionModule/NewQuotationsVC.dart +++ b/lib/application/views/salesandordermodule/views/quotataionModule/NewQuotationsVC.dart @@ -2051,7 +2051,7 @@ class _NewQuotationsVCState extends BaseStatefulState { Future> getTax() async { var items = []; - await viewModel + await APIManager() .getResponse(Constants.GET_WOSUL_SETTINGS) .then((value) { final response = WosulSettings.fromJson(value); diff --git a/lib/helpers/ThemeDropDown.dart b/lib/helpers/ThemeDropDown.dart index 0866764..8cc49df 100644 --- a/lib/helpers/ThemeDropDown.dart +++ b/lib/helpers/ThemeDropDown.dart @@ -1,8 +1,29 @@ import 'package:dropdown_search/dropdown_search.dart'; import 'package:flutter/material.dart'; import 'package:wosull/application/theme/MyColors.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, diff --git a/lib/helpers/ThemeText.dart b/lib/helpers/ThemeText.dart index 0ca8188..d3c3d03 100644 --- a/lib/helpers/ThemeText.dart +++ b/lib/helpers/ThemeText.dart @@ -123,7 +123,7 @@ abstract class ThemeText { static const TextStyle textStyleValue = TextStyle( fontStyle: FontStyle.normal, fontFamily: MyFonts.Medium, - fontSize: 10, + fontSize: 11, fontWeight: FontWeight.w100, color: MyColors.textColorBlack20); diff --git a/lib/objectbox-model.json b/lib/objectbox-model.json index 79bf2ae..5c0237a 100644 --- a/lib/objectbox-model.json +++ b/lib/objectbox-model.json @@ -5,7 +5,7 @@ "entities": [ { "id": "1:6932070486419484075", - "lastPropertyId": "32:4971480019915069043", + "lastPropertyId": "33:3192907363118089052", "name": "AddIngredient", "properties": [ { @@ -168,6 +168,11 @@ "id": "32:4971480019915069043", "name": "id", "type": 9 + }, + { + "id": "33:3192907363118089052", + "name": "quantity", + "type": 9 } ], "relations": [] diff --git a/lib/objectbox.g.dart b/lib/objectbox.g.dart index c77c3da..b615dff 100644 --- a/lib/objectbox.g.dart +++ b/lib/objectbox.g.dart @@ -20,6 +20,7 @@ import 'application/model/DeliveryPartner/GetDeliveryPartner.dart'; import 'application/model/DeliveryPartner/ItemsDeliveryPartner.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/ingredients/AddIngredient.dart'; @@ -35,7 +36,7 @@ final _entities = [ ModelEntity( id: const IdUid(1, 6932070486419484075), name: 'AddIngredient', - lastPropertyId: const IdUid(32, 4971480019915069043), + lastPropertyId: const IdUid(33, 3192907363118089052), flags: 0, properties: [ ModelProperty( @@ -197,6 +198,11 @@ final _entities = [ id: const IdUid(32, 4971480019915069043), name: 'id', type: 9, + flags: 0), + ModelProperty( + id: const IdUid(33, 3192907363118089052), + name: 'quantity', + type: 9, flags: 0) ], relations: [], @@ -1320,7 +1326,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(34); fbb.addInt64(0, object.obid); fbb.addOffset(1, nameOffset); fbb.addOffset(2, descriptionOffset); @@ -1353,6 +1360,7 @@ ModelDefinition getObjectBoxModel() { fbb.addOffset(29, measuringUnitOffset); fbb.addBool(30, object.checked); fbb.addOffset(31, idOffset); + fbb.addOffset(32, quantityOffset); fbb.finish(fbb.endTable()); return object.obid; }, @@ -1366,6 +1374,8 @@ 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 categoryIdParam = const fb.StringReader(asciiOptimization: true) .vTableGet(buffer, rootOffset, 12, ''); final productIdParam = const fb.StringReader(asciiOptimization: true) @@ -1435,6 +1445,7 @@ ModelDefinition getObjectBoxModel() { name: nameParam, description: descriptionParam, value: valueParam, + quantity: quantityParam, categoryId: categoryIdParam, productId: productIdParam, details: detailsParam, @@ -2146,13 +2157,13 @@ 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; }), @@ -2799,6 +2810,10 @@ class AddIngredient_ { /// see [AddIngredient.id] static final id = QueryStringProperty(_entities[0].properties[31]); + + /// see [AddIngredient.quantity] + static final quantity = + QueryStringProperty(_entities[0].properties[32]); } /// [ComboProduct] entity fields to define ObjectBox queries. diff --git a/lib/widgets/CustomAddButton.dart b/lib/widgets/CustomAddButton.dart index 5f1441c..aa7e443 100644 --- a/lib/widgets/CustomAddButton.dart +++ b/lib/widgets/CustomAddButton.dart @@ -3,8 +3,14 @@ import 'package:wosull/application/theme/MyColors.dart'; class CustomAddButton extends StatelessWidget { final void Function() onPressed; + Color? backgroundColor; + Color? iconColor; - const CustomAddButton({super.key, required this.onPressed}); + CustomAddButton( + {super.key, + required this.onPressed, + this.backgroundColor, + this.iconColor}); @override Widget build(BuildContext context) { @@ -13,14 +19,14 @@ class CustomAddButton extends StatelessWidget { margin: const EdgeInsets.all(5), width: 32, height: 32, - decoration: const BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(4)), - color: MyColors.fillColorGray2), + decoration: BoxDecoration( + borderRadius: const BorderRadius.all(Radius.circular(4)), + color: backgroundColor ?? MyColors.fillColorGray2), child: IconButton( - icon: const Icon( + icon: Icon( size: 14, Icons.add, - color: MyColors.textColorBlack, + color: iconColor ?? MyColors.textColorBlack, ), onPressed: onPressed), ), diff --git a/lib/widgets/ItemCategoryDropdown.dart b/lib/widgets/ItemCategoryDropdown.dart index 089c4ab..f28504d 100644 --- a/lib/widgets/ItemCategoryDropdown.dart +++ b/lib/widgets/ItemCategoryDropdown.dart @@ -40,12 +40,12 @@ class ItemCategoryDropdown extends StatelessWidget { if (s.hasData) { var itemsList = s.data ?? []; return DropdownSearch( - dropdownButtonProps: ThemeDropDown.dropdownButtonProps, - popupProps: const PopupProps.menu( - fit: FlexFit.loose, - constraints: BoxConstraints(maxHeight: 300), - ), clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), selectedItem: selectedCategoryDropDown, items: itemsList, itemAsString: (ItemCategory u) => u.name, 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, + ); + } +} From 8bcd9b553d2651ce43828d2492abe45624a4e552 Mon Sep 17 00:00:00 2001 From: waqasYeepeey Date: Fri, 29 Sep 2023 14:24:59 +0500 Subject: [PATCH 05/11] 'inventory search chaanges' --- .../SearchStockTransferResponse.dart | 17 +++ .../SearchSubCategoryResponse.dart | 18 +++ lib/application/theme/MyColors.dart | 9 +- lib/application/utils/Constants.dart | 4 +- .../InventoryCategoriesModule.dart | 2 +- .../widgets/CategoryListView.dart | 61 +++++---- .../comboviews/InventoryComboVC.dart | 10 +- .../InventoryDeliveryPartnerPriceVC.dart | 10 +- .../ingredientsViews/IngredientsVC.dart | 20 ++- .../viewModels/IngredientViewModel.dart | 40 ++++++ .../InventoryMeasurementVC.dart | 8 +- .../views/NewModifierOptionVC.dart | 15 ++- .../AddNewInventoryProductVC.dart | 120 +++++------------- .../productviews/InventoryProductVC.dart | 2 +- .../viewModels/AddProductViewModel.dart | 15 +-- .../viewModels/ProductViewModel.dart | 2 +- .../InventoryStockTransferVC.dart | 20 ++- .../viewModels/StockTransferViewModel.dart | 41 ++++++ .../subCategoryViews/SubCategoryVC.dart | 22 +++- .../viewModels/SubCategoryViewModel.dart | 35 +++++ lib/helpers/ThemeDropDown.dart | 4 +- lib/widgets/CustomPopuoMenuButton.dart | 24 ++++ lib/widgets/CustomTextFieldForm.dart | 3 +- lib/widgets/ItemCategoryDropdown.dart | 2 +- lib/widgets/SearchBox.dart | 12 +- 25 files changed, 335 insertions(+), 181 deletions(-) create mode 100644 lib/application/model/StockTransfer/SearchStockTransferResponse.dart create mode 100644 lib/application/model/inventory/subCategory/SearchSubCategoryResponse.dart create mode 100644 lib/widgets/CustomPopuoMenuButton.dart 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/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/theme/MyColors.dart b/lib/application/theme/MyColors.dart index 269edc1..6d552db 100644 --- a/lib/application/theme/MyColors.dart +++ b/lib/application/theme/MyColors.dart @@ -120,7 +120,14 @@ class MyColors { labelStyle: ThemeText.textStyleValue, hintStyle: ThemeText.textStyleValue, isDense: true, - contentPadding: const EdgeInsets.only(left: 8), // Added + 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 diff --git a/lib/application/utils/Constants.dart b/lib/application/utils/Constants.dart index f1e08f4..68143b8 100644 --- a/lib/application/utils/Constants.dart +++ b/lib/application/utils/Constants.dart @@ -66,7 +66,7 @@ class Constants { 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'; @@ -152,6 +152,7 @@ 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'; @@ -159,6 +160,7 @@ class Constants { static const GET_ORDER_BY_STATUS = 'api/store/get_order_by_status'; static const UPDATE_CASHIER_ORDER = 'api/store/update_cashier_orders'; + 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'; diff --git a/lib/application/views/inventorymodule/categoryviews/InventoryCategoriesModule.dart b/lib/application/views/inventorymodule/categoryviews/InventoryCategoriesModule.dart index a7fbf94..cbe0903 100644 --- a/lib/application/views/inventorymodule/categoryviews/InventoryCategoriesModule.dart +++ b/lib/application/views/inventorymodule/categoryviews/InventoryCategoriesModule.dart @@ -141,7 +141,7 @@ class _InventoryCategoriesModuleState width: SizerUtil.deviceType == DeviceType.mobile ? 200 - : 240, + : 200, height: 48, child: SearchBox( onEditingDone: (text) { diff --git a/lib/application/views/inventorymodule/categoryviews/widgets/CategoryListView.dart b/lib/application/views/inventorymodule/categoryviews/widgets/CategoryListView.dart index 0f72f18..1e09ec8 100644 --- a/lib/application/views/inventorymodule/categoryviews/widgets/CategoryListView.dart +++ b/lib/application/views/inventorymodule/categoryviews/widgets/CategoryListView.dart @@ -3,6 +3,8 @@ 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/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'; @@ -109,36 +111,8 @@ class CategoryListView 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, data[position], position), - ), + child: ActionPopUpContainer( + child: getMenuBuilder(context, position), ), ), )) @@ -154,7 +128,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 +137,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/InventoryComboVC.dart b/lib/application/views/inventorymodule/comboviews/InventoryComboVC.dart index bceaedd..b4f48be 100644 --- a/lib/application/views/inventorymodule/comboviews/InventoryComboVC.dart +++ b/lib/application/views/inventorymodule/comboviews/InventoryComboVC.dart @@ -101,10 +101,10 @@ class _InventoryComboVCState extends BaseStatefulState { height: 48, child: SearchBox( onEditingDone: (text) { - // filterSearchResults(text); + filterSearchResults(text); }, onChanged: (text) { - // filterSearchResults(text); + filterSearchResults(text); }, hint: AppLocalizations.of(context)!.search, ), @@ -137,14 +137,14 @@ class _InventoryComboVCState extends BaseStatefulState { SizedBox( width: SizerUtil.deviceType == DeviceType.mobile ? 200 - : 240, + : 200, height: 48, child: SearchBox( onEditingDone: (text) { - // filterSearchResults(text); + filterSearchResults(text); }, onChanged: (text) { - // filterSearchResults(text); + filterSearchResults(text); }, hint: AppLocalizations.of(context)!.search, ), diff --git a/lib/application/views/inventorymodule/deliveryPartnerViews/InventoryDeliveryPartnerPriceVC.dart b/lib/application/views/inventorymodule/deliveryPartnerViews/InventoryDeliveryPartnerPriceVC.dart index e058f85..dd2a776 100644 --- a/lib/application/views/inventorymodule/deliveryPartnerViews/InventoryDeliveryPartnerPriceVC.dart +++ b/lib/application/views/inventorymodule/deliveryPartnerViews/InventoryDeliveryPartnerPriceVC.dart @@ -74,10 +74,10 @@ class _InventoryDeliveryPartnerPriceVCState Flexible( child: SearchBox( onEditingDone: (text) { - // filterSearchResults(text); + filterSearchResults(text); }, onChanged: (text) { - // filterSearchResults(text); + filterSearchResults(text); }, hint: AppLocalizations.of(context)!.search, ), @@ -107,14 +107,14 @@ class _InventoryDeliveryPartnerPriceVCState SizedBox( width: SizerUtil.deviceType == DeviceType.mobile ? 200 - : 240, + : 200, height: 48, child: SearchBox( onEditingDone: (text) { - // filterSearchResults(text); + filterSearchResults(text); }, onChanged: (text) { - // filterSearchResults(text); + filterSearchResults(text); }, hint: AppLocalizations.of(context)!.search, ), diff --git a/lib/application/views/inventorymodule/ingredientsViews/IngredientsVC.dart b/lib/application/views/inventorymodule/ingredientsViews/IngredientsVC.dart index e5b4638..d6fbfdf 100644 --- a/lib/application/views/inventorymodule/ingredientsViews/IngredientsVC.dart +++ b/lib/application/views/inventorymodule/ingredientsViews/IngredientsVC.dart @@ -76,14 +76,14 @@ class _IngredientsVCState extends State { : SizedBox( width: SizerUtil.deviceType == DeviceType.mobile ? 200 - : 240, + : 200, height: 48, child: SearchBox( onEditingDone: (text) { - // filterSearchResults(text); + filterSearchResults(text); }, onChanged: (text) { - // filterSearchResults(text); + filterSearchResults(text); }, hint: AppLocalizations.of(context)!.search, ), @@ -99,10 +99,10 @@ class _IngredientsVCState extends State { height: 48, child: SearchBox( onEditingDone: (text) { - // filterSearchResults(text); + filterSearchResults(text); }, onChanged: (text) { - // filterSearchResults(text); + filterSearchResults(text); }, hint: AppLocalizations.of(context)!.search, ), @@ -292,6 +292,16 @@ class _IngredientsVCState extends State { ); } + Future filterSearchResults(String query) async { + if (query.isNotEmpty) { + viewModel.search(searchValue: query); + } else { + Future.delayed(const Duration(milliseconds: 700), () { + viewModel.search(searchValue: ""); + }); + } + } + bool _scrollNotification() { if (!viewModel.isLoading && _controller.position.extentAfter < 300) { viewModel.fetch(limit: viewModel.limit); diff --git a/lib/application/views/inventorymodule/ingredientsViews/viewModels/IngredientViewModel.dart b/lib/application/views/inventorymodule/ingredientsViews/viewModels/IngredientViewModel.dart index d687f6a..89a5a52 100644 --- a/lib/application/views/inventorymodule/ingredientsViews/viewModels/IngredientViewModel.dart +++ b/lib/application/views/inventorymodule/ingredientsViews/viewModels/IngredientViewModel.dart @@ -11,6 +11,10 @@ class IngredientViewModel with ChangeNotifier { List _filteredList = []; List get filteredList => _filteredList; + + List _dataList = []; + + List get dataList => _dataList; int limit = 10; bool _didLastLoad = false; bool _isLoading = false; @@ -56,9 +60,11 @@ class IngredientViewModel with ChangeNotifier { final value = GetIngredientModel.fromJson(result); if (_dataState == DataState.refreshing) { _filteredList.clear(); + _dataList.clear(); } if (value.success) { _filteredList.addAll(value.ingredient); + _dataList.addAll(value.ingredient); if (value.ingredient.length < this.limit) { _didLastLoad = true; } else { @@ -82,6 +88,40 @@ 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 APIManager() + .fetchData(Constants.searchIngredients, data) + .then((result) { + final value = GetIngredientModel.fromJson(result); + _filteredList.clear(); + if (value.success) { + _filteredList.addAll(value.ingredient); + } + _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() diff --git a/lib/application/views/inventorymodule/measurementviews/InventoryMeasurementVC.dart b/lib/application/views/inventorymodule/measurementviews/InventoryMeasurementVC.dart index fe30410..adccd13 100644 --- a/lib/application/views/inventorymodule/measurementviews/InventoryMeasurementVC.dart +++ b/lib/application/views/inventorymodule/measurementviews/InventoryMeasurementVC.dart @@ -107,10 +107,10 @@ class _InventoryMeasurementVCState height: 48, child: SearchBox( onEditingDone: (text) { - // filterSearchResults(text); + filterSearchResults(text); }, onChanged: (text) { - // filterSearchResults(text); + filterSearchResults(text); }, hint: AppLocalizations.of(context)!.search, ), @@ -162,10 +162,10 @@ class _InventoryMeasurementVCState height: 48, child: SearchBox( onEditingDone: (text) { - // filterSearchResults(text); + filterSearchResults(text); }, onChanged: (text) { - // filterSearchResults(text); + filterSearchResults(text); }, hint: AppLocalizations.of(context)!.search, ), diff --git a/lib/application/views/inventorymodule/modiferOption/views/NewModifierOptionVC.dart b/lib/application/views/inventorymodule/modiferOption/views/NewModifierOptionVC.dart index cb4fd8d..0b47c99 100644 --- a/lib/application/views/inventorymodule/modiferOption/views/NewModifierOptionVC.dart +++ b/lib/application/views/inventorymodule/modiferOption/views/NewModifierOptionVC.dart @@ -180,9 +180,10 @@ class _NewModifierOptionVCState extends State { return DropdownSearch( enabled: !widget.isView, dropdownButtonProps: ThemeDropDown.dropdownButtonProps, - popupProps: const PopupProps.menu( + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, fit: FlexFit.loose, - constraints: BoxConstraints(maxHeight: 300), + constraints: const BoxConstraints(maxHeight: 300), ), clearButtonProps: ThemeDropDown.clearButton, selectedItem: viewModel.selectedModifier, @@ -209,9 +210,10 @@ class _NewModifierOptionVCState extends State { return DropdownSearch( enabled: !widget.isView, dropdownButtonProps: ThemeDropDown.dropdownButtonProps, - popupProps: const PopupProps.menu( + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, fit: FlexFit.loose, - constraints: BoxConstraints(maxHeight: 300), + constraints: const BoxConstraints(maxHeight: 300), ), clearButtonProps: ThemeDropDown.clearButton, //selectedItem: selectedCategoryDropDown, @@ -375,9 +377,10 @@ class _NewModifierOptionVCState extends State { enabled: !widget.isView, dropdownButtonProps: ThemeDropDown.dropdownButtonProps, selectedItem: viewModel.selectedMeasurementUnits[position], - popupProps: const PopupProps.menu( + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, fit: FlexFit.loose, - constraints: BoxConstraints(maxHeight: 300), + constraints: const BoxConstraints(maxHeight: 300), ), clearButtonProps: ThemeDropDown.clearButton, items: itemsList, diff --git a/lib/application/views/inventorymodule/productviews/AddNewInventoryProductVC.dart b/lib/application/views/inventorymodule/productviews/AddNewInventoryProductVC.dart index 035cc23..b19e6ed 100644 --- a/lib/application/views/inventorymodule/productviews/AddNewInventoryProductVC.dart +++ b/lib/application/views/inventorymodule/productviews/AddNewInventoryProductVC.dart @@ -5,6 +5,7 @@ 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/ingredients/AddIngredient.dart'; import 'package:wosull/application/model/inventory/category/ItemCategory.dart'; @@ -27,6 +28,7 @@ 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/CustomTextButtonIcon.dart'; import 'package:wosull/widgets/CustomTextFieldForm.dart'; import 'package:wosull/widgets/HeadingContainer.dart'; import 'package:wosull/widgets/HeadingText.dart'; @@ -1236,55 +1238,24 @@ class _AddNewInventoryProductVCState extends State 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, - ) - ], - ), - ), + getManufactureDateButton() ], ); } + Widget getManufactureDateButton() { + return CustomTextButtonIcon( + backgroundColor: MyColors.white, + icon: Icons.calendar_month, + heading: viewModel.storeItem.manufactureDate.isEmpty + ? 'dd/mm/yyyy' + : DataTimeFormat.getFormatDate(viewModel.storeItem.manufactureDate), + onPressed: () { + viewModel.presentDatePicker(context, true); + }, + ); + } + getExpireDate() { return Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -1293,55 +1264,24 @@ class _AddNewInventoryProductVCState extends State 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, - ) - ], - ), - ), + getExpireDateButton(), ], ); } + Widget getExpireDateButton() { + return CustomTextButtonIcon( + backgroundColor: MyColors.white, + icon: Icons.calendar_month, + heading: viewModel.storeItem.expireDate.isEmpty + ? 'dd/mm/yyyy' + : DataTimeFormat.getFormatDate(viewModel.storeItem.expireDate), + onPressed: () { + viewModel.presentDatePicker(context, true); + }, + ); + } + getAddDeliveryPartnerButton() { return CustomAddButton(onPressed: () { viewModel.addNewDeliveryPartner(); diff --git a/lib/application/views/inventorymodule/productviews/InventoryProductVC.dart b/lib/application/views/inventorymodule/productviews/InventoryProductVC.dart index 473013f..646b086 100644 --- a/lib/application/views/inventorymodule/productviews/InventoryProductVC.dart +++ b/lib/application/views/inventorymodule/productviews/InventoryProductVC.dart @@ -271,7 +271,7 @@ class _InventoryProductVCState extends BaseStatefulState { backGroundColor: MyColors.backColorBlue50, heading: AppLocalizations.of(context)!.add_product, onPressed: () async { - onNewProduct(true, true, ''); + onNewProduct(false, false, ''); }, ); } diff --git a/lib/application/views/inventorymodule/productviews/viewModels/AddProductViewModel.dart b/lib/application/views/inventorymodule/productviews/viewModels/AddProductViewModel.dart index 616510c..41cb224 100644 --- a/lib/application/views/inventorymodule/productviews/viewModels/AddProductViewModel.dart +++ b/lib/application/views/inventorymodule/productviews/viewModels/AddProductViewModel.dart @@ -146,16 +146,6 @@ class AddProductViewModel with ChangeNotifier { if (isEdit) { await getProductById(itemId); notifyListeners(); - // 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(); } else { storeItem = AddProduct( isUnlimitedQuantity: false, @@ -210,9 +200,10 @@ class AddProductViewModel with ChangeNotifier { } if (isStart) { storeItem.manufactureDate = - DataTimeFormat.formatDateFromPicket(pickedDate); + DataTimeFormat.formatDateFromPicketINVOICE(pickedDate); } else { - storeItem.expireDate = DataTimeFormat.formatDateFromPicket(pickedDate); + storeItem.expireDate = + DataTimeFormat.formatDateFromPicketINVOICE(pickedDate); } notifyListeners(); }); diff --git a/lib/application/views/inventorymodule/productviews/viewModels/ProductViewModel.dart b/lib/application/views/inventorymodule/productviews/viewModels/ProductViewModel.dart index aa211ec..2031f6b 100644 --- a/lib/application/views/inventorymodule/productviews/viewModels/ProductViewModel.dart +++ b/lib/application/views/inventorymodule/productviews/viewModels/ProductViewModel.dart @@ -181,7 +181,7 @@ class ProductViewModel with ChangeNotifier { notifyListeners(); try { await APIManager() - .fetchData(Constants.SEARCH_CATEGORY, data) + .fetchData(Constants.SEARCH_PRODUCT, data) .then((result) { final value = SearchItemsResponse.fromJson(result); _filteredList.clear(); diff --git a/lib/application/views/inventorymodule/stockTransferViews/InventoryStockTransferVC.dart b/lib/application/views/inventorymodule/stockTransferViews/InventoryStockTransferVC.dart index 047acdf..0438d35 100644 --- a/lib/application/views/inventorymodule/stockTransferViews/InventoryStockTransferVC.dart +++ b/lib/application/views/inventorymodule/stockTransferViews/InventoryStockTransferVC.dart @@ -74,10 +74,10 @@ class _InventoryStockTransferVCState Flexible( child: SearchBox( onEditingDone: (text) { - // filterSearchResults(text); + filterSearchResults(text); }, onChanged: (text) { - // filterSearchResults(text); + filterSearchResults(text); }, hint: AppLocalizations.of(context)!.search, ), @@ -105,14 +105,14 @@ class _InventoryStockTransferVCState SizedBox( width: SizerUtil.deviceType == DeviceType.mobile ? 200 - : 240, + : 200, height: 48, child: SearchBox( onEditingDone: (text) { - // filterSearchResults(text); + filterSearchResults(text); }, onChanged: (text) { - // filterSearchResults(text); + filterSearchResults(text); }, hint: AppLocalizations.of(context)!.search, ), @@ -188,6 +188,16 @@ class _InventoryStockTransferVCState 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, diff --git a/lib/application/views/inventorymodule/stockTransferViews/viewModels/StockTransferViewModel.dart b/lib/application/views/inventorymodule/stockTransferViews/viewModels/StockTransferViewModel.dart index a549b14..c4299f0 100644 --- a/lib/application/views/inventorymodule/stockTransferViews/viewModels/StockTransferViewModel.dart +++ b/lib/application/views/inventorymodule/stockTransferViews/viewModels/StockTransferViewModel.dart @@ -3,6 +3,7 @@ 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/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'; @@ -24,6 +25,10 @@ class StockTransferViewModel with ChangeNotifier { List get filteredList => _filteredList; + List _dataList = []; + + List get dataList => _dataList; + fetch({bool isRefresh = false, int limit = 10}) async { this.limit = limit; _isLoading = true; @@ -53,9 +58,11 @@ class StockTransferViewModel with ChangeNotifier { final value = StockTransferDetailsModel.fromJson(result); if (_dataState == DataState.refreshing) { _filteredList.clear(); + _dataList.clear(); } if (value.success) { _filteredList.addAll(value.stockTransfers); + _dataList.addAll(value.stockTransfers); if (value.stockTransfers.length < this.limit) { _didLastLoad = true; } else { @@ -78,6 +85,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 APIManager() + .fetchData(Constants.searchStockTransfer, data) + .then((result) { + final value = SearchStockTransferResponse.fromJson(result); + _filteredList.clear(); + if (value.success) { + _filteredList.addAll(value.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() diff --git a/lib/application/views/inventorymodule/subCategoryViews/SubCategoryVC.dart b/lib/application/views/inventorymodule/subCategoryViews/SubCategoryVC.dart index dd6294b..be2324a 100644 --- a/lib/application/views/inventorymodule/subCategoryViews/SubCategoryVC.dart +++ b/lib/application/views/inventorymodule/subCategoryViews/SubCategoryVC.dart @@ -88,10 +88,10 @@ class _SubCategoryVCState extends State { height: 48, child: SearchBox( onEditingDone: (text) { - // filterSearchResults(text); + filterSearchResults(text); }, onChanged: (text) { - // filterSearchResults(text); + filterSearchResults(text); }, hint: AppLocalizations.of(context)!.search, ), @@ -115,14 +115,14 @@ class _SubCategoryVCState extends State { SizedBox( width: SizerUtil.deviceType == DeviceType.mobile ? 200 - : 240, + : 200, height: 48, child: SearchBox( onEditingDone: (text) { - // filterSearchResults(text); + filterSearchResults(text); }, onChanged: (text) { - // filterSearchResults(text); + filterSearchResults(text); }, hint: AppLocalizations.of(context)!.search, ), @@ -248,6 +248,18 @@ class _SubCategoryVCState extends State { 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/viewModels/SubCategoryViewModel.dart b/lib/application/views/inventorymodule/subCategoryViews/viewModels/SubCategoryViewModel.dart index d9e4b92..daa3fc0 100644 --- a/lib/application/views/inventorymodule/subCategoryViews/viewModels/SubCategoryViewModel.dart +++ b/lib/application/views/inventorymodule/subCategoryViews/viewModels/SubCategoryViewModel.dart @@ -5,6 +5,7 @@ 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/SearchSubCategoryResponse.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'; @@ -143,6 +144,40 @@ class SubCategoryViewModel 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.SEARCH_SUB_CATEGORY, data) + .then((result) { + final value = SearchSubCategoryResponse.fromJson(result); + _filteredList.clear(); + if (value.success) { + _filteredList.addAll(value.categories); + } + _dataState = DataState.fetched; + }).onError((error, stackTrace) { + _dataState = DataState.error; + }); + notifyListeners(); + } catch (e) { + _dataState = DataState.error; + notifyListeners(); + } + } + } + Future getSpecificStores(bool isEdit) async { Map data = { 'is_included': false, diff --git a/lib/helpers/ThemeDropDown.dart b/lib/helpers/ThemeDropDown.dart index 8cc49df..de096b2 100644 --- a/lib/helpers/ThemeDropDown.dart +++ b/lib/helpers/ThemeDropDown.dart @@ -28,7 +28,7 @@ abstract class ThemeDropDown { alignment: Alignment.centerRight, padding: EdgeInsets.zero, icon: Icon(Icons.clear, size: 12), - color: MyColors.black, + color: MyColors.textColorBlack20, isVisible: true, ); @@ -37,7 +37,7 @@ abstract class ThemeDropDown { constraints: BoxConstraints(maxHeight: 300), ); - static const DropdownButtonProps dropdownButtonProps = DropdownButtonProps( + static DropdownButtonProps dropdownButtonProps = const DropdownButtonProps( padding: EdgeInsets.only(left: 0, right: 4), constraints: BoxConstraints(maxHeight: 38)); } 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/CustomTextFieldForm.dart b/lib/widgets/CustomTextFieldForm.dart index c324dab..9bffb54 100644 --- a/lib/widgets/CustomTextFieldForm.dart +++ b/lib/widgets/CustomTextFieldForm.dart @@ -47,7 +47,8 @@ class CustomTextFieldForm extends StatelessWidget { hintText: hintText, isDense: true, // focusedBorder: OutlineInputBorder( - borderSide: const BorderSide(color: Colors.transparent, width: 1.0), + borderSide: + const BorderSide(color: MyColors.textColorGray, width: 0.5), borderRadius: BorderRadius.circular(8.0), ), enabledBorder: OutlineInputBorder( diff --git a/lib/widgets/ItemCategoryDropdown.dart b/lib/widgets/ItemCategoryDropdown.dart index f28504d..70419b7 100644 --- a/lib/widgets/ItemCategoryDropdown.dart +++ b/lib/widgets/ItemCategoryDropdown.dart @@ -51,7 +51,7 @@ class ItemCategoryDropdown extends StatelessWidget { itemAsString: (ItemCategory u) => u.name, onChanged: onChanged, dropdownDecoratorProps: - MyColors.dropDownStyle(fillColor: fillColor), + MyColors.dropDownStyle(hint: 'Choose', fillColor: fillColor), ); } else { return AppLoader(); diff --git a/lib/widgets/SearchBox.dart b/lib/widgets/SearchBox.dart index ab0f5cd..3ed22fb 100644 --- a/lib/widgets/SearchBox.dart +++ b/lib/widgets/SearchBox.dart @@ -21,23 +21,27 @@ 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, fontFamily: MyFonts.DMREGULAR, - color: MyColors.textColorBlack), + fontSize: MyFonts.normal, + color: MyColors.black), decoration: InputDecoration( contentPadding: const EdgeInsets.symmetric(vertical: 0), hintText: hint, + prefixIconColor: MaterialStateColor.resolveWith((states) => + states.contains(MaterialState.focused) + ? MyColors.textColorBlack20 + : MyColors.textColorBlack20), prefixIcon: const Icon(Icons.search), 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( From a34a365752386c8b743babfdacdb8ef5800437b7 Mon Sep 17 00:00:00 2001 From: waqasYeepeey Date: Fri, 13 Oct 2023 11:09:39 +0500 Subject: [PATCH 06/11] 'UI Fixes' --- .vscode/launch.json | 25 + images/active_cart.svg | 12 + images/active_cashier.svg | 14 + images/active_hold.svg | 11 + images/cart.svg | 1 + images/cart_icon_svg.svg | 1 + images/cashier.svg | 1 + images/hold_order.svg | 1 + images/home.svg | 1 + images/home_active.svg | 14 + lib/application/MyApp.dart | 18 +- .../ViewModel/InventoryViewModel.dart | 73 - lib/application/localdb/SharedPrefs.dart | 7 + .../BusinessRegister/BusinessRegister.dart | 39 + .../BusinessRegisterResponse.dart | 17 + .../DeliveryPartner/GetDeliveryPartner.dart | 35 +- .../Measurement/GetStoreMeasurementModel.dart | 18 + lib/application/model/Modifiers/Modifier.dart | 4 +- .../model/Modifiers/ModifierOption.dart | 21 +- .../model/Products/AddProduct.dart | 38 +- .../model/ReturnStock/ReturnStock.dart | 22 +- .../ProductItemCategoryModel.dart | 10 +- .../StockTransferDetailsModel.dart | 4 +- .../StockTransfer/ViewStockTransferModel.dart | 4 +- .../model/cart/GetHoldOrderModel.dart | 41 + .../model/converters/DataTimeFormat.dart | 11 +- .../model/dashboard/AdminDashboardModel.dart | 12 + .../model/ingredients/AddIngredient.dart | 45 +- .../model/ingredients/GetIngredientModel.dart | 8 +- .../inventory/category/ItemCategory.dart | 2 +- lib/application/model/invoice/Account.dart | 12 + .../model/invoice/MakePayment.dart | 22 + .../model/invoice/PaymentHistory.dart | 26 + .../model/invoice/PaymentMethod.dart | 15 + .../model/invoice/PaymentMethodResponse.dart | 19 + .../model/invoice/QuotationInvioceModel.dart | 10 +- .../invoice/StoreIncomeAccountResponse.dart | 19 + .../model/invoice/StoreInvoice.dart | 15 + .../model/modifierOptions/ModifierOption.dart | 2 +- .../model/reports/CashierOrderHistory.dart | 19 +- lib/application/model/store/WosulStore.dart | 18 +- lib/application/network/APIManager.dart | 1 + .../repository/WosulRepository.dart | 229 ++ lib/application/theme/MyColors.dart | 62 +- lib/application/theme/MyFonts.dart | 16 +- lib/application/utils/AppError.dart | 1 + lib/application/utils/AppLoader.dart | 9 +- lib/application/utils/Constants.dart | 42 +- .../CheckInPopUp.dart | 151 +- .../checkinViews/repo/CheckInRepository.dart | 73 + .../viewModel/CheckInViewModel.dart | 98 +- .../loginViews/AlreadyLoggedView.dart | 9 +- .../views/authModule/loginViews/LoginVC.dart | 278 +- .../viewModel/LoginViewModel.dart | 3 + .../loginViews/widgets/LoginButton.dart | 54 + .../loginViews/widgets/RememberCheckbox.dart | 48 + .../registerViews/CategoryPopUp.dart | 2 +- .../authModule/registerViews/CityPopUp.dart | 2 +- .../authModule/registerViews/RegisterVC.dart | 699 ++--- .../viewModel/AuthViewModel.dart | 0 .../viewModel/CityViewModel.dart | 0 .../viewModel/CountryViewModel.dart | 0 .../BillingCounterDashBoard.dart | 10 +- .../widgets/BillingCounterView.dart | 6 +- .../BusinessAccountMainVC.dart | 81 + .../TransactionPosReturnRepository.dart | 39 + .../TransactionPosReturnViewModel.dart | 116 + .../views/TransactionPOSReturnVC.dart | 211 ++ .../views/TransactionPosDamageVC.dart | 210 ++ .../views/ViewPOSOrderVC.dart | 753 +++++ .../widgets/PosReturnDamageListView.dart | 266 ++ .../views/create_order_module/CartVC.dart | 46 +- .../create_order_module/HoldOrderVC.dart | 22 +- .../repo/CreateOrderRepository.dart | 254 ++ .../viewModels/CartViewModel.dart | 1 - .../viewModels/CounterCloseViewMdoel.dart | 64 + .../viewModels/CreateOrderViewModel.dart | 270 +- .../viewModels/PaymentOptionViewModel.dart | 17 +- .../views/PrintInvoiceVC.dart | 57 +- .../views/PrintReceiptVC.dart | 207 +- .../views/TabBarHomeVC.dart | 37 +- .../views/popups/CashOutVC.dart | 4 +- .../views/popups/CounterCloseVC.dart | 35 +- .../views/popups/DeliveryPartnerPopUp.dart | 103 +- .../views/popups/DineInPopup.dart | 122 +- .../views/popups/ItemModifiersPopUp.dart | 483 ++-- .../views/popups/LogoutVC.dart | 7 +- .../views/popups/PaymentOptionPopUpVC.dart | 45 +- .../views/popups/RegisterCashVC.dart | 4 +- .../views/popups/SelectComboPopUp.dart | 2 +- .../widgets/CartItemView.dart | 35 +- .../widgets/ProductItemView.dart | 37 +- lib/application/views/dashboard/HomeVC.dart | 207 +- .../widgets/AnimatedProgressBar.dart | 4 +- .../views/dashboard/widgets/Indicator.dart | 5 +- .../dashboard/widgets/InvoiceDetailsView.dart | 4 +- .../dashboard/widgets/InvoiceStatusGraph.dart | 10 +- .../dashboard/widgets/OrderDetailsView.dart | 171 +- .../dashboard/widgets/POSStatusGraph.dart | 8 +- .../views/dashboard/widgets/RevenueGraph.dart | 2 +- .../dashboard/widgets/TodaySaleGraph.dart | 30 +- .../viewModels/NewDiscountViewModel.dart | 66 +- .../discountModule/views/DiscountVC.dart | 49 +- .../discountModule/views/NewDiscountVC.dart | 100 +- .../discountModule/views/ViewDiscountVC.dart | 329 +-- .../widgets/DiscountFilterItemView.dart | 53 + .../widgets/DiscountListView.dart | 70 +- lib/application/views/home/HomePage.dart | 205 +- .../views/home/HomePageViewModel.dart | 62 +- .../InventoryModuleMainVC.dart | 139 +- .../categoryviews/InventoryAddCategoryVC.dart | 31 +- .../InventoryCategoriesModule.dart | 28 +- .../ViewInventoryCategoriesVC.dart | 9 +- .../repo/CategoryRepository.dart | 98 + .../viewModels/AddCategoryViewModel.dart | 66 +- .../viewModels/CategoryViewModel.dart | 53 +- .../widgets/CategoryListView.dart | 215 +- .../comboviews/ComboAddSizesVC.dart | 7 +- .../comboviews/ComboInformationPopup.dart | 2 +- .../comboviews/CreateComboGroupVC.dart | 117 +- .../comboviews/InventoryComboVC.dart | 16 +- .../comboviews/InventoryNewComboVC.dart | 665 ++--- .../viewModels/AddComboSizeViewModel.dart | 2 +- .../viewModels/AddNewComboViewModel.dart | 66 +- .../comboviews/widgets/ComboListView.dart | 69 +- .../InventoryDeliveryPartnerPriceVC.dart | 27 +- .../ViewInventoryDeliveryPricesVC.dart | 52 +- .../inventoryAddDeliveryPriceVC.dart | 40 +- .../repository/DeliveryPartnerRepository.dart | 67 + .../DeliveryPartnerPriceViewModel.dart | 86 +- .../NewDeliveryPartnerViewModel.dart | 21 +- .../widgets/DeliveryPartnerPriceListView.dart | 132 +- .../AddProductIngredientVC.dart | 799 ++---- .../ingredientsViews/IngredientsVC.dart | 215 +- .../viewModels/AddIngredientViewModel.dart | 166 +- .../widgets/IngredientListView.dart | 248 ++ .../AddMeasurementUnitVC.dart | 3 +- .../InventoryAddMeasurementVC.dart | 49 +- .../InventoryMeasurementVC.dart | 377 +-- .../ViewInventoryMeasurementVC.dart | 2 +- .../viewModels/AddMeasurementViewModel.dart | 41 +- .../viewModels/MeasurementViewModel.dart | 13 +- .../widgets/MeasurementListView.dart | 275 ++ .../NewModifierOptionViewModel.dart | 36 +- .../modiferOption/views/ModiferOptionVC.dart | 87 +- .../views/NewModifierOptionVC.dart | 63 +- .../widgets/ModifierOptionsListView.dart | 96 +- .../modifierviews/InventoryModifierVC.dart | 41 +- .../modifierviews/InventoryNewModifierVC.dart | 2 +- .../ViewInventoryModifiersVC.dart | 4 +- .../viewModels/NewModifierVM.dart | 3 +- .../widgets/ModifierListView.dart | 103 +- .../AddNewInventoryProductVC.dart | 443 +-- .../productviews/InventoryProductVC.dart | 43 +- .../productviews/SearchProductVC.dart | 6 +- .../viewModels/AddProductViewModel.dart | 40 +- .../productviews/views/ProductListView.dart | 281 +- .../widgets/GenerateBarCodeButton.dart | 31 + .../viewmodels/NewStockReturnViewModel.dart | 11 +- .../stockReturn/views/NewStockReturnVC.dart | 346 ++- .../stockReturn/views/StockReturnVC.dart | 83 +- .../widgets/StockReturnListView.dart | 107 +- .../InventoryNewStockTransferVC.dart | 365 +-- .../InventoryStockTransferVC.dart | 94 +- .../StockTransferViewVC.dart | 1554 ++++------- .../viewModels/NewStockTransferVM.dart | 68 +- .../viewModels/StockTransferViewModel.dart | 1 + .../widgets/StockTransferListView.dart | 84 +- .../InventorySubCategoryVC.dart | 83 +- .../subCategoryViews/SubCategoryVC.dart | 74 +- .../subCategoryViews/ViewSubCategoryVC.dart | 105 +- .../viewModels/AddSubCategoryViewModel.dart | 89 +- .../viewModels/SubCategoryViewModel.dart | 73 +- .../widgets/SubCategoryListView.dart | 288 +- .../views/kitchen/widgets/ItemsListView.dart | 6 +- .../kitchen/widgets/KitchenListView.dart | 4 +- .../offline/KitchenOfflineItemListView.dart | 6 +- .../offline/KitchenOfflineListView.dart | 4 +- .../views/table/KitchenNewTableVC.dart | 2 +- .../views/table/KitchenTableVC.dart | 29 +- .../views/table/ViewTableVC.dart | 20 +- .../views/popups/CountryPopUp.dart | 2 +- .../views/popups/DeleteRecordPopUp.dart | 2 +- .../views/popups/SelectMultiStoresPopUp.dart | 205 +- .../views/popups/ViewItemNotesPopUp.dart | 2 +- .../SalesAndOrderMainVC.dart | 23 +- .../viewModel/QuotationViewModel.dart | 61 +- .../views/ReturnInvoiceVC.dart | 210 +- .../invoiceModule/repo/InvoiceRepository.dart | 28 + .../viewModels/InvoiceViewModel.dart | 38 + .../viewModels/MakePaymentViewModel.dart | 144 + .../viewModels/NewInvoiceViewModel.dart | 163 +- .../ReturnDamageInvoiceViewModel.dart | 1 + .../views}/AddInvoiceAndPrintVC.dart | 554 +++- .../views/InvoiceMakePaymentVC.dart | 462 ++++ .../invoiceModule/{ => views}/InvoicesVC.dart | 174 +- .../{ => views}/NewInvoiceVC.dart | 745 ++--- .../invoiceModule/widgets/AmountWidget.dart | 36 + .../widgets/InvoiceItemListView.dart | 149 +- .../widgets/InvoiceListView.dart | 308 ++- .../views/ordersModule/OrderVC.dart | 251 +- .../viewModel/OrderViewModel.dart | 144 +- .../ordersModule/views/OrderCashierVC.dart} | 12 +- .../quotataionModule/NewQuotationsVC.dart | 2453 ++++------------- .../views/quotataionModule/QuotationsVC.dart | 799 +----- .../repo/QuotationRepository.dart | 84 + .../viewModels/NewQuotationViewModel.dart | 486 ++++ .../widgets/QuotationsListView.dart | 494 ++++ lib/application/views/settings/ReportsVC.dart | 197 +- .../reportsViews/BestSuppliersVC.dart | 14 +- .../settings/reportsViews/POSCompleteVC.dart | 112 +- .../reportsViews/POSReturnOrderVC.dart | 8 +- .../reportsViews/ReportsCategoryVC.dart | 163 +- .../reportsViews/ReportsCustomerVC.dart | 6 +- .../reportsViews/ReportsInvoiceVC.dart | 369 +-- .../reportsViews/ReportsProductsVC.dart | 196 +- .../reportsViews/ReportsQuotationVC.dart | 13 +- .../viewModels/POSReturnOrderViewModel.dart | 3 +- .../transactions/TransactionInvoicesVC.dart | 986 ------- .../transactions/TransactionPOSReturnVC.dart | 473 ---- .../views/transactions/TransactionVC.dart | 117 +- .../views/transactions/return/ReturnPOS.dart | 309 +-- .../return/ReturnReasonPopUp.dart | 16 +- .../CashierTransactionViewModel.dart | 4 + .../transactions/{ => views}/EditOrderVC.dart | 408 ++- .../ReturnTransactionInvoiceVC.dart | 13 +- .../views/TransactionCashierVC.dart | 97 + .../TransactionDamageInvoiceVC.dart | 4 +- .../views/TransactionInvoicesVC.dart | 282 ++ .../{ => views}/TransactionQuotationVC.dart | 8 +- .../views/ViewCashierTransactionVC.dart | 637 +++++ .../{ => views}/ViewPOSReturnVC.dart | 9 +- .../widgets/CashierOrderListView.dart | 74 +- .../TransactionCashierOrderListView.dart | 400 +++ lib/helpers/DatePicker.dart | 22 + lib/helpers/ThemeDropDown.dart | 10 +- lib/helpers/ThemePadding.dart | 6 + lib/helpers/ThemeText.dart | 89 +- lib/l10n/app_ar.arb | 2 +- lib/l10n/app_en.arb | 10 +- lib/objectbox-model.json | 91 +- lib/objectbox.g.dart | 234 +- lib/widgets/ActionPopUpContainer.dart | 4 +- lib/widgets/BackButtonWidget.dart | 4 +- lib/widgets/BoxContainer.dart | 31 + lib/widgets/ButtonText.dart | 1 + lib/widgets/CustomAddButton.dart | 2 +- lib/widgets/CustomCheckBox.dart | 13 +- lib/widgets/CustomOptionalTitle.dart | 2 +- lib/widgets/CustomTabView.dart | 4 +- lib/widgets/CustomTextAddProduct.dart | 16 + lib/widgets/CustomTextButton.dart | 11 +- lib/widgets/CustomTextButtonIcon.dart | 6 +- lib/widgets/CustomTextButtonUnderLine.dart | 10 +- lib/widgets/CustomTextFieldForm.dart | 14 +- lib/widgets/CustomTextFieldPassword.dart | 2 +- lib/widgets/DialogHeader.dart | 2 +- lib/widgets/EmptyDataWidget.dart | 22 +- lib/widgets/ItemCategoryDropdown.dart | 3 +- lib/widgets/LanguageDropdown.dart | 76 +- lib/widgets/MandatoryTitleText.dart | 4 +- lib/widgets/PageLimitDropDown.dart | 113 +- lib/widgets/PortraitContainer.dart | 4 +- lib/widgets/QRCodeGenerate.dart | 6 +- lib/widgets/SearchBox.dart | 2 +- pubspec.lock | 8 + pubspec.yaml | 1 + 267 files changed, 16598 insertions(+), 13529 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 images/active_cart.svg create mode 100644 images/active_cashier.svg create mode 100644 images/active_hold.svg create mode 100644 images/cart.svg create mode 100644 images/cart_icon_svg.svg create mode 100644 images/cashier.svg create mode 100644 images/hold_order.svg create mode 100644 images/home.svg create mode 100644 images/home_active.svg delete mode 100644 lib/application/ViewModel/InventoryViewModel.dart create mode 100644 lib/application/model/BusinessRegister/BusinessRegister.dart create mode 100644 lib/application/model/BusinessRegister/BusinessRegisterResponse.dart create mode 100644 lib/application/model/Measurement/GetStoreMeasurementModel.dart create mode 100644 lib/application/model/invoice/Account.dart create mode 100644 lib/application/model/invoice/MakePayment.dart create mode 100644 lib/application/model/invoice/PaymentHistory.dart create mode 100644 lib/application/model/invoice/PaymentMethod.dart create mode 100644 lib/application/model/invoice/PaymentMethodResponse.dart create mode 100644 lib/application/model/invoice/StoreIncomeAccountResponse.dart create mode 100644 lib/application/repository/WosulRepository.dart rename lib/application/views/authModule/{loginViews => checkinViews}/CheckInPopUp.dart (66%) create mode 100644 lib/application/views/authModule/checkinViews/repo/CheckInRepository.dart rename lib/application/views/authModule/{ => checkinViews}/viewModel/CheckInViewModel.dart (81%) rename lib/application/views/authModule/{ => loginViews}/viewModel/LoginViewModel.dart (98%) create mode 100644 lib/application/views/authModule/loginViews/widgets/LoginButton.dart create mode 100644 lib/application/views/authModule/loginViews/widgets/RememberCheckbox.dart rename lib/application/views/authModule/{ => registerViews}/viewModel/AuthViewModel.dart (100%) rename lib/application/views/authModule/{ => registerViews}/viewModel/CityViewModel.dart (100%) rename lib/application/views/authModule/{ => registerViews}/viewModel/CountryViewModel.dart (100%) create mode 100644 lib/application/views/businessAccounts/BusinessAccountMainVC.dart create mode 100644 lib/application/views/businessAccounts/repository/TransactionPosReturnRepository.dart create mode 100644 lib/application/views/businessAccounts/viewModels/TransactionPosReturnViewModel.dart create mode 100644 lib/application/views/businessAccounts/views/TransactionPOSReturnVC.dart create mode 100644 lib/application/views/businessAccounts/views/TransactionPosDamageVC.dart create mode 100644 lib/application/views/businessAccounts/views/ViewPOSOrderVC.dart create mode 100644 lib/application/views/businessAccounts/widgets/PosReturnDamageListView.dart create mode 100644 lib/application/views/create_order_module/repo/CreateOrderRepository.dart create mode 100644 lib/application/views/create_order_module/viewModels/CounterCloseViewMdoel.dart create mode 100644 lib/application/views/discountModule/widgets/DiscountFilterItemView.dart create mode 100644 lib/application/views/inventorymodule/categoryviews/repo/CategoryRepository.dart create mode 100644 lib/application/views/inventorymodule/deliveryPartnerViews/repository/DeliveryPartnerRepository.dart rename lib/application/views/inventorymodule/{productviews => ingredientsViews}/viewModels/AddIngredientViewModel.dart (73%) create mode 100644 lib/application/views/inventorymodule/ingredientsViews/widgets/IngredientListView.dart create mode 100644 lib/application/views/inventorymodule/measurementviews/widgets/MeasurementListView.dart create mode 100644 lib/application/views/inventorymodule/productviews/widgets/GenerateBarCodeButton.dart create mode 100644 lib/application/views/salesandordermodule/views/invoiceModule/repo/InvoiceRepository.dart create mode 100644 lib/application/views/salesandordermodule/views/invoiceModule/viewModels/MakePaymentViewModel.dart rename lib/application/views/salesandordermodule/views/{ => invoiceModule/views}/AddInvoiceAndPrintVC.dart (56%) create mode 100644 lib/application/views/salesandordermodule/views/invoiceModule/views/InvoiceMakePaymentVC.dart rename lib/application/views/salesandordermodule/views/invoiceModule/{ => views}/InvoicesVC.dart (63%) rename lib/application/views/salesandordermodule/views/invoiceModule/{ => views}/NewInvoiceVC.dart (70%) create mode 100644 lib/application/views/salesandordermodule/views/invoiceModule/widgets/AmountWidget.dart rename lib/application/views/{transactions/CashierTransactionsVC.dart => salesandordermodule/views/ordersModule/views/OrderCashierVC.dart} (91%) create mode 100644 lib/application/views/salesandordermodule/views/quotataionModule/repo/QuotationRepository.dart create mode 100644 lib/application/views/salesandordermodule/views/quotataionModule/viewModels/NewQuotationViewModel.dart create mode 100644 lib/application/views/salesandordermodule/views/quotataionModule/widgets/QuotationsListView.dart delete mode 100644 lib/application/views/transactions/TransactionInvoicesVC.dart delete mode 100644 lib/application/views/transactions/TransactionPOSReturnVC.dart rename lib/application/views/transactions/{ => views}/EditOrderVC.dart (70%) rename lib/application/views/transactions/{ => views}/ReturnTransactionInvoiceVC.dart (99%) create mode 100644 lib/application/views/transactions/views/TransactionCashierVC.dart rename lib/application/views/transactions/{ => views}/TransactionDamageInvoiceVC.dart (99%) create mode 100644 lib/application/views/transactions/views/TransactionInvoicesVC.dart rename lib/application/views/transactions/{ => views}/TransactionQuotationVC.dart (99%) create mode 100644 lib/application/views/transactions/views/ViewCashierTransactionVC.dart rename lib/application/views/transactions/{ => views}/ViewPOSReturnVC.dart (97%) create mode 100644 lib/application/views/transactions/widgets/TransactionCashierOrderListView.dart create mode 100644 lib/helpers/DatePicker.dart create mode 100644 lib/helpers/ThemePadding.dart create mode 100644 lib/widgets/BoxContainer.dart create mode 100644 lib/widgets/CustomTextAddProduct.dart 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/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/lib/application/MyApp.dart b/lib/application/MyApp.dart index 808fd3d..612ca4d 100644 --- a/lib/application/MyApp.dart +++ b/lib/application/MyApp.dart @@ -4,10 +4,11 @@ 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/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/PaymentOptionViewModel.dart'; import 'package:wosull/application/views/create_order_module/viewModels/PrintInvoiceViewModel.dart'; @@ -20,17 +21,20 @@ import 'package:wosull/application/views/inventorymodule/comboviews/viewModels/A 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/transactions/viewmodels/TransactionQuotationViewModel.dart'; import 'package:wosull/application/views/transactions/widgets/EditOrderViewModel.dart'; @@ -51,6 +55,14 @@ class MyApp extends StatelessWidget { Widget build(BuildContext context) { return MultiProvider( providers: [ + ChangeNotifierProvider( + create: (context) => MakePaymentViewModel()), + ChangeNotifierProvider( + create: (context) => ReturnDamageInvoiceViewModel()), + ChangeNotifierProvider( + create: (context) => CounterCloseViewModel()), + ChangeNotifierProvider( + create: (context) => NewQuotationViewModel()), ChangeNotifierProvider( create: (context) => NewStockReturnViewModel()), ChangeNotifierProvider( diff --git a/lib/application/ViewModel/InventoryViewModel.dart b/lib/application/ViewModel/InventoryViewModel.dart deleted file mode 100644 index 4a1f6d4..0000000 --- a/lib/application/ViewModel/InventoryViewModel.dart +++ /dev/null @@ -1,73 +0,0 @@ -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/GetStoreSupplier.dart'; -import 'package:wosull/application/model/store/StoreInvoicesModel.dart'; -import 'package:wosull/application/network/APIManager.dart'; -import 'package:wosull/application/repo/AuthRepository.dart'; -import 'package:wosull/application/utils/Constants.dart'; - -class InventoryViewModel { - 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 { - try { - dynamic response = await AuthRepository().postResponseAuth( - Constants.SEARCH_ITEM_STORE, Constants.getStorePayload()); - final value = ProductItemCategoryModel.fromJson(response); - return value.categories; - } catch (e) { - return []; - } - } - - 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/localdb/SharedPrefs.dart b/lib/application/localdb/SharedPrefs.dart index 768a4f4..a7f59ca 100644 --- a/lib/application/localdb/SharedPrefs.dart +++ b/lib/application/localdb/SharedPrefs.dart @@ -125,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/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/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/Modifiers/Modifier.dart b/lib/application/model/Modifiers/Modifier.dart index 43b923f..cd336b8 100644 --- a/lib/application/model/Modifiers/Modifier.dart +++ b/lib/application/model/Modifiers/Modifier.dart @@ -13,7 +13,7 @@ class Modifier { String arabicName; String description; double price; - String status = "Inactive"; + String status = "Active"; bool isMultiple; var options = ToMany(); var selected = ToMany(); @@ -30,7 +30,7 @@ class Modifier { this.price = 0.0, required this.options, required this.selected, - this.status = '', + this.status = 'Active', this.isSelected = false, this.isMultiple = false, this.createdOn = '', diff --git a/lib/application/model/Modifiers/ModifierOption.dart b/lib/application/model/Modifiers/ModifierOption.dart index f0b6aca..2cad390 100644 --- a/lib/application/model/Modifiers/ModifierOption.dart +++ b/lib/application/model/Modifiers/ModifierOption.dart @@ -1,4 +1,5 @@ import 'package:objectbox/objectbox.dart'; +import 'package:wosull/application/model/ingredients/AddIngredient.dart'; import 'package:wosull/helpers/Utils.dart'; @Entity() @@ -6,29 +7,43 @@ 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( - name: json['name'] ?? "", - arabicName: json['arabic_name'] ?? "", + 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'] ?? "", + modifierName: json['modifier'] ?? '', qtyIdx: json['qtyIdx'] ?? 1, + ingredients: ToMany( + items: json['ingredients'] != null + ? List.from(json['ingredients']) + .map((i) => AddIngredient.fromJson(i)) + .toList() + : []), ); } diff --git a/lib/application/model/Products/AddProduct.dart b/lib/application/model/Products/AddProduct.dart index 1eeed88..247ec7e 100644 --- a/lib/application/model/Products/AddProduct.dart +++ b/lib/application/model/Products/AddProduct.dart @@ -19,8 +19,8 @@ class AddProduct { String productIdSt = ''; String product_product_id = ''; - double price; - int uniqueId; + double? price; + int? uniqueId; String uniqueIdForStoreData; int? quantity; @@ -29,12 +29,12 @@ class AddProduct { bool isItemInStock = false; String description; String descriptionArabic; - double purchasePrice; - int stockAlertQuantity; - double itemPriceWithOutOffer; - int totalAddedQuantity; - int totalUsedQuantity; - double salePriceExclusiveTax; + double? purchasePrice; + int? stockAlertQuantity; + double? itemPriceWithOutOffer; + int? totalAddedQuantity; + int? totalUsedQuantity; + double? salePriceExclusiveTax; double? totalItemPrice; String supplier; @@ -64,24 +64,24 @@ class AddProduct { this.deliveryPartner = '', this.itemNameArabic = '', this.productId, - this.price = 0.0, - this.uniqueId = 0, + this.price, + this.uniqueId, this.measurementUnit = '', this.uniqueIdForStoreData = '', this.quantity, this.imageUrl = '', this.updatedAt = '', - this.totalItemPrice = 0.0, + this.totalItemPrice, this.isItemInStock = false, this.description = '', this.descriptionArabic = '', - this.purchasePrice = 0.0, - this.stockAlertQuantity = 0, - this.itemPriceWithOutOffer = 0, - this.totalAddedQuantity = 0, + this.purchasePrice, + this.stockAlertQuantity, + this.itemPriceWithOutOffer, + this.totalAddedQuantity, this.noteForItem, - this.totalUsedQuantity = 0, - this.salePriceExclusiveTax = 0, + this.totalUsedQuantity, + this.salePriceExclusiveTax, required this.modifiers, required this.ingredients, required this.selectedModifiers, @@ -154,7 +154,7 @@ class AddProduct { data['store_id'] = sharedPrefs.storeId; data['name'] = name; data['unlimited_quantity'] = isUnlimitedQuantity; - data['unique_id_for_store_data'] = uniqueId; + data['unique_id_for_store_data'] = uniqueIdForStoreData; data['is_item_in_stock'] = isItemInStock; data['item_name_arabic'] = itemNameArabic; data['item_description_arabic'] = descriptionArabic; @@ -189,7 +189,7 @@ class AddProduct { data['unlimited_quantity'] = isUnlimitedQuantity ?? false; data['productId'] = product_product_id ?? "0"; data['_id'] = itemId; - data['unique_id_for_store_data'] = uniqueId; + data['unique_id_for_store_data'] = uniqueIdForStoreData; data['is_item_in_stock'] = isItemInStock; data['item_name_arabic'] = itemNameArabic; data['item_description_arabic'] = descriptionArabic; diff --git a/lib/application/model/ReturnStock/ReturnStock.dart b/lib/application/model/ReturnStock/ReturnStock.dart index cc11474..05331f1 100644 --- a/lib/application/model/ReturnStock/ReturnStock.dart +++ b/lib/application/model/ReturnStock/ReturnStock.dart @@ -91,20 +91,36 @@ class ReturnStock { Map toJson() { final Map data = {}; data['store_id'] = sharedPrefs.storeId; - data['invoiceId'] = id ?? ''; 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'] = totalExcludingVat; - data['total_taxable_amount'] = totalTaxableAmount; + 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/StockTransfer/ProductItemCategoryModel.dart b/lib/application/model/StockTransfer/ProductItemCategoryModel.dart index 5e06307..f252b68 100644 --- a/lib/application/model/StockTransfer/ProductItemCategoryModel.dart +++ b/lib/application/model/StockTransfer/ProductItemCategoryModel.dart @@ -59,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/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/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 a2b4ec6..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(); @@ -17,6 +17,12 @@ class DataTimeFormat { 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))); @@ -29,6 +35,9 @@ 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); 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/ingredients/AddIngredient.dart b/lib/application/model/ingredients/AddIngredient.dart index d0fe7b9..31cfdb8 100644 --- a/lib/application/model/ingredients/AddIngredient.dart +++ b/lib/application/model/ingredients/AddIngredient.dart @@ -1,5 +1,6 @@ import 'package:objectbox/objectbox.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/helpers/Utils.dart'; @Entity() class AddIngredient { @@ -9,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; @@ -41,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; @@ -119,17 +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'] ?? '', @@ -153,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/GetIngredientModel.dart b/lib/application/model/ingredients/GetIngredientModel.dart index 0e8fa25..b92ba9f 100644 --- a/lib/application/model/ingredients/GetIngredientModel.dart +++ b/lib/application/model/ingredients/GetIngredientModel.dart @@ -9,8 +9,10 @@ class GetIngredientModel { factory GetIngredientModel.fromJson(Map json) { return GetIngredientModel( success: json['success'] as bool, - ingredient: List.from(json['ingrediant']) - .map((i) => AddIngredient.fromJson(i)) - .toList()); + ingredient: json['ingrediant'] != null + ? List.from(json['ingrediant']) + .map((i) => AddIngredient.fromJson(i)) + .toList() + : []); } } 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/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..c75b9a8 --- /dev/null +++ b/lib/application/model/invoice/PaymentMethod.dart @@ -0,0 +1,15 @@ +class PaymentMethod { + String id; + String paymentMethod; + bool status; + + PaymentMethod(this.id, this.paymentMethod, this.status); + + factory PaymentMethod.fromJson(Map json) { + return PaymentMethod( + json['_id'] ?? '', + json['paymentMethod'] ?? '', + json['status'] ?? false, + ); + } +} 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/ModifierOption.dart b/lib/application/model/modifierOptions/ModifierOption.dart index 05ba7e4..102bf46 100644 --- a/lib/application/model/modifierOptions/ModifierOption.dart +++ b/lib/application/model/modifierOptions/ModifierOption.dart @@ -21,7 +21,7 @@ class ModifierOption { this.store, this.name = '', this.price, - this.status = false, + this.status = true, this.createdAt, this.updatedAt, this.ingredients}); diff --git a/lib/application/model/reports/CashierOrderHistory.dart b/lib/application/model/reports/CashierOrderHistory.dart index ca330ad..9cf24df 100644 --- a/lib/application/model/reports/CashierOrderHistory.dart +++ b/lib/application/model/reports/CashierOrderHistory.dart @@ -21,6 +21,23 @@ class CashierOrderHistory { } } +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() + : []); + } +} + class CashierSingleOrderHistory { bool? success; CashierOrder? order; @@ -118,7 +135,7 @@ class CashierOrder { cardNumber: json['card_number'] ?? 0, cart: json['cart_id'] != null ? CashierCart.fromJson(json['cart_id']) - : null, + : CashierCart(orderDetails: []), timer: json['timer'] ?? 0, deliveryNotes: json['delivery_notes'] ?? "", referenceNo: json['reference'] ?? 0, 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 960ad8b..e1c1ab9 100644 --- a/lib/application/network/APIManager.dart +++ b/lib/application/network/APIManager.dart @@ -42,6 +42,7 @@ class APIManager { .timeout(const Duration(seconds: 60)); return response; } catch (e) { + print(e.toString()); return e; } } diff --git a/lib/application/repository/WosulRepository.dart b/lib/application/repository/WosulRepository.dart new file mode 100644 index 0000000..7f2c3ac --- /dev/null +++ b/lib/application/repository/WosulRepository.dart @@ -0,0 +1,229 @@ +import 'package:wosull/application/localdb/SharedPrefs.dart'; +import 'package:wosull/application/model/Measurement/InventoryMeasurementModel.dart'; +import 'package:wosull/application/model/Measurement/MeasurementUnitModel.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/customers/GetStoreCustomer.dart'; +import 'package:wosull/application/model/discount/StoreDiscountModel.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/network/APIManager.dart'; +import 'package:wosull/application/repo/AuthRepository.dart'; +import 'package:wosull/application/utils/Constants.dart'; + +class WosulRepository { + Future> getPaymentMethods() async { + var items = []; + var data = {'page': 1, 'is_pagination_included': false}; + await APIManager() + .getResponseAuth( + "${Constants.getPaymentMethods}/${sharedPrefs.storeId}", data) + .then((result) { + final value = PaymentMethodResponse.fromJson(result); + if (value.status) { + items.addAll(value.paymentMethods); + } + }).onError((error, stackTrace) { + print(stackTrace.toString()); + }); + 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> 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> 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) { + print(stackTrace.toString()); + }); + 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()); + } + } +} diff --git a/lib/application/theme/MyColors.dart b/lib/application/theme/MyColors.dart index 6d552db..ab11569 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'; @@ -78,7 +79,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); } @@ -104,15 +106,54 @@ class MyColors { fontSize: 13, fontFamily: MyFonts.Medium, color: MyColors.black); } - static DropDownDecoratorProps dropDownStyle( + 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: 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( fillColor: fillColor, @@ -127,7 +168,8 @@ class MyColors { color: MyColors.textColorGray, ), borderRadius: BorderRadius.circular(8.0), - ), // Added + ), + // Added enabledBorder: OutlineInputBorder( borderSide: const BorderSide( width: 0, //<-- SEE HERE @@ -141,11 +183,11 @@ class MyColors { } 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 1c241dc..345771d 100644 --- a/lib/application/theme/MyFonts.dart +++ b/lib/application/theme/MyFonts.dart @@ -1,3 +1,5 @@ +import 'package:sizer/sizer.dart'; + class MyFonts { static const Medium = 'DMSansMedium'; @@ -11,15 +13,17 @@ class MyFonts { static const DejaVu = 'DejaVuSansMono'; - static const bold = 18.0; + static final bold = SizerUtil.deviceType == DeviceType.tablet ? 18.0 : 15.0; - static const H1 = 16.0; + static final H1 = SizerUtil.deviceType == DeviceType.tablet ? 16.0 : 14.0; - static const H2 = 14.0; + static final H2 = SizerUtil.deviceType == DeviceType.tablet ? 14.0 : 12.0; - static const normal = 12.0; + static final normal = SizerUtil.deviceType == DeviceType.tablet ? 12.0 : 11.0; - static const normalButton = 14.0; + static final normalButton = + SizerUtil.deviceType == DeviceType.tablet ? 14.0 : 12.0; - static const mediumText = 13.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 4d0caca..8527888 100644 --- a/lib/application/utils/AppError.dart +++ b/lib/application/utils/AppError.dart @@ -11,6 +11,7 @@ class AppError extends StatelessWidget { Widget build(BuildContext context) { // TODO: implement build return Container( + height: 42, margin: const EdgeInsets.only(top: 16), decoration: const BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(16)), 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 68143b8..beac531 100644 --- a/lib/application/utils/Constants.dart +++ b/lib/application/utils/Constants.dart @@ -22,7 +22,8 @@ class Constants { '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'; @@ -127,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'; @@ -159,7 +161,7 @@ class Constants { 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'; @@ -187,12 +189,18 @@ 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'; //ingredients static const getIngredientsList = 'api/store/get_ingrediant_list'; @@ -205,6 +213,7 @@ 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; @@ -255,9 +264,12 @@ class Constants { ]; static const quotationStatus = [ - 'Open', + 'All', + 'Pending', 'Accepted', - 'Rejected', + 'Declined', + 'Expired', + 'Cancelled', ]; static const orderStatus = [ @@ -300,6 +312,18 @@ 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', @@ -316,6 +340,14 @@ class Constants { 'Cancelled', ]; + static const quotationStatusTypes = [ + 'Pending', + 'Accepted', + 'Declined', + 'Expired', + 'Cancelled', + ]; + static const discountFilters = [ "All Products", "Specific Products", diff --git a/lib/application/views/authModule/loginViews/CheckInPopUp.dart b/lib/application/views/authModule/checkinViews/CheckInPopUp.dart similarity index 66% rename from lib/application/views/authModule/loginViews/CheckInPopUp.dart rename to lib/application/views/authModule/checkinViews/CheckInPopUp.dart index 158e490..fc53949 100644 --- a/lib/application/views/authModule/loginViews/CheckInPopUp.dart +++ b/lib/application/views/authModule/checkinViews/CheckInPopUp.dart @@ -5,15 +5,17 @@ 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/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 { - CheckInPopUp({ + const CheckInPopUp({ Key? key, }) : super(key: key); @@ -41,16 +43,13 @@ class _CheckInPopUpState extends BaseStatefulState { @override Widget build(BuildContext context) { viewModel = context.watch(); - if (viewModel.crudOperationState == CRUDOperationState.emptyCounters) { - closePopUp(); - } 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 = @@ -65,33 +64,15 @@ class _CheckInPopUpState extends BaseStatefulState { 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, + DialogHeader( + title: AppLocalizations.of(context)!.check_in, ), Container( margin: const EdgeInsets.all(12), child: Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ - const MandatoryTitleText(hint: 'Cash In Amount'), + const MandatoryTitleText(hint: 'Opening Amount'), AppSpaces.verticalSmall, CustomTextFieldForm( keyboardType: TextInputType.number, @@ -104,61 +85,24 @@ class _CheckInPopUpState extends BaseStatefulState { mainAxisAlignment: MainAxisAlignment.start, mainAxisSize: MainAxisSize.max, children: [ - Container( - width: 20, - height: 20, - decoration: const BoxDecoration( - color: MyColors.fillColor3, - borderRadius: - BorderRadius.all(Radius.circular(4)), - ), - ), + Flexible( + child: BoxContainer( + fillColor: MyColors.fillColor3, + title: 'Available', + )), 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)), - ), + Flexible( + child: BoxContainer( + fillColor: MyColors.fillRed, + title: AppLocalizations.of(context)! + .not_available), ), 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), + Flexible( + child: BoxContainer( + fillColor: MyColors.greenColor, + title: + AppLocalizations.of(context)!.selected), ), ], ), @@ -229,26 +173,31 @@ class _CheckInPopUpState extends BaseStatefulState { 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), - ), + 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), + ), + ) ], )) ], @@ -259,9 +208,7 @@ class _CheckInPopUpState extends BaseStatefulState { return AppLoader(); } }), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, SizedBox( width: 100, child: CustomSimpleButton( 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 81% rename from lib/application/views/authModule/viewModel/CheckInViewModel.dart rename to lib/application/views/authModule/checkinViews/viewModel/CheckInViewModel.dart index 353bcf4..e499c9e 100644 --- a/lib/application/views/authModule/viewModel/CheckInViewModel.dart +++ b/lib/application/views/authModule/checkinViews/viewModel/CheckInViewModel.dart @@ -1,12 +1,9 @@ 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 { @@ -19,14 +16,14 @@ class CheckInViewModel with ChangeNotifier { 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 = '0.0'; @@ -69,7 +66,7 @@ class CheckInViewModel with ChangeNotifier { } else if (cashAmount.isEmpty) { Utils.showMessage('Please Enter cash amount'); } else { - await addCounter(loginCounterParams()); + await addCounter(checkInCounterParams()); } } @@ -109,12 +106,17 @@ class CheckInViewModel with ChangeNotifier { 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; balanceInHand = actualBalanceInHand.toStringAsFixed(2); @@ -127,10 +129,7 @@ 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') @@ -152,7 +151,7 @@ class CheckInViewModel with ChangeNotifier { }); } - Map loginCounterParams() { + Map checkInCounterParams() { Map data = { 'amount_cash_in': double.parse(cashAmount), 'available_cash': double.parse(cashAmount), @@ -173,7 +172,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 }; @@ -185,7 +185,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), @@ -223,10 +222,7 @@ class CheckInViewModel with ChangeNotifier { Future updateCounter(Map data) async { setLoading(true); - 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 { @@ -240,19 +236,36 @@ class CheckInViewModel with ChangeNotifier { Future addCounter(Map data) async { setLoading(true); - 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; } + }).onError((error, stackTrace) { + setLoading(false); + }); + } - // 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); }); @@ -260,36 +273,17 @@ class CheckInViewModel with ChangeNotifier { 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/LoginVC.dart b/lib/application/views/authModule/loginViews/LoginVC.dart index a12eec1..93f0d46 100644 --- a/lib/application/views/authModule/loginViews/LoginVC.dart +++ b/lib/application/views/authModule/loginViews/LoginVC.dart @@ -3,18 +3,18 @@ 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'; @@ -48,122 +48,115 @@ class _LoginVCState extends State { viewModel = context.watch(); return Directionality( textDirection: TextDirection.ltr, - child: Scaffold( - resizeToAvoidBottomInset: false, - body: SingleChildScrollView( - child: Container( - decoration: const BoxDecoration( - color: MyColors.fillColor, - image: DecorationImage( - image: AssetImage(ThemeImage.background), - fit: BoxFit.contain, + 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: [ - AppSpaces.verticalLarge, - Image.asset(ThemeImage.logo, height: 80), - AppSpaces.verticalLarge, - AppSpaces.verticalLarge, - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Container( - height: 48, - width: 100, - padding: const EdgeInsets.all(8), - margin: const EdgeInsets.only(right: 16), - decoration: const BoxDecoration( + 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, - borderRadius: BorderRadius.all(Radius.circular(4)), - ), - 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, - ) - ], - ), - 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: () { + 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( @@ -171,16 +164,49 @@ class _LoginVCState extends State { const RegisterVC()), ); }, - heading: AppLocalizations.of(context)! - .dont_account) - ], + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.center, + children: [ + 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... + ], + ), + ) + ], + ), + ) + ], + ), ), ), ), ), - ), - ], - ) /* add child content here */, + ], + ) /* add child content here */, + ), ), ), )); @@ -226,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); diff --git a/lib/application/views/authModule/viewModel/LoginViewModel.dart b/lib/application/views/authModule/loginViews/viewModel/LoginViewModel.dart similarity index 98% rename from lib/application/views/authModule/viewModel/LoginViewModel.dart rename to lib/application/views/authModule/loginViews/viewModel/LoginViewModel.dart index b69a9d0..a448db5 100644 --- a/lib/application/views/authModule/viewModel/LoginViewModel.dart +++ b/lib/application/views/authModule/loginViews/viewModel/LoginViewModel.dart @@ -64,6 +64,7 @@ class LoginViewModel with ChangeNotifier { _appLocale.changeLocale(Locale(language.languageCode)); // setDropDownValue(context); sharedPrefs.setLocale(language.languageCode); + notifyListeners(); } bool isValidate() { @@ -172,6 +173,8 @@ class LoginViewModel with ChangeNotifier { sharedPrefs.token = response.access!.accessToken ?? ''; _dataState = LoginState.showAccessAccount; setLoading(false); + } else { + _dataState = LoginState.toHome; } }).onError((error, stackTrace) async { print(stackTrace.toString()); 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..72c1973 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); diff --git a/lib/application/views/authModule/registerViews/CityPopUp.dart b/lib/application/views/authModule/registerViews/CityPopUp.dart index cb464fd..4da82e8 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); diff --git a/lib/application/views/authModule/registerViews/RegisterVC.dart b/lib/application/views/authModule/registerViews/RegisterVC.dart index 43eaf29..1cd6204 100644 --- a/lib/application/views/authModule/registerViews/RegisterVC.dart +++ b/lib/application/views/authModule/registerViews/RegisterVC.dart @@ -11,7 +11,6 @@ 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'; @@ -20,11 +19,18 @@ import 'package:wosull/application/theme/MyFonts.dart'; import 'package:wosull/application/utils/Constants.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/authModule/registerViews/viewModel/AuthViewModel.dart'; import 'package:wosull/application/views/home/HomePage.dart'; import 'package:wosull/application/views/popups/CountryPopUp.dart'; import 'package:wosull/base/BaseStatefulState.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/CustomSimpleButton.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); @@ -47,6 +53,8 @@ class _RegisterVCState extends BaseStatefulState { late var lat; late var lng; + bool obscureText = true; + AuthViewModel authView = AuthViewModel(); CountryModel selectedCountry = CountryModel( countryFlag: "", @@ -60,6 +68,12 @@ class _RegisterVCState extends BaseStatefulState { bool _isInAsyncCall = false; + void showHidePassword() { + setState(() { + obscureText = !obscureText; + }); + } + bool isValidate() { if (nameController.text.isEmpty) { showMessage('Enter company name'); @@ -119,21 +133,16 @@ class _RegisterVCState extends BaseStatefulState { child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - Image.asset('images/logo_sub_title.png', height: 80), - const SizedBox( - height: 16, - ), + Image.asset(ThemeImage.wosulLogo, height: 80), + AppSpaces.verticalLarge, Text( AppLocalizations.of(context)!.register, - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 40, - fontFamily: MyFonts.Bold), + style: ThemeText.bigHeader, ), Container( margin: const EdgeInsets.all(16), child: Center( - child: getMainDesign('Email'), + child: getMainDesign(), ), ), ], @@ -147,9 +156,6 @@ class _RegisterVCState extends BaseStatefulState { void onError(PlacesAutocompleteResponse response) { SnackBar(content: Text(response.errorMessage!)); - // homeScaffoldKey.currentState.showSnackBar( - // - // ); } Future _handlePressButton() async { @@ -194,61 +200,36 @@ class _RegisterVCState extends BaseStatefulState { setState(() { addressController = p.description!; }); - // print("object${p.description}"); - - //SnackBar(content: Text("${p.description} - $lat/$lng")); - // scaffold.showSnackBar( - // - // ); } 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, + TextFormField( controller: controller, - style: const TextStyle( + style: TextStyle( fontFamily: MyFonts.DMREGULAR, - fontSize: 16, + fontSize: MyFonts.normal, color: MyColors.black), decoration: InputDecoration( - hintText: hint, - fillColor: MyColors.fillColor, + constraints: const BoxConstraints(maxHeight: 48, minHeight: 48), + fillColor: MyColors.backFillColor, filled: true, + border: InputBorder.none, + hintText: hint, + isDense: true, focusedBorder: OutlineInputBorder( borderSide: - const BorderSide(color: MyColors.strokeColor, width: 1.0), + const BorderSide(color: MyColors.textColorGray, width: 0.5), borderRadius: BorderRadius.circular(8.0), ), enabledBorder: OutlineInputBorder( borderSide: const BorderSide( width: 1, //<-- SEE HERE - color: MyColors.strokeColor, + color: Colors.transparent, ), borderRadius: BorderRadius.circular(8.0), ), @@ -258,10 +239,10 @@ class _RegisterVCState extends BaseStatefulState { ); } - 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, @@ -273,92 +254,74 @@ class _RegisterVCState extends BaseStatefulState { nameController, AppLocalizations.of(context)!.company_name, 'Enter Company name'), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, getMandatoryTextField(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 - ), + AppSpaces.verticalLarge, + CustomSimpleButton( + backGroundColor: MyColors.primary, + textColor: MyColors.white, 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); - } + validate(); + }, + heading: AppLocalizations.of(context)!.register, + ), + GestureDetector( + onTap: () { + Navigator.pop(context); }, - child: Text( - AppLocalizations.of(context)!.register, - style: const TextStyle( - fontSize: MyFonts.bold, - color: MyColors.white, - fontFamily: MyFonts.Bold), + 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 +332,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: selectedCountry.countryName!.isEmpty + ? hint + : selectedCountry.countryName!, + onPressed: () { + _navigateAndDisplayCountry(context); + }, ) ], ); @@ -445,77 +351,19 @@ 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: + selectedCity.cityName!.isEmpty ? hint : selectedCity.cityName!, + onPressed: () { + if (selectedCountry.id!.isNotEmpty) { + _navigateAndDisplayCity(context); + } else { + showMessage('Select country'); + } + }, ) ], ); @@ -525,77 +373,19 @@ 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: + addressController.isEmpty ? 'Enter Address' : addressController, + onPressed: () { + if (selectedCountry.id!.isNotEmpty) { + _handlePressButton(); + } else { + showMessage('Select city'); + } + }, ) ], ); @@ -605,77 +395,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: selectedCategory.deliveryName!.isEmpty + ? hint + : selectedCategory.deliveryName!, + onPressed: () { + if (selectedCity.id!.isNotEmpty) { + _navigateAndDisplayDelivery(context); + } else { + showMessage('Select City'); + } + }, ) ], ); @@ -683,38 +416,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 +434,7 @@ class _RegisterVCState extends BaseStatefulState { ElevatedButton( style: ElevatedButton.styleFrom( elevation: 0, - backgroundColor: MyColors.fillColor, + backgroundColor: MyColors.backFillColor, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), // <-- Radius ), @@ -734,16 +445,17 @@ class _RegisterVCState extends BaseStatefulState { children: [ Text( selectedCountry.phoneCode!, - style: const TextStyle(color: MyColors.black), + 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 +463,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( + 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 +486,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: obscureText, + hint: 'Enter your password', + onChanged: (value) { + passwordController.text = value; + }, + onPressed: () { + showHidePassword(); + }, + )); + } + + Widget buildPassword() { + return Column(children: [ + MandatoryTitleText(hint: AppLocalizations.of(context)!.password), + AppSpaces.verticalSmall, + password(), ]); } @@ -894,7 +566,7 @@ class _RegisterVCState extends BaseStatefulState { void registerUser(Map map) async { progressDialogue(context); - StoreResponse storeResponse = await authView.loginRegisterUser(map); + final storeResponse = await authView.loginRegisterUser(map); if (storeResponse.success) { addAccount(storeResponse.store); } else { @@ -945,4 +617,33 @@ class _RegisterVCState extends BaseStatefulState { setState(() {}); } } + + void validate() { + 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); + } + } } diff --git a/lib/application/views/authModule/viewModel/AuthViewModel.dart b/lib/application/views/authModule/registerViews/viewModel/AuthViewModel.dart similarity index 100% rename from lib/application/views/authModule/viewModel/AuthViewModel.dart rename to lib/application/views/authModule/registerViews/viewModel/AuthViewModel.dart 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 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/billingCounterDashboard/BillingCounterDashBoard.dart b/lib/application/views/billingCounterDashboard/BillingCounterDashBoard.dart index 654553f..c025c76 100644 --- a/lib/application/views/billingCounterDashboard/BillingCounterDashBoard.dart +++ b/lib/application/views/billingCounterDashboard/BillingCounterDashBoard.dart @@ -50,7 +50,7 @@ class _BillingCounterDashBoardState extends State { Row( mainAxisAlignment: MainAxisAlignment.start, children: [ - const Text( + Text( 'Billing Counter Dashboard', style: ThemeText.textStylePageHeading, ), @@ -73,7 +73,7 @@ class _BillingCounterDashBoardState extends State { ) : Row( children: [ - const Text( + Text( 'Billing Counter Dashboard', style: ThemeText.textStylePageHeading, ), @@ -84,17 +84,17 @@ class _BillingCounterDashBoardState extends State { crossAxisAlignment: CrossAxisAlignment.end, children: [ SizedBox( - width: 120, + width: 130, child: getCounterTypeDropdown(), ), AppSpaces.horizontalSmall, SizedBox( - width: 120, + width: 130, child: getStartDateButton(), ), AppSpaces.horizontalSmall, SizedBox( - width: 120, + width: 130, child: getEndDateButton(), ), ], diff --git a/lib/application/views/billingCounterDashboard/widgets/BillingCounterView.dart b/lib/application/views/billingCounterDashboard/widgets/BillingCounterView.dart index f992de5..78d1f66 100644 --- a/lib/application/views/billingCounterDashboard/widgets/BillingCounterView.dart +++ b/lib/application/views/billingCounterDashboard/widgets/BillingCounterView.dart @@ -61,7 +61,7 @@ class BillingCounterView extends StatelessWidget { AppSpaces.verticalMedium, const LineView(), AppSpaces.verticalLarge, - const Row( + Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( @@ -91,7 +91,7 @@ class BillingCounterView extends StatelessWidget { AppSpaces.verticalLarge, const LineView(), AppSpaces.verticalLarge, - const Row( + Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Flexible( @@ -143,7 +143,7 @@ class BillingCounterView extends StatelessWidget { AppSpaces.verticalMedium, const LineView(), AppSpaces.verticalLarge, - const Row( + Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 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..45258e5 --- /dev/null +++ b/lib/application/views/businessAccounts/views/TransactionPOSReturnVC.dart @@ -0,0 +1,211 @@ +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() { + // TODO: implement 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..c48667e --- /dev/null +++ b/lib/application/views/businessAccounts/views/TransactionPosDamageVC.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/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() { + // TODO: implement 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..4e9e87c --- /dev/null +++ b/lib/application/views/businessAccounts/views/ViewPOSOrderVC.dart @@ -0,0 +1,753 @@ +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/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, + 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 8116eca..d546914 100644 --- a/lib/application/views/create_order_module/CartVC.dart +++ b/lib/application/views/create_order_module/CartVC.dart @@ -22,9 +22,10 @@ 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 { final DrawerWidgetSelect delegateDrawer; @@ -77,7 +78,7 @@ class _CartVCState extends BaseStatefulState { CreateAndUpdateOrder .cartOrder.selectedTableName ?? "", - style: const TextStyle( + style: TextStyle( fontFamily: MyFonts.Medium, fontSize: MyFonts.normal, color: MyColors.black), @@ -86,33 +87,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, ))), ], ), @@ -148,7 +132,7 @@ class _CartVCState extends BaseStatefulState { alignment: Alignment.centerRight, child: Text( '${AppLocalizations.of(context)!.total_amount} ${CreateAndUpdateOrder.cartOrder.totalCartPrice?.toStringAsFixed(2) ?? 0.0} ${sharedPrefs.currency}', - style: const TextStyle( + style: TextStyle( fontWeight: FontWeight.bold, fontSize: MyFonts.normal, fontFamily: MyFonts.Bold, @@ -312,13 +296,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( diff --git a/lib/application/views/create_order_module/HoldOrderVC.dart b/lib/application/views/create_order_module/HoldOrderVC.dart index b8511da..5f82167 100644 --- a/lib/application/views/create_order_module/HoldOrderVC.dart +++ b/lib/application/views/create_order_module/HoldOrderVC.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:wosull/application/interfaces/DrawerWidgetSelect.dart'; import 'package:wosull/application/model/CreateAndUpdateOrder.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/create_order_module/states/CashierState.dart'; @@ -10,14 +11,14 @@ import 'package:wosull/application/views/create_order_module/views/popups/Paymen 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(); @@ -35,6 +36,7 @@ class _HoldOrderVCState extends BaseStatefulState { @override Widget build(BuildContext context) { return Scaffold( + backgroundColor: MyColors.white, body: Padding( padding: const EdgeInsets.all(12), child: Column( @@ -74,13 +76,7 @@ class _HoldOrderVCState extends BaseStatefulState { itemCount: cartItems.length, ); } else { - return Align( - alignment: Alignment.center, - child: Image.asset( - ThemeImage.emptyImage, - height: 128, - ), - ); + return const EmptyDataWidget(); } } else { return AppLoader(); @@ -116,13 +112,7 @@ class _HoldOrderVCState extends BaseStatefulState { itemCount: cartItems.length, ); } else { - return Align( - alignment: Alignment.center, - child: Image.asset( - ThemeImage.emptyImage, - height: 128, - ), - ); + return const EmptyDataWidget(); } } else { return AppLoader(); 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 02986f6..8ee6364 100644 --- a/lib/application/views/create_order_module/viewModels/CartViewModel.dart +++ b/lib/application/views/create_order_module/viewModels/CartViewModel.dart @@ -489,7 +489,6 @@ class CartViewModel with ChangeNotifier { _cashierState = CashierState.sendToKitchen; } } - createOrderId = response.orderModel!.id ?? ''; await clearCartData(); 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..dfcb68c --- /dev/null +++ b/lib/application/views/create_order_module/viewModels/CounterCloseViewMdoel.dart @@ -0,0 +1,64 @@ +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) { + 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 83b7ae6..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'; @@ -7,25 +6,19 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; 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/Combo/SearchComboItemModel.dart'; import 'package:wosull/application/model/CreateAndUpdateOrder.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/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/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'; @@ -50,12 +43,12 @@ class CreateOrderViewModel with ChangeNotifier { late ItemSubCategory itemSubCategory; var searchController = ''; - //bool isConnected = false; late var selectedTable = StoreTable(); + var repository = CreateOrderRepository(); + String tableName = ''; - //Store store = Store(name: ""); int categoryPosition = 0; int selectedSubCategoryPosition = 0; int selectedService = 0; @@ -120,25 +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 { - await APIManager() - .fetchData(Constants.GET_STORE_CATEGORY_LIST, getCategoryParam()) - .then((value) { + await repository.fetchCategories(getCategoryParam()).then((response) { getSelectedService(); - final response = ItemCategoryResponse.fromJson(value); if (response.success && response.categories.isNotEmpty) { itemCategories.clear(); itemCategories.addAll(response.categories); @@ -157,10 +144,7 @@ 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); @@ -186,6 +170,8 @@ 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) { @@ -210,12 +196,7 @@ class CreateOrderViewModel with ChangeNotifier { '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(); @@ -294,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) {}); @@ -312,52 +285,22 @@ class CreateOrderViewModel with ChangeNotifier { } Future searchItems(String searchValue) async { - if (!isConnected) { + await repository.searchItems(searchValue).then((value) async { searchedItems.clear(); - searchedItems.addAll(objectbox.searchItems(searchValue)); - notifyListeners(); - } else { - Map data = { - 'store_id': sharedPrefs.storeId, - 'search_value': searchValue, - 'page': 1 - }; - await APIManager() - .fetchData(Constants.SEARCH_ALL_ITEMS, data) - .then((value) async { + if (!isConnected) { searchedItems.clear(); - final response = SearchItemResponse.fromJson(value); + searchedItems.addAll(value); + notifyListeners(); + } else { await searchCombo(searchValue); - if (response.success!) { - if (response.item!.isNotEmpty) { - if (response.item!.first.storeItems!.isNotEmpty) { - searchedItems.addAll(response.item!.first.storeItems!); - notifyListeners(); - } - } - } - }).onError((error, stackTrace) {}); - } + 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) {}); } @@ -380,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); @@ -395,37 +331,19 @@ 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 { - Map data = {}; - data = { - 'store_id': sharedPrefs.storeId, - 'order_id': id, - 'status': status, - }; - - print(jsonEncode(data)); - 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 == Constants.cancelled) { isCartShow = false; @@ -437,7 +355,6 @@ class CreateOrderViewModel with ChangeNotifier { } }).onError((error, stackTrace) { _cashierState = CashierState.error; - // Utils.hideProgressBar(context); }); } @@ -456,30 +373,16 @@ class CreateOrderViewModel with ChangeNotifier { } 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) { @@ -625,58 +528,19 @@ class CreateOrderViewModel with ChangeNotifier { 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': services[selectedService].name!, - '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 { - data = { - 'payment_mode': paymentMode, - 'total_discount': totalDiscount, - 'discountId': discountId, - 'billing_counter_id': sharedPrefs.billingCounterId, - 'store_id': sharedPrefs.storeId, - 'cart_id': sharedPrefs.cartID, - '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 = { - 'billing_counter_id': sharedPrefs.billingCounterId, - '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); + await repository + .sendToKitchen( + paymentStatus, + status, + changeBalanceAmount, + deliveryNotes, + timer, + amount, + totalAmount, + paymentMode, + totalDiscount, + discountId) + .then((response) async { if (response.success!) { if (paymentStatus) { _cashierState = CashierState.createOrder; @@ -730,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); @@ -851,6 +707,8 @@ 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! && @@ -860,9 +718,10 @@ class CreateOrderViewModel with ChangeNotifier { // } else { //edit + print('on eidt'); isCartShow = true; CreateAndUpdateOrder.cartOrder.clearCart(); - getCartById(newOrder.cart!.id!, newOrder.id!); + await getCartById(newOrder.cart!.id!, newOrder.id!); } } @@ -1127,4 +986,23 @@ class CreateOrderViewModel with ChangeNotifier { 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/PaymentOptionViewModel.dart b/lib/application/views/create_order_module/viewModels/PaymentOptionViewModel.dart index c98bf47..75eaee9 100644 --- a/lib/application/views/create_order_module/viewModels/PaymentOptionViewModel.dart +++ b/lib/application/views/create_order_module/viewModels/PaymentOptionViewModel.dart @@ -2,7 +2,9 @@ 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'; @@ -21,8 +23,10 @@ class PaymentOptionViewModel with ChangeNotifier { String discountId = ''; double totalAmount = 0.0; double subTotalAmount = 0.0; + List paymentMethod = []; void disposeData() { + paymentMethod.clear(); enable = false; isCash = true; isCard = false; @@ -37,6 +41,15 @@ class PaymentOptionViewModel with ChangeNotifier { 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) { @@ -218,11 +231,11 @@ class PaymentOptionViewModel with ChangeNotifier { } } - void setPaymentMethod(String? data) { + void setPaymentMethod(PaymentMethod? data) { if (data == null) { selectedPaymentMethod = ''; } else { - selectedPaymentMethod = data; + selectedPaymentMethod = data.paymentMethod; } } } diff --git a/lib/application/views/create_order_module/views/PrintInvoiceVC.dart b/lib/application/views/create_order_module/views/PrintInvoiceVC.dart index 8c7bb0c..7c41e51 100644 --- a/lib/application/views/create_order_module/views/PrintInvoiceVC.dart +++ b/lib/application/views/create_order_module/views/PrintInvoiceVC.dart @@ -10,6 +10,7 @@ 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'; @@ -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 index 3a70775..68bf432 100644 --- a/lib/application/views/create_order_module/views/PrintReceiptVC.dart +++ b/lib/application/views/create_order_module/views/PrintReceiptVC.dart @@ -12,6 +12,7 @@ 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'; @@ -52,6 +53,7 @@ class _PrintReceiptVCState extends State { viewModel = context.watch(); return Scaffold( resizeToAvoidBottomInset: true, + backgroundColor: MyColors.white, appBar: AppBar( leading: BackButton( color: MyColors.black1, @@ -68,7 +70,7 @@ class _PrintReceiptVCState extends State { child: Container( width: double.infinity, color: MyColors.white, - padding: const EdgeInsets.all(16), + padding: const EdgeInsets.all(10), child: isConnected ? viewModel.order.status == Status.LOADING ? AppLoader() @@ -88,7 +90,7 @@ class _PrintReceiptVCState extends State { mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ - getActionButtons(), + getActionButtons(order.orderStatus == Constants.completed), AppSpaces.verticalLarge, Screenshot( controller: screenshotController, @@ -99,7 +101,10 @@ class _PrintReceiptVCState extends State { mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ - Image.asset(ThemeImage.logo), + Image.asset( + ThemeImage.wosulLogo, + width: 80, + ), AppSpaces.verticalLarge, const Text( 'info@wosul.ae', @@ -318,7 +323,7 @@ class _PrintReceiptVCState extends State { mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ - getActionButtons(), + getActionButtons(order.status == Constants.completed), AppSpaces.verticalLarge, Screenshot( controller: screenshotController, @@ -329,25 +334,23 @@ class _PrintReceiptVCState extends State { mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ - Image.asset(ThemeImage.logo), - AppSpaces.verticalLarge, - const Text( - 'info@wosul.ae', - style: ThemeText.textStyleSmallDJMono, + Image.asset( + ThemeImage.wosulLogo, + width: 80, ), - AppSpaces.verticalSmall, - const Text( - 'Tel :0549249523', + AppSpaces.verticalLarge, + Text( + order.storeId!.email, style: ThemeText.textStyleSmallDJMono, ), AppSpaces.verticalSmall, - const Text( - 'VAT Reg. #: 45398587537', + Text( + 'Tel: ${order.storeId!.phone}', style: ThemeText.textStyleSmallDJMono, ), AppSpaces.verticalSmall, - const Text( - 'Address :شارع العليا العام - الرياض', + Text( + 'Address: ${order.storeId!.address}', style: ThemeText.textStyleSmallDJMono, ), AppSpaces.verticalLarge, @@ -441,20 +444,6 @@ class _PrintReceiptVCState extends State { 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: [ @@ -469,29 +458,15 @@ class _PrintReceiptVCState extends State { ], ), AppSpaces.verticalMedium, - const Row( + Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( + const 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', + '${sharedPrefs.currency} ${order.amount!.toStringAsFixed(2)}', style: ThemeText.textStyleMediumDJMono, ), ], @@ -526,11 +501,6 @@ class _PrintReceiptVCState extends State { style: ThemeText.textStyleMediumDJMono, ), AppSpaces.verticalSmall, - const Text( - 'شكراً لزيارتكم وعشمنا منكم وفيكم', - style: ThemeText.textStyleMediumDJMono, - ), - AppSpaces.verticalSmall, const Text( 'POWERED BY WOSUL', style: ThemeText.textStyleMediumDJMono, @@ -562,57 +532,55 @@ class _PrintReceiptVCState extends State { }).catchError((onError) {}); } - Widget getActionButtons() { + Widget getActionButtons(bool orderCompleted) { return Container( margin: - EdgeInsets.fromLTRB(isPortrait ? 8 : 80, 0, isPortrait ? 8 : 80, 0), - child: Row( - crossAxisAlignment: CrossAxisAlignment.end, - mainAxisAlignment: MainAxisAlignment.end, - children: [ - SizedBox( - width: 110, - child: CustomIconButton( - textColor: MyColors.white, - backgroundColor: MyColors.blueThemeColor, - onPressed: () {}, - icon: Icons.print, - heading: AppLocalizations.of(context)!.print_now, - ), - ), - AppSpaces.horizontalSmall, - SizedBox( - width: 140, - child: CustomIconButton( - textColor: MyColors.white, - backgroundColor: MyColors.blueThemeColor, - onPressed: () { - captureImage(); - }, - heading: AppLocalizations.of(context)!.download, - icon: Icons.download, - ), - ), - AppSpaces.horizontalSmall, - SizedBox( - width: 90, - child: 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, + 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(), + ), + ], + ), + Visibility( + visible: orderCompleted, + child: getDoneButton(), + ) + ], + ) + : Row( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + SizedBox( + width: 110, + child: getPrintButton(), + ), + AppSpaces.horizontalSmall, + SizedBox( + width: 140, + child: getDownloadButton(), + ), + AppSpaces.horizontalSmall, + Visibility( + visible: orderCompleted, + child: SizedBox( + width: 90, + child: getDoneButton(), + ), + ) + ], ), - ), - ], - ), ); } @@ -680,6 +648,45 @@ class _PrintReceiptVCState extends State { ); } + 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( diff --git a/lib/application/views/create_order_module/views/TabBarHomeVC.dart b/lib/application/views/create_order_module/views/TabBarHomeVC.dart index ba93b72..7def1a6 100644 --- a/lib/application/views/create_order_module/views/TabBarHomeVC.dart +++ b/lib/application/views/create_order_module/views/TabBarHomeVC.dart @@ -17,6 +17,7 @@ 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/PrintReceiptVC.dart'; @@ -65,6 +66,11 @@ class _TabBarHomeVCState extends BaseStatefulState { @override void initState() { context.read().getStoreDetails(); + Future.delayed(const Duration(seconds: 3), () { + if (sharedPrefs.billingCounterId.isEmpty) { + showCounters(); + } + }); super.initState(); } @@ -74,11 +80,13 @@ class _TabBarHomeVCState extends BaseStatefulState { // isConnected = // Provider.of(context) == // InternetConnectionStatus.connected; + if (viewModel.itemCategories.isEmpty && isConnected) { viewModel.fetchData(); } else { viewModel.setLoadingOffline(false); } + return Directionality( textDirection: TextDirection.ltr, child: SafeArea( @@ -136,13 +144,6 @@ class _TabBarHomeVCState extends BaseStatefulState { ); }), ))); - - // return WillPopScope( - // child: , - // onWillPop: () { - // viewModel.dispose(); - // return Future.value(false); - // }); } Widget getCategoryWidget() { @@ -330,6 +331,16 @@ class _TabBarHomeVCState extends BaseStatefulState { } 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, @@ -531,7 +542,7 @@ class _TabBarHomeVCState extends BaseStatefulState { Visibility( visible: viewModel.count(), child: SizedBox( - width: 105, + width: 90, child: CustomSimpleButton( textColor: MyColors.white, backGroundColor: @@ -775,9 +786,9 @@ class _TabBarHomeVCState extends BaseStatefulState { 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, @@ -785,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), ), )), @@ -973,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(); 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 e50d6d6..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'; @@ -44,7 +44,7 @@ class _CashOutVCState 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(c).orientation == Orientation.portrait; diff --git a/lib/application/views/create_order_module/views/popups/CounterCloseVC.dart b/lib/application/views/create_order_module/views/popups/CounterCloseVC.dart index 9ff16e7..1be1205 100644 --- a/lib/application/views/create_order_module/views/popups/CounterCloseVC.dart +++ b/lib/application/views/create_order_module/views/popups/CounterCloseVC.dart @@ -1,5 +1,8 @@ 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'; @@ -15,6 +18,13 @@ class CounterCloseVC extends StatefulWidget { class _CounterCloseVCState extends State { bool isPortrait = true; + var viewModel = CounterCloseViewModel(); + + @override + void initState() { + context.read().getBusinessRegisterById(); + super.initState(); + } @override Widget build(BuildContext context) { @@ -24,7 +34,7 @@ class _CounterCloseVCState 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(c).orientation == Orientation.portrait; @@ -44,19 +54,26 @@ class _CounterCloseVCState extends State { Padding( padding: const EdgeInsets.all(12), child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ const CustomOptionalTitle(hint: 'Credit'), AppSpaces.verticalSmall, CustomTextFieldForm( keyboardType: TextInputType.number, - onChanged: (value) {}, + initialValue: viewModel.creditAmount, + onChanged: (value) { + viewModel.creditAmount = value; + }, hintText: '0.0'), AppSpaces.verticalMedium, const CustomOptionalTitle(hint: 'Cash'), AppSpaces.verticalSmall, CustomTextFieldForm( keyboardType: TextInputType.number, - onChanged: (value) {}, + initialValue: viewModel.cashAmount, + onChanged: (value) { + viewModel.cashAmount = value; + }, hintText: '0.0'), ], ), @@ -71,7 +88,11 @@ class _CounterCloseVCState extends State { child: CustomSimpleButton( textColor: MyColors.white, backGroundColor: MyColors.blueThemeColor, - onPressed: () async {}, + isLoading: viewModel.isLoading, + onPressed: () async { + await viewModel.isValidate(); + checkState(); + }, heading: 'Close', ), ), @@ -85,4 +106,10 @@ class _CounterCloseVCState extends State { }), )); } + + 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 256d22b..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', ), @@ -121,24 +129,71 @@ class _DeliveryPartnerPopUpState extends State { ); } - Widget partnersWidget(partners) { - print(viewModel.selectedType); - 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() { 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 adba0a2..fa0b8ff 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:sizer/sizer.dart'; -import 'package:wosull/application/ViewModel/InventoryViewModel.dart'; import 'package:wosull/application/model/tables/GetStoreTable.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/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'; @@ -49,16 +51,15 @@ class _DineInPopupState 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( - 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 +76,14 @@ 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]); }, - child: Text( - AppLocalizations.of(context)!.apply, - style: const TextStyle( - fontSize: MyFonts.normalButton, - color: MyColors.white, - fontFamily: MyFonts.Bold), - ), + heading: AppLocalizations.of(context)!.apply, ), ), ], @@ -224,7 +214,7 @@ class _DineInPopupState extends State { // = await (Connectivity().checkConnectivity()); var items = []; if (isConnected) { - final viewModel = InventoryViewModel(); + final viewModel = WosulRepository(); await viewModel .getData(Constants.GET_STORE_TABLES, Constants.getStorePayload()) .then((value) { @@ -335,7 +325,7 @@ class _DineInPopupState extends State { children: [ Row( children: [ - const Text( + Text( 'Seats:', style: TextStyle( fontSize: MyFonts.H1, @@ -343,9 +333,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 @@ -361,71 +349,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( @@ -433,7 +375,7 @@ class _DineInPopupState extends State { Expanded( child: Row( children: [ - const Text( + Text( 'Seats:', style: TextStyle( fontSize: MyFonts.H1, @@ -469,7 +411,7 @@ class _DineInPopupState extends State { ), Text( AppLocalizations.of(context)!.available, - style: const TextStyle( + style: TextStyle( fontSize: MyFonts.H2, fontWeight: FontWeight.bold, fontFamily: MyFonts.Bold, @@ -491,7 +433,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, @@ -513,7 +455,7 @@ class _DineInPopupState extends State { ), Text( AppLocalizations.of(context)!.selected, - style: const TextStyle( + style: TextStyle( fontSize: MyFonts.H2, fontWeight: FontWeight.bold, fontFamily: MyFonts.Bold, 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 205b9bf..ecfb4b6 100644 --- a/lib/application/views/create_order_module/views/popups/ItemModifiersPopUp.dart +++ b/lib/application/views/create_order_module/views/popups/ItemModifiersPopUp.dart @@ -11,6 +11,7 @@ import 'package:wosull/application/theme/MyFonts.dart'; import 'package:wosull/helpers/AppSpaces.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; @@ -35,10 +36,10 @@ class _ItemModifiersPopUpState extends State { super.initState(); 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(); + 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; @@ -54,7 +55,7 @@ class _ItemModifiersPopUpState 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 = @@ -82,7 +83,7 @@ class _ItemModifiersPopUpState extends State { children: [ Text( AppLocalizations.of(context)!.note, - style: const TextStyle( + style: TextStyle( fontSize: MyFonts.normalButton, fontWeight: FontWeight.w600, fontFamily: MyFonts.DMREGULAR, @@ -100,232 +101,276 @@ class _ItemModifiersPopUpState extends State { 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 - .item - .modifiers![position] - .options![i] - .isSelected = true; - modifier.selected!.add(widget + if (widget.item.modifiers[position].options + .isNotEmpty) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + HeadingText( + widget.item.modifiers[position].name), + AppSpaces.verticalSmall, + GridView.builder( + shrinkWrap: true, + itemCount: widget.item + .modifiers[position].options.length, + physics: + const NeverScrollableScrollPhysics(), + gridDelegate: + SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: widget .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 < + .modifiers[position] + .options + .isEmpty + ? 1 + : 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 + .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 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 + .item + .modifiers[ + position] + .options + .length; + j++) { widget .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 + .modifiers[position] + .options[j] + .isSelected = false; + } + 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( + .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] - .name, - style: TextStyle( - fontSize: MyFonts.H2, - fontFamily: - MyFonts.Bold, + .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![ + .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( + widget .item - .modifiers![ + .modifiers[ position] - .options![i] - .isSelected - ? MyColors.white - : MyColors - .textColorBlack, - ), - ), - ], - )) - ], - ), - )); - }); + .options[i] + .name, + style: TextStyle( + fontSize: + MyFonts.H2, + fontFamily: + MyFonts.Bold, + color: widget + .item + .modifiers[ + position] + .options[ + i] + .isSelected + ? MyColors + .white + : MyColors + .textColorBlack, + fontWeight: + FontWeight + .bold), + ), + AppSpaces.verticalSmall, + Text( + '${widget.item.modifiers[position].options[i].price.toString()} ${sharedPrefs.currency}', + style: TextStyle( + fontSize: + MyFonts.normal, + fontFamily: + MyFonts.Medium, + color: widget + .item + .modifiers[ + position] + .options[i] + .isSelected + ? MyColors.white + : MyColors + .textColorBlack, + ), + ), + ], + )) + ], + ), + )); + }) + ], + ); + } }, - itemCount: widget.item.modifiers!.length, + itemCount: widget.item.modifiers.length, ), AppSpaces.verticalMedium, Row( @@ -380,7 +425,7 @@ class _ItemModifiersPopUpState extends State { }, child: Text( AppLocalizations.of(context)!.apply, - style: const TextStyle( + style: TextStyle( fontSize: MyFonts.normalButton, color: MyColors.white, fontFamily: MyFonts.Bold), 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 d91f6cd..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'; @@ -36,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; 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 bb34df9..f074bd2 100644 --- a/lib/application/views/create_order_module/views/popups/PaymentOptionPopUpVC.dart +++ b/lib/application/views/create_order_module/views/popups/PaymentOptionPopUpVC.dart @@ -3,6 +3,7 @@ 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/invoice/PaymentMethod.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/theme/MyFonts.dart'; import 'package:wosull/application/theme/MySeparator.dart'; @@ -63,7 +64,7 @@ class _PaymentOptionPopUpVCState 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 = @@ -181,7 +182,7 @@ class _PaymentOptionPopUpVCState width: 2, ), const Text( - 'Credit Card', + 'Credit', style: TextStyle( fontSize: 10, color: MyColors.black, @@ -301,7 +302,7 @@ class _PaymentOptionPopUpVCState Text( AppLocalizations.of(context)! .cash, - style: const TextStyle( + style: TextStyle( fontSize: MyFonts.H2, color: MyColors.black, fontFamily: @@ -352,8 +353,8 @@ class _PaymentOptionPopUpVCState width: 8, ), Text( - 'Credit Card', - style: const TextStyle( + 'Credit', + style: TextStyle( fontSize: MyFonts.H2, color: MyColors.black, fontFamily: @@ -451,14 +452,14 @@ class _PaymentOptionPopUpVCState 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: [ - const Text( - 'Credit Card', + Text( + 'Credit', style: ThemeText.textStylePageHeading, ), AppSpaces.verticalMedium, @@ -514,7 +515,7 @@ class _PaymentOptionPopUpVCState 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, @@ -760,13 +761,15 @@ class _PaymentOptionPopUpVCState } Widget paymentMethod() { - return DropdownSearch( + return DropdownSearch( dropdownButtonProps: ThemeDropDown.dropdownButtonProps, - popupProps: const PopupProps.menu( - fit: FlexFit.loose, constraints: BoxConstraints(maxHeight: 250)), - items: Constants.paymentMethodForOrders, - itemAsString: (String u) => u, - onChanged: (String? data) { + popupProps: PopupProps.menu( + 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'), @@ -817,7 +820,7 @@ class _PaymentOptionPopUpVCState visible: viewModel.isCredit, child: Card( child: Container( - padding: const EdgeInsets.all(MyFonts.normal), + padding: EdgeInsets.all(MyFonts.normal), width: double.infinity, child: Column( mainAxisAlignment: MainAxisAlignment.start, @@ -841,7 +844,7 @@ class _PaymentOptionPopUpVCState children: [ Text( AppLocalizations.of(context)!.credit, - style: const TextStyle( + style: TextStyle( fontSize: MyFonts.normal, fontWeight: FontWeight.w600, fontFamily: MyFonts.DMREGULAR, @@ -858,7 +861,7 @@ class _PaymentOptionPopUpVCState SizedBox( height: 42, child: TextField( - style: const TextStyle( + style: TextStyle( fontFamily: MyFonts.DMREGULAR, fontSize: MyFonts.normal, color: MyColors.black), @@ -896,7 +899,7 @@ class _PaymentOptionPopUpVCState children: [ Text( AppLocalizations.of(context)!.balance_change, - style: const TextStyle( + style: TextStyle( fontSize: MyFonts.normal, fontWeight: FontWeight.w600, fontFamily: MyFonts.DMREGULAR, @@ -913,7 +916,7 @@ class _PaymentOptionPopUpVCState SizedBox( height: 42, child: TextField( - style: const TextStyle( + style: TextStyle( fontFamily: MyFonts.DMREGULAR, fontSize: MyFonts.normal, color: MyColors.black), @@ -959,7 +962,7 @@ class _PaymentOptionPopUpVCState widget.status == "ready" ? AppLocalizations.of(context)!.done : AppLocalizations.of(context)!.send_to_kitchen, - style: const TextStyle( + style: TextStyle( fontSize: MyFonts.bold, color: MyColors.white, fontFamily: MyFonts.Bold), 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 6de3d24..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'; @@ -45,7 +45,7 @@ class _RegisterCashVCState 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(c).orientation == Orientation.portrait; 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 53a8844..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'; @@ -50,9 +51,7 @@ class CartItemView extends StatelessWidget { ? Image.network(storeItems.imageUrl) : Image.asset(ThemeImage.wosulLogo), ), - const SizedBox( - width: 4, - ), + AppSpaces.horizontalMedium, Expanded( flex: 2, child: Column( @@ -69,9 +68,7 @@ class CartItemView extends StatelessWidget { 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: [ diff --git a/lib/application/views/create_order_module/widgets/ProductItemView.dart b/lib/application/views/create_order_module/widgets/ProductItemView.dart index cef3f9b..d90fdba 100644 --- a/lib/application/views/create_order_module/widgets/ProductItemView.dart +++ b/lib/application/views/create_order_module/widgets/ProductItemView.dart @@ -111,11 +111,9 @@ class ProductItemView extends StatelessWidget { topRight: Radius.circular(12), bottomRight: Radius.circular(12)), ), - child: Center( - child: Text( - storeItems.deliveryPartner, - style: ThemeText.textStyleSmallWhite, - ), + child: Text( + storeItems.deliveryPartner, + style: ThemeText.textStyleSmallWhite, ), )), ) @@ -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 a242f33..f265834 100644 --- a/lib/application/views/dashboard/HomeVC.dart +++ b/lib/application/views/dashboard/HomeVC.dart @@ -8,6 +8,7 @@ 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/utils/AppLoader.dart'; import 'package:wosull/application/views/dashboard/viewModel/DashboardViewModel.dart'; import 'package:wosull/application/views/dashboard/widgets/AnimatedProgressBar.dart'; import 'package:wosull/application/views/dashboard/widgets/InvoiceDetailsView.dart'; @@ -44,9 +45,6 @@ class _HomeVCState extends BaseStatefulState implements ReportsCVS { @override void initState() { - // WidgetsBinding.instance.addPostFrameCallback((timeStamp) { - // Provider.of(context, listen: false).getService(); - // }); context.read().getService(false); super.initState(); } @@ -63,8 +61,6 @@ class _HomeVCState extends BaseStatefulState implements ReportsCVS { @override Widget build(BuildContext context) { viewModel = context.watch(); - // viewModel.getService(); - // viewModel = Provider.of(context); return SafeArea( child: Scaffold( backgroundColor: MyColors.fillColor, @@ -159,9 +155,7 @@ class _HomeVCState extends BaseStatefulState implements ReportsCVS { Container( padding: const EdgeInsets.all(12), child: viewModel.isLoading - ? const Center( - child: CircularProgressIndicator(), - ) + ? AppLoader() : Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -194,7 +188,7 @@ class _HomeVCState extends BaseStatefulState implements ReportsCVS { "0.0")), ], ), - const SizedBox(height: 8), + AppSpaces.verticalMedium, Row( children: [ Flexible( @@ -220,7 +214,7 @@ class _HomeVCState extends BaseStatefulState implements ReportsCVS { "0")), ], ), - const SizedBox(height: 8), + AppSpaces.verticalMedium, Row( children: [ Flexible( @@ -326,50 +320,161 @@ class _HomeVCState extends BaseStatefulState implements ReportsCVS { ), AppSpaces.verticalMedium, - TodaySaleGraph( - todaySales: - viewModel.graphData.todaySales ?? [], - ), - AppSpaces.verticalMedium, - TodayPOSSales( - todaySales: - viewModel.graphData.todaySales ?? [], - ), - AppSpaces.verticalMedium, - RevenueGraph( - data: viewModel - .graphData.totalIncomeExpense ?? - []), - AppSpaces.verticalMedium, - InvoiceStatusGraph( - data: viewModel - .graphData.allInvoiceStatus ?? - []), - AppSpaces.verticalMedium, - POSStatusGraph( - data: viewModel.graphData.allPosStatus ?? - []), - AppSpaces.verticalMedium, - POSOrderCountDayWiseGraph( - data: viewModel - .graphData.posOrderCountDayWise ?? - [], - ), + + 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 ?? + [], + ), + ), + AppSpaces.horizontalMedium, + Flexible( + child: RevenueGraph( + data: viewModel.graphData + .totalIncomeExpense ?? + []), + ), + ], + ), + AppSpaces.verticalMedium, - POSOrderValueDayWise( - data: viewModel.graphData.array ?? []), + 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, - POSOrderCountTimeWiseGraph( - data: viewModel.graphData - .posOrderCountTodayTimewise ?? - [], - ), + + viewModel.isPortrait + ? Column(children: [ + POSOrderCountDayWiseGraph( + data: viewModel.graphData + .posOrderCountDayWise ?? + [], + ), + AppSpaces.verticalMedium, + POSOrderValueDayWise( + data: viewModel.graphData.array ?? + []), + ]) + : Row( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Flexible( + child: POSOrderCountDayWiseGraph( + data: viewModel.graphData + .posOrderCountDayWise ?? + [], + ), + ), + AppSpaces.horizontalMedium, + Flexible( + child: POSOrderValueDayWise( + data: viewModel + .graphData.array ?? + []), + ), + ], + ), + AppSpaces.verticalMedium, - POSOrderValueTimeWise( - data: viewModel.graphData - .posOrderCountTodayTimewise ?? - [], - ), + + viewModel.isPortrait + ? Column(children: [ + POSOrderCountTimeWiseGraph( + data: viewModel.graphData + .posOrderCountTodayTimewise ?? + [], + ), + AppSpaces.verticalMedium, + POSOrderValueTimeWise( + data: viewModel.graphData + .posOrderCountTodayTimewise ?? + [], + ), + ]) + : 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( 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..08d1407 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, ), ], 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/POSStatusGraph.dart b/lib/application/views/dashboard/widgets/POSStatusGraph.dart index 6e266e3..6dceb9c 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, ), ], diff --git a/lib/application/views/dashboard/widgets/RevenueGraph.dart b/lib/application/views/dashboard/widgets/RevenueGraph.dart index 66a6a9d..fb0f3f2 100644 --- a/lib/application/views/dashboard/widgets/RevenueGraph.dart +++ b/lib/application/views/dashboard/widgets/RevenueGraph.dart @@ -46,7 +46,7 @@ class RevenueGraph extends StatelessWidget { AppSpaces.verticalLarge, data.isNotEmpty ? AspectRatio( - aspectRatio: 2, + aspectRatio: 1.70, child: PieChart( PieChartData( pieTouchData: PieTouchData( diff --git a/lib/application/views/dashboard/widgets/TodaySaleGraph.dart b/lib/application/views/dashboard/widgets/TodaySaleGraph.dart index c224421..063ea88 100644 --- a/lib/application/views/dashboard/widgets/TodaySaleGraph.dart +++ b/lib/application/views/dashboard/widgets/TodaySaleGraph.dart @@ -10,7 +10,7 @@ import 'package:wosull/helpers/ThemeText.dart'; class TodaySaleGraph extends StatelessWidget { List gradientColors = [ - MyColors.blueThemeColor, + MyColors.backColorBlue50, MyColors.blueThemeColor, ]; List todaySales = []; @@ -78,7 +78,7 @@ class TodaySaleGraph extends StatelessWidget { todaySales[value.toInt()].id!.createdAt!), style: style); } else { - text = Text('', style: style); + text = const Text('', style: style); } return SideTitleWidget( @@ -89,6 +89,29 @@ class TodaySaleGraph extends StatelessWidget { LineChartData mainData() { return LineChartData( + minY: 0, + minX: 0, + gridData: FlGridData( + show: true, + getDrawingHorizontalLine: (value) => const FlLine( + color: MyColors.fillColorGray, + strokeWidth: 1, + ), + getDrawingVerticalLine: (value) { + return const FlLine( + color: MyColors.fillColorGray, + strokeWidth: 1, + ); + }, + drawVerticalLine: true, + horizontalInterval: 1, + verticalInterval: 1, + ), + lineTouchData: LineTouchData(enabled: true), + borderData: FlBorderData( + show: true, + border: Border.all(color: MyColors.fillColorGray2), + ), titlesData: FlTitlesData( show: true, rightTitles: const AxisTitles( @@ -108,6 +131,7 @@ class TodaySaleGraph extends StatelessWidget { ), lineBarsData: [ LineChartBarData( + show: true, spots: getSpots(), isCurved: true, gradient: LinearGradient( @@ -115,6 +139,7 @@ class TodaySaleGraph extends StatelessWidget { ), barWidth: 5, isStrokeCapRound: true, + isStepLineChart: true, dotData: const FlDotData( show: true, ), @@ -138,6 +163,7 @@ class TodaySaleGraph extends StatelessWidget { 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/viewModels/NewDiscountViewModel.dart b/lib/application/views/discountModule/viewModels/NewDiscountViewModel.dart index 7cc7d30..13b3433 100644 --- a/lib/application/views/discountModule/viewModels/NewDiscountViewModel.dart +++ b/lib/application/views/discountModule/viewModels/NewDiscountViewModel.dart @@ -11,14 +11,10 @@ import 'package:wosull/application/model/store/GetItemsByStoreId.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/DatePicker.dart'; import 'package:wosull/helpers/Utils.dart'; class NewDiscountViewModel with ChangeNotifier { - var items = [ - 'Percentage', - 'Amount', - ]; - String selectedDiscountType = "Percentage"; late StoreDiscount storeDiscount; @@ -26,27 +22,25 @@ class NewDiscountViewModel with ChangeNotifier { CRUDOperationState get crudOperation => _crudOperation; - final types = [ - "Manual", - "Automatic", - ]; String typesGroupValue = "Manual"; - String verticalGroupValue = ""; + String verticalGroupValue = ''; bool isLoading = false; bool isGettingItems = false; bool isTablet = true; bool isPortrait = true; + String type = '1'; + List filteredItems = []; List data = []; disposeData() { isLoading = false; isGettingItems = false; - selectedDiscountType = items[0]; - typesGroupValue = types[0]; - verticalGroupValue = Constants.discountFilters[0]; + selectedDiscountType = Constants.discountType[0]; + typesGroupValue = Constants.types[0]; + verticalGroupValue = ''; filteredItems.clear(); data.clear(); } @@ -87,34 +81,29 @@ class NewDiscountViewModel with ChangeNotifier { } } - void presentDatePicker(BuildContext context, bool isStart) { + Future presentDatePicker(BuildContext context, bool isStart) async { // 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) { - storeDiscount.discountStartDate = - DataTimeFormat.formatDateFromPicket(pickedDate); - } else { - storeDiscount.discountEndDate = - DataTimeFormat.formatDateFromPicket(pickedDate); - } - notifyListeners(); - }); + 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 == items[0] && + } else if (selectedDiscountType == Constants.discountType[0] && storeDiscount.discountPercentage == null) { Utils.showMessage('Enter Discount $selectedDiscountType'); } else { @@ -137,7 +126,7 @@ class NewDiscountViewModel with ChangeNotifier { 'limit_of_discount': storeDiscount.limitOfDiscount ?? 0.0, 'discount_start_date': storeDiscount.discountStartDate ?? '', 'discount_end_date': storeDiscount.discountEndDate ?? '', - 'type': selectedDiscountType == 'Percentage' ? '2' : '1', + 'type': type, 'is_deleted': false, 'products': storeDiscount.products, 'categories': storeDiscount.categories, @@ -190,9 +179,11 @@ class NewDiscountViewModel with ChangeNotifier { 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"; final response = await APIManager().fetchData( Constants.GET_STORE_CATEGORY_LIST, Constants.getStorePayload()); final itemsResponse = ItemCategoryResponse.fromJson(response); @@ -203,6 +194,11 @@ class NewDiscountViewModel with ChangeNotifier { data.addAll(itemsResponse.categories); } } else { + if (verticalGroupValue == Constants.discountFilters.elementAt(1)) { + type = "2"; + } else if (verticalGroupValue == Constants.discountFilters.elementAt(3)) { + type = "4"; + } final response = await APIManager().fetchData( Constants.GET_STORE_CATEGORY_LIST_ID, Constants.getStorePayload()); final getItemsByStoreId = GetItemsByStoreId.fromJson(response); diff --git a/lib/application/views/discountModule/views/DiscountVC.dart b/lib/application/views/discountModule/views/DiscountVC.dart index ee47827..e66bc59 100644 --- a/lib/application/views/discountModule/views/DiscountVC.dart +++ b/lib/application/views/discountModule/views/DiscountVC.dart @@ -59,13 +59,13 @@ class _DiscountVCState extends BaseStatefulState { children: [ pageLabel(), AppSpaces.horizontalSmall, - newDiscountButton(), - Flexible( - child: PageLimitDropdown(onChange: (value) { + Flexible(child: newDiscountButton()), + AppSpaces.horizontalSmall, + PageLimitDropdown(onChange: (value) { viewModel.fetch( isRefresh: true, limit: int.parse(value!)); - })) + }) ], ), AppSpaces.verticalSmall, @@ -77,14 +77,22 @@ class _DiscountVCState extends BaseStatefulState { children: [ pageLabel(), AppSpaces.horizontalSmall, - newDiscountButton(), + SizedBox( + width: 110, + child: newDiscountButton(), + ), AppSpaces.horizontalSmall, getSearchBar(), - Flexible( - child: PageLimitDropdown(onChange: (value) { - viewModel.fetch( - isRefresh: true, limit: int.parse(value!)); - })) + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + PageLimitDropdown(onChange: (value) { + viewModel.fetch( + isRefresh: true, + limit: int.parse(value!)); + }) + ], + ) ], ), AppSpaces.verticalMedium, @@ -139,7 +147,7 @@ class _DiscountVCState extends BaseStatefulState { context: context, builder: (context) { return ViewDiscountVC( - storeDiscount: discount, + discount, ); }, ); @@ -198,17 +206,14 @@ class _DiscountVCState extends BaseStatefulState { } Widget newDiscountButton() { - return SizedBox( - width: 130, - child: CustomSimpleButton( - height: 38, - textColor: MyColors.blueThemeColor, - backGroundColor: MyColors.backColorBlue50, - onPressed: () async { - toDiscount(false, StoreDiscount()); - }, - 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, ); } diff --git a/lib/application/views/discountModule/views/NewDiscountVC.dart b/lib/application/views/discountModule/views/NewDiscountVC.dart index 9e9244c..4a78ff3 100644 --- a/lib/application/views/discountModule/views/NewDiscountVC.dart +++ b/lib/application/views/discountModule/views/NewDiscountVC.dart @@ -3,14 +3,15 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:group_radio_button/group_radio_button.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/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'; @@ -58,6 +59,7 @@ class _NewDiscountVCState extends BaseStatefulState { Widget build(BuildContext context) { viewModel = context.watch(); return Scaffold( + backgroundColor: MyColors.fillColor, resizeToAvoidBottomInset: true, appBar: CustomAppBar( heading: AppLocalizations.of(context)!.add_discount, @@ -68,12 +70,13 @@ class _NewDiscountVCState extends BaseStatefulState { 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), ), @@ -202,9 +205,12 @@ class _NewDiscountVCState extends BaseStatefulState { } Widget getProductContainer() { + print(!(viewModel.verticalGroupValue.toLowerCase() == + Constants.discountFilters[0].toLowerCase()) || + viewModel.verticalGroupValue.isNotEmpty); return Visibility( - visible: viewModel.verticalGroupValue != - Constants.discountFilters.elementAt(0), + visible: !(viewModel.verticalGroupValue.toLowerCase() == + Constants.discountFilters[0].toLowerCase()), child: Container( height: 200, padding: const EdgeInsets.all(16), @@ -220,7 +226,7 @@ class _NewDiscountVCState extends BaseStatefulState { Row( children: [ Expanded( - flex: 2, + flex: viewModel.isPortrait ? 1 : 2, child: Text( AppLocalizations.of(context)!.choose_product, style: ThemeText.textStylePageHeading, @@ -261,51 +267,12 @@ class _NewDiscountVCState extends BaseStatefulState { onTap: () { viewModel.onChangeDiscountType(filteredItem); }, - child: Container( - margin: const EdgeInsets.all(4), - padding: const EdgeInsets.all(4), - decoration: BoxDecoration( - color: viewModel.storeDiscount.products! - .contains(filteredItem.id) || - viewModel - .storeDiscount.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: viewModel.storeDiscount - .products! - .contains( - filteredItem - .id) || - viewModel.storeDiscount - .categories! - .contains( - filteredItem.id) - ? MyColors.white - : MyColors.textColorBlack, - fontWeight: FontWeight.bold), - ), - ], - )) - ], - ), + child: DiscountFilterItemView( + products: + viewModel.storeDiscount.products ?? [], + categories: + viewModel.storeDiscount.categories ?? [], + filteredItem: filteredItem, )); }), ) @@ -341,7 +308,7 @@ class _NewDiscountVCState extends BaseStatefulState { onChanged: (value) { viewModel.changeDiscount(value); }, - items: viewModel.types, + items: Constants.types, itemBuilder: (item) => RadioButtonBuilder( item, ), @@ -420,9 +387,11 @@ class _NewDiscountVCState extends BaseStatefulState { DropdownSearch( selectedItem: viewModel.selectedDiscountType, dropdownButtonProps: ThemeDropDown.dropdownButtonProps, - popupProps: const PopupProps.menu( - fit: FlexFit.loose, constraints: BoxConstraints(maxHeight: 250)), - items: viewModel.items, + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: Constants.discountType, itemAsString: (String u) => u, onChanged: (String? data) { viewModel.updateDiscountType(data); @@ -431,9 +400,7 @@ class _NewDiscountVCState extends BaseStatefulState { MyColors.dropDownStyle(hint: 'Choose Discount Type'), ), AppSpaces.verticalMedium, - Visibility( - visible: viewModel.selectedDiscountType == viewModel.items[0], - child: getDiscountPercentageValueWidget()) + getDiscountPercentageValueWidget() ], ); } @@ -457,8 +424,10 @@ class _NewDiscountVCState extends BaseStatefulState { backgroundColor: MyColors.backFillColor, icon: Icons.calendar_month, heading: widget.isEdit - ? viewModel.storeDiscount.discountEndDate! - : viewModel.storeDiscount.discountEndDate ?? 'dd/mm/yyyy', + ? DataTimeFormat.getFormatDate( + viewModel.storeDiscount.discountEndDate ?? '') + : DataTimeFormat.getFormatDate( + viewModel.storeDiscount.discountEndDate ?? ''), onPressed: () { viewModel.presentDatePicker(context, false); }, @@ -470,8 +439,11 @@ class _NewDiscountVCState extends BaseStatefulState { backgroundColor: MyColors.backFillColor, icon: Icons.calendar_month, heading: widget.isEdit - ? viewModel.storeDiscount.discountStartDate! - : viewModel.storeDiscount.discountStartDate ?? 'dd/mm/yyyy', + ? DataTimeFormat.getFormatDate( + viewModel.storeDiscount.discountStartDate ?? '') + : DataTimeFormat.getFormatDate( + viewModel.storeDiscount.discountStartDate ?? '') ?? + 'dd/mm/yyyy', onPressed: () { viewModel.presentDatePicker(context, true); }, @@ -647,13 +619,11 @@ class _NewDiscountVCState extends BaseStatefulState { MandatoryTitleText( hint: viewModel.selectedDiscountType == 'Percentage' ? AppLocalizations.of(context)!.discount_percentage - : AppLocalizations.of(context)!.discount_value, + : 'Discount Amount', ), AppSpaces.verticalSmall, CustomTextFieldForm( - hintText: viewModel.selectedDiscountType == 'Percentage' - ? 'Enter Discount Percentage' - : 'Enter Discount Value', + hintText: 'Enter Discount ${viewModel.selectedDiscountType}', keyboardType: TextInputType.number, initialValue: viewModel.storeDiscount.discountPercentage ?? '', onChanged: (value) { 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 index 42b4051..5a616a4 100644 --- a/lib/application/views/discountModule/widgets/DiscountListView.dart +++ b/lib/application/views/discountModule/widgets/DiscountListView.dart @@ -4,9 +4,12 @@ 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 { @@ -34,10 +37,7 @@ class DiscountListView extends StatelessWidget { children: [ isPortrait ? Container() - : Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 48, - color: MyColors.containerBackColor, + : ListHeadingContainer( child: Row( children: [ Expanded( @@ -191,10 +191,7 @@ class DiscountListView 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(discount.name!)), @@ -210,15 +207,7 @@ class DiscountListView extends StatelessWidget { child: CustomSwitch( value: discount.getStatus(), onToggle: (value) { - // setState(() { - // if (value) { - // discount.status = "Active"; - // } else { - // discount.status = "Inactive"; - // } - // }); onUpdate(discount, value); - // _updateStatus(discount.id!, value); }, ), )), @@ -237,11 +226,7 @@ class DiscountListView 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: ActionPopUpContainer( child: getPopUpMenuButton(context, discount), ), @@ -271,31 +256,28 @@ class DiscountListView extends StatelessWidget { } Widget getPopUpMenuButton(BuildContext context, StoreDiscount discount) { - return PopupMenuButton( - icon: const Icon(Icons.more_vert), - itemBuilder: (c) { - return [ - PopupMenuItem( - value: 'edit', - child: ValueText( - lang(context).edit, - ), + 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: 'view', + child: ValueText( + lang(context).view, ), - PopupMenuItem( - value: 'delete', - child: ValueText( - lang(context).delete, - ), - ) - ]; - }, - onSelected: (String value) => actionPopUpItemSelected(value, discount), + ), + PopupMenuItem( + value: 'delete', + child: ValueText( + lang(context).delete, + ), + ) + ], ); } } diff --git a/lib/application/views/home/HomePage.dart b/lib/application/views/home/HomePage.dart index d6642f5..5ec710b 100644 --- a/lib/application/views/home/HomePage.dart +++ b/lib/application/views/home/HomePage.dart @@ -3,18 +3,21 @@ 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/localdb/SharedPrefs.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/authModule/loginViews/CheckInPopUp.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'; @@ -26,7 +29,9 @@ import 'package:wosull/application/views/salesandordermodule/SalesAndOrderMainVC 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/CustomListTIle.dart'; import 'package:wosull/widgets/LanguageDropdown.dart'; @@ -109,7 +114,7 @@ class _HomePageState extends BaseStatefulState getSyncButton(), AppSpaces.horizontalMedium, SizedBox( - width: 130, + width: 110, child: ElevatedButton.icon( style: ElevatedButton.styleFrom( elevation: 0, @@ -124,10 +129,7 @@ class _HomePageState extends BaseStatefulState }, label: Text( AppLocalizations.of(context)!.cashier, - style: TextStyle( - fontSize: 13, - color: MyColors.blueThemeColor, - fontFamily: MyFonts.Medium), + style: ThemeText.textStyleBlueMedium, ), icon: ImageIcon( color: MyColors.blueThemeColor, @@ -138,7 +140,7 @@ class _HomePageState extends BaseStatefulState ), AppSpaces.horizontalMedium, SizedBox( - width: 130, + width: 110, child: ElevatedButton.icon( style: ElevatedButton.styleFrom( elevation: 0, @@ -148,13 +150,12 @@ class _HomePageState extends BaseStatefulState backgroundColor: MyColors.backFillColor, minimumSize: const Size.fromHeight(38), // NEW ), - onPressed: () {}, + onPressed: () { + showCloseCounter(); + }, label: Text( 'Counter', - style: TextStyle( - fontSize: 13, - color: MyColors.blueThemeColor, - fontFamily: MyFonts.Medium), + style: ThemeText.textStyleBlueMedium, ), icon: ImageIcon( color: MyColors.blueThemeColor, @@ -165,7 +166,7 @@ class _HomePageState extends BaseStatefulState ), AppSpaces.horizontalMedium, SizedBox( - width: 120, + width: 110, child: ElevatedButton.icon( style: ElevatedButton.styleFrom( elevation: 0, @@ -180,10 +181,7 @@ class _HomePageState extends BaseStatefulState }, label: Text( AppLocalizations.of(context)!.kitchen, - style: TextStyle( - fontSize: 13, - color: MyColors.blueThemeColor, - fontFamily: MyFonts.Medium), + style: ThemeText.textStyleBlueMedium, ), icon: ImageIcon( color: MyColors.blueThemeColor, @@ -194,6 +192,9 @@ class _HomePageState extends BaseStatefulState ), AppSpaces.horizontalMedium, PopupMenuButton( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), padding: EdgeInsets.zero, child: Container( decoration: BoxDecoration( @@ -223,8 +224,8 @@ class _HomePageState extends BaseStatefulState ), Text( sharedPrefs.store_name, - style: const TextStyle( - fontSize: MyFonts.normalButton, + style: TextStyle( + fontSize: MyFonts.mediumText, fontFamily: MyFonts.Medium, color: MyColors.textColorBlack), ), @@ -250,10 +251,13 @@ class _HomePageState extends BaseStatefulState mainAxisSize: MainAxisSize.min, children: [ getLangDropdown(), - AppSpaces.horizontalMedium, + AppSpaces.horizontalSmall, getSyncButton(), - AppSpaces.horizontalMedium, + AppSpaces.horizontalSmall, PopupMenuButton( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), padding: EdgeInsets.zero, child: Container( decoration: BoxDecoration( @@ -283,7 +287,7 @@ class _HomePageState extends BaseStatefulState ), Text( sharedPrefs.store_name, - style: const TextStyle( + style: TextStyle( fontSize: MyFonts.normalButton, fontFamily: MyFonts.Medium, color: MyColors.textColorBlack), @@ -301,7 +305,7 @@ class _HomePageState extends BaseStatefulState onSelected: (String value) => actionPopUpItemSelected(value), ), - AppSpaces.horizontalMedium, + AppSpaces.horizontalSmall, ], )) ], @@ -327,34 +331,60 @@ class _HomePageState extends BaseStatefulState } List> getPopUpMenu() { - return [ - 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), - ), - ]; + 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') { @@ -366,11 +396,17 @@ class _HomePageState extends BaseStatefulState return [ PopupMenuItem( value: 'fetch', - child: ValueText('Fetch Data'), + child: Text( + 'Fetch Data', + style: ThemeDropDown.dropDownTextStyle, + ), ), PopupMenuItem( value: 'upload', - child: ValueText('Upload Order'), + child: Text( + 'Upload Order', + style: ThemeDropDown.dropDownTextStyle, + ), ), ]; } @@ -388,11 +424,7 @@ class _HomePageState extends BaseStatefulState if (result != null) { final updated = result; if (updated) { - sharedPrefs.isLoggedIn = false; - Navigator.pushReplacement( - context, - MaterialPageRoute(builder: (context) => const LoginVC()), - ); + clearData(); } } } @@ -407,6 +439,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, @@ -430,7 +482,7 @@ class _HomePageState extends BaseStatefulState barrierColor: Colors.black26, context: context, builder: (context) { - return CheckInPopUp(); + return const CheckInPopUp(); }, ); @@ -503,26 +555,33 @@ class _HomePageState extends BaseStatefulState CustomListTile( wasTaped: viewModel.isTaped[5], path: 'images/sales_order.svg', - title: AppLocalizations.of(context)!.sales_and_orders, + title: 'Business Accounts', onTap: () { viewModel.onSelectItem(5); }), CustomListTile( wasTaped: viewModel.isTaped[6], + path: 'images/sales_order.svg', + title: AppLocalizations.of(context)!.sales_and_orders, + onTap: () { + viewModel.onSelectItem(6); + }), + CustomListTile( + wasTaped: viewModel.isTaped[7], path: 'images/kitchen.svg', title: AppLocalizations.of(context)!.kitchen, onTap: () { viewModel.tableIndex = 0; - viewModel.onSelectItem(6); + viewModel.onSelectItem(7); }), Align( alignment: FractionalOffset.bottomCenter, child: CustomListTile( - wasTaped: viewModel.isTaped[7], + wasTaped: viewModel.isTaped[8], path: 'images/setting.svg', title: AppLocalizations.of(context)!.settings, onTap: () { - viewModel.onSelectItem(7); + viewModel.onSelectItem(8); }), ) ], @@ -547,6 +606,7 @@ class _HomePageState extends BaseStatefulState Widget getLangDropdown() { return LanguageDropdown( + fillColor: MyColors.backFillColor, dropdownValue: viewModel.dropdownValue, onChange: (language) { viewModel.dropdownValue = language!; @@ -555,7 +615,6 @@ class _HomePageState extends BaseStatefulState } _getDrawerItemWidget(int pos) { - print(pos); switch (pos) { case 0: return HomeVC(delegateDrawer: this); @@ -573,21 +632,25 @@ class _HomePageState extends BaseStatefulState delegateDrawer: this, ); case 5: - return SalesAndOrderMainVC( + return BusinessAccountMainVC( delegateDrawer: this, ); case 6: + return SalesAndOrderMainVC( + delegateDrawer: this, + ); + case 7: return KitchenMainVC( delegateDrawer: this, initialIndex: 0, ); - case 7: - return SettingsMainVC(delegateDrawer: this); case 8: - return HomeVC(delegateDrawer: this); + return SettingsMainVC(delegateDrawer: this); case 9: + return HomeVC(delegateDrawer: this); + case 12: return CartVC(delegateDrawer: this); - case 10: + case 11: return HoldOrderVC( delegateDrawer: this, ); @@ -599,12 +662,15 @@ class _HomePageState extends BaseStatefulState 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: 44, + height: 38, child: viewModel.isInSync ? AppLoader() : Row( @@ -616,16 +682,13 @@ class _HomePageState extends BaseStatefulState height: 24, child: Icon( Icons.sync, - size: 14, + size: 18, color: MyColors.blueThemeColor, ), ), - const Text( + Text( 'Sync', - style: TextStyle( - fontSize: MyFonts.normalButton, - fontFamily: MyFonts.Medium, - color: MyColors.textColorBlack), + style: ThemeText.textStyleBlueMedium, ), ], ), @@ -636,4 +699,12 @@ class _HomePageState extends BaseStatefulState onSelected: (String value) => actionPopUpItemSelected(value), ); } + + void clearData() { + viewModel.clearLogoutData(); + Navigator.pushReplacement( + context, + MaterialPageRoute(builder: (context) => const LoginVC()), + ); + } } diff --git a/lib/application/views/home/HomePageViewModel.dart b/lib/application/views/home/HomePageViewModel.dart index fae9452..684d3fc 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'; @@ -16,9 +17,11 @@ class HomePageViewModel with ChangeNotifier { // List cashierItems = []; var _appLocale; + //late String currentDefaultSystemLocale; bool _isInSync = false; + bool get isInSync => _isInSync; int currentIndex = 1; @@ -35,6 +38,7 @@ class HomePageViewModel with ChangeNotifier { false, false, false, + false, ]; // the first is true because when the app void changeHighlight(int index) { @@ -51,8 +55,8 @@ class HomePageViewModel with ChangeNotifier { sharedPrefs.isChanged = true; _appLocale ??= Provider.of(context, listen: false); _appLocale.changeLocale(Locale(language.languageCode)); - // setFlag(); sharedPrefs.setLocale(language.languageCode); + notifyListeners(); } void onDepChange() { @@ -83,15 +87,45 @@ class HomePageViewModel with ChangeNotifier { void setHomeMenus() { homeItems = [ - const BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'), BottomNavigationBarItem( - icon: const Icon(Icons.money), + icon: SvgPicture.asset( + 'images/home.svg', + width: 24, + ), + activeIcon: SvgPicture.asset( + 'images/home_active.svg', + width: 24, + ), + label: 'Home'), + BottomNavigationBarItem( + 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) ]; } @@ -137,7 +171,6 @@ class HomePageViewModel with ChangeNotifier { } void onItemTapped(int index) async { - print('index' + index.toString()); currentIndex = index; if (index == 0) { // isCashier = false; @@ -147,9 +180,9 @@ class HomePageViewModel with ChangeNotifier { // currentIndex = 1; setSelectedDrawer(2); } else if (index == 2) { - setSelectedDrawer(9); + setSelectedDrawer(12); } else if (index == 3) { - setSelectedDrawer(10); + setSelectedDrawer(11); } } @@ -187,4 +220,17 @@ class HomePageViewModel with ChangeNotifier { _isInSync = value; notifyListeners(); } + + void clearCounterData() { + sharedPrefs.businessRegisterId = ''; + sharedPrefs.billingCounterId = ''; + } + + void clearLogoutData() { + sharedPrefs.isLoggedIn = false; + sharedPrefs.storeId = ''; + sharedPrefs.store_name = ''; + // sharedPrefs.businessRegisterId = ''; + // sharedPrefs.billingCounterId = ''; + } } diff --git a/lib/application/views/inventorymodule/InventoryModuleMainVC.dart b/lib/application/views/inventorymodule/InventoryModuleMainVC.dart index a0fc5d1..6e2cacc 100644 --- a/lib/application/views/inventorymodule/InventoryModuleMainVC.dart +++ b/lib/application/views/inventorymodule/InventoryModuleMainVC.dart @@ -2,7 +2,6 @@ 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'; @@ -12,7 +11,7 @@ import 'package:wosull/application/views/inventorymodule/productviews/InventoryP 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/helpers/ThemeText.dart'; +import 'package:wosull/widgets/BackTabBarContainer.dart'; import 'categoryviews/InventoryCategoriesModule.dart'; import 'deliveryPartnerViews/InventoryDeliveryPartnerPriceVC.dart'; @@ -44,103 +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: ThemeText.tabLabelStyle, - isScrollable: true, - unselectedLabelStyle: ThemeText.unSelectedTabLabelStyle, - unselectedLabelColor: MyColors.textColorBlack, - labelColor: MyColors.blueThemeColor, - 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, - ), - ], - )) - ], - ), + 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( diff --git a/lib/application/views/inventorymodule/categoryviews/InventoryAddCategoryVC.dart b/lib/application/views/inventorymodule/categoryviews/InventoryAddCategoryVC.dart index 7b97b47..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'; @@ -54,28 +55,14 @@ class _InventoryAddCategoryVCState @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 = @@ -152,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, @@ -304,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 cbe0903..fa60cd2 100644 --- a/lib/application/views/inventorymodule/categoryviews/InventoryCategoriesModule.dart +++ b/lib/application/views/inventorymodule/categoryviews/InventoryCategoriesModule.dart @@ -47,8 +47,9 @@ class _InventoryCategoriesModuleState Widget build(BuildContext context) { //not doing watch because using state to get the data //and listener - // categoryViewModel = CategoryViewModel(); + //categoryViewModel = CategoryViewModel(); //scroll state for pagination + print('here ${categoryViewModel.limit}'); _controller = ScrollController()..addListener(_scrollNotification); return Scaffold( backgroundColor: MyColors.fillColor, @@ -76,8 +77,7 @@ class _InventoryCategoriesModuleState style: ThemeText.textStylePageHeading, ), AppSpaces.horizontalSmall, - SizedBox( - width: 120, + Flexible( child: CustomSimpleButton( textColor: MyColors.blueThemeColor, backGroundColor: MyColors.backColorBlue50, @@ -88,13 +88,15 @@ class _InventoryCategoriesModuleState }, ), ), - Flexible(child: PageLimitDropdown( + AppSpaces.horizontalSmall, + PageLimitDropdown( + value: categoryViewModel.limit.toString(), onChange: (value) { categoryViewModel.fetchCategories( isRefresh: true, limit: int.parse(value!)); }, - )) + ) ], ), AppSpaces.verticalSmall, @@ -155,6 +157,7 @@ class _InventoryCategoriesModuleState ), AppSpaces.horizontalSmall, PageLimitDropdown( + value: categoryViewModel.limit.toString(), onChange: (value) { categoryViewModel.fetchCategories( isRefresh: true, @@ -174,23 +177,21 @@ class _InventoryCategoriesModuleState switch (controller.dataState) { case DataState.uninitialized: Future(() { - controller.fetchCategories(); + controller.fetchCategories( + limit: categoryViewModel.limit); }); - return categoryListViewWidget( - controller.filteredList); + return showData(controller.filteredList); case DataState.initialFetching: return AppLoader(); case DataState.moreFetching: case DataState.refreshing: - return categoryListViewWidget( - controller.filteredList); + return showData(controller.filteredList); case DataState.error: return AppError(); case DataState.searching: case DataState.fetched: case DataState.noMoreData: - return categoryListViewWidget( - controller.filteredList); + return showData(controller.filteredList); } }, ), @@ -202,11 +203,12 @@ class _InventoryCategoriesModuleState })); } - Widget categoryListViewWidget(List data) { + Widget showData(List data) { return Column( children: [ CategoryListView( data: data, + isPortrait: isPortrait, onUpdate: (item, status) { update(item.id, status); }, 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 c6b1eb1..4b107a9 100644 --- a/lib/application/views/inventorymodule/categoryviews/viewModels/CategoryViewModel.dart +++ b/lib/application/views/inventorymodule/categoryviews/viewModels/CategoryViewModel.dart @@ -4,16 +4,14 @@ 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; + //using this state to handle for get data and pagination DataState _dataState = DataState.uninitialized; @@ -36,6 +34,9 @@ class CategoryViewModel extends ChangeNotifier { List get dataList => _dataList; List get filteredList => _filteredList; + + var repository = CategoryRepository(); + int limit = 10; var wosulError = WosulError(message: ''); @@ -70,18 +71,15 @@ class CategoryViewModel extends ChangeNotifier { 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 < this.limit) { + if (value.isNotEmpty) { + _filteredList.addAll(value); + _dataList.addAll(value); + if (value.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; @@ -105,10 +103,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); @@ -125,13 +120,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; @@ -163,13 +152,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) { @@ -183,15 +169,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 1e09ec8..2d7cc8f 100644 --- a/lib/application/views/inventorymodule/categoryviews/widgets/CategoryListView.dart +++ b/lib/application/views/inventorymodule/categoryviews/widgets/CategoryListView.dart @@ -2,17 +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; @@ -20,6 +22,7 @@ class CategoryListView extends StatelessWidget { CategoryListView( {super.key, + required this.isPortrait, required this.data, required this.onUpdate, required this.onDelete, @@ -32,94 +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: ActionPopUpContainer( - child: getMenuBuilder(context, 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, ) diff --git a/lib/application/views/inventorymodule/comboviews/ComboAddSizesVC.dart b/lib/application/views/inventorymodule/comboviews/ComboAddSizesVC.dart index 51242a6..161a9af 100644 --- a/lib/application/views/inventorymodule/comboviews/ComboAddSizesVC.dart +++ b/lib/application/views/inventorymodule/comboviews/ComboAddSizesVC.dart @@ -13,7 +13,7 @@ import 'package:wosull/widgets/DialogHeader.dart'; import 'package:wosull/widgets/MandatoryTitleText.dart'; class ComboAddSizesVC extends StatefulWidget { - ComboAddSizesVC({ + const ComboAddSizesVC({ Key? key, }) : super(key: key); @@ -45,7 +45,7 @@ class _ComboAddSizesVCState extends BaseStatefulState { elevation: 0, backgroundColor: const Color(0xffffffff), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(15.0), + borderRadius: BorderRadius.circular(8.0), ), child: OrientationBuilder(builder: (context, orientation) { viewModel.isPortrait = @@ -129,6 +129,7 @@ class _ComboAddSizesVCState extends BaseStatefulState { height: 42, child: CustomTextFieldForm( hintText: 'Enter Size Name', + key: Key(viewModel.newSizeController), initialValue: viewModel.newSizeController, onChanged: (String value) { @@ -140,7 +141,6 @@ class _ComboAddSizesVCState extends BaseStatefulState { SizedBox( width: 100, child: CustomSimpleButton( - isLoading: viewModel.isLoading, textColor: MyColors.textColorBlack20, backGroundColor: MyColors.fillColorGray2, @@ -160,6 +160,7 @@ class _ComboAddSizesVCState extends BaseStatefulState { child: SizedBox( width: 120, child: CustomSimpleButton( + isLoading: viewModel.isLoading, textColor: MyColors.white, backGroundColor: MyColors.blueThemeColor, onPressed: () async { 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 485f633..7580292 100644 --- a/lib/application/views/inventorymodule/comboviews/CreateComboGroupVC.dart +++ b/lib/application/views/inventorymodule/comboviews/CreateComboGroupVC.dart @@ -6,11 +6,15 @@ 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/HeadingText.dart'; +import 'package:wosull/widgets/HeadingContainer.dart'; +import 'package:wosull/widgets/WrapHeightContainer.dart'; class CreateComboGroupVC extends StatefulWidget { const CreateComboGroupVC({Key? key}) : super(key: key); @@ -38,7 +42,7 @@ class _CreateComboGroupVCState extends BaseStatefulState { elevation: 0, backgroundColor: const Color(0xffffffff), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(15.0), + borderRadius: BorderRadius.circular(8.0), ), child: OrientationBuilder(builder: (context, orientation) { viewModel.isPortrait = @@ -72,54 +76,19 @@ class _CreateComboGroupVCState extends BaseStatefulState { }, hintText: 'Enter Group Name', ), - AppSpaces.verticalSmall, - Container( - height: 48, - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all( - width: 1, color: MyColors.fillColorGray2), - color: MyColors.containerBackColor, - ), + AppSpaces.verticalLarge, + BorderContainer( child: Row( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ Expanded( - child: Container( - padding: - const EdgeInsets.only(left: 4, right: 4), - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Align( - alignment: Alignment.centerLeft, - child: HeadingText( - AppLocalizations.of(context)! - .sub_group_name), - ), - )), - Container( + child: HeadingContainer( + heading: AppLocalizations.of(context)! + .sub_group_name)), + HeadingContainer( width: 80, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - width: 1.0, - color: MyColors.fillColorGray2), - ), - ), - child: Center( - child: HeadingText( - AppLocalizations.of(context)!.action, - ), - ), + heading: AppLocalizations.of(context)!.action, ) ], ), @@ -131,30 +100,12 @@ class _CreateComboGroupVCState extends BaseStatefulState { shrinkWrap: true, itemBuilder: (context, position) { // viewModel.subGroupNameController.add(''); - 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 WrapHeightContainer( 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: ChildContainer( child: CustomTextFieldForm( - height: 42, hintText: '', initialValue: viewModel.addComboGroup .subGroups![position].name ?? @@ -174,26 +125,10 @@ class _CreateComboGroupVCState extends BaseStatefulState { const EdgeInsets.only(right: 4), child: Align( alignment: Alignment.centerRight, - 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 - .removeGroup(position); - }), + child: CustomRemoveItemButton( + onPressed: () { + viewModel.removeGroup(position); + }, ), ), )), @@ -204,18 +139,8 @@ class _CreateComboGroupVCState extends BaseStatefulState { itemCount: viewModel.addComboGroup.subGroups!.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, + BorderContainer( + backgroundColor: MyColors.white, child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ diff --git a/lib/application/views/inventorymodule/comboviews/InventoryComboVC.dart b/lib/application/views/inventorymodule/comboviews/InventoryComboVC.dart index b4f48be..159db29 100644 --- a/lib/application/views/inventorymodule/comboviews/InventoryComboVC.dart +++ b/lib/application/views/inventorymodule/comboviews/InventoryComboVC.dart @@ -68,13 +68,11 @@ class _InventoryComboVCState extends BaseStatefulState { style: ThemeText.textStylePageHeading, ), AppSpaces.horizontalSmall, - SizedBox( - width: 120, + Flexible( child: newComboGroup(), ), AppSpaces.horizontalSmall, - SizedBox( - width: 115, + Flexible( child: addGroupButton(), ), ], @@ -83,17 +81,17 @@ class _InventoryComboVCState extends BaseStatefulState { Row( mainAxisAlignment: MainAxisAlignment.start, children: [ - SizedBox( - width: 120, + Flexible( child: addSizesButton(), ), - Flexible(child: PageLimitDropdown( + AppSpaces.horizontalSmall, + PageLimitDropdown( onChange: (value) { viewModel.fetch( isRefresh: true, limit: int.parse(value!)); }, - )) + ) ], ), AppSpaces.verticalSmall, @@ -265,7 +263,7 @@ class _InventoryComboVCState extends BaseStatefulState { barrierColor: Colors.black26, context: context, builder: (context) { - return ComboAddSizesVC(); + return const ComboAddSizesVC(); }, ); }, diff --git a/lib/application/views/inventorymodule/comboviews/InventoryNewComboVC.dart b/lib/application/views/inventorymodule/comboviews/InventoryNewComboVC.dart index 22d39d7..8954d07 100644 --- a/lib/application/views/inventorymodule/comboviews/InventoryNewComboVC.dart +++ b/lib/application/views/inventorymodule/comboviews/InventoryNewComboVC.dart @@ -6,21 +6,27 @@ 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/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/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/HeadingContainer.dart'; -import 'package:wosull/widgets/ItemCategoryDropdown.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 { const InventoryNewComboVC({Key? key}) : super(key: key); @@ -34,33 +40,24 @@ class _InventoryNewComboVCState extends BaseStatefulState { @override void initState() { - // TODO: implement initState - super.initState(); context.read().initData(); + super.initState(); + } + + @override + void dispose() { + viewModel.disposeData(); + super.dispose(); } @override 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: const Text( - 'Create Combo', - style: TextStyle( - color: MyColors.textColorBlack, - fontFamily: MyFonts.Bold, - fontSize: 22), - ), - backgroundColor: MyColors.white, - elevation: 5, + appBar: CustomAppBar( + heading: 'Create Combo', ), body: OrientationBuilder(builder: (c, orientation) { viewModel.isPortrait = @@ -72,9 +69,7 @@ class _InventoryNewComboVCState extends BaseStatefulState { : EdgeInsets.zero, padding: const EdgeInsets.only(bottom: 8), child: viewModel.isLoadingFirst - ? const Center( - child: CircularProgressIndicator(), - ) + ? AppLoader() : Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.end, @@ -141,308 +136,278 @@ class _InventoryNewComboVCState extends BaseStatefulState { } Widget getCategoriesDropdown() { - return ItemCategoryDropdown( - selectedCategoryDropDown: viewModel.selectedItemCategory, - onChanged: (data) { - viewModel.setSelectedCategory(data); - }); + return DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + 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: ThemeText.textStylePageHeading, - ), - AppSpaces.verticalLarge, - viewModel.isPortrait - ? Container() - : Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius.all(Radius.circular( - 1.0) // <--- border radius here + 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, ), - border: - Border.all(width: 1, color: MyColors.fillColorGray2), - color: MyColors.fillColor2, - ), - height: 48, - 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, - ), - HeadingContainer( - width: 100, - height: 48, - heading: AppLocalizations.of(context)!.price, - ), - HeadingContainer( - width: 48, - height: 48, - heading: '', - ) - ], - ), - ), - ListView.builder( - padding: EdgeInsets.zero, - scrollDirection: Axis.vertical, - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - itemBuilder: (c, position) { - if (viewModel.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: PortraitContainer( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - 'Size', - style: MyColors.textStylePopUpHeading(), + 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', + ), ), - ), - )), - Expanded( - child: PortraitContainer( - child: getSizesDropdown(position), - )) - ], - ), - Row( - children: [ - Expanded( - child: PortraitContainer( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)!.group, - style: MyColors.textStylePopUpHeading(), + )), + Expanded( + child: PortraitContainer( + child: getSizesDropdown(position), + )) + ], + ), + Row( + children: [ + Expanded( + child: PortraitContainer( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + AppLocalizations.of(context)!.group, + ), ), - ), - )), - Expanded( - child: PortraitContainer( - child: getComboGroupDropdown(position), - )) - ], - ), - Row( - children: [ - Expanded( - child: PortraitContainer( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)!.sub_group, - style: MyColors.textStylePopUpHeading(), + )), + Expanded( + child: PortraitContainer( + child: getComboGroupDropdown(position), + )) + ], + ), + Row( + children: [ + Expanded( + child: PortraitContainer( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + AppLocalizations.of(context)!.sub_group, + ), ), - ), - )), - Expanded( - child: PortraitContainer( - child: getSubGroupDropdown(position), - )) - ], - ), - Row( - children: [ - Expanded( - child: PortraitContainer( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - 'Product', - style: MyColors.textStylePopUpHeading(), + )), + Expanded( + child: PortraitContainer( + child: getSubGroupDropdown(position), + )) + ], + ), + Row( + children: [ + Expanded( + child: PortraitContainer( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + 'Product', + ), ), - ), - )), - Expanded( - child: PortraitContainer( - child: getProductDropdown(position), - )) - ], - ), - Row( - children: [ - Expanded( - child: PortraitContainer( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)!.measurement, - style: MyColors.textStylePopUpHeading(), + )), + Expanded( + child: PortraitContainer( + child: getProductDropdown(position), + )) + ], + ), + Row( + children: [ + Expanded( + child: PortraitContainer( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + AppLocalizations.of(context)!.measurement, + ), ), - ), - )), - Expanded( - child: PortraitContainer( - child: getMeasurementDropdown(position), - )) - ], - ), - Row( - children: [ - Expanded( - child: PortraitContainer( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)!.quantity, - style: MyColors.textStylePopUpHeading(), + )), + Expanded( + child: PortraitContainer( + child: getMeasurementDropdown(position), + )) + ], + ), + Row( + children: [ + Expanded( + child: PortraitContainer( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + AppLocalizations.of(context)!.quantity, + ), ), - ), - )), - Expanded( - child: PortraitContainer( - child: quantityTextField(position), - )) - ], - ), - Row( - children: [ - Expanded( - child: PortraitContainer( - child: Align( - alignment: Alignment.centerLeft, - child: Text( - AppLocalizations.of(context)!.price, - style: MyColors.textStylePopUpHeading(), + )), + Expanded( + child: PortraitContainer( + child: quantityTextField(position), + )) + ], + ), + Row( + children: [ + Expanded( + child: PortraitContainer( + child: Align( + alignment: Alignment.centerLeft, + child: HeadingText( + AppLocalizations.of(context)!.price, + ), ), - ), - )), - Expanded( - child: PortraitContainer( - child: getPriceTextField(position), - )) - ], + )), + 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: quantityTextField(position), ), - ], - )), - getRemoveButton(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: 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: quantityTextField(position), ), - ), - ChildContainer( - width: 100, - height: 48, - child: Center( - child: getPriceTextField(position), + ChildContainer( + width: 100, + height: 48, + child: Center( + child: getPriceTextField(position), + ), ), - ), - getRemoveButton(position) - ], - ), - ); - } - }, - itemCount: viewModel.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, + getRemoveButton(position) + ], + ), + ); + } + }, + itemCount: viewModel.addCombo.comboProducts.length, ), - height: 48, - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [getAddComboButton()], + BorderContainer( + backgroundColor: MyColors.white, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [getAddComboButton()], + ), ), - ), - ], + ], + ), ), ); } @@ -451,15 +416,17 @@ class _InventoryNewComboVCState extends BaseStatefulState { return DropdownSearch( clearButtonProps: ThemeDropDown.clearButton, dropdownButtonProps: ThemeDropDown.dropdownButtonProps, - popupProps: const PopupProps.menu( - fit: FlexFit.loose, constraints: BoxConstraints(maxHeight: 250)), + popupProps: PopupProps.menu( + 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.dropDownStyle(hint: 'Choose'), + dropdownDecoratorProps: MyColors.dropDownStyleAddProduct(hint: 'Choose'), ); } @@ -467,15 +434,17 @@ class _InventoryNewComboVCState extends BaseStatefulState { return DropdownSearch( clearButtonProps: ThemeDropDown.clearButton, dropdownButtonProps: ThemeDropDown.dropdownButtonProps, - popupProps: const PopupProps.menu( - fit: FlexFit.loose, constraints: BoxConstraints(maxHeight: 250)), + popupProps: PopupProps.menu( + 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.dropDownStyle(hint: 'Choose'), + dropdownDecoratorProps: MyColors.dropDownStyleAddProduct(hint: 'Choose'), ); } @@ -483,15 +452,17 @@ class _InventoryNewComboVCState extends BaseStatefulState { return DropdownSearch( clearButtonProps: ThemeDropDown.clearButton, dropdownButtonProps: ThemeDropDown.dropdownButtonProps, - popupProps: const PopupProps.menu( - fit: FlexFit.loose, constraints: BoxConstraints(maxHeight: 250)), + popupProps: PopupProps.menu( + 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.dropDownStyle(hint: 'Choose'), + dropdownDecoratorProps: MyColors.dropDownStyleAddProduct(hint: 'Choose'), ); } @@ -499,15 +470,17 @@ class _InventoryNewComboVCState extends BaseStatefulState { return DropdownSearch( clearButtonProps: ThemeDropDown.clearButton, dropdownButtonProps: ThemeDropDown.dropdownButtonProps, - popupProps: const PopupProps.menu( - fit: FlexFit.loose, constraints: BoxConstraints(maxHeight: 250)), + popupProps: PopupProps.menu( + 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.dropDownStyle(hint: 'Choose'), + dropdownDecoratorProps: MyColors.dropDownStyleAddProduct(hint: 'Choose'), ); } @@ -515,14 +488,16 @@ class _InventoryNewComboVCState extends BaseStatefulState { return DropdownSearch( clearButtonProps: ThemeDropDown.clearButton, dropdownButtonProps: ThemeDropDown.dropdownButtonProps, - popupProps: const PopupProps.menu( - fit: FlexFit.loose, constraints: BoxConstraints(maxHeight: 250)), + popupProps: PopupProps.menu( + 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.dropDownStyle(hint: 'Choose'), + dropdownDecoratorProps: MyColors.dropDownStyleAddProduct(hint: 'Choose'), ); } @@ -549,51 +524,15 @@ class _InventoryNewComboVCState extends BaseStatefulState { } Widget getRemoveButton(int position) { - return 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: 14, - Icons.close, - color: MyColors.textColorBlack, - ), - onPressed: () { - viewModel.removeComboProduct(position); - }), - ), - )); + return CustomRemoveItemButton(onPressed: () { + viewModel.removeComboProduct(position); + }); } Widget getAddComboButton() { - return 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: 14, - Icons.add, - color: MyColors.textColorBlack, - ), - onPressed: () { - viewModel.addNewCombo(); - }), - ), - )); + return CustomAddButton(onPressed: () { + viewModel.addNewCombo(); + }); } void checkState() { diff --git a/lib/application/views/inventorymodule/comboviews/viewModels/AddComboSizeViewModel.dart b/lib/application/views/inventorymodule/comboviews/viewModels/AddComboSizeViewModel.dart index a0e29d8..10944c4 100644 --- a/lib/application/views/inventorymodule/comboviews/viewModels/AddComboSizeViewModel.dart +++ b/lib/application/views/inventorymodule/comboviews/viewModels/AddComboSizeViewModel.dart @@ -61,7 +61,7 @@ class AddComboSizeViewModel with ChangeNotifier { void addNewSizeToList() { if (newSizeController.isNotEmpty) { controller.add(newSizeController); - newSizeController = ""; + newSizeController = ''; notifyListeners(); } else { Utils.showMessage('Enter Size name'); diff --git a/lib/application/views/inventorymodule/comboviews/viewModels/AddNewComboViewModel.dart b/lib/application/views/inventorymodule/comboviews/viewModels/AddNewComboViewModel.dart index d858272..06aed3f 100644 --- a/lib/application/views/inventorymodule/comboviews/viewModels/AddNewComboViewModel.dart +++ b/lib/application/views/inventorymodule/comboviews/viewModels/AddNewComboViewModel.dart @@ -11,12 +11,13 @@ 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/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 AddNewComboViewModel with ChangeNotifier { - var isLoadingFirst = false; + var isLoadingFirst = true; var isLoadingData = false; bool isPortrait = true; @@ -26,6 +27,7 @@ class AddNewComboViewModel with ChangeNotifier { List comboProduct = []; List comboGroups = []; + List categoriesList = []; List comboMeasurement = []; List subGroup = []; List comboSize = []; @@ -43,18 +45,50 @@ class AddNewComboViewModel with ChangeNotifier { CRUDOperationState get crudOperation => _crudOperation; + void disposeData() { + addCombo = AddNewComboModel(); + selectedItemCategory = null; + selectedSizeValue.clear(); + comboTotalPriceController = ''; + comboNameController = ''; + isLoadingFirst = true; + selectedGroup.clear(); + selectedSubGroup.clear(); + selectedProduct.clear(); + selectedMeasurement.clear(); + priceController.clear(); + comboSize.clear(); + quantityController.clear(); + } + void setLoading(bool value) { isLoadingData = value; notifyListeners(); } - void initData() { + 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; + } loadSizes(); } - void loadSizes() async { + Future loadSizes() async { await APIManager() .fetchData(Constants.GET_COMBO_SIZES, Constants.getStorePayload()) .then((value) { @@ -63,7 +97,7 @@ class AddNewComboViewModel with ChangeNotifier { comboSize.addAll(response.comboSizes!.sizes!); loadGroups(); } else { - setLoading(false); + setLoadingFirst(false); } }).onError((error, stackTrace) { print('size' + error.toString()); @@ -71,7 +105,7 @@ class AddNewComboViewModel with ChangeNotifier { }); } - void loadGroups() async { + Future loadGroups() async { await APIManager() .fetchData(Constants.GET_COMBO_GROUPS, Constants.getStorePayload()) .then((value) { @@ -80,31 +114,33 @@ class AddNewComboViewModel with ChangeNotifier { comboGroups.addAll(response.comboGroup!); loadMeasurement(); } else { - setLoading(false); + setLoadingFirst(false); } }).onError((error, stackTrace) { - setLoading(false); + setLoadingFirst(false); print(error.toString()); }); } - void loadMeasurement() async { + Future loadMeasurement() async { await APIManager() .fetchData(Constants.GET_MEASUREMENT, Constants.getStorePayload()) .then((value) { final response = GetComboMeasurementModel.fromJson(value); if (response.success!) { comboMeasurement.addAll(response.measurements!); - setLoading(false); + if (categoriesList.isNotEmpty) { + loadProduct(); + } } else { - setLoading(false); + setLoadingFirst(false); } }).onError((error, stackTrace) { - setLoading(false); + setLoadingFirst(false); }); } - void loadProduct() async { + Future loadProduct() async { ItemCategory itemCategory = selectedItemCategory; Map data = { 'store_id': sharedPrefs.storeId, @@ -118,12 +154,12 @@ class AddNewComboViewModel with ChangeNotifier { comboProduct.clear(); comboProduct.addAll(response.products!); - setLoading(false); + setLoadingFirst(false); } else { - setLoading(false); + setLoadingFirst(false); } }).onError((error, stackTrace) { - setLoading(false); + setLoadingFirst(false); }); } 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 dd2a776..c5aa39d 100644 --- a/lib/application/views/inventorymodule/deliveryPartnerViews/InventoryDeliveryPartnerPriceVC.dart +++ b/lib/application/views/inventorymodule/deliveryPartnerViews/InventoryDeliveryPartnerPriceVC.dart @@ -29,7 +29,6 @@ class InventoryDeliveryPartnerPriceVC extends StatefulWidget { class _InventoryDeliveryPartnerPriceVCState extends BaseStatefulState { - bool isPortrait = true; final viewModel = DeliveryPartnerPriceViewModel(); late ScrollController _controller; @@ -45,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( @@ -54,7 +53,7 @@ class _InventoryDeliveryPartnerPriceVCState padding: const EdgeInsets.all(12), child: Column( children: [ - isPortrait + viewModel.isPortrait ? Column( children: [ Row( @@ -72,14 +71,18 @@ class _InventoryDeliveryPartnerPriceVCState Row( children: [ Flexible( - child: SearchBox( - onEditingDone: (text) { - filterSearchResults(text); - }, - onChanged: (text) { - filterSearchResults(text); - }, - hint: AppLocalizations.of(context)!.search, + child: SizedBox( + height: 48, + child: SearchBox( + onEditingDone: (text) { + filterSearchResults(text); + }, + onChanged: (text) { + filterSearchResults(text); + }, + hint: + AppLocalizations.of(context)!.search, + ), ), ), PageLimitDropdown( @@ -166,7 +169,7 @@ class _InventoryDeliveryPartnerPriceVCState children: [ DeliveryPartnerPriceListView( data: data, - isPortrait: isPortrait, + isPortrait: viewModel.isPortrait, onUpdate: (partner, value) { _updateStatus(partner.id, value); }, 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 543aaaa..a190a10 100644 --- a/lib/application/views/inventorymodule/deliveryPartnerViews/inventoryAddDeliveryPriceVC.dart +++ b/lib/application/views/inventorymodule/deliveryPartnerViews/inventoryAddDeliveryPriceVC.dart @@ -4,12 +4,12 @@ import 'package:provider/provider.dart'; import 'package:wosull/application/model/DeliveryPartner/GetDeliveryPartner.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/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'; @@ -36,6 +36,12 @@ class _InventoryAddDeliveryPriceVCState extends BaseStatefulState { var viewModel = NewDeliveryPartnerViewModel(); + @override + void dispose() { + viewModel.disposeData(); + super.dispose(); + } + @override void initState() { // TODO: implement initState @@ -50,25 +56,11 @@ class _InventoryAddDeliveryPriceVCState viewModel = context.watch(); return Scaffold( resizeToAvoidBottomInset: true, - appBar: AppBar( - leading: BackButton( - color: Colors.black, - onPressed: () { - Navigator.pop(context); - }, // <-- SEE HERE - ), - centerTitle: true, - title: Text( - viewModel.isEdit - ? 'Edit Prices' - : AppLocalizations.of(context)!.add_prices, - style: const TextStyle( - color: MyColors.textColorBlack, - fontFamily: MyFonts.Bold, - fontSize: 22), - ), - backgroundColor: MyColors.white, - elevation: 5, + backgroundColor: MyColors.white, + appBar: CustomAppBar( + heading: viewModel.isEdit + ? 'Edit Prices' + : AppLocalizations.of(context)!.add_prices, ), body: OrientationBuilder(builder: (c, orientation) { viewModel.isPortrait = @@ -115,13 +107,7 @@ class _InventoryAddDeliveryPriceVCState CustomSwitch( value: viewModel.deliveryPartner.getStatus(), onToggle: (value) { - setState(() { - if (value) { - viewModel.deliveryPartner.status = "Active"; - } else { - viewModel.deliveryPartner.status = "Inactive"; - } - }); + viewModel.updateStatus(value); }, ), ], 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 7d823d7..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,29 +23,29 @@ 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) { - print('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; } @@ -73,18 +73,15 @@ class DeliveryPartnerPriceViewModel with ChangeNotifier { 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 < this.limit) { + if (value.isNotEmpty) { + _filteredList.addAll(value); + _dataList.addAll(value); + if (value.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; @@ -112,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) { @@ -140,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(); @@ -153,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 index 8708ba1..736eb3b 100644 --- a/lib/application/views/inventorymodule/deliveryPartnerViews/viewModels/NewDeliveryPartnerViewModel.dart +++ b/lib/application/views/inventorymodule/deliveryPartnerViews/viewModels/NewDeliveryPartnerViewModel.dart @@ -26,12 +26,19 @@ class NewDeliveryPartnerViewModel with ChangeNotifier { late DeliveryPartner deliveryPartner; var isEdit = false; + void disposeData() { + nameController = ''; + arabicNameController = ''; + selectedStoreObject.clear(); + stores.clear(); + } + void setLoading(bool value) { _isLoading = value; notifyListeners(); } - void initPartner(bool isEdit, DeliveryPartner deliveryPartner) { + Future initPartner(bool isEdit, DeliveryPartner deliveryPartner) async { this.isEdit = isEdit; this.deliveryPartner = deliveryPartner; if (isEdit) { @@ -40,9 +47,10 @@ class NewDeliveryPartnerViewModel with ChangeNotifier { } else { deliveryPartner.status = "Active"; } + await getAllStores(); } - getAllStores() async { + Future getAllStores() async { Map data = { 'store_id': sharedPrefs.storeId, 'is_included': true, @@ -125,4 +133,13 @@ class NewDeliveryPartnerViewModel with ChangeNotifier { } 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 bcd393b..8f94d0f 100644 --- a/lib/application/views/inventorymodule/ingredientsViews/AddProductIngredientVC.dart +++ b/lib/application/views/inventorymodule/ingredientsViews/AddProductIngredientVC.dart @@ -2,23 +2,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:wosull/application/model/Measurement/GetMeasurementCategory.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/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/MandatoryTitleText.dart'; @@ -45,6 +49,10 @@ class _AddProductIngredientVCState @override void initState() { + if (widget.isView || widget.isEdit) { + context.read().setData(widget.ingredient); + } + super.initState(); } @@ -57,41 +65,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 +94,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 +110,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 +155,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 +168,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 +196,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 +223,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 +250,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 +280,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 +305,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 +334,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 +351,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 +381,7 @@ class _AddProductIngredientVCState const CustomOptionalTitle( hint: 'Discount', ), - const SizedBox( - height: 4, - ), + AppSpaces.verticalSmall, getDiscountWidget(context), ], )), @@ -420,82 +391,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 +425,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 +451,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 +466,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 +484,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 +533,7 @@ class _AddProductIngredientVCState ), ), ), - const SizedBox( - height: 12, - ), + AppSpaces.verticalLarge, Visibility( visible: !widget.isView, child: SizedBox( @@ -827,29 +562,21 @@ 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( + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), + items: itemsList, + itemAsString: (Brand u) => u.name!, + onChanged: (Brand? data) { + viewModel.setIngredient(data); + }, + dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), ); } else { return AppLoader(); @@ -859,33 +586,25 @@ 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( + 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 +618,20 @@ 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( + 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 +645,21 @@ 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); - }, - 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( + 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 +672,21 @@ 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( + 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 +705,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 d6fbfdf..8af2429 100644 --- a/lib/application/views/inventorymodule/ingredientsViews/IngredientsVC.dart +++ b/lib/application/views/inventorymodule/ingredientsViews/IngredientsVC.dart @@ -3,24 +3,20 @@ 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/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/PageLimitDropDown.dart'; import 'package:wosull/widgets/SearchBox.dart'; -import 'package:wosull/widgets/ValueText.dart'; class IngredientsVC extends StatefulWidget { const IngredientsVC({super.key}); @@ -46,7 +42,7 @@ class _IngredientsVCState extends State { return SingleChildScrollView( controller: _controller, child: Container( - padding: const EdgeInsets.all(12), + padding: const EdgeInsets.all(10), child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center, @@ -54,22 +50,17 @@ class _IngredientsVCState extends State { Row( mainAxisAlignment: MainAxisAlignment.start, children: [ - const Text( + Text( 'Ingredient', style: ThemeText.textStylePageHeading, ), AppSpaces.horizontalSmall, - SizedBox( - width: 120, - child: CustomSimpleButton( - textColor: MyColors.blueThemeColor, - backGroundColor: MyColors.backColorBlue50, - heading: AppLocalizations.of(context)!.add_ingredient, - onPressed: () { - addUpdateIngredient(false, false, AddIngredient()); - }, - ), - ), + isPortrait + ? Flexible(child: newIngredientButton()) + : SizedBox( + width: 120, + child: newIngredientButton(), + ), AppSpaces.horizontalMedium, isPortrait ? Container() @@ -147,146 +138,21 @@ class _IngredientsVCState extends State { 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, - ), - )), - 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( - 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, - ) - ], - ), + 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(), ], ); @@ -309,17 +175,6 @@ class _IngredientsVCState extends State { 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); - } - } - Future update(String id, bool value) async { Utils.progressDialogue(context); await viewModel.update(id, value); @@ -346,8 +201,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( @@ -355,6 +211,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}) { @@ -379,4 +241,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/productviews/viewModels/AddIngredientViewModel.dart b/lib/application/views/inventorymodule/ingredientsViews/viewModels/AddIngredientViewModel.dart similarity index 73% rename from lib/application/views/inventorymodule/productviews/viewModels/AddIngredientViewModel.dart rename to lib/application/views/inventorymodule/ingredientsViews/viewModels/AddIngredientViewModel.dart index bda4992..34cb875 100644 --- a/lib/application/views/inventorymodule/productviews/viewModels/AddIngredientViewModel.dart +++ b/lib/application/views/inventorymodule/ingredientsViews/viewModels/AddIngredientViewModel.dart @@ -1,6 +1,8 @@ +import 'dart:convert'; + import 'package:flutter/material.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; -import 'package:wosull/application/model/Measurement/GetMeasurementCategory.dart'; +import 'package:wosull/application/model/Measurement/InventoryMeasurementModel.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'; @@ -23,16 +25,16 @@ class AddIngredientViewModel with ChangeNotifier { // 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 nameController = ''; + // var productCode = ''; + // var salePriceExclTax = ''; + // var salePriceIncludeTax = ''; + // var purchasePriceExclTax = ''; + // var stockAlertQuantity = ''; + // var quantityController = ''; + // var descriptionController = ''; + // var descriptionArabic = ''; + // var barCodeController = ''; var isEditView = false; @@ -55,37 +57,31 @@ class AddIngredientViewModel with ChangeNotifier { isEditView = false; selectedCategory = null; addIngredient = AddIngredient(); - nameController = ''; - productCode = ''; - salePriceExclTax = ''; - salePriceIncludeTax = ''; - purchasePriceExclTax = ''; - stockAlertQuantity = ''; - quantityController = ''; - descriptionController = ''; - descriptionArabic = ''; - barCodeController = ''; + selectedMeasurement = null; + selectedSupplier = null; + selectedDiscount = null; + selectedBrand = null; + // 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) { + if (addIngredient.name.isEmpty) { Utils.showMessage('Enter Ingredient Name'); } else { await addIngredientToServer(); @@ -119,15 +115,16 @@ class AddIngredientViewModel with ChangeNotifier { 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); - + // 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); + setLoading(true); + print(jsonEncode(addIngredient.toJson())); await APIManager() .fetchData(Constants.ADD_INGREDIENTS, addIngredient.toJson()) .then((value) { @@ -185,8 +182,9 @@ class AddIngredientViewModel with ChangeNotifier { generateCode() { String number = Utils.generateCode(); - barCodeController = number.toString(); - print(barCodeController); + addIngredient.uniqueIdForStoreData = number; + // barCodeController = number.toString(); + // print(barCodeController); notifyListeners(); } @@ -204,10 +202,10 @@ class AddIngredientViewModel with ChangeNotifier { } if (isStart) { addIngredient.manufacturerDate = - DataTimeFormat.formatDateFromPicket(pickedDate); + DataTimeFormat.formatDateFromPicketINVOICE(pickedDate); } else { addIngredient.expiryDate = - DataTimeFormat.formatDateFromPicket(pickedDate); + DataTimeFormat.formatDateFromPicketINVOICE(pickedDate); } notifyListeners(); }); @@ -314,27 +312,23 @@ class AddIngredientViewModel with ChangeNotifier { return items; } - Future> getMeasurementData() async { - var items = []; - + Future> getMeasurement() async { + var items = []; await APIManager() - .getResponseAuth(Constants.GET_MEASUREMENT_CATEGORY) + .fetchData(Constants.GET_MEASUREMENT, Constants.getStorePayload()) .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)); + final response = ProductMeasurementModel.fromJson(value); + if (response.success!) { + items.addAll(response.measurements!); + if (isEditView) { + final name = items + .singleWhere( + (element) => element.name == addIngredient.measurement) + .name; + selectedMeasurement = Measurement(id: '', name: name ?? ''); + } + } + }).onError((error, stackTrace) {}); return items; } @@ -346,9 +340,9 @@ class AddIngredientViewModel with ChangeNotifier { notifyListeners(); } - void setMeasurement(MeasurementCategory? data) { + void setMeasurement(Measurement? data) { if (data != null) { - addIngredient.measurementCategory = data.name!; + addIngredient.measurement = data.name!; } notifyListeners(); } @@ -377,4 +371,44 @@ class AddIngredientViewModel with ChangeNotifier { 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/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 f71e291..f1eae26 100644 --- a/lib/application/views/inventorymodule/measurementviews/InventoryAddMeasurementVC.dart +++ b/lib/application/views/inventorymodule/measurementviews/InventoryAddMeasurementVC.dart @@ -5,7 +5,6 @@ import 'package:provider/provider.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'; @@ -59,7 +58,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( @@ -104,9 +103,7 @@ class _InventoryAddMeasurementVCState measurementUnitWidget(), AppSpaces.verticalMedium, HeadingText(AppLocalizations.of(context)!.status), - const SizedBox( - height: 12, - ), + AppSpaces.verticalLarge, Row( children: [ CustomSwitch( @@ -117,9 +114,7 @@ class _InventoryAddMeasurementVCState ), ], ), - const SizedBox( - height: 12, - ), + AppSpaces.verticalLarge, Align( alignment: Alignment.centerRight, child: SizedBox( @@ -149,29 +144,21 @@ class _InventoryAddMeasurementVCState } Widget measurementUnitWidget() { - return FutureBuilder( - future: viewModel.getMeasurementUnits(), - builder: (c, s) { - if (s.hasData) { - final units = s.data ?? []; - return DropdownSearch( - clearButtonProps: ThemeDropDown.clearButton, - dropdownButtonProps: ThemeDropDown.dropdownButtonProps, - popupProps: const PopupProps.menu( - fit: FlexFit.loose, - constraints: BoxConstraints(maxHeight: 250)), - 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( + 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 adccd13..7575f72 100644 --- a/lib/application/views/inventorymodule/measurementviews/InventoryMeasurementVC.dart +++ b/lib/application/views/inventorymodule/measurementviews/InventoryMeasurementVC.dart @@ -4,7 +4,6 @@ import 'package:provider/provider.dart'; import 'package:sizer/sizer.dart'; import 'package:wosull/application/enum/DataState.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/application/utils/AppError.dart'; import 'package:wosull/application/utils/AppLoader.dart'; @@ -12,17 +11,14 @@ import 'package:wosull/application/views/inventorymodule/measurementviews/AddMea 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/PageLimitDropDown.dart'; import 'package:wosull/widgets/SearchBox.dart'; -import 'package:wosull/widgets/ValueText.dart'; class InventoryMeasurementVC extends StatefulWidget { const InventoryMeasurementVC({Key? key}) : super(key: key); @@ -38,6 +34,12 @@ class _InventoryMeasurementVCState late ScrollController _controller; + @override + void dispose() { + viewModel.disposeData(); + super.dispose(); + } + @override Widget build(BuildContext context) { _controller = ScrollController()..addListener(_scrollNotification); @@ -65,8 +67,7 @@ class _InventoryMeasurementVCState style: ThemeText.textStylePageHeading, ), AppSpaces.horizontalMedium, - SizedBox( - width: 160, + Flexible( child: CustomSimpleButton( textColor: MyColors.blueThemeColor, backGroundColor: MyColors.backColorBlue50, @@ -83,8 +84,7 @@ class _InventoryMeasurementVCState Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - SizedBox( - width: 160, + Flexible( child: CustomSimpleButton( textColor: MyColors.blueThemeColor, backGroundColor: MyColors.backColorBlue50, @@ -94,13 +94,14 @@ class _InventoryMeasurementVCState heading: '+ Add Measurement Unit', ), ), - Flexible(child: PageLimitDropdown( + AppSpaces.horizontalSmall, + PageLimitDropdown( onChange: (value) { viewModel.fetch( isRefresh: true, limit: int.parse(value!)); }, - )) + ) ], ), SizedBox( @@ -193,9 +194,7 @@ class _InventoryMeasurementVCState }); return showData(controller.filteredList); case DataState.initialFetching: - return const Center( - child: CircularProgressIndicator(), - ); + return AppLoader(); case DataState.moreFetching: case DataState.refreshing: return showData(controller.filteredList); @@ -221,298 +220,27 @@ class _InventoryMeasurementVCState 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, - 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!)), - ], - )), - ], - ), - )), - 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, - ), - ) - ]; - }, - 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( - 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); - }, - ), - )), - 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), - ), - ), - ), - )) - ], - ), - ), - ); - } - }, - itemCount: data.length, - ) - ], - ), + 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(), ], ); @@ -525,31 +253,18 @@ class _InventoryMeasurementVCState 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!); } } @@ -602,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 789d79e..b22c8af 100644 --- a/lib/application/views/inventorymodule/measurementviews/ViewInventoryMeasurementVC.dart +++ b/lib/application/views/inventorymodule/measurementviews/ViewInventoryMeasurementVC.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/viewModels/AddMeasurementViewModel.dart b/lib/application/views/inventorymodule/measurementviews/viewModels/AddMeasurementViewModel.dart index 9370c0b..997f4b7 100644 --- a/lib/application/views/inventorymodule/measurementviews/viewModels/AddMeasurementViewModel.dart +++ b/lib/application/views/inventorymodule/measurementviews/viewModels/AddMeasurementViewModel.dart @@ -4,6 +4,7 @@ import 'package:wosull/application/model/Measurement/InventoryMeasurementModel.d import 'package:wosull/application/model/Measurement/MeasurementUnitModel.dart'; import 'package:wosull/application/model/SimpleResponsModel.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'; @@ -11,6 +12,8 @@ import 'package:wosull/helpers/Utils.dart'; class AddMeasurementViewModel with ChangeNotifier { void disposeData() { _isLoading = false; + measurementUnits.clear(); + dropdownValue = null; measurement = Measurement(); } @@ -18,6 +21,8 @@ class AddMeasurementViewModel with ChangeNotifier { bool get isLoading => _isLoading; + List measurementUnits = []; + bool isEdit = false; var dropdownValue; var _crudOperation = CRUDOperationState.uninitialized; @@ -30,9 +35,20 @@ class AddMeasurementViewModel with ChangeNotifier { notifyListeners(); } - void fillValueOnEdit(bool isEdit, 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); + } + print(measurement.measurement); + + print(dropdownValue); + dropdownValue ??= MeasurementUnit(id: '', name: 'Choose'); + notifyListeners(); } Future isValidate() async { @@ -53,7 +69,7 @@ class AddMeasurementViewModel with ChangeNotifier { 'store_id': sharedPrefs.storeId, 'name': measurement.name ?? '', 'measurement_unit': unit.name, - 'status': measurement.getStatus(), + 'status': measurement.getStatus() ? 'Active' : 'Inactive', 'measurement_id': measurement.id ?? '', }; @@ -71,27 +87,6 @@ class AddMeasurementViewModel with ChangeNotifier { }).onError((error, stackTrace) {}); } - 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); - if (isEdit) { - dropdownValue ??= - items.where((element) => element.name == measurement.measurement); - } - } - }).onError((error, stackTrace) {}); - dropdownValue ??= MeasurementUnit(name: 'Choose'); - return items; - } - void setMeasurementUnit(MeasurementUnit? value) { if (value != null) { dropdownValue = value; diff --git a/lib/application/views/inventorymodule/measurementviews/viewModels/MeasurementViewModel.dart b/lib/application/views/inventorymodule/measurementviews/viewModels/MeasurementViewModel.dart index 54fc06d..a17035d 100644 --- a/lib/application/views/inventorymodule/measurementviews/viewModels/MeasurementViewModel.dart +++ b/lib/application/views/inventorymodule/measurementviews/viewModels/MeasurementViewModel.dart @@ -1,6 +1,9 @@ +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/Measurement/GetStoreMeasurementModel.dart'; import 'package:wosull/application/model/Measurement/InventoryMeasurementModel.dart'; import 'package:wosull/application/network/APIManager.dart'; import 'package:wosull/application/utils/Constants.dart'; @@ -21,6 +24,11 @@ class MeasurementViewModel extends ChangeNotifier { List get filteredList => _filteredList; + void disposeData() { + _filteredList.clear(); + _dataState = DataState.uninitialized; + } + fetch({bool isRefresh = false, int limit = 10}) async { this.limit = limit; _isLoading = true; @@ -47,7 +55,7 @@ class MeasurementViewModel extends ChangeNotifier { await APIManager() .fetchData(Constants.GET_INVENTORY_MEASUREMENTS, data) .then((result) { - final value = InvoiceMeasurementModel.fromJson(result); + final value = GetStoreMeasurementModel.fromJson(result); if (_dataState == DataState.refreshing) { _filteredList.clear(); } @@ -85,13 +93,14 @@ class MeasurementViewModel extends ChangeNotifier { 'store_id': sharedPrefs.storeId, 'searchTerm': searchValue }; + print(jsonEncode(data)); _dataState = DataState.searching; notifyListeners(); try { await APIManager() .fetchData(Constants.SEARCH_MEASUREMENT, data) .then((result) { - final value = InvoiceMeasurementModel.fromJson(result); + final value = GetStoreMeasurementModel.fromJson(result); filteredList.clear(); if (value.success!) { filteredList.addAll(value.measurements!); 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/viewModels/NewModifierOptionViewModel.dart b/lib/application/views/inventorymodule/modiferOption/viewModels/NewModifierOptionViewModel.dart index cef376f..2122531 100644 --- a/lib/application/views/inventorymodule/modiferOption/viewModels/NewModifierOptionViewModel.dart +++ b/lib/application/views/inventorymodule/modiferOption/viewModels/NewModifierOptionViewModel.dart @@ -11,6 +11,7 @@ import 'package:wosull/application/model/ingredients/GetIngredientModel.dart'; import 'package:wosull/application/model/modifierOptions/ModifierId.dart'; import 'package:wosull/application/model/modifierOptions/ModifierOption.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'; @@ -21,6 +22,7 @@ class NewModifierOptionViewModel with ChangeNotifier { bool get isLoading => _isLoading; var modifierOption = ModifierOption(); var selectedMeasurementUnits = []; + var modifiers = []; bool isEdit = false; dynamic selectedModifier; @@ -32,9 +34,10 @@ class NewModifierOptionViewModel with ChangeNotifier { _crudOperation = state; } - void init(bool isEdit, ModifierOption modifierOption) { + Future init(bool isEdit, ModifierOption modifierOption) async { this.modifierOption = modifierOption; this.isEdit = isEdit; + if (isEdit) { selectedModifier = Modifier( options: ToMany(items: []), @@ -48,6 +51,23 @@ class NewModifierOptionViewModel with ChangeNotifier { } else { this.modifierOption.ingredients = []; } + + final response = await WosulRepository().getModifiers(); + modifiers.addAll(response); + } + + 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 isValidate() async { @@ -94,20 +114,6 @@ class NewModifierOptionViewModel with ChangeNotifier { notifyListeners(); } - 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> getMeasurements() async { var items = []; diff --git a/lib/application/views/inventorymodule/modiferOption/views/ModiferOptionVC.dart b/lib/application/views/inventorymodule/modiferOption/views/ModiferOptionVC.dart index 1c8a503..a95f74d 100644 --- a/lib/application/views/inventorymodule/modiferOption/views/ModiferOptionVC.dart +++ b/lib/application/views/inventorymodule/modiferOption/views/ModiferOptionVC.dart @@ -41,21 +41,59 @@ class _ModifierOptionVCState extends BaseStatefulState { padding: const EdgeInsets.all(12), child: Column( children: [ - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - const Text( - 'Modifier Options', - style: ThemeText.textStylePageHeading, - ), - AppSpaces.horizontalSmall, - newModifier(), - Flexible(child: PageLimitDropdown(onChange: (value) { - viewModel.fetch( - isRefresh: true, limit: int.parse(value!)); - })) - ], - ), + 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, @@ -151,17 +189,14 @@ class _ModifierOptionVCState extends BaseStatefulState { } Widget newModifier() { - return SizedBox( - width: 170, - child: CustomSimpleButton( - heading: '+ New Modifiers Options', - textColor: MyColors.blueThemeColor, - backGroundColor: MyColors.backColorBlue50, - height: 38, - onPressed: () { - addEditModifierOption(false, ModifierOption()); - }, - ), + return CustomSimpleButton( + heading: '+ New Modifiers Options', + textColor: MyColors.blueThemeColor, + backGroundColor: MyColors.backColorBlue50, + height: 38, + onPressed: () { + addEditModifierOption(false, ModifierOption()); + }, ); } diff --git a/lib/application/views/inventorymodule/modiferOption/views/NewModifierOptionVC.dart b/lib/application/views/inventorymodule/modiferOption/views/NewModifierOptionVC.dart index 0b47c99..400bf7a 100644 --- a/lib/application/views/inventorymodule/modiferOption/views/NewModifierOptionVC.dart +++ b/lib/application/views/inventorymodule/modiferOption/views/NewModifierOptionVC.dart @@ -63,7 +63,7 @@ class _NewModifierOptionVCState 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 = @@ -84,7 +84,7 @@ class _NewModifierOptionVCState extends State { ? 'Edit Modifier Options' : 'New Modifier Options'), Padding( - padding: const EdgeInsets.all(16), + padding: const EdgeInsets.all(12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -172,33 +172,23 @@ class _NewModifierOptionVCState extends State { } Widget getModifierWidget() { - return FutureBuilder( - future: viewModel.getModifiers(), - builder: (c, s) { - if (s.hasData) { - var itemsList = s.data ?? []; - return DropdownSearch( - enabled: !widget.isView, - dropdownButtonProps: ThemeDropDown.dropdownButtonProps, - popupProps: PopupProps.menu( - menuProps: ThemeDropDown.menuProps, - fit: FlexFit.loose, - constraints: const BoxConstraints(maxHeight: 300), - ), - clearButtonProps: ThemeDropDown.clearButton, - selectedItem: viewModel.selectedModifier, - items: itemsList, - itemAsString: (Modifier u) => u.name, - onChanged: (options) { - viewModel.onSelectModifier(options); - }, - dropdownDecoratorProps: - MyColors.dropDownStyle(hint: 'Choose Modifier'), - ); - } else { - return AppLoader(); - } - }); + return DropdownSearch( + enabled: !widget.isView, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + 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() { @@ -322,7 +312,9 @@ class _NewModifierOptionVCState extends State { )), Expanded( child: PortraitContainer( - child: getMeasurementUnit(position), + child: Center( + child: getMeasurementUnit(position), + ), )) ], ), @@ -333,14 +325,7 @@ class _NewModifierOptionVCState extends State { ), ); } 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 WrapHeightContainer( child: Row( children: [ Expanded( @@ -389,7 +374,7 @@ class _NewModifierOptionVCState extends State { viewModel.setMeasurementUnit(position, data); }, dropdownDecoratorProps: - MyColors.dropDownStyle(hint: 'Choose Unit')); + MyColors.dropDownStyleAddProduct(hint: 'Choose Unit')); } else { return AppLoader(); } diff --git a/lib/application/views/inventorymodule/modiferOption/widgets/ModifierOptionsListView.dart b/lib/application/views/inventorymodule/modiferOption/widgets/ModifierOptionsListView.dart index 77e07d1..9537526 100644 --- a/lib/application/views/inventorymodule/modiferOption/widgets/ModifierOptionsListView.dart +++ b/lib/application/views/inventorymodule/modiferOption/widgets/ModifierOptionsListView.dart @@ -5,9 +5,11 @@ 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 { @@ -35,10 +37,7 @@ class ModifierOptionsListView extends StatelessWidget { children: [ isPortrait ? Container() - : Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 48, - color: MyColors.containerBackColor, + : ListHeadingContainer( child: Row( children: [ Expanded( @@ -140,33 +139,7 @@ class ModifierOptionsListView extends StatelessWidget { ], ), )), - 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), - ) + getPopupMenuButton(context, position) ], ), ), @@ -176,10 +149,7 @@ class ModifierOptionsListView 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!)), @@ -205,34 +175,7 @@ class ModifierOptionsListView extends StatelessWidget { child: Align( alignment: Alignment.centerRight, child: ActionPopUpContainer( - 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: getPopupMenuButton(context, position), ), ), )) @@ -258,4 +201,31 @@ class ModifierOptionsListView extends StatelessWidget { 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 b7b2f27..6fda598 100644 --- a/lib/application/views/inventorymodule/modifierviews/InventoryModifierVC.dart +++ b/lib/application/views/inventorymodule/modifierviews/InventoryModifierVC.dart @@ -52,11 +52,23 @@ class _InventoryModifierVCState extends BaseStatefulState { style: ThemeText.textStylePageHeading, ), AppSpaces.horizontalSmall, - newModifier(), - Flexible(child: PageLimitDropdown(onChange: (value) { - viewModel.fetch( - isRefresh: true, limit: int.parse(value!)); - })) + 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, @@ -170,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 4c3c519..0b7073a 100644 --- a/lib/application/views/inventorymodule/modifierviews/InventoryNewModifierVC.dart +++ b/lib/application/views/inventorymodule/modifierviews/InventoryNewModifierVC.dart @@ -54,7 +54,7 @@ class _InventoryNewModifierVCState 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/modifierviews/ViewInventoryModifiersVC.dart b/lib/application/views/inventorymodule/modifierviews/ViewInventoryModifiersVC.dart index abb7a8c..66bed18 100644 --- a/lib/application/views/inventorymodule/modifierviews/ViewInventoryModifiersVC.dart +++ b/lib/application/views/inventorymodule/modifierviews/ViewInventoryModifiersVC.dart @@ -22,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( @@ -58,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/viewModels/NewModifierVM.dart b/lib/application/views/inventorymodule/modifierviews/viewModels/NewModifierVM.dart index 29a8b20..3317e8c 100644 --- a/lib/application/views/inventorymodule/modifierviews/viewModels/NewModifierVM.dart +++ b/lib/application/views/inventorymodule/modifierviews/viewModels/NewModifierVM.dart @@ -97,7 +97,8 @@ class NewModifierVM with ChangeNotifier { // 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 bca59b5..c42f5bb 100644 --- a/lib/application/views/inventorymodule/modifierviews/widgets/ModifierListView.dart +++ b/lib/application/views/inventorymodule/modifierviews/widgets/ModifierListView.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 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 b19e6ed..2d608ff 100644 --- a/lib/application/views/inventorymodule/productviews/AddNewInventoryProductVC.dart +++ b/lib/application/views/inventorymodule/productviews/AddNewInventoryProductVC.dart @@ -14,7 +14,9 @@ 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'; @@ -28,6 +30,7 @@ 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/HeadingContainer.dart'; @@ -200,11 +203,21 @@ class _AddNewInventoryProductVCState extends State Expanded(child: getSalePriceExclTax()), AppSpaces.horizontalMedium, Expanded(child: getPriceIncludeTax()), - AppSpaces.horizontalMedium, - Expanded( - child: getStockAlertQuantityWidget()), + isPortrait + ? Container() + : AppSpaces.horizontalMedium, + isPortrait + ? Container() + : Expanded( + child: getStockAlertQuantityWidget()), ], ), + isPortrait + ? AppSpaces.verticalMedium + : Container(), + isPortrait + ? getStockAlertQuantityWidget() + : Container(), AppSpaces.verticalLarge, Row( crossAxisAlignment: CrossAxisAlignment.start, @@ -498,7 +511,7 @@ class _AddNewInventoryProductVCState extends State viewModel.editDeliveryPartner(position, partner); }, dropdownDecoratorProps: - MyColors.dropDownStyle(hint: 'Choose Partner')); + MyColors.dropDownStyleAddProduct(hint: 'Choose Partner')); } else { return AppLoader(); } @@ -526,14 +539,15 @@ class _AddNewInventoryProductVCState extends State onChanged: (MeasurementUnit? data) { viewModel.setMeasurementUnit(position, data); }, - dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose')); + dropdownDecoratorProps: + MyColors.dropDownStyleAddProduct(hint: 'Choose')); } else { return AppLoader(); } }); } - Widget getSupplierWidget(BuildContext context) { + Widget getSupplierWidget() { return FutureBuilder( future: viewModel.getSuppliersData(), builder: (c, s) { @@ -589,7 +603,7 @@ class _AddNewInventoryProductVCState extends State }); } - Widget getDiscounts(BuildContext context) { + Widget getDiscounts() { return FutureBuilder( future: viewModel.getDiscount(), builder: (c, s) { @@ -650,93 +664,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, - 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, - ), + 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, ), ), - // 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(), - // ), - ], - )) - ], - ), - )); - }), - ); + ), + // 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(); } @@ -775,7 +786,7 @@ class _AddNewInventoryProductVCState extends State fit: FlexFit.loose, constraints: const BoxConstraints(maxHeight: 250)), items: itemsList, - itemAsString: (MeasurementUnit u) => u.name!, + itemAsString: (MeasurementUnit u) => u.name, onChanged: (MeasurementUnit? data) { viewModel.setMeasurementUnitProduct(data); }, @@ -841,50 +852,54 @@ class _AddNewInventoryProductVCState extends State 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: [ - PortraitContainer( - width: double.infinity, - height: 48, - child: Align( - alignment: Alignment.centerLeft, - child: HeadingText( - AppLocalizations.of(context)!.name, - ), - ), + 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, ), - PortraitContainer( - width: double.infinity, - height: 48, - child: Align( - alignment: Alignment.centerLeft, - child: HeadingText( - 'Delivery Partner Price', - ), - ), - ) - ], - )), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - getDeliveryPartner(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) ], ), @@ -899,7 +914,9 @@ class _AddNewInventoryProductVCState extends State child: getDeliveryPartner(position), ), Expanded( - child: deliveryPartnerPrice(position), + child: ChildContainer( + child: deliveryPartnerPrice(position), + ), ), removeDeliveryPartnerButton(position), ], @@ -907,9 +924,7 @@ class _AddNewInventoryProductVCState extends State ); } }, - itemCount: viewModel.storeItem.deliveryPartners != null - ? viewModel.storeItem.deliveryPartners.length - : 0, + itemCount: viewModel.storeItem.deliveryPartners.length, ); } @@ -922,18 +937,15 @@ class _AddNewInventoryProductVCState extends State } Widget deliveryPartnerPrice(int position) { - return ChildContainer( - width: double.infinity, - child: 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); - }, - ), + 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); + }, ); } @@ -959,13 +971,42 @@ class _AddNewInventoryProductVCState extends State getCategory() { return Column( children: [ - MandatoryTitleText(hint: AppLocalizations.of(context)!.category), + 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: [ @@ -987,7 +1028,8 @@ class _AddNewInventoryProductVCState extends State AppSpaces.verticalSmall, CustomTextFieldForm( hintText: 'Enter Quantity', - initialValue: viewModel.storeItem.totalAddedQuantity.toString() ?? '', + initialValue: + viewModel.storeItem.totalAddedQuantity?.toString() ?? '', readOnly: widget.isView || viewModel.storeItem.isUnlimitedQuantity, keyboardType: TextInputType.number, onChanged: (value) { @@ -1005,34 +1047,37 @@ class _AddNewInventoryProductVCState extends State hint: AppLocalizations.of(context)!.barcode, ), AppSpaces.verticalSmall, - Row( - children: [ - Expanded( - child: CustomTextFieldForm( - hintText: 'Enter Barcode', - readOnly: widget.isView, - key: Key(viewModel.storeItem.uniqueIdForStoreData.toString()), - initialValue: viewModel.storeItem.uniqueIdForStoreData.toString(), - onChanged: (value) { - viewModel.storeItem.uniqueIdForStoreData = value; - }, - )), - SizedBox( - width: 100, - child: CustomSimpleButton( - height: 48, - backGroundColor: MyColors.backColorBlue50, - textColor: MyColors.blueThemeColor, - onPressed: () { - if (!widget.isView) { - viewModel.generateCode(); - } + 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; }, - heading: 'Generate', + hintText: 'Enter bar code', + )), + AppSpaces.horizontalSmall, + SizedBox( + width: 80, + child: GenerateBarCodeButton( + onPressed: () { + if (!widget.isView) { + viewModel.generateCode(); + } + }, + ), ), - ), - ], - ), + ], + ), + ) ], ); } @@ -1092,7 +1137,7 @@ class _AddNewInventoryProductVCState extends State CustomTextFieldForm( hintText: 'Enter Price (Incl. Tax)', readOnly: widget.isView, - initialValue: viewModel.storeItem.price.toStringAsFixed(2), + initialValue: viewModel.storeItem.price?.toStringAsFixed(2) ?? '', keyboardType: TextInputType.number, onChanged: (value) { viewModel.setPrice(value); @@ -1152,8 +1197,9 @@ class _AddNewInventoryProductVCState extends State AppSpaces.verticalSmall, CustomTextFieldForm( readOnly: true, - initialValue: viewModel.storeItem.salePriceExclusiveTax.toString(), - key: Key(viewModel.storeItem.salePriceExclusiveTax.toString()), + initialValue: + viewModel.storeItem.salePriceExclusiveTax?.toString() ?? '', + key: Key(viewModel.storeItem.salePriceExclusiveTax?.toString() ?? ''), keyboardType: TextInputType.number, onChanged: (value) {}, hintText: 'Enter Sale Price (Excl. Tax)', @@ -1171,12 +1217,12 @@ class _AddNewInventoryProductVCState extends State ), AppSpaces.verticalSmall, CustomTextFieldForm( - initialValue: viewModel.storeItem.purchasePrice.toString(), + initialValue: viewModel.storeItem.purchasePrice?.toString() ?? '', hintText: 'Enter Price (Incl. Tax)', readOnly: widget.isView, keyboardType: TextInputType.number, onChanged: (value) { - viewModel.storeItem.purchasePrice = double.parse(value); + viewModel.updatePurchasePrice(value); }, ), ], @@ -1192,12 +1238,13 @@ class _AddNewInventoryProductVCState extends State ), AppSpaces.verticalSmall, CustomTextFieldForm( - initialValue: viewModel.storeItem.stockAlertQuantity.toString() ?? '', + initialValue: + viewModel.storeItem.stockAlertQuantity?.toString() ?? '', hintText: 'Enter Stock Alert Quantity', readOnly: widget.isView, keyboardType: TextInputType.number, onChanged: (value) { - viewModel.storeItem.stockAlertQuantity = int.parse(value); + viewModel.updateStockAlert(value); }, ), ], @@ -1212,7 +1259,7 @@ class _AddNewInventoryProductVCState extends State hint: AppLocalizations.of(context)!.discount, ), AppSpaces.verticalSmall, - getDiscounts(context), + getDiscounts(), ], ); } @@ -1225,7 +1272,7 @@ class _AddNewInventoryProductVCState extends State hint: AppLocalizations.of(context)!.supplier, ), AppSpaces.verticalSmall, - getSupplierWidget(context), + getSupplierWidget(), ], ); } @@ -1245,11 +1292,12 @@ class _AddNewInventoryProductVCState extends State Widget getManufactureDateButton() { return CustomTextButtonIcon( - backgroundColor: MyColors.white, + backgroundColor: MyColors.backFillColor, icon: Icons.calendar_month, heading: viewModel.storeItem.manufactureDate.isEmpty ? 'dd/mm/yyyy' - : DataTimeFormat.getFormatDate(viewModel.storeItem.manufactureDate), + : DataTimeFormat.getFormatDateString( + viewModel.storeItem.manufactureDate), onPressed: () { viewModel.presentDatePicker(context, true); }, @@ -1271,13 +1319,13 @@ class _AddNewInventoryProductVCState extends State Widget getExpireDateButton() { return CustomTextButtonIcon( - backgroundColor: MyColors.white, + backgroundColor: MyColors.backFillColor, icon: Icons.calendar_month, heading: viewModel.storeItem.expireDate.isEmpty ? 'dd/mm/yyyy' - : DataTimeFormat.getFormatDate(viewModel.storeItem.expireDate), + : DataTimeFormat.getFormatDateString(viewModel.storeItem.expireDate), onPressed: () { - viewModel.presentDatePicker(context, true); + viewModel.presentDatePicker(context, false); }, ); } @@ -1334,7 +1382,7 @@ class _AddNewInventoryProductVCState extends State Center( child: Text( AppLocalizations.of(context)!.image_information_txt, - style: const TextStyle( + style: TextStyle( fontFamily: MyFonts.DMREGULAR, fontSize: MyFonts.normal, color: MyColors.textColorGray), @@ -1419,7 +1467,7 @@ class _AddNewInventoryProductVCState extends State child: PortraitContainer( child: Align( alignment: Alignment.centerLeft, - child: ValueText(viewModel + child: CustomTextAddProduct(viewModel .storeItem.ingredients[position].name), ), ), @@ -1439,7 +1487,7 @@ class _AddNewInventoryProductVCState extends State child: PortraitContainer( child: Align( alignment: Alignment.centerLeft, - child: ValueText( + child: CustomTextAddProduct( viewModel.storeItem.ingredients[position] .purchaseCost! .toString(), @@ -1461,7 +1509,6 @@ class _AddNewInventoryProductVCState extends State Expanded( child: PortraitContainer( width: 100, - height: 48, child: Center( child: getSalePriceOneUnitIngredient(position), ), diff --git a/lib/application/views/inventorymodule/productviews/InventoryProductVC.dart b/lib/application/views/inventorymodule/productviews/InventoryProductVC.dart index 646b086..9657e1a 100644 --- a/lib/application/views/inventorymodule/productviews/InventoryProductVC.dart +++ b/lib/application/views/inventorymodule/productviews/InventoryProductVC.dart @@ -52,36 +52,41 @@ class _InventoryProductVCState extends BaseStatefulState { ? Column( children: [ Row( - mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, children: [ Text( AppLocalizations.of(context)!.our_products, style: ThemeText.textStylePageHeading, ), - AppSpaces.horizontalSmall, - SizedBox( - height: 38, - width: 150, - child: getCategoriesDropdown()), - AppSpaces.horizontalSmall, - SizedBox( - width: 120, - child: addProductButton(), + AppSpaces.horizontalMedium, + Flexible( + child: SizedBox( + height: 38, + child: getCategoriesDropdown())), + AppSpaces.horizontalMedium, + Flexible( + child: SizedBox( + child: addProductButton(), + ), ), ], ), - AppSpaces.verticalMedium, Row( children: [ Flexible( - child: SearchBox( - onEditingDone: (text) { - // filterSearchResults(text); - }, - onChanged: (text) { - // filterSearchResults(text); - }, - hint: AppLocalizations.of(context)!.search, + child: SizedBox( + height: 48, + child: SearchBox( + onEditingDone: (text) { + // filterSearchResults(text); + }, + onChanged: (text) { + // filterSearchResults(text); + }, + hint: + AppLocalizations.of(context)!.search, + ), ), ), PageLimitDropdown(onChange: (value) { diff --git a/lib/application/views/inventorymodule/productviews/SearchProductVC.dart b/lib/application/views/inventorymodule/productviews/SearchProductVC.dart index 8e1b08d..274a406 100644 --- a/lib/application/views/inventorymodule/productviews/SearchProductVC.dart +++ b/lib/application/views/inventorymodule/productviews/SearchProductVC.dart @@ -1,7 +1,7 @@ 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'; @@ -32,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; @@ -155,7 +155,7 @@ class _SearchProductVCState extends State { setState(() { _isInAsyncCall = true; }); - InventoryViewModel viewModel = InventoryViewModel(); + final viewModel = WosulRepository(); Map data = { 'store_id': sharedPrefs.storeId, diff --git a/lib/application/views/inventorymodule/productviews/viewModels/AddProductViewModel.dart b/lib/application/views/inventorymodule/productviews/viewModels/AddProductViewModel.dart index 41cb224..b93cea7 100644 --- a/lib/application/views/inventorymodule/productviews/viewModels/AddProductViewModel.dart +++ b/lib/application/views/inventorymodule/productviews/viewModels/AddProductViewModel.dart @@ -65,8 +65,8 @@ class AddProductViewModel with ChangeNotifier { } void initDeliveryPartner() { - storeItem.deliveryPartners = ToMany(items: []); storeItem.deliveryPartners.add(ItemsDeliveryPartner()); + selectedPartners.add(DeliveryPartner(id: '', name: 'Choose Partner')); } void disposeData() { @@ -78,9 +78,7 @@ class AddProductViewModel with ChangeNotifier { selectedDiscount = null; selectedSupplier = null; selectedMeasurement = null; - ; selectedMeasurementUnit = null; - ; isLoadingData = false; imageFile = null; isImageUploaded = false; @@ -154,6 +152,7 @@ class AddProductViewModel with ChangeNotifier { selectedModifiers: ToMany(items: []), deliveryPartners: ToMany(items: []), ); + initDeliveryPartner(); } } @@ -405,6 +404,7 @@ class AddProductViewModel with ChangeNotifier { } } } + selectedDiscount ??= StoreDiscount(name: 'Choose'); } }).onError((error, stackTrace) {}); @@ -440,9 +440,11 @@ class AddProductViewModel with ChangeNotifier { 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 (isEdit) { if (selectedCategory == null) { selectedCategory = items.singleWhere( @@ -452,12 +454,13 @@ class AddProductViewModel with ChangeNotifier { storeItem.productIdSt = selectedCategory.id!; } } else { - storeItem.productIdSt = selectedCategory.id!; + selectedCategory = items[0]; + storeItem.productIdSt = items.first.id; } - - selectedCategory ??= items[0]; } - }).onError((error, stackTrace) {}); + }).onError((error, stackTrace) { + print(error.toString()); + }); return items; } @@ -514,7 +517,8 @@ class AddProductViewModel with ChangeNotifier { items.addAll(response.measurementUnits); if (isEdit && !isIngredient) { final name = items - .singleWhere((element) => element.name == storeItem.measurement) + .singleWhere( + (element) => element.name == storeItem.measurementUnit) .name; selectedMeasurementUnit = MeasurementUnit(id: '', name: name ?? ''); } else if (isEdit && isIngredient) { @@ -682,16 +686,32 @@ class AddProductViewModel with ChangeNotifier { void updateIngredientUnitPrice(int position, String value) { if (value.isNotEmpty) { - storeItem.ingredients[position].price = int.parse(value); + storeItem.ingredients[position].price = double.parse(value); } } void setMeasurementUnitProduct(MeasurementUnit? data) { if (data != null) { selectedMeasurementUnit = data; - storeItem.measurementUnit = data.name!; + 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/views/ProductListView.dart b/lib/application/views/inventorymodule/productviews/views/ProductListView.dart index 7badd87..8b7926c 100644 --- a/lib/application/views/inventorymodule/productviews/views/ProductListView.dart +++ b/lib/application/views/inventorymodule/productviews/views/ProductListView.dart @@ -4,10 +4,14 @@ 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 { @@ -39,10 +43,7 @@ class ProductListView extends StatelessWidget { children: [ isPortrait ? Container() - : Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 48, - color: MyColors.containerBackColor, + : ListHeadingContainer( child: Row( children: [ Expanded( @@ -82,111 +83,129 @@ class ProductListView extends StatelessWidget { shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.0), ), - elevation: 2, + elevation: 5, 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)), - ), - ), + 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( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.start, - children: [ - HeadingText(lang(context).name), - const SizedBox( - height: 8, - ), - HeadingText(lang(context).category), - const SizedBox( - height: 8, - ), - HeadingText(lang(context).price), - const SizedBox( - height: 8, - ), - HeadingText(lang(context).status), - const SizedBox( - height: 8, - ), - HeadingText(lang(context).updated_on), - ], - )), - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.end, - mainAxisAlignment: - MainAxisAlignment.start, - children: [ - ValueText(item.name), - AppSpaces.verticalMedium, - ValueText(selectedCategoryName), - AppSpaces.verticalMedium, - ValueText(item.price.toString()), - AppSpaces.verticalMedium, - Row( - mainAxisAlignment: - MainAxisAlignment.end, - crossAxisAlignment: - CrossAxisAlignment.end, - children: [ - CustomSwitch( - value: item.isItemInStock, - onToggle: (value) { - onUpdate(item, value); - }, - ) - ], - ), - AppSpaces.verticalMedium, - ValueText( - DataTimeFormat.getFormatDate( - item.updatedAt)), - ], - )), - ], - ) - ], + ), ), - )), - getPopUpBuilder(context, item) - ], - ), + 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 { @@ -194,10 +213,7 @@ class ProductListView 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( @@ -273,35 +289,28 @@ class ProductListView extends StatelessWidget { } } - PopupMenuButton getPopUpBuilder( - BuildContext context, StoreItems item) { - return PopupMenuButton( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - icon: const Icon(Icons.more_vert), - itemBuilder: (c) { - return [ - PopupMenuItem( - value: 'edit', - child: ValueText( - lang(context).edit, - ), + 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: 'view', - child: ValueText( - lang(context).view, - ), + ), + PopupMenuItem( + value: 'delete', + child: ValueText( + lang(context).delete, ), - 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/viewmodels/NewStockReturnViewModel.dart b/lib/application/views/inventorymodule/stockReturn/viewmodels/NewStockReturnViewModel.dart index 6f83991..9359574 100644 --- a/lib/application/views/inventorymodule/stockReturn/viewmodels/NewStockReturnViewModel.dart +++ b/lib/application/views/inventorymodule/stockReturn/viewmodels/NewStockReturnViewModel.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:wosull/application/ViewModel/InventoryViewModel.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'; @@ -10,6 +9,7 @@ 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/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'; @@ -22,9 +22,9 @@ class NewStockReturnViewModel with ChangeNotifier { List selectedMeasurement = []; List selectedTax = []; List filteredProductItems = []; - late var stockReturn; + late ReturnStock stockReturn; var returnCharge = ReturnStockCharges(amount: '', name: ''); - var fetchDataHelper = InventoryViewModel(); + var fetchDataHelper = WosulRepository(); bool _isLoading = false; @@ -57,9 +57,8 @@ class NewStockReturnViewModel with ChangeNotifier { stockReturn = stock; if (isEdit) { } else { + stockReturn = ReturnStock(products: [], charges: []); addEmptyService(); - stockReturn.products = []; - stockReturn.charges = []; } final response = await fetchDataHelper.getAllProducts(); @@ -141,7 +140,7 @@ class NewStockReturnViewModel with ChangeNotifier { } void addEmptyService() { - selectedProduct.add(ProductItem()); + selectedProduct.add(ProductItem(name: 'Choose')); selectedDiscount.add(StoreDiscount( categories: [], products: [], discountPercentage: "Choose")); selectedTax.add(VAT(name: 'VAT', value: "Choose")); diff --git a/lib/application/views/inventorymodule/stockReturn/views/NewStockReturnVC.dart b/lib/application/views/inventorymodule/stockReturn/views/NewStockReturnVC.dart index 1d19c6d..c009579 100644 --- a/lib/application/views/inventorymodule/stockReturn/views/NewStockReturnVC.dart +++ b/lib/application/views/inventorymodule/stockReturn/views/NewStockReturnVC.dart @@ -7,6 +7,7 @@ import 'package:wosull/application/model/Measurement/InventoryMeasurementModel.d 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'; @@ -24,13 +25,14 @@ 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/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 NewStockReturnVC extends StatefulWidget { bool isEdit = false; @@ -267,167 +269,158 @@ class _NewStockReturnVCState extends State { shrinkWrap: true, itemBuilder: (c, position) { if (viewModel.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, - ), + return WrapHeightContainer( child: Row( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ Expanded( flex: 2, - child: Container( - 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, - ), + 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)! + .quantity, ), ), - 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)! + .unit_price, ), ), - 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_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)! + .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)! + .select_tax, ), ), - PortraitContainer( - width: double.infinity, - child: Align( - alignment: Alignment.centerLeft, - child: HeadingText( - '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), + ), + ], + )), + 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: getProductQuantity(position), - ), + ), + PortraitContainer( + width: double.infinity, + child: Center( + child: getProductPrice(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: getDiscountsTypes(position), - ), + ), + PortraitContainer( + width: double.infinity, + child: Center( + child: getDiscounts(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: getTaxWidget(position), - ), - ), - PortraitContainer( - width: double.infinity, - child: Center( - child: getMeasurementWidget(position), - ), + ), + PortraitContainer( + width: double.infinity, + child: Center( + child: getMeasurementWidget(position), ), - PortraitContainer( - width: double.infinity, + ), + PortraitContainer( + width: double.infinity, + child: Align( + alignment: Alignment.centerRight, child: getSingleItemTaxWidget(position), ), - ], - )), - ], - ), + ), + ], + )), + ], )), getRemoveProductButton(position) ], @@ -479,7 +472,9 @@ class _NewStockReturnVCState extends State { ChildContainer(child: getTaxWidget(position))), ChildContainer( width: 80, - child: getSingleItemTaxWidget(position), + child: Center( + child: getSingleItemTaxWidget(position), + ), ), getRemoveProductButton(position) ], @@ -570,7 +565,9 @@ class _NewStockReturnVCState extends State { AppSpaces.verticalMedium, Row( children: [ - const Expanded(child: Text('')), + viewModel.isPortrait + ? Container() + : const Expanded(child: Text('')), Expanded( child: Row( children: [ @@ -599,7 +596,9 @@ class _NewStockReturnVCState extends State { AppSpaces.verticalMedium, Row( children: [ - const Expanded(child: Text('')), + viewModel.isPortrait + ? Container() + : const Expanded(child: Text('')), Expanded( child: Row( children: [ @@ -628,7 +627,9 @@ class _NewStockReturnVCState extends State { AppSpaces.verticalMedium, Row( children: [ - const Expanded(child: Text('')), + viewModel.isPortrait + ? Container() + : const Expanded(child: Text('')), Expanded( child: Row( children: [ @@ -637,15 +638,15 @@ class _NewStockReturnVCState extends State { alignment: Alignment.centerRight, child: Text( AppLocalizations.of(context)!.total_amount, - style: ThemeText.textStyleAmountValue, + style: ThemeText.textStyleAmountHeadingBlack, ), )), Expanded( child: Align( alignment: Alignment.centerRight, child: Text( - viewModel.getTotalProductsPrice(), - style: ThemeText.textStyleAmountValue, + "${sharedPrefs.currency} ${viewModel.getTotalProductsPrice()}", + style: ThemeText.textStyleAmountHeadingBlack, ), )), AppSpaces.horizontalMedium, @@ -688,7 +689,8 @@ class _NewStockReturnVCState extends State { onChanged: (Measurement? data) { viewModel.setMeasurement(data, position); }, - dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), + dropdownDecoratorProps: + MyColors.dropDownStyleAddProduct(hint: 'Choose'), ); } else { return AppLoader(); @@ -718,7 +720,8 @@ class _NewStockReturnVCState extends State { onChanged: (VAT? data) { viewModel.setVat(data, position); }, - dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), + dropdownDecoratorProps: + MyColors.dropDownStyleAddProduct(hint: 'Choose'), ); } else { return AppLoader(); @@ -742,7 +745,7 @@ class _NewStockReturnVCState extends State { onChanged: (String? data) { viewModel.setDiscountType(position, data); }, - dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), + dropdownDecoratorProps: MyColors.dropDownStyleAddProduct(hint: 'Choose'), ); } @@ -765,24 +768,15 @@ class _NewStockReturnVCState extends State { } 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( - readOnly: widget.isView, - initialValue: viewModel - .stockReturn.products![position].discountPercentage - ?.toString() ?? - '', - onChanged: (String value) { - viewModel.onChangeManualDiscount(value, position); - }, - hintText: '', - ), + return CustomTextFieldForm( + readOnly: widget.isView, + initialValue: viewModel.stockReturn.products![position].discountPercentage + ?.toString() ?? + '', + onChanged: (String value) { + viewModel.onChangeManualDiscount(value, position); + }, + hintText: '', ); } @@ -806,7 +800,8 @@ class _NewStockReturnVCState extends State { onChanged: (StoreDiscount? data) { viewModel.onChangeAutoDiscount(data, position); }, - dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), + dropdownDecoratorProps: + MyColors.dropDownStyleAddProduct(hint: 'Choose'), ); } else { return AppLoader(); @@ -873,22 +868,18 @@ class _NewStockReturnVCState extends State { onChanged: (ProductItem? data) { viewModel.updateProduct(data, position); }, - dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), + dropdownDecoratorProps: MyColors.dropDownStyleAddProduct(hint: 'Choose'), ); } getSingleItemTaxWidget(int position) { - return Center( - child: ValueText( - viewModel.stockReturn.products![position].tax!.toStringAsFixed(2)), - ); + return CustomTextAddProduct( + viewModel.stockReturn.products![position].tax!.toStringAsFixed(2)); } getSingleItemAmountWidget(int position) { - return Center( - child: ValueText( - viewModel.stockReturn.products![position].amount!.toStringAsFixed(2)), - ); + return CustomTextAddProduct( + viewModel.stockReturn.products![position].amount!.toStringAsFixed(2)); } Widget getStockReturnDate() { @@ -909,7 +900,8 @@ class _NewStockReturnVCState extends State { height: 48, backgroundColor: MyColors.backFillColor, icon: Icons.calendar_month, - heading: viewModel.stockReturn.stockReturnDate ?? 'dd/mm/yyyy', + heading: DataTimeFormat.getFormatDateString( + viewModel.stockReturn.stockReturnDate ?? ''), onPressed: () { if (!widget.isView) { viewModel.presentDatePicker(context); @@ -968,7 +960,7 @@ class _NewStockReturnVCState extends State { viewModel.updateTaxOption(data); }, dropdownDecoratorProps: - MyColors.dropDownStyle(hint: 'Choose Tax Option'), + MyColors.dropDownStyleAddProduct(hint: 'Choose Tax Option'), ) ], ); @@ -1062,14 +1054,12 @@ class _NewStockReturnVCState extends State { getChargeView() { return Row( children: [ - const Expanded(child: Text('')), + viewModel.isPortrait ? Container() : const Expanded(child: Text('')), Expanded( child: Row( children: [ Expanded( child: CustomTextFieldForm( - height: 42, - key: Key(viewModel.returnCharge.name), initialValue: viewModel.returnCharge.name, onChanged: (String value) { viewModel.returnCharge.name = value; @@ -1080,8 +1070,6 @@ class _NewStockReturnVCState extends State { Expanded( child: CustomTextFieldForm( keyboardType: TextInputType.number, - height: 42, - key: Key(viewModel.returnCharge.amount), onChanged: (String value) { viewModel.returnCharge.amount = value; }, @@ -1103,14 +1091,13 @@ class _NewStockReturnVCState extends State { getRemoveChargeView(int position) { return Row( children: [ - const Expanded(child: Text('')), + viewModel.isPortrait ? Container() : const Expanded(child: Text('')), Expanded( child: Row( children: [ Expanded( child: CustomTextFieldForm( readOnly: widget.isView, - height: 42, initialValue: viewModel.stockReturn.charges![position].name, onChanged: (String value) { viewModel.stockReturn.charges![position].name = value; @@ -1120,7 +1107,6 @@ class _NewStockReturnVCState extends State { AppSpaces.horizontalMedium, Expanded( child: CustomTextFieldForm( - height: 42, readOnly: widget.isView, initialValue: viewModel.stockReturn.charges![position].amount, onChanged: (String value) { diff --git a/lib/application/views/inventorymodule/stockReturn/views/StockReturnVC.dart b/lib/application/views/inventorymodule/stockReturn/views/StockReturnVC.dart index 9679176..376b3dc 100644 --- a/lib/application/views/inventorymodule/stockReturn/views/StockReturnVC.dart +++ b/lib/application/views/inventorymodule/stockReturn/views/StockReturnVC.dart @@ -41,21 +41,53 @@ class _StockReturnVCState extends BaseStatefulState { padding: const EdgeInsets.all(12), child: Column( children: [ - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - const Text( - 'Stock Return', - style: ThemeText.textStylePageHeading, - ), - AppSpaces.horizontalSmall, - newModifier(), - Flexible(child: PageLimitDropdown(onChange: (value) { - viewModel.fetch( - isRefresh: true, limit: int.parse(value!)); - })) - ], - ), + 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(), + ), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + PageLimitDropdown(onChange: (value) { + viewModel.fetch( + isRefresh: true, + limit: int.parse(value!)); + }) + ], + ) + ], + ), AppSpaces.verticalMedium, ChangeNotifierProvider( create: (context) => viewModel, @@ -141,18 +173,15 @@ class _StockReturnVCState extends BaseStatefulState { hideProgressBar(); } - Widget newModifier() { - return SizedBox( - width: 150, - child: CustomSimpleButton( - heading: '+ New Stock Return', - textColor: MyColors.blueThemeColor, - backGroundColor: MyColors.backColorBlue50, - height: 38, - onPressed: () { - openStockReturn(false, ReturnStock(), false); - }, - ), + Widget newStock() { + return CustomSimpleButton( + heading: '+ New Stock Return', + textColor: MyColors.blueThemeColor, + backGroundColor: MyColors.backColorBlue50, + height: 38, + onPressed: () { + openStockReturn(false, ReturnStock(), false); + }, ); } diff --git a/lib/application/views/inventorymodule/stockReturn/widgets/StockReturnListView.dart b/lib/application/views/inventorymodule/stockReturn/widgets/StockReturnListView.dart index daf6167..9713840 100644 --- a/lib/application/views/inventorymodule/stockReturn/widgets/StockReturnListView.dart +++ b/lib/application/views/inventorymodule/stockReturn/widgets/StockReturnListView.dart @@ -5,8 +5,10 @@ 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 { @@ -32,10 +34,7 @@ class StockReturnListView extends StatelessWidget { children: [ isPortrait ? Container() - : Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 48, - color: MyColors.containerBackColor, + : ListHeadingContainer( child: Row( children: [ Expanded( @@ -104,10 +103,18 @@ class StockReturnListView extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.start, children: [ HeadingText( - lang(context).modifier, + 'Stock Return Number', ), AppSpaces.verticalMedium, - HeadingText(lang(context).status), + HeadingText( + 'Bill To', + ), + AppSpaces.verticalMedium, + HeadingText( + 'Return Date', + ), + AppSpaces.verticalMedium, + HeadingText('Total Amount'), AppSpaces.verticalMedium, HeadingText(lang(context).created_on), AppSpaces.verticalMedium, @@ -139,33 +146,7 @@ class StockReturnListView extends StatelessWidget { ], ), )), - 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, stock), - ) + getPopupMenuButton(context, position) ], ), ), @@ -175,10 +156,7 @@ class StockReturnListView extends StatelessWidget { shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.0), ), - child: Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 48, - color: MyColors.containerBackColor, + child: ListHeadingContainer( child: Row( children: [ Expanded( @@ -203,33 +181,7 @@ class StockReturnListView extends StatelessWidget { child: Align( alignment: Alignment.centerRight, child: ActionPopUpContainer( - 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, stock), - ), + child: getPopupMenuButton(context, position), ), ), )) @@ -254,4 +206,31 @@ class StockReturnListView extends StatelessWidget { 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..9bf841c 100644 --- a/lib/application/views/inventorymodule/stockTransferViews/InventoryNewStockTransferVC.dart +++ b/lib/application/views/inventorymodule/stockTransferViews/InventoryNewStockTransferVC.dart @@ -3,15 +3,15 @@ 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'; @@ -20,7 +20,7 @@ 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,7 +34,7 @@ class _InventoryNewStockTransferVCState @override void initState() { - // TODO: implement initState + context.read().initData(); super.initState(); } @@ -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,25 @@ 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), + return DropdownSearch( + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + searchFieldProps: ThemeDropDown.textFieldProps, + searchDelay: Duration.zero, + interceptCallBacks: false, + showSearchBox: true, + isFilterOnline: false, + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 200), ), - 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, - ) - ], - ), - ); - } - - 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 +207,22 @@ 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( + 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 +235,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 +257,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 +275,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 +293,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 +309,84 @@ 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( + 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 0438d35..e32fb71 100644 --- a/lib/application/views/inventorymodule/stockTransferViews/InventoryStockTransferVC.dart +++ b/lib/application/views/inventorymodule/stockTransferViews/InventoryStockTransferVC.dart @@ -5,6 +5,7 @@ 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'; @@ -65,31 +66,32 @@ class _InventoryStockTransferVCState style: ThemeText.textStylePageHeading, ), AppSpaces.horizontalSmall, - getNewStockTransferBtn(), - ], - ), - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Flexible( - child: SearchBox( - onEditingDone: (text) { - filterSearchResults(text); - }, - onChanged: (text) { - filterSearchResults(text); - }, - hint: AppLocalizations.of(context)!.search, - ), - ), + Flexible(child: getNewStockTransferBtn()), AppSpaces.horizontalSmall, - PageLimitDropdown(onChange: (value) { - viewModel.fetch( - isRefresh: true, - limit: int.parse(value!)); - }) + 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( @@ -100,7 +102,10 @@ class _InventoryStockTransferVCState style: ThemeText.textStylePageHeading, ), AppSpaces.horizontalSmall, - getNewStockTransferBtn(), + SizedBox( + width: 140, + child: getNewStockTransferBtn(), + ), AppSpaces.horizontalSmall, SizedBox( width: SizerUtil.deviceType == DeviceType.mobile @@ -117,11 +122,16 @@ class _InventoryStockTransferVCState hint: AppLocalizations.of(context)!.search, ), ), - Flexible( - child: PageLimitDropdown(onChange: (value) { - viewModel.fetch( - isRefresh: true, limit: int.parse(value!)); - })) + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + PageLimitDropdown(onChange: (value) { + viewModel.fetch( + isRefresh: true, + limit: int.parse(value!)); + }) + ], + ) ], ), AppSpaces.verticalMedium, @@ -142,8 +152,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: @@ -227,7 +237,7 @@ class _InventoryStockTransferVCState ); } }).onError((error, stackTrace) { - print(error.toString()); + print(stackTrace.toString()); hideProgressBar(); }); } @@ -245,24 +255,22 @@ class _InventoryStockTransferVCState } Widget getNewStockTransferBtn() { - return SizedBox( - width: 140, - 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/viewModels/NewStockTransferVM.dart b/lib/application/views/inventorymodule/stockTransferViews/viewModels/NewStockTransferVM.dart index c7a651b..82e6fae 100644 --- a/lib/application/views/inventorymodule/stockTransferViews/viewModels/NewStockTransferVM.dart +++ b/lib/application/views/inventorymodule/stockTransferViews/viewModels/NewStockTransferVM.dart @@ -7,6 +7,7 @@ import 'package:wosull/application/model/StockTransfer/ProductItemCategoryModel. 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/helpers/Utils.dart'; @@ -21,16 +22,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,6 +45,12 @@ class NewStockTransferVM with ChangeNotifier { notifyListeners(); } + Future initData() async { + final response = await WosulRepository().getAllProducts(); + filteredProductItems.addAll(response); + notifyListeners(); + } + Future> getStores() async { var stores = []; Map data = { @@ -86,11 +88,11 @@ 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)); @@ -135,13 +137,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 +162,11 @@ 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!; + // nameController = productItem.name!; + // quantityController = productItem.total_quantity!.toString(); + // priceController = productItem.price!.toString(); + // uniqueIdController = productItem.uniqueIdForStoreData!; + // descriptionController = productItem.details!; } notifyListeners(); @@ -170,14 +174,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 +188,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 c4299f0..737343d 100644 --- a/lib/application/views/inventorymodule/stockTransferViews/viewModels/StockTransferViewModel.dart +++ b/lib/application/views/inventorymodule/stockTransferViews/viewModels/StockTransferViewModel.dart @@ -73,6 +73,7 @@ class StockTransferViewModel with ChangeNotifier { _dataState = DataState.fetched; _currentPageNumber += 1; }).onError((error, stackTrace) { + print(stackTrace.toString()); _isLoading = false; _dataState = DataState.error; }); 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 70c8cc6..e19f31c 100644 --- a/lib/application/views/inventorymodule/subCategoryViews/InventorySubCategoryVC.dart +++ b/lib/application/views/inventorymodule/subCategoryViews/InventorySubCategoryVC.dart @@ -1,18 +1,20 @@ +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/ItemSubCategoryResponse.dart'; +import 'package:wosull/application/model/inventory/category/ItemCategory.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/utils/CRUDOperatoinState.dart'; import 'package:wosull/application/views/inventorymodule/subCategoryViews/viewModels/AddSubCategoryViewModel.dart'; import 'package:wosull/base/BaseStatefulState.dart'; import 'package:wosull/helpers/AppSpaces.dart'; +import 'package:wosull/helpers/ThemeDropDown.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/ItemCategoryDropdown.dart'; import 'package:wosull/widgets/MandatoryTitleText.dart'; class InventorySubCategoryVC extends StatefulWidget { @@ -50,14 +52,13 @@ class _InventorySubCategoryVCState @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 = MediaQuery.of(c).orientation == Orientation.portrait; @@ -76,14 +77,12 @@ 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: [ @@ -92,9 +91,7 @@ class _InventorySubCategoryVCState AppLocalizations.of(context)!.category), AppSpaces.verticalSmall, getCategoryWidget(), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, getSubCategoryName(), isPortrait ? Column( @@ -104,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, @@ -131,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( @@ -162,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, @@ -188,9 +168,7 @@ class _InventorySubCategoryVCState viewModel.setActiveStatus(value); }, ), - const SizedBox( - width: 8, - ), + AppSpaces.horizontalMedium, CustomOptionalTitle( hint: AppLocalizations.of(context)! @@ -206,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, @@ -232,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; @@ -271,13 +247,22 @@ class _InventorySubCategoryVCState } Widget getCategoryWidget() { - return ItemCategoryDropdown( - isEdit: widget.isEdit, - categoryId: viewModel.categoryId, - onChanged: (data) { - viewModel.setCategory(data); + return DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + 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); }, - selectedCategoryDropDown: viewModel.selectedCategory, + dropdownDecoratorProps: MyColors.dropDownStyle( + hint: 'Choose', + ), ); } diff --git a/lib/application/views/inventorymodule/subCategoryViews/SubCategoryVC.dart b/lib/application/views/inventorymodule/subCategoryViews/SubCategoryVC.dart index be2324a..173195a 100644 --- a/lib/application/views/inventorymodule/subCategoryViews/SubCategoryVC.dart +++ b/lib/application/views/inventorymodule/subCategoryViews/SubCategoryVC.dart @@ -1,3 +1,4 @@ +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'; @@ -15,10 +16,10 @@ 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/ItemCategoryDropdown.dart'; import 'package:wosull/widgets/PageLimitDropDown.dart'; import 'package:wosull/widgets/SearchBox.dart'; @@ -58,24 +59,24 @@ class _SubCategoryVCState extends State { Row( mainAxisAlignment: MainAxisAlignment.start, children: [ - const Text( + Text( 'Sub Categories', style: ThemeText.textStylePageHeading, ), - const SizedBox( - width: 4, - ), - Flexible(child: getCategoriesDropdown()), + AppSpaces.horizontalSmall, + Flexible( + child: SizedBox( + height: 38, + child: getCategory(), + )), ], ), AppSpaces.verticalSmall, Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - SizedBox( - width: 140, - child: addSubCategoryButton(), - ), + Flexible(child: addSubCategoryButton()), + AppSpaces.horizontalSmall, PageLimitDropdown(onChange: (value) { viewModel.fetchCategories( isRefresh: true, @@ -100,13 +101,13 @@ class _SubCategoryVCState extends State { ) : Row( children: [ - const Text( + Text( 'Sub Categories', style: ThemeText.textStylePageHeading, ), AppSpaces.horizontalSmall, SizedBox( - width: 150, child: getCategoriesDropdown()), + height: 38, width: 150, child: getCategory()), AppSpaces.horizontalSmall, SizedBox( width: 140, @@ -149,7 +150,7 @@ class _SubCategoryVCState extends State { switch (controller.dataState) { case DataState.uninitialized: Future(() { - controller.fetchCategories(); + controller.initData(); }); return showList(controller.filteredList); case DataState.initialFetching: @@ -179,6 +180,7 @@ class _SubCategoryVCState extends State { children: [ SubCategoryListView( data: data, + isPortrait: isPortrait, onUpdate: (item, value) { update(item.id, value); }, @@ -207,40 +209,24 @@ class _SubCategoryVCState extends State { ); } - Widget getCategoriesDropdown() { - return SizedBox( - height: 38, - child: ItemCategoryDropdown( - fillColor: MyColors.white, - onChanged: (data) { - viewModel.fetchCategories(isRefresh: true, category: data); - }), + Widget getCategory() { + return DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + 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), ); } - // Widget getCategoriesDropdown() { - // return FutureBuilder( - // future: viewModel.getCategory(), - // builder: (context, snapshot) { - // if (snapshot.hasData) { - // var itemsData = snapshot.data ?? []; - // return SizedBox( - // height: 38, - // child: ItemCategoryDropdown( - // fillColor: MyColors.white, - // items: itemsData, - // onChanged: (data) { - // viewModel.fetchCategories(isRefresh: true, category: data); - // }, - // selectedCategoryDropDown: viewModel.selectedCategoryDropDown), - // ); - // } else { - // return AppLoader(); - // } - // }, - // ); - // } - bool _scrollNotification() { if (!viewModel.isLoading && _controller.position.extentAfter < 300) { viewModel.fetchCategories(limit: viewModel.limit); 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/viewModels/AddSubCategoryViewModel.dart b/lib/application/views/inventorymodule/subCategoryViews/viewModels/AddSubCategoryViewModel.dart index 4e5fed2..58f9a17 100644 --- a/lib/application/views/inventorymodule/subCategoryViews/viewModels/AddSubCategoryViewModel.dart +++ b/lib/application/views/inventorymodule/subCategoryViews/viewModels/AddSubCategoryViewModel.dart @@ -1,13 +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/helpers/Utils.dart'; @@ -21,7 +19,7 @@ class AddSubCategoryViewModel with ChangeNotifier { String categoryId = ''; String subCategoryId = ''; - + List itemsList = []; List storeIds = []; var nameController = ''; @@ -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,19 +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; - } - - getStores(); - } - Future addCategory() async { setLoading(true); if (storeIds.isEmpty) { @@ -112,7 +112,6 @@ class AddSubCategoryViewModel with ChangeNotifier { 'is_visible_in_store': activeInActiveStatus, }; - print(jsonEncode(data)); await APIManager() .fetchData(Constants.ADD_SUB_CATEGORY, data) .then((value) { @@ -121,45 +120,29 @@ class AddSubCategoryViewModel with ChangeNotifier { _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 { @@ -176,5 +159,7 @@ class AddSubCategoryViewModel with ChangeNotifier { if (storeIds.isEmpty) { storeIds.add(sharedPrefs.storeId); } + + notifyListeners(); } } diff --git a/lib/application/views/inventorymodule/subCategoryViews/viewModels/SubCategoryViewModel.dart b/lib/application/views/inventorymodule/subCategoryViews/viewModels/SubCategoryViewModel.dart index daa3fc0..62724ae 100644 --- a/lib/application/views/inventorymodule/subCategoryViews/viewModels/SubCategoryViewModel.dart +++ b/lib/application/views/inventorymodule/subCategoryViews/viewModels/SubCategoryViewModel.dart @@ -3,25 +3,25 @@ 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/SearchSubCategoryResponse.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/utils/CRUDOperatoinState.dart'; import 'package:wosull/application/utils/Constants.dart'; +import '../../../../repository/WosulRepository.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; @@ -42,38 +42,15 @@ 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; + Future initData() async { + final response = await WosulRepository().getCategoriesData(); + itemsList.addAll(response); + fetchCategories(); } fetchCategories( @@ -178,32 +155,6 @@ class SubCategoryViewModel with ChangeNotifier { } } - 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; - } - }).onError((error, stackTrace) { - _crudOperationState = CRUDOperationState.error; - }); - } - Future viewCategory(String id) async { await APIManager() .getResponseAuth('${Constants.GET_SUB_CATEGORY_BY_ID}$id') @@ -216,7 +167,7 @@ class SubCategoryViewModel with ChangeNotifier { _crudOperationState = CRUDOperationState.error; } }).onError((error, stackTrace) { - _crudOperationState == CRUDOperationState.error; + _crudOperationState = CRUDOperationState.error; }); } @@ -248,17 +199,19 @@ class SubCategoryViewModel with ChangeNotifier { .getResponsePatch(Constants.UPDATE_SUB_CATEGORY, data) .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) { + print(stackTrace.toString()); + _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/kitchenmodule/views/kitchen/widgets/ItemsListView.dart b/lib/application/views/kitchenmodule/views/kitchen/widgets/ItemsListView.dart index 1c41fda..f14adfa 100644 --- a/lib/application/views/kitchenmodule/views/kitchen/widgets/ItemsListView.dart +++ b/lib/application/views/kitchenmodule/views/kitchen/widgets/ItemsListView.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 fa53735..0cbf658 100644 --- a/lib/application/views/kitchenmodule/views/kitchen/widgets/KitchenListView.dart +++ b/lib/application/views/kitchenmodule/views/kitchen/widgets/KitchenListView.dart @@ -74,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, @@ -86,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/offline/KitchenOfflineItemListView.dart b/lib/application/views/kitchenmodule/views/kitchen/widgets/offline/KitchenOfflineItemListView.dart index 62c5363..c38940d 100644 --- a/lib/application/views/kitchenmodule/views/kitchen/widgets/offline/KitchenOfflineItemListView.dart +++ b/lib/application/views/kitchenmodule/views/kitchen/widgets/offline/KitchenOfflineItemListView.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 bb0962a..9117c71 100644 --- a/lib/application/views/kitchenmodule/views/kitchen/widgets/offline/KitchenOfflineListView.dart +++ b/lib/application/views/kitchenmodule/views/kitchen/widgets/offline/KitchenOfflineListView.dart @@ -85,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, @@ -97,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, diff --git a/lib/application/views/kitchenmodule/views/table/KitchenNewTableVC.dart b/lib/application/views/kitchenmodule/views/table/KitchenNewTableVC.dart index d7fd0c5..a79e02e 100644 --- a/lib/application/views/kitchenmodule/views/table/KitchenNewTableVC.dart +++ b/lib/application/views/kitchenmodule/views/table/KitchenNewTableVC.dart @@ -53,7 +53,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 f4f245e..c385fe9 100644 --- a/lib/application/views/kitchenmodule/views/table/KitchenTableVC.dart +++ b/lib/application/views/kitchenmodule/views/table/KitchenTableVC.dart @@ -88,11 +88,16 @@ class _KitchenTableVCState extends BaseStatefulState { ), ), Flexible( - child: PageLimitDropdown(onChange: (value) { - viewModel.fetch( - isRefresh: true, - limit: int.parse(value!)); - })) + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + PageLimitDropdown(onChange: (value) { + viewModel.fetch( + isRefresh: true, + limit: int.parse(value!)); + }) + ], + )) ], ), AppSpaces.verticalSmall, @@ -165,10 +170,16 @@ class _KitchenTableVCState extends BaseStatefulState { ], )), Flexible( - child: PageLimitDropdown(onChange: (value) { - viewModel.fetch( - isRefresh: true, limit: int.parse(value!)); - })) + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + PageLimitDropdown(onChange: (value) { + viewModel.fetch( + isRefresh: true, + limit: int.parse(value!)); + }) + ], + )) ], ), AppSpaces.verticalMedium, 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/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 af5785f..d9355d9 100644 --- a/lib/application/views/salesandordermodule/SalesAndOrderMainVC.dart +++ b/lib/application/views/salesandordermodule/SalesAndOrderMainVC.dart @@ -2,10 +2,9 @@ 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/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 { @@ -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, @@ -49,18 +48,20 @@ class _SalesAndOrderMainVCState extends State { Tab( text: AppLocalizations.of(context)!.quotations, ), - Tab( - text: AppLocalizations.of(context)!.transactions, - ), + // Tab( + // text: AppLocalizations.of(context)!.transactions, + // ), ], ), - const Expanded( + Expanded( child: TabBarView( children: [ - OrderVC(), - InvoicesVC(), - QuotationsVC(), - TransactionVC() + const OrderVC(), + InvoicesVC( + filter: 'All', + ), + const QuotationsVC(), + //TransactionVC() ], )) ], diff --git a/lib/application/views/salesandordermodule/viewModel/QuotationViewModel.dart b/lib/application/views/salesandordermodule/viewModel/QuotationViewModel.dart index 8f43428..f5f5801 100644 --- a/lib/application/views/salesandordermodule/viewModel/QuotationViewModel.dart +++ b/lib/application/views/salesandordermodule/viewModel/QuotationViewModel.dart @@ -2,10 +2,11 @@ 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; @@ -48,22 +49,17 @@ class QuotationViewModel with ChangeNotifier { 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 < this.limit) { - _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; @@ -81,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(); @@ -95,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 eb23bb5..9cdfbb1 100644 --- a/lib/application/views/salesandordermodule/views/ReturnInvoiceVC.dart +++ b/lib/application/views/salesandordermodule/views/ReturnInvoiceVC.dart @@ -17,13 +17,14 @@ 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/ValueText.dart'; +import 'package:wosull/widgets/WrapHeightContainer.dart'; class ReturnInvoiceVC extends StatefulWidget { StoreInvoice storeInvoice; @@ -72,6 +73,7 @@ class _ReturnInvoiceVCState extends BaseStatefulState { ), AppSpaces.verticalLarge, Card( + elevation: 5, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(4.0), ), @@ -141,23 +143,35 @@ class _ReturnInvoiceVCState extends BaseStatefulState { shrinkWrap: true, itemBuilder: (c, position) { if (viewModel.isPortrait) { - return Row( + return WrapHeightContainer( + child: Row( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ - returnCheckBoxWidget(position), + 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), + )), + Expanded( flex: 2, child: Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius - .all( - Radius.circular( - 1.0) // <--- border radius here - ), - border: Border.all( - width: 1, - color: MyColors.fillColorGray2), + decoration: const BoxDecoration( + border: Border( + left: BorderSide( + width: 1.0, + color: + MyColors.fillColorGray2), + ), ), child: Row( crossAxisAlignment: @@ -241,7 +255,10 @@ class _ReturnInvoiceVCState extends BaseStatefulState { mainAxisAlignment: MainAxisAlignment.start, children: [ - getItemsWidget(position), + PortraitContainer( + width: double.infinity, + child: getItemsWidget( + position)), PortraitContainer( width: double.infinity, child: getDescriptionWidget( @@ -259,12 +276,17 @@ class _ReturnInvoiceVCState extends BaseStatefulState { ), PortraitContainer( width: double.infinity, - child: Center( - child: ValueText(widget - .storeInvoice - .products[position] - .amount! - .toStringAsFixed(2)), + child: Align( + alignment: + Alignment.centerLeft, + child: CustomTextAddProduct( + widget + .storeInvoice + .products[ + position] + .amount! + .toStringAsFixed( + 2)), ), ), ], @@ -272,9 +294,9 @@ class _ReturnInvoiceVCState extends BaseStatefulState { ], ), )), - getRemoveButtonWidget(position) + // getRemoveButtonWidget(position) ], - ); + )); } else { return BorderContainer( backgroundColor: Colors.transparent, @@ -305,14 +327,14 @@ class _ReturnInvoiceVCState extends BaseStatefulState { width: 84, child: Align( alignment: Alignment.centerLeft, - child: ValueText( + child: CustomTextAddProduct( viewModel.storeInvoice .products[position].amount! .toStringAsFixed(2), ), ), ), - getRemoveButtonWidget(position) + //getRemoveButtonWidget(position) ], ), ); @@ -325,18 +347,22 @@ class _ReturnInvoiceVCState extends BaseStatefulState { backgroundColor: Colors.transparent, child: Row( children: [ + // getAddButtonWidget(), + SizedBox( + width: 45, + height: 44, + child: HeadingContainer( + heading: '', + )), Expanded( child: HeadingContainer( height: 48, - heading: '', + heading: 'Grand Total', )), Expanded( child: HeadingContainer( - height: 48, - heading: - viewModel.getTotalProductsPrice(), - )), - getAddButtonWidget(), + heading: viewModel + .getTotalProductsPrice())), ], ), ) @@ -368,19 +394,21 @@ class _ReturnInvoiceVCState extends BaseStatefulState { height: 48, heading: '', )), - HeadingContainer( + ChildContainer( width: 84, - heading: - viewModel.getTotalProductsPrice(), + child: CustomTextAddProduct( + viewModel.getTotalProductsPrice()), ), - getAddButtonWidget(), + // getAddButtonWidget(), ], ), ), AppSpaces.verticalLarge, Row( children: [ - const Expanded(child: Text('')), + viewModel.isPortrait + ? Container() + : const Expanded(child: Text('')), Expanded( child: Row( children: [ @@ -398,7 +426,7 @@ class _ReturnInvoiceVCState extends BaseStatefulState { alignment: Alignment.centerRight, child: Text( viewModel.getTotalDiscount(), - style: ThemeText.textStyleAmountHeading, + style: ThemeText.textStyleAmountValue, ), )), ], @@ -408,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: [ @@ -426,7 +456,7 @@ class _ReturnInvoiceVCState extends BaseStatefulState { alignment: Alignment.centerRight, child: Text( viewModel.getTotalVatDiscount(), - style: ThemeText.textStyleAmountHeading, + style: ThemeText.textStyleAmountValue, ), )), ], @@ -436,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: [ @@ -446,7 +478,8 @@ class _ReturnInvoiceVCState extends BaseStatefulState { child: Text( AppLocalizations.of(context)! .total_amount, - style: ThemeText.textStyleAmountHeading, + style: + ThemeText.textStyleAmountHeadingBlack, ), )), AppSpaces.horizontalMedium, @@ -456,7 +489,8 @@ class _ReturnInvoiceVCState extends BaseStatefulState { child: Text( viewModel.storeInvoice.totalAmount! .toStringAsFixed(2), - style: ThemeText.textStyleAmountHeading, + style: + ThemeText.textStyleAmountValueBlack, ), )), ], @@ -474,37 +508,26 @@ class _ReturnInvoiceVCState extends BaseStatefulState { mainAxisAlignment: MainAxisAlignment.end, children: [AppLoader()], ) - : Row( - crossAxisAlignment: CrossAxisAlignment.end, - mainAxisAlignment: MainAxisAlignment.end, - children: [ - SizedBox( - width: 180, - child: CustomSimpleButton( - textColor: MyColors.white, - backGroundColor: MyColors.blueThemeColor, - onPressed: () async { - await viewModel.update(); - checkState(); - }, - heading: viewModel.isReturn - ? 'Return whole order' - : "Damage whole order")), - AppSpaces.horizontalMedium, - SizedBox( - width: 100, - child: CustomSimpleButton( - textColor: MyColors.white, - backGroundColor: MyColors.blueThemeColor, - onPressed: () async { - await viewModel.returnInvoice(); - checkState(); - }, - heading: AppLocalizations.of(context)!.save, - ), + : 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(), + ), + ], ) - ], - ) ], ), ), @@ -519,18 +542,15 @@ class _ReturnInvoiceVCState extends BaseStatefulState { } getItemsWidget(int position) { - return TransparentBorderContainer( - height: 48, - backgroundColor: MyColors.backFillColor, - child: CustomTextButtonIcon( - onPressed: () { - showSheet(position); - }, - heading: viewModel.selectedProduct[position].isEmpty - ? 'Choose' - : viewModel.selectedProduct[position], - icon: Icons.arrow_drop_down), - ); + return CustomTextButtonIcon( + backgroundColor: MyColors.backFillColor, + onPressed: () { + showSheet(position); + }, + heading: viewModel.selectedProduct[position].isEmpty + ? 'Choose' + : viewModel.selectedProduct[position], + icon: Icons.arrow_drop_down); } void showSheet(int index) async { @@ -595,7 +615,7 @@ class _ReturnInvoiceVCState extends BaseStatefulState { backgroundColor: MyColors.disableColor, child: Align( alignment: Alignment.centerLeft, - child: HeadingText( + child: CustomTextAddProduct( viewModel.storeInvoice.products[position].description ?? "", ), ), @@ -618,4 +638,28 @@ class _ReturnInvoiceVCState extends BaseStatefulState { viewModel.onAddNewProduct(); }); } + + getOnlyItemsButton() { + return CustomSimpleButton( + textColor: MyColors.white, + backGroundColor: MyColors.blueThemeColor, + onPressed: () async { + await viewModel.returnInvoice(); + checkState(); + }, + heading: + viewModel.isReturn ? 'Return Only order' : "Damage Only order"); + } + + getWholeOrderButton() { + return CustomSimpleButton( + textColor: MyColors.white, + backGroundColor: MyColors.blueThemeColor, + onPressed: () async { + await viewModel.update(); + checkState(); + }, + heading: + viewModel.isReturn ? 'Return whole order' : "Damage whole order"); + } } 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/views/invoiceModule/viewModels/InvoiceViewModel.dart b/lib/application/views/salesandordermodule/views/invoiceModule/viewModels/InvoiceViewModel.dart index ee1a739..7d9d083 100644 --- a/lib/application/views/salesandordermodule/views/invoiceModule/viewModels/InvoiceViewModel.dart +++ b/lib/application/views/salesandordermodule/views/invoiceModule/viewModels/InvoiceViewModel.dart @@ -26,6 +26,10 @@ class InvoiceViewModel with ChangeNotifier { List get filteredList => _filteredList; + void initData(String filter) { + filterValue = filter; + } + fetch({bool isRefresh = false, String filter = 'All', int limit = 10}) async { this.limit = limit; _isLoading = true; @@ -84,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 index a589594..2b0f18f 100644 --- a/lib/application/views/salesandordermodule/views/invoiceModule/viewModels/NewInvoiceViewModel.dart +++ b/lib/application/views/salesandordermodule/views/invoiceModule/viewModels/NewInvoiceViewModel.dart @@ -11,6 +11,7 @@ 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'; @@ -18,8 +19,8 @@ import 'package:wosull/helpers/Utils.dart'; class NewInvoiceViewModel with ChangeNotifier { late StoreInvoice addInvoice = StoreInvoice(products: []); bool isPortrait = true; - - //var selectedSupplier; + bool isEdit = true; + String invoiceId = ''; List selectedProduct = []; var isLoadingFirst = false; @@ -32,12 +33,39 @@ class NewInvoiceViewModel with ChangeNotifier { 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(); @@ -45,7 +73,7 @@ class NewInvoiceViewModel with ChangeNotifier { Future getInvoiceById(String id) async { await APIManager() - .getResponseAuth("${Constants.GET_INVOICE_BY_ID}/${id}") + .getResponseAuth("${Constants.GET_INVOICE_BY_ID}/$id") .then((value) async { final response = StoreInvoicesByIdModel.fromJson(value); if (response.success!) { @@ -53,22 +81,31 @@ class NewInvoiceViewModel with ChangeNotifier { } notifyListeners(); }).onError((error, stackTrace) { - print(error.toString()); isLoadingFirst = false; notifyListeners(); }); } Future initData(bool isEdit, StoreInvoice storeInvoice) async { + this.isEdit = isEdit; + isLoadingFirst = true; if (isEdit) { - // addInvoice = storeInvoice; - isLoadingFirst = true; 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() { @@ -91,8 +128,6 @@ class NewInvoiceViewModel with ChangeNotifier { Utils.showMessage('Select Invoice for'); } else if (addInvoice.customerId!.isEmpty) { Utils.showMessage('Select $selectedInvoiceFor'); - } else if (addInvoice.status == null) { - Utils.showMessage('Select Status'); } else if (addInvoice.products.isEmpty) { Utils.showMessage('Add At least One Product'); } else if (selectedProduct[0].isEmpty) { @@ -102,49 +137,19 @@ class NewInvoiceViewModel with ChangeNotifier { } } - 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 getTax() async { + final response = await WosulRepository().getTax(); + taxes.addAll(response); } - 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 getMeasurement() async { + final response = await WosulRepository().getMeasurement(); + measurements.addAll(response); } - 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 getDiscount() async { + final response = await WosulRepository().getDiscount(); + storeDiscounts.addAll(response); } void calculateVat(double data, int position) { @@ -163,22 +168,7 @@ class NewInvoiceViewModel with ChangeNotifier { 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; - // } notifyListeners(); } @@ -277,6 +267,7 @@ class NewInvoiceViewModel with ChangeNotifier { final response = StoreInvoicesByIdModel.fromJson(value); if (response.success!) { Utils.showMessage(response.message ?? ''); + invoiceId = response.invoice!.id ?? ''; if (isPrint) { _crudOperation = CRUDOperationState.view; } else { @@ -354,39 +345,23 @@ class NewInvoiceViewModel with ChangeNotifier { notifyListeners(); } - 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!); - } + 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!); } } - }).onError((error, stackTrace) {}); - - return currencies; + } } - Future> getCompany() async { - var items = []; - await APIManager() - .fetchData(Constants.GET_STORE_CUSTOMER, Constants.getStorePayload()) - .then((value) { - final response = GetStoreCustomer.fromJson(value); - if (response.success!) { - items.addAll(response.topOrders!); - selectedCustomerCompany ??= StoreCustomer(name: "Choose", id: ""); - } - }).onError((error, stackTrace) {}); - - return items; + Future getCompany() async { + final response = await WosulRepository().getCompany(); + companies.addAll(response); + if (isEdit) {} + selectedCustomerCompany ??= StoreCustomer(name: "Choose", id: ""); } void presentDatePicker(BuildContext context, bool isStart) { @@ -448,6 +423,7 @@ class NewInvoiceViewModel with ChangeNotifier { 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 { @@ -532,4 +508,9 @@ class NewInvoiceViewModel with ChangeNotifier { } 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 index f8d8f8a..0204197 100644 --- a/lib/application/views/salesandordermodule/views/invoiceModule/viewModels/ReturnDamageInvoiceViewModel.dart +++ b/lib/application/views/salesandordermodule/views/invoiceModule/viewModels/ReturnDamageInvoiceViewModel.dart @@ -191,6 +191,7 @@ class ReturnDamageInvoiceViewModel with ChangeNotifier { returnDamageOrder.details.removeWhere((element) => element.itemId! == storeInvoice.products[position].itemId!); } + notifyListeners(); } void onAddNewProduct() { 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 4c5930b..2ee5354 100644 --- a/lib/application/views/salesandordermodule/views/AddInvoiceAndPrintVC.dart +++ b/lib/application/views/salesandordermodule/views/invoiceModule/views/AddInvoiceAndPrintVC.dart @@ -7,11 +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'; @@ -25,6 +27,7 @@ class AddInvoiceAndPrintVC extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( + backgroundColor: MyColors.fillColor, resizeToAvoidBottomInset: true, appBar: CustomAppBar( heading: '', @@ -40,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), @@ -66,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), @@ -98,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', @@ -124,7 +133,9 @@ class AddInvoiceAndPrintVC extends StatelessWidget { CrossAxisAlignment.end, children: [ Text( - storeInvoice.supplier != null + storeInvoice.invoiceFor! + .first == + "Company" ? storeInvoice .supplier!.name ?? '' @@ -142,7 +153,8 @@ class AddInvoiceAndPrintVC extends StatelessWidget { ), AppSpaces.verticalMedium, Text( - storeInvoice.supplier != null + storeInvoice.invoiceFor!.first == + "Company" ? storeInvoice .supplier!.address ?? 'N/A' @@ -165,7 +177,8 @@ class AddInvoiceAndPrintVC extends StatelessWidget { ), AppSpaces.horizontalSmall, Text( - storeInvoice.supplier != null + storeInvoice.invoiceFor!.first == + "Company" ? storeInvoice .supplier!.email ?? 'N/A' @@ -190,7 +203,9 @@ class AddInvoiceAndPrintVC extends StatelessWidget { ), AppSpaces.horizontalSmall, Text( - storeInvoice.supplier != null + storeInvoice.invoiceFor! + .first == + "Company" ? storeInvoice.supplier! .contact ?? 'N/A' @@ -245,7 +260,6 @@ class AddInvoiceAndPrintVC extends StatelessWidget { isPortrait ? Container( margin: const EdgeInsets.only(top: 12), - width: 300, child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: @@ -258,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 ?? @@ -274,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 ?? @@ -295,7 +311,8 @@ class AddInvoiceAndPrintVC extends StatelessWidget { ), AppSpaces.horizontalSmall, Text( - storeInvoice.supplier != null + storeInvoice.invoiceFor!.first == + "Company" ? storeInvoice .supplier!.email ?? 'N/A' @@ -320,7 +337,8 @@ class AddInvoiceAndPrintVC extends StatelessWidget { ), AppSpaces.horizontalSmall, Text( - storeInvoice.supplier != null + storeInvoice.invoiceFor!.first == + "Company" ? storeInvoice .supplier!.contact ?? 'N/A' @@ -371,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( @@ -420,7 +433,8 @@ class AddInvoiceAndPrintVC extends StatelessWidget { MainAxisAlignment.end, children: [ Text( - storeInvoice.supplier != null + storeInvoice.invoiceFor!.first == + "Company" ? storeInvoice .supplier!.name ?? 'N/A' @@ -431,7 +445,8 @@ class AddInvoiceAndPrintVC extends StatelessWidget { ), AppSpaces.verticalMedium, Text( - storeInvoice.supplier != null + storeInvoice.invoiceFor!.first == + "Company" ? storeInvoice .supplier!.email ?? 'N/A' @@ -442,7 +457,8 @@ class AddInvoiceAndPrintVC extends StatelessWidget { ), AppSpaces.verticalMedium, Text( - storeInvoice.supplier != null + storeInvoice.invoiceFor!.first == + "Company" ? storeInvoice .supplier!.contact ?? 'N/A' @@ -460,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( @@ -518,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( @@ -565,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: @@ -611,8 +798,9 @@ class AddInvoiceAndPrintVC extends StatelessWidget { ), const Spacer(), Text( - storeInvoice.totalTaxExcluding! - .toString(), + storeInvoice.totalTaxExcluding + ?.toStringAsFixed(2) ?? + '', style: ThemeText.robotoValue, ), ], @@ -643,8 +831,9 @@ class AddInvoiceAndPrintVC extends StatelessWidget { style: ThemeText.robotoHeading, )), Text( - storeInvoice.totalTaxableAmount! - .toString(), + storeInvoice.totalTaxableAmount + ?.toStringAsFixed(2) ?? + '', style: ThemeText.robotoValue, ), ], @@ -660,7 +849,9 @@ class AddInvoiceAndPrintVC extends StatelessWidget { ), ), Text( - storeInvoice.totalTax!.toString(), + storeInvoice.totalTax + ?.toStringAsFixed(2) ?? + '', style: ThemeText.robotoValue, ), ], @@ -682,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, @@ -730,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..8015eb6 --- /dev/null +++ b/lib/application/views/salesandordermodule/views/invoiceModule/views/InvoiceMakePaymentVC.dart @@ -0,0 +1,462 @@ +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/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( + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: 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( + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: 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/InvoicesVC.dart b/lib/application/views/salesandordermodule/views/invoiceModule/views/InvoicesVC.dart similarity index 63% rename from lib/application/views/salesandordermodule/views/invoiceModule/InvoicesVC.dart rename to lib/application/views/salesandordermodule/views/invoiceModule/views/InvoicesVC.dart index 4650b5c..f3f4d9e 100644 --- a/lib/application/views/salesandordermodule/views/invoiceModule/InvoicesVC.dart +++ b/lib/application/views/salesandordermodule/views/invoiceModule/views/InvoicesVC.dart @@ -10,10 +10,10 @@ 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/AddInvoiceAndPrintVC.dart'; import 'package:wosull/application/views/salesandordermodule/views/ReturnInvoiceVC.dart'; -import 'package:wosull/application/views/salesandordermodule/views/invoiceModule/NewInvoiceVC.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'; @@ -24,7 +24,9 @@ import 'package:wosull/widgets/PageLimitDropDown.dart'; import 'package:wosull/widgets/SearchBox.dart'; class InvoicesVC extends StatefulWidget { - const InvoicesVC({Key? key}) : super(key: key); + String filter = 'All'; + + InvoicesVC({Key? key, this.filter = 'All'}) : super(key: key); @override State createState() => _InvoicesVCState(); @@ -39,6 +41,7 @@ class _InvoicesVCState extends BaseStatefulState { @override void initState() { + context.read().initData(widget.filter); super.initState(); } @@ -68,41 +71,15 @@ class _InvoicesVCState extends BaseStatefulState { style: ThemeText.textStylePageHeading, ), AppSpaces.horizontalSmall, - SizedBox( - height: 38, - width: 160, - child: DropdownSearch( - dropdownButtonProps: - ThemeDropDown.dropdownButtonProps, - popupProps: const PopupProps.menu( - constraints: - 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), + Flexible( + child: SizedBox( + height: 38, + child: getDropdownFilterType(), ), ), AppSpaces.horizontalSmall, Flexible( - child: CustomSimpleButton( - textColor: MyColors.blueThemeColor, - backGroundColor: MyColors.backColorBlue50, - onPressed: () { - toNewInvoice( - false, StoreInvoice(products: [])); - }, - heading: AppLocalizations.of(context)! - .new_invoices, - ), + child: getAddInvoiceButton(), ), ], ), @@ -111,18 +88,13 @@ class _InvoicesVCState extends BaseStatefulState { mainAxisAlignment: MainAxisAlignment.start, children: [ Flexible( - child: SearchBox( - onEditingDone: (text) {}, - onChanged: (text) {}, - hint: AppLocalizations.of(context)!.search, + child: SizedBox( + height: 48, + child: getSearchBox(), ), ), AppSpaces.horizontalSmall, - PageLimitDropdown(onChange: (value) { - viewModel.fetch( - isRefresh: true, - limit: int.parse(value!)); - }) + getPageLimit() ], ), ], @@ -138,37 +110,12 @@ class _InvoicesVCState extends BaseStatefulState { SizedBox( height: 38, width: 160, - child: DropdownSearch( - dropdownButtonProps: - ThemeDropDown.dropdownButtonProps, - popupProps: const PopupProps.menu( - constraints: 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), - ), + child: getDropdownFilterType(), ), AppSpaces.horizontalSmall, SizedBox( width: 120, - child: CustomSimpleButton( - textColor: MyColors.blueThemeColor, - backGroundColor: MyColors.backColorBlue50, - onPressed: () { - toNewInvoice( - false, StoreInvoice(products: [])); - // newInvoice(false, StoreInvoice(products: [])); - }, - heading: - AppLocalizations.of(context)!.new_invoices, - ), + child: getAddInvoiceButton(), ), AppSpaces.horizontalSmall, SizedBox( @@ -176,17 +123,9 @@ class _InvoicesVCState extends BaseStatefulState { ? 200 : 240, height: 48, - child: SearchBox( - onEditingDone: (text) {}, - onChanged: (text) {}, - hint: AppLocalizations.of(context)!.search, - ), + child: getSearchBox(), ), - Flexible( - child: PageLimitDropdown(onChange: (value) { - viewModel.fetch( - isRefresh: true, limit: int.parse(value!)); - })) + Flexible(child: getPageLimit()) ], ), AppSpaces.verticalLarge, @@ -198,7 +137,7 @@ class _InvoicesVCState extends BaseStatefulState { switch (controller.dataState) { case DataState.uninitialized: Future(() { - controller.fetch(); + controller.fetch(filter: widget.filter); }); return showData(controller.filteredList); case DataState.initialFetching: @@ -301,12 +240,16 @@ class _InvoicesVCState extends BaseStatefulState { } } - void onPrint(String invoiceId) { - Navigator.push( + 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 { @@ -320,7 +263,68 @@ class _InvoicesVCState extends BaseStatefulState { ); if (!mounted) return; - if (result != null) {} - viewModel.fetch(isRefresh: true); + if (result != null) { + viewModel.fetch(isRefresh: true, limit: viewModel.limit); + } + } + + getDropdownFilterType() { + return DropdownSearch( + selectedItem: viewModel.filterValue, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + 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/NewInvoiceVC.dart b/lib/application/views/salesandordermodule/views/invoiceModule/views/NewInvoiceVC.dart similarity index 70% rename from lib/application/views/salesandordermodule/views/invoiceModule/NewInvoiceVC.dart rename to lib/application/views/salesandordermodule/views/invoiceModule/views/NewInvoiceVC.dart index 4fdd900..d9e46d8 100644 --- a/lib/application/views/salesandordermodule/views/invoiceModule/NewInvoiceVC.dart +++ b/lib/application/views/salesandordermodule/views/invoiceModule/views/NewInvoiceVC.dart @@ -3,6 +3,7 @@ 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'; @@ -24,6 +25,7 @@ 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/HeadingContainer.dart'; @@ -31,12 +33,11 @@ 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/customers/GetStoreCustomer.dart'; -import '../../../../model/discount/StoreDiscountModel.dart'; -import '../../../inventorymodule/productviews/SearchProductVC.dart'; -import '../AddInvoiceAndPrintVC.dart'; +import '../../../../../model/customers/GetStoreCustomer.dart'; +import '../../../../../model/discount/StoreDiscountModel.dart'; +import 'AddInvoiceAndPrintVC.dart'; class NewInvoiceVC extends StatefulWidget { StoreInvoice storeInvoice; @@ -61,6 +62,12 @@ class _NewInvoiceVCState extends BaseStatefulState { super.initState(); } + @override + void dispose() { + viewModel.disposeData(); + super.dispose(); + } + @override Widget build(BuildContext context) { viewModel = context.watch(); @@ -76,15 +83,45 @@ class _NewInvoiceVCState extends BaseStatefulState { MediaQuery.of(context).orientation == Orientation.portrait; return SingleChildScrollView( child: Container( - color: MyColors.white, - padding: const EdgeInsets.all(4), + padding: const EdgeInsets.all(8), child: viewModel.isLoadingFirst - ? const Center( - child: CircularProgressIndicator(), - ) + ? 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), ), @@ -109,7 +146,7 @@ class _NewInvoiceVCState extends BaseStatefulState { AppSpaces.verticalLarge, getInvoiceDate(), AppSpaces.verticalLarge, - getDefaultStatus(), + getSelectedCurrencyWidget(), viewModel.isPortrait ? Column( crossAxisAlignment: @@ -126,9 +163,9 @@ class _NewInvoiceVCState extends BaseStatefulState { AppSpaces.verticalLarge, getInvoiceReferNo(), AppSpaces.verticalLarge, - getDefaultStatus(), - AppSpaces.verticalLarge, getVatNumber(), + // AppSpaces.verticalLarge, + // getVatNumber(), ], ) : Container() @@ -163,7 +200,7 @@ class _NewInvoiceVCState extends BaseStatefulState { AppSpaces.verticalLarge, getInvoiceDueDate(), AppSpaces.verticalLarge, - getSelectedCurrencyWidget() + getVatNumber() ], )), AppSpaces.horizontalMedium, @@ -176,8 +213,8 @@ class _NewInvoiceVCState extends BaseStatefulState { getInvoiceNumber(), AppSpaces.verticalLarge, getInvoiceReferNo(), - AppSpaces.verticalLarge, - getVatNumber() + // AppSpaces.verticalLarge, + // getVatNumber() ], )), ], @@ -194,6 +231,7 @@ class _NewInvoiceVCState extends BaseStatefulState { ), AppSpaces.verticalLarge, Card( + elevation: 5, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.0), ), @@ -219,11 +257,12 @@ class _NewInvoiceVCState 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, @@ -231,7 +270,7 @@ class _NewInvoiceVCState extends BaseStatefulState { Text( AppLocalizations.of(context)! .search_and_add_products, - style: ThemeText.textStylePageHeading, + style: ThemeText.textStyleHeadingCart, ), AppSpaces.verticalMedium, viewModel.isPortrait @@ -244,7 +283,7 @@ class _NewInvoiceVCState extends BaseStatefulState { AppLocalizations.of(context)! .name_or_barcode, height: 48, - width: 110, + width: 150, ), HeadingContainer( heading: @@ -320,30 +359,37 @@ class _NewInvoiceVCState extends BaseStatefulState { shrinkWrap: true, itemBuilder: (c, position) { if (viewModel.isPortrait) { - return Container( - padding: - 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: MyColors.white, - ), + 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, @@ -360,6 +406,8 @@ class _NewInvoiceVCState extends BaseStatefulState { .start, children: [ PortraitContainer( + width: + double.infinity, child: Align( alignment: Alignment .centerLeft, @@ -371,6 +419,8 @@ class _NewInvoiceVCState extends BaseStatefulState { ), ), PortraitContainer( + width: + double.infinity, child: Align( alignment: Alignment .centerLeft, @@ -382,6 +432,8 @@ class _NewInvoiceVCState extends BaseStatefulState { ), ), PortraitContainer( + width: + double.infinity, child: Align( alignment: Alignment .centerLeft, @@ -393,6 +445,8 @@ class _NewInvoiceVCState extends BaseStatefulState { ), ), PortraitContainer( + width: + double.infinity, child: Align( alignment: Alignment .centerLeft, @@ -404,6 +458,8 @@ class _NewInvoiceVCState extends BaseStatefulState { ), ), PortraitContainer( + width: + double.infinity, child: Align( alignment: Alignment .centerLeft, @@ -415,6 +471,8 @@ class _NewInvoiceVCState extends BaseStatefulState { ), ), PortraitContainer( + width: + double.infinity, child: Align( alignment: Alignment .centerLeft, @@ -426,6 +484,8 @@ class _NewInvoiceVCState extends BaseStatefulState { ), ), PortraitContainer( + width: + double.infinity, child: Align( alignment: Alignment .centerLeft, @@ -437,6 +497,8 @@ class _NewInvoiceVCState extends BaseStatefulState { ), ), PortraitContainer( + width: + double.infinity, child: Align( alignment: Alignment .centerLeft, @@ -448,6 +510,8 @@ class _NewInvoiceVCState extends BaseStatefulState { ), ), PortraitContainer( + width: + double.infinity, child: Align( alignment: Alignment .centerLeft, @@ -457,6 +521,8 @@ class _NewInvoiceVCState extends BaseStatefulState { ), ), PortraitContainer( + width: + double.infinity, child: Align( alignment: Alignment .centerLeft, @@ -478,9 +544,15 @@ class _NewInvoiceVCState extends BaseStatefulState { MainAxisAlignment .start, children: [ - getItemsWidget( - position), PortraitContainer( + width: + double.infinity, + child: getItemsWidget( + position), + ), + PortraitContainer( + width: + double.infinity, child: Center( child: getProductDescription( @@ -488,6 +560,8 @@ class _NewInvoiceVCState extends BaseStatefulState { ), ), PortraitContainer( + width: + double.infinity, child: Center( child: getProductQuantity( @@ -495,53 +569,76 @@ class _NewInvoiceVCState extends BaseStatefulState { ), ), PortraitContainer( + width: + double.infinity, child: Center( child: getProductPrice( position), ), ), - getDiscountsTypes( - position), - getDiscounts(position), - getTaxWidget(position), - getMeasurementWidget( - position), PortraitContainer( + width: + double.infinity, child: - getSingleItemTaxWidget( + getDiscountsTypes( position), ), PortraitContainer( + width: + double.infinity, + child: getDiscounts( + position), + ), + PortraitContainer( + width: + double.infinity, + child: getTaxWidget( + position), + ), + PortraitContainer( + width: + double.infinity, child: - getSingleItemAmountWidget( + 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), + ), + ), ], )), ], ), )), - 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 WrapHeightContainer( child: Row( children: [ ChildContainer( - width: 110, + width: 150, child: getItemsWidget(position), ), ChildContainer( @@ -552,7 +649,6 @@ class _NewInvoiceVCState extends BaseStatefulState { ), ), ChildContainer( - height: 48, width: 60, child: Center( child: @@ -566,15 +662,22 @@ class _NewInvoiceVCState extends BaseStatefulState { ), ), Expanded( - child: - getDiscountsTypes(position)), + child: ChildContainer( + child: getDiscountsTypes(position), + )), Expanded( - child: getDiscounts(position)), + child: ChildContainer( + child: getDiscounts(position), + )), Expanded( - child: getTaxWidget(position)), + child: ChildContainer( + child: getTaxWidget(position), + )), Expanded( - child: getMeasurementWidget( - position)), + child: ChildContainer( + child: + getMeasurementWidget(position), + )), ChildContainer( width: 44, child: getSingleItemTaxWidget( @@ -598,8 +701,19 @@ class _NewInvoiceVCState extends BaseStatefulState { backgroundColor: MyColors.white, child: Row( children: [ + Container( + decoration: const BoxDecoration( + border: Border( + right: BorderSide( + width: 1.0, + color: MyColors + .fillColorGray2), + ), + ), + child: getAddItemButtonWidget(), + ), Expanded( - child: PortraitContainer( + child: ChildContainer( height: 48, child: Center( child: Text( @@ -612,16 +726,14 @@ class _NewInvoiceVCState extends BaseStatefulState { Expanded( child: ChildContainer( height: 48, - child: Center( - child: Text( + child: Align( + alignment: Alignment.centerRight, + child: CustomTextAddProduct( viewModel .getTotalProductsPrice(), - style: - MyColors.textStyleValue(), ), ), )), - getAddItemButtonWidget() ], ), ) @@ -629,18 +741,22 @@ class _NewInvoiceVCState extends BaseStatefulState { backgroundColor: MyColors.white, child: Row( children: [ - Expanded( - child: HeadingContainer( + HeadingContainer( + width: 150, heading: '', - )), - Expanded( - child: HeadingContainer( + ), + HeadingContainer( + width: 100, heading: '', - )), - Expanded( - child: HeadingContainer( + ), + HeadingContainer( + width: 60, heading: '', - )), + ), + HeadingContainer( + width: 80, + heading: '', + ), Expanded( child: HeadingContainer( heading: '', @@ -672,7 +788,9 @@ class _NewInvoiceVCState extends BaseStatefulState { AppSpaces.verticalLarge, Row( children: [ - const Expanded(child: Text('')), + viewModel.isPortrait + ? Container() + : const Expanded(child: Text('')), Expanded( child: Row( children: [ @@ -702,7 +820,9 @@ class _NewInvoiceVCState extends BaseStatefulState { AppSpaces.verticalSmall, Row( children: [ - const Expanded(child: Text('')), + viewModel.isPortrait + ? Container() + : const Expanded(child: Text('')), Expanded( child: Row( children: [ @@ -731,7 +851,9 @@ class _NewInvoiceVCState extends BaseStatefulState { AppSpaces.verticalSmall, Row( children: [ - const Expanded(child: Text('')), + viewModel.isPortrait + ? Container() + : const Expanded(child: Text('')), Expanded( child: Row( children: [ @@ -741,8 +863,8 @@ class _NewInvoiceVCState extends BaseStatefulState { child: Text( AppLocalizations.of(context)! .total_amount, - style: - ThemeText.textStyleImageHeading, + style: ThemeText + .textStyleAmountHeadingBlack, ), )), AppSpaces.horizontalMedium, @@ -753,8 +875,8 @@ class _NewInvoiceVCState extends BaseStatefulState { viewModel.addInvoice.totalAmount ?.toStringAsFixed(2) ?? '0.0', - style: - ThemeText.textStyleImageHeading, + style: ThemeText + .textStyleAmountValueBlack, ), )), ], @@ -774,55 +896,38 @@ class _NewInvoiceVCState extends BaseStatefulState { AppLoader(), ], ) - : 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: () { - viewModel.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: () async { - await viewModel.isValidate(false); - checkState(); - }, - )), - AppSpaces.horizontalMedium, - SizedBox( - width: 160, - child: CustomSimpleButton( - backGroundColor: MyColors.blueThemeColor, - textColor: MyColors.white, - height: 38, - heading: AppLocalizations.of(context)! - .add_invoice_and_print, - onPressed: () async { - await viewModel.isValidate(true); - checkState(); - }, - ), + : 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()), + ], ) - ], - ) ], ), ), @@ -838,7 +943,7 @@ class _NewInvoiceVCState extends BaseStatefulState { context, MaterialPageRoute( builder: (context) => AddInvoiceAndPrintVC( - id: 'response.invoice!.id!', + id: viewModel.invoiceId, )), ); } else if (viewModel.crudOperation == CRUDOperationState.add) { @@ -847,107 +952,79 @@ class _NewInvoiceVCState extends BaseStatefulState { } Widget getMeasurementWidget(int position) { - return FutureBuilder( - future: viewModel.getMeasurement(), - builder: (c, s) { - if (s.hasData) { - var itemsList = s.data!; - return ChildContainer( - child: DropdownSearch( - clearButtonProps: ThemeDropDown.clearButton, - dropdownButtonProps: ThemeDropDown.dropdownButtonProps, - popupProps: const PopupProps.menu( - fit: FlexFit.loose, - constraints: BoxConstraints(maxHeight: 250)), - selectedItem: viewModel.selectedMeasurement[position], - items: itemsList, - itemAsString: (Measurement u) => u.name!, - onChanged: (Measurement? data) { - viewModel.setMeasurement(data, position); - }, - dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), - ), - ); - } else { - return AppLoader(); - } - }); + return DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, + 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 FutureBuilder( - future: viewModel.getTax(), - builder: (c, s) { - if (s.hasData) { - var itemsList = s.data!; - return ChildContainer( - child: DropdownSearch( - clearButtonProps: ThemeDropDown.clearButton, - dropdownButtonProps: ThemeDropDown.dropdownButtonProps, - popupProps: const PopupProps.menu( - fit: FlexFit.loose, - constraints: BoxConstraints(maxHeight: 250)), - selectedItem: viewModel.selectedTax[position], - items: itemsList, - itemAsString: (VAT u) { - return u.value!; - }, - onChanged: (VAT? data) { - viewModel.setVat(data, position); - }, - dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), - ), - ); - } else { - return AppLoader(); - } - }); + return DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, + 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 FutureBuilder( - future: viewModel.getCompany(), - builder: (c, s) { - if (s.hasData) { - var itemsList = s.data!; - return DropdownSearch( - clearButtonProps: ThemeDropDown.clearButton, - dropdownButtonProps: ThemeDropDown.dropdownButtonProps, - popupProps: const PopupProps.menu( - fit: FlexFit.loose, - constraints: BoxConstraints(maxHeight: 250)), - selectedItem: viewModel.selectedCustomerCompany, - items: itemsList, - itemAsString: (StoreCustomer u) { - return u.name!; - }, - onChanged: (StoreCustomer? data) { - viewModel.changeCustomer(data); - }, - dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), - ); - } else { - return AppLoader(); - } - }); + return DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, + 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 ChildContainer( - child: DropdownSearch( - clearButtonProps: ThemeDropDown.clearButton, - dropdownButtonProps: ThemeDropDown.dropdownButtonProps, - popupProps: const PopupProps.menu( - fit: FlexFit.loose, constraints: 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.dropDownStyle(hint: 'Choose'), - ), + return DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, + 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'), ); } @@ -970,67 +1047,35 @@ class _NewInvoiceVCState 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( - initialValue: viewModel.addInvoice.products[position].discountPercentage - ?.toString() ?? - '', - onChanged: (String value) { - viewModel.onChangeManualDiscount(value, position); - }, - hintText: '', - ), + 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 FutureBuilder( - future: viewModel.getDiscount(), - builder: (c, s) { - if (s.hasData) { - var itemsList = s.data!; - return ChildContainer( - child: DropdownSearch( - clearButtonProps: ThemeDropDown.clearButton, - dropdownButtonProps: ThemeDropDown.dropdownButtonProps, - popupProps: const PopupProps.menu( - fit: FlexFit.loose, - constraints: BoxConstraints(maxHeight: 250)), - selectedItem: viewModel.selectedDiscount[position], - items: itemsList, - itemAsString: (StoreDiscount u) => u.name ?? '', - onChanged: (StoreDiscount? data) { - viewModel.onChangeAutoDiscount(data, position); - // calculateDiscount(data, position); - }, - dropdownDecoratorProps: MyColors.dropDownStyle(hint: 'Choose'), - ), - ); - } else { - return AppLoader(); - } - }); - } - - void showSheet(int index) async { - final result = await showDialog( - barrierColor: Colors.black26, - context: context, - builder: (context) { - return const SearchProductVC(); + return DropdownSearch( + clearButtonProps: ThemeDropDown.clearButton, + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, + 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'), ); - - if (!mounted) return; - try { - viewModel.updateProduct(result, index); - } catch (e) {} } Widget getDefaultStatus() { @@ -1043,8 +1088,10 @@ class _NewInvoiceVCState extends BaseStatefulState { DropdownSearch( dropdownButtonProps: ThemeDropDown.dropdownButtonProps, selectedItem: viewModel.addInvoice.status ?? 'Choose', - popupProps: const PopupProps.menu( - fit: FlexFit.loose, constraints: BoxConstraints(maxHeight: 250)), + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), items: Constants.statusTypes, itemAsString: (String u) => u, onChanged: (String? data) { @@ -1146,10 +1193,10 @@ class _NewInvoiceVCState extends BaseStatefulState { DropdownSearch( dropdownButtonProps: ThemeDropDown.dropdownButtonProps, selectedItem: viewModel.selectedInvoiceFor ?? "Choose", - popupProps: const PopupProps.menu( - fit: FlexFit.loose, - constraints: BoxConstraints(maxHeight: 100), - ), + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), items: Constants.chooseInvoiceForTypes, itemAsString: (String u) => u, onChanged: (String? data) { @@ -1174,34 +1221,25 @@ class _NewInvoiceVCState extends BaseStatefulState { } getSelectedCurrencyDropdown() { - return FutureBuilder( - future: viewModel.getCurrency(), - builder: (c, snapShot) { - if (snapShot.hasData) { - var currency = snapShot.data!; - return DropdownSearch( - dropdownButtonProps: ThemeDropDown.dropdownButtonProps, - selectedItem: viewModel.selectedCurrency, - popupProps: const PopupProps.menu( - fit: FlexFit.loose, - constraints: BoxConstraints(maxHeight: 200), - ), - items: currency, - itemAsString: (Currency u) => u.name!, - onChanged: (Currency? data) { - viewModel.addInvoice.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, + 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, @@ -1328,32 +1366,79 @@ class _NewInvoiceVCState extends BaseStatefulState { getItemsWidget(int position) { return TransparentBorderContainer( - height: 48, backgroundColor: MyColors.backFillColor, - child: CustomTextButtonIcon( - onPressed: () { - showSheet(position); - }, - heading: viewModel.selectedProduct[position].isEmpty - ? 'Choose' - : viewModel.selectedProduct[position], - icon: Icons.arrow_drop_down), + child: DropdownSearch( + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + 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 Center( - child: ValueText( - viewModel.addInvoice.products[position].tax!.toStringAsFixed(2) ?? - 0.toString(), - ), + return CustomTextAddProduct( + viewModel.addInvoice.products[position].tax!.toStringAsFixed(2) ?? + 0.toString(), ); } getSingleItemAmountWidget(int position) { - return Center( - child: ValueText( - viewModel.addInvoice.products[position].amount!.toStringAsFixed(2)), + 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 index 368f7b7..d4be514 100644 --- a/lib/application/views/salesandordermodule/views/invoiceModule/widgets/InvoiceListView.dart +++ b/lib/application/views/salesandordermodule/views/invoiceModule/widgets/InvoiceListView.dart @@ -1,14 +1,14 @@ import 'package:flutter/material.dart'; -import 'package:sizer/sizer.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 { @@ -42,10 +42,7 @@ class InvoiceListView extends StatelessWidget { children: [ isPortrait ? Container() - : Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 50, - color: MyColors.containerBackColor, + : ListHeadingContainer( child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ @@ -88,19 +85,19 @@ class InvoiceListView extends StatelessWidget { style: ThemeText.textStyleHeadingSmall, ), )), - SizedBox( - width: 120, - child: Align( - alignment: Alignment.centerLeft, - child: Text( - lang(context).switch_status, - style: ThemeText.textStyleHeadingSmall, - ), - )), - AppSpaces.horizontalMedium, + // SizedBox( + // width: 120, + // child: Align( + // alignment: Alignment.centerLeft, + // child: Text( + // lang(context).switch_status, + // style: ThemeText.textStyleHeadingSmall, + // ), + // )), + // AppSpaces.horizontalMedium, Expanded( child: Align( - alignment: Alignment.centerLeft, + alignment: Alignment.center, child: Text( lang(context).status, style: ThemeText.textStyleHeadingSmall, @@ -165,6 +162,7 @@ class InvoiceListView extends StatelessWidget { )) ], ), + AppSpaces.verticalMedium, Row( children: [ Expanded( @@ -184,6 +182,7 @@ class InvoiceListView extends StatelessWidget { )) ], ), + AppSpaces.verticalMedium, Row( children: [ Expanded( @@ -199,11 +198,16 @@ class InvoiceListView extends StatelessWidget { child: Align( alignment: Alignment.centerRight, child: ValueText( - invoice.supplier!.name ?? "", + invoice.invoiceFor?.first == + "Company" + ? invoice.supplier!.name ?? "" + : invoice.customer!.name ?? + '', ), )) ], ), + AppSpaces.verticalMedium, Row( children: [ Expanded( @@ -224,6 +228,7 @@ class InvoiceListView extends StatelessWidget { )) ], ), + AppSpaces.verticalMedium, Row( children: [ Expanded( @@ -245,6 +250,7 @@ class InvoiceListView extends StatelessWidget { )) ], ), + AppSpaces.verticalMedium, Row( children: [ Expanded( @@ -265,6 +271,7 @@ class InvoiceListView extends StatelessWidget { )) ], ), + AppSpaces.verticalMedium, Row( children: [ Expanded( @@ -287,55 +294,55 @@ class InvoiceListView extends StatelessWidget { )) ], ), - 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); - }, - ), - ), - )) - ], - ), + // 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); + // }, + // ), + // ), + // )) + // ], + // ), ], ), )), @@ -349,10 +356,7 @@ class InvoiceListView 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( @@ -395,54 +399,59 @@ class InvoiceListView extends StatelessWidget { 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, + // 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: 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, - ), - ))), + 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), @@ -481,43 +490,40 @@ class InvoiceListView extends StatelessWidget { } Widget getPopUpMenuButton(BuildContext context, StoreInvoice invoice) { - return PopupMenuButton( - icon: const Icon(Icons.more_vert), - itemBuilder: (c) { - return [ - PopupMenuItem( - value: 'edit', - child: ValueText( - lang(context).edit, - ), + return CustomPopupMenuButton( + onSelected: (String value) => actionPopUpItemSelected(value, invoice), + items: [ + // PopupMenuItem( + // value: 'edit', + // child: ValueText( + // lang(context).edit, + // ), + // ), + PopupMenuItem( + value: 'return', + child: ValueText( + lang(context).return_txt, ), - PopupMenuItem( - value: 'return', - child: ValueText( - lang(context).return_txt, - ), + ), + PopupMenuItem( + value: 'damage', + child: ValueText( + "Damage", ), - PopupMenuItem( - value: 'damage', - child: ValueText( - "Damage", - ), + ), + PopupMenuItem( + value: 'view', + child: ValueText( + lang(context).print_or_download, ), - PopupMenuItem( - value: 'view', - child: ValueText( - lang(context).print_or_download, - ), + ), + PopupMenuItem( + value: 'delete', + child: ValueText( + lang(context).delete, ), - PopupMenuItem( - value: 'delete', - child: ValueText( - lang(context).delete, - ), - ) - ]; - }, - onSelected: (String value) => actionPopUpItemSelected(value, invoice), + ) + ], ); } } diff --git a/lib/application/views/salesandordermodule/views/ordersModule/OrderVC.dart b/lib/application/views/salesandordermodule/views/ordersModule/OrderVC.dart index e2a789b..c0831a1 100644 --- a/lib/application/views/salesandordermodule/views/ordersModule/OrderVC.dart +++ b/lib/application/views/salesandordermodule/views/ordersModule/OrderVC.dart @@ -3,16 +3,19 @@ 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/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'; @@ -33,97 +36,167 @@ class _OrderVCState extends State implements TransactionCVS { @override Widget build(BuildContext context) { - viewModel = context.watch(); + //viewModel = context.watch(); return Scaffold( backgroundColor: MyColors.fillColor, body: OrientationBuilder(builder: (c, orientation) { isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; - return Container( - padding: const EdgeInsets.all(12), - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - const Text( - 'Order', - style: ThemeText.textStylePageHeading, - ), - AppSpaces.horizontalSmall, - SizedBox( - height: 38, - width: 160, - child: DropdownSearch( - dropdownButtonProps: ThemeDropDown.dropdownButtonProps, - popupProps: const PopupProps.menu( - fit: FlexFit.loose, - constraints: BoxConstraints(maxHeight: 170)), - clearButtonProps: ThemeDropDown.clearButton, - items: Constants.orderStatus, - itemAsString: (String u) => u, - onChanged: (String? data) { - if (data != null) { - viewModel.setSelectedFilter(data); - } else { - viewModel.setSelectedFilter('All'); - } - }, - dropdownDecoratorProps: MyColors.dropDownStyle( - hint: Constants.orderStatus[0], - fillColor: MyColors.white), + return SingleChildScrollView( + child: Container( + padding: const EdgeInsets.all(12), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + 'Order', + style: ThemeText.textStylePageHeading, ), - ), - AppSpaces.horizontalSmall, - isPortrait - ? Container() - : SizedBox( - width: SizerUtil.deviceType == DeviceType.mobile - ? 200 - : 240, - height: 48, - child: SearchBox( - onEditingDone: (text) {}, - onChanged: (text) {}, - hint: AppLocalizations.of(context)!.search, + 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); + }, + 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, ), - Flexible(child: PageLimitDropdown(onChange: (value) { - viewModel.setLimit(int.parse(value!)); - })) - ], - ), - isPortrait - ? SizedBox( - height: 48, - child: SearchBox( - onEditingDone: (text) {}, - onChanged: (text) {}, - hint: AppLocalizations.of(context)!.search, - ), - ) - : Container(), - AppSpaces.verticalLarge, - Expanded( - child: CashierTransactionsVC( - context: context, - delegate: this, - isPortrait: isPortrait, - limit: viewModel.limit, - isOrder: true, - filter: viewModel.selectedFilter.toLowerCase(), - )) - ], + ) + : Container(), + AppSpaces.verticalLarge, + 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); + } + }, + ), + ) + ], + ), ), ); }), ); } + 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; @@ -168,7 +241,31 @@ 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, + 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/viewModel/OrderViewModel.dart b/lib/application/views/salesandordermodule/views/ordersModule/viewModel/OrderViewModel.dart index 83dc78c..c8c74d6 100644 --- a/lib/application/views/salesandordermodule/views/ordersModule/viewModel/OrderViewModel.dart +++ b/lib/application/views/salesandordermodule/views/ordersModule/viewModel/OrderViewModel.dart @@ -1,15 +1,157 @@ +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/reports/CashierOrderHistory.dart'; +import 'package:wosull/application/network/APIManager.dart'; +import 'package:wosull/application/utils/Constants.dart'; class OrderViewModel with ChangeNotifier { String selectedFilter = 'All'; int limit = 10; + void setSelectedFilter(String filter) { selectedFilter = filter; - notifyListeners(); + // notifyListeners(); } void setLimit(int parse) { limit = parse; + //notifyListeners(); + } + + 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; + + 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() + }; + print(jsonEncode(data)); + 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) { + print(stackTrace.toString()); + _dataState = DataState.error; + }); + } + _isLoading = false; + notifyListeners(); + } catch (e) { + print(e.toString()); + _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 APIManager() + .fetchData(Constants.searchCashier, data) + .then((result) { + print(result); + final value = SearchCashierOrderHistory.fromJson(result); + _filteredList.clear(); + if (value.success!) { + _filteredList.addAll(value.topOrders!); + } + _dataState = DataState.fetched; + }).onError((error, stackTrace) { + print(stackTrace.toString()); + _dataState = DataState.error; + }); + notifyListeners(); + } catch (e) { + _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/CashierTransactionsVC.dart b/lib/application/views/salesandordermodule/views/ordersModule/views/OrderCashierVC.dart similarity index 91% rename from lib/application/views/transactions/CashierTransactionsVC.dart rename to lib/application/views/salesandordermodule/views/ordersModule/views/OrderCashierVC.dart index 72bdcd5..c6ef975 100644 --- a/lib/application/views/transactions/CashierTransactionsVC.dart +++ b/lib/application/views/salesandordermodule/views/ordersModule/views/OrderCashierVC.dart @@ -5,12 +5,12 @@ import 'package:wosull/application/interfaces/DrawerWidgetSelect.dart'; import 'package:wosull/application/model/reports/CashierOrderHistory.dart'; import 'package:wosull/application/utils/AppError.dart'; import 'package:wosull/application/utils/AppLoader.dart'; -import 'package:wosull/application/views/transactions/ViewPOSReturnVC.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 CashierTransactionsVC extends StatefulWidget { +class OrderCashierVC extends StatefulWidget { TransactionCVS delegate; BuildContext context; bool? isOrder = false; @@ -18,7 +18,7 @@ class CashierTransactionsVC extends StatefulWidget { int limit = 10; bool isPortrait = false; - CashierTransactionsVC( + OrderCashierVC( {super.key, required this.delegate, required this.context, @@ -28,11 +28,10 @@ class CashierTransactionsVC extends StatefulWidget { this.isOrder}); @override - State createState() => _CashierTransactionsVCState(); + State createState() => _OrderCashierVCState(); } -class _CashierTransactionsVCState - extends BaseStatefulState { +class _OrderCashierVCState extends BaseStatefulState { late ScrollController _controller; final viewModel = CashierTransactionViewModel(); @@ -44,6 +43,7 @@ class _CashierTransactionsVCState @override Widget build(BuildContext context) { + print(viewModel.dataState); return SingleChildScrollView( controller: _controller, child: ChangeNotifierProvider( diff --git a/lib/application/views/salesandordermodule/views/quotataionModule/NewQuotationsVC.dart b/lib/application/views/salesandordermodule/views/quotataionModule/NewQuotationsVC.dart index a886f5c..d64c528 100644 --- a/lib/application/views/salesandordermodule/views/quotataionModule/NewQuotationsVC.dart +++ b/lib/application/views/salesandordermodule/views/quotataionModule/NewQuotationsVC.dart @@ -1,37 +1,42 @@ -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/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 '../../../inventorymodule/productviews/SearchProductVC.dart'; class NewQuotationsVC extends StatefulWidget { QuotationInvoice storeQuotation; @@ -46,158 +51,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), ), @@ -222,8 +115,8 @@ class _NewQuotationsVCState extends BaseStatefulState { AppSpaces.verticalLarge, getQuotationDate(), AppSpaces.verticalLarge, - getDefaultStatus(), - isPortrait + getCurrencyWidget(), + viewModel.isPortrait ? Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -238,18 +131,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, @@ -274,12 +167,7 @@ class _NewQuotationsVCState extends BaseStatefulState { AppSpaces.verticalLarge, getQuotationDueDate(), AppSpaces.verticalLarge, - CustomOptionalTitle( - hint: AppLocalizations - .of(context)! - .currency), - AppSpaces.verticalSmall, - getSelectedCurrencyDropdown() + getCurrencyWidget() ], )), AppSpaces.horizontalMedium, @@ -306,6 +194,7 @@ class _NewQuotationsVCState extends BaseStatefulState { ), AppSpaces.verticalLarge, Card( + elevation: 5, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.0), ), @@ -321,7 +210,8 @@ class _NewQuotationsVCState extends BaseStatefulState { CustomTextFieldForm( height: 100, maxLines: 5, - initialValue: addQuotation.terms ?? '', + initialValue: + viewModel.addQuotation.terms ?? '', onChanged: (value) {}, hintText: AppLocalizations.of(context)!.terms) ], @@ -330,11 +220,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, @@ -342,27 +233,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( @@ -370,7 +246,7 @@ class _NewQuotationsVCState extends BaseStatefulState { AppLocalizations.of(context)! .name_or_barcode, height: 48, - width: 110, + width: 150, ), HeadingContainer( heading: @@ -445,22 +321,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, @@ -476,429 +368,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), ), ), ), @@ -913,193 +506,102 @@ class _NewQuotationsVCState extends BaseStatefulState { MainAxisAlignment .start, children: [ - TransparentBorderContainer( - height: 48, - backgroundColor: - MyColors - .backFillColor, - 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)), ), ), ], @@ -1107,163 +609,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(), ), ), ), @@ -1273,28 +690,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( @@ -1303,6 +707,10 @@ class _NewQuotationsVCState extends BaseStatefulState { .fillColorGray2), ), ), + child: getItemAddButton(), + ), + Expanded( + child: PortraitContainer( child: Center( child: Text( '', @@ -1312,269 +720,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: [ @@ -1584,26 +798,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, ), )), ], @@ -1613,7 +818,9 @@ class _NewQuotationsVCState extends BaseStatefulState { AppSpaces.verticalSmall, Row( children: [ - const Expanded(child: Text('')), + viewModel.isPortrait + ? Container() + : const Expanded(child: Text('')), Expanded( child: Row( children: [ @@ -1621,27 +828,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, ), )), ], @@ -1651,7 +849,9 @@ class _NewQuotationsVCState extends BaseStatefulState { AppSpaces.verticalSmall, Row( children: [ - const Expanded(child: Text('')), + viewModel.isPortrait + ? Container() + : const Expanded(child: Text('')), Expanded( child: Row( children: [ @@ -1661,27 +861,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, ), )), ], @@ -1693,74 +885,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, )), ], ) @@ -1772,69 +927,60 @@ 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, + 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: ThemeDropDown.dropdownButtonProps, - // 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, + 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 { @@ -1845,367 +991,96 @@ 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( - dropdownButtonProps: ThemeDropDown.dropdownButtonProps, - 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( - dropdownButtonProps: ThemeDropDown.dropdownButtonProps, - 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( - dropdownButtonProps: ThemeDropDown.dropdownButtonProps, - 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 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; - } - - 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( - dropdownButtonProps: ThemeDropDown.dropdownButtonProps, - 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, + 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, + 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, + 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, + 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() { @@ -2215,36 +1090,20 @@ 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( - dropdownButtonProps: ThemeDropDown.dropdownButtonProps, - 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, + 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'), ), ], ); @@ -2254,51 +1113,30 @@ 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( - dropdownButtonProps: ThemeDropDown.dropdownButtonProps, - 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, + 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() { @@ -2311,8 +1149,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', ), @@ -2322,10 +1161,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: '', ); @@ -2334,12 +1173,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: '', ); @@ -2347,66 +1187,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() { @@ -2416,32 +1212,21 @@ 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( - dropdownButtonProps: ThemeDropDown.dropdownButtonProps, - 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, + 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'), + ) ], ); } @@ -2469,139 +1254,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, @@ -2620,13 +1282,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); }, ); } @@ -2636,100 +1299,38 @@ 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() { + 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 6050d47..0945c17 100644 --- a/lib/application/views/salesandordermodule/views/quotataionModule/QuotationsVC.dart +++ b/lib/application/views/salesandordermodule/views/quotataionModule/QuotationsVC.dart @@ -4,26 +4,23 @@ 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/PageLimitDropDown.dart'; import 'package:wosull/widgets/SearchBox.dart'; -import 'package:wosull/widgets/ValueText.dart'; class QuotationsVC extends StatefulWidget { const QuotationsVC({Key? key}) : super(key: key); @@ -76,37 +73,11 @@ class _QuotationsVCState extends BaseStatefulState { SizerUtil.deviceType == DeviceType.mobile ? 120 : 100, - child: DropdownSearch( - dropdownButtonProps: - ThemeDropDown.dropdownButtonProps, - 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: - MyColors.dropDownStyle( - hint: 'All', - fillColor: MyColors.white), - ), + child: getDropdownFilter(), ), AppSpaces.horizontalSmall, Flexible( - child: CustomSimpleButton( - textColor: MyColors.blueThemeColor, - backGroundColor: MyColors.backColorBlue50, - heading: AppLocalizations.of(context)! - .new_quotations, - onPressed: () { - newInvoice(false, - QuotationInvoice(products: [])); - }, - ), + child: getNewQuotationButton(), ), ], ), @@ -115,18 +86,13 @@ class _QuotationsVCState extends BaseStatefulState { mainAxisAlignment: MainAxisAlignment.start, children: [ Flexible( - child: SearchBox( - onEditingDone: (text) {}, - onChanged: (text) {}, - hint: AppLocalizations.of(context)!.search, + child: SizedBox( + height: 48, + child: getSearchBox(), ), ), AppSpaces.horizontalSmall, - PageLimitDropdown(onChange: (value) { - viewModel.fetch( - isRefresh: true, - limit: int.parse(value!)); - }) + getPageLimitDropdown() ], ), ], @@ -142,36 +108,12 @@ class _QuotationsVCState extends BaseStatefulState { SizedBox( height: 38, width: 160, - child: DropdownSearch( - dropdownButtonProps: - ThemeDropDown.dropdownButtonProps, - popupProps: const PopupProps.menu( - constraints: 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), - ), + child: getDropdownFilter(), ), AppSpaces.horizontalSmall, SizedBox( width: 140, - child: CustomSimpleButton( - textColor: MyColors.blueThemeColor, - backGroundColor: MyColors.backColorBlue50, - heading: AppLocalizations.of(context)! - .new_quotations, - onPressed: () { - newInvoice( - false, QuotationInvoice(products: [])); - }, - ), + child: getNewQuotationButton(), ), AppSpaces.horizontalSmall, SizedBox( @@ -179,17 +121,9 @@ class _QuotationsVCState extends BaseStatefulState { ? 200 : 240, height: 48, - child: SearchBox( - onEditingDone: (text) {}, - onChanged: (text) {}, - hint: AppLocalizations.of(context)!.search, - ), + child: getSearchBox(), ), - Flexible( - child: PageLimitDropdown(onChange: (value) { - viewModel.fetch( - isRefresh: true, limit: int.parse(value!)); - })) + Flexible(child: getPageLimitDropdown()) ], ), AppSpaces.verticalMedium, @@ -203,18 +137,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); } }, ), @@ -226,610 +160,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(), ], ); @@ -854,7 +203,6 @@ class _QuotationsVCState extends BaseStatefulState { getCurrency(isEdit, response.invoices!); } }).onError((error, stackTrace) { - print(stackTrace.toString()); //hideProgressBar(); }); } else { @@ -890,23 +238,74 @@ 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, 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..966a188 --- /dev/null +++ b/lib/application/views/salesandordermodule/views/quotataionModule/repo/QuotationRepository.dart @@ -0,0 +1,84 @@ +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'; +import 'package:wosull/helpers/Utils.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 { + await APIManager().fetchData(Constants.ADD_QUOTATION, map).then((value) { + final response = SimpleResponseModel.fromJson(value); + if (response.success) { + Utils.showMessage(response.message); + } + return true; + }).onError((error, stackTrace) { + return false; + }); + return false; + } +} 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..c472aff --- /dev/null +++ b/lib/application/views/salesandordermodule/views/quotataionModule/viewModels/NewQuotationViewModel.dart @@ -0,0 +1,486 @@ +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) { + 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 index 5cc3f42..08c65d0 100644 --- a/lib/application/views/settings/ReportsVC.dart +++ b/lib/application/views/settings/ReportsVC.dart @@ -5,15 +5,14 @@ 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/repository/WosulRepository.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'; @@ -21,6 +20,7 @@ import 'package:wosull/application/views/settings/reportsViews/ReportsInvoiceVC. 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/ThemeDropDown.dart'; import 'package:wosull/helpers/ThemeText.dart'; import 'package:wosull/widgets/PageLimitDropDown.dart'; @@ -36,7 +36,7 @@ class ReportsVC extends StatefulWidget { class _ReportsVCState extends BaseStatefulState implements ReportsCVS { - final viewModel = InventoryViewModel(); + final viewModel = WosulRepository(); bool isPortrait = true; bool isLoading = true; @@ -51,7 +51,7 @@ class _ReportsVCState extends BaseStatefulState var items = [ 'Best Seller', 'POS Complete', - 'POS Return', + 'POS Return & Damage', 'Invoices', 'Quotations', 'Categories', @@ -68,98 +68,62 @@ class _ReportsVCState extends BaseStatefulState @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 - ? Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Text( - AppLocalizations.of(context)!.pos_sales, - style: ThemeText.textStylePageHeading, - ), - AppSpaces.horizontalSmall, - Flexible( + 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(), ), - Flexible( - child: PageLimitDropdown(onChange: (value) { - limit = int.parse(value!); - })) - ], - ) - : Row( - children: [ - Text( - AppLocalizations.of(context)!.pos_sales, - style: ThemeText.textStylePageHeading, - ), - AppSpaces.horizontalSmall, - 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'), - ), - ), - ), - ), - ), - ), - Flexible( - child: PageLimitDropdown(onChange: (value) { - limit = int.parse(value!); - })) - ], - ), - AppSpaces.verticalMedium, - Expanded( - child: getReportsType(), - ) - ], - ), - ); - })), - ); + ), + 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: PageLimitDropdown(onChange: (value) { + limit = int.parse(value!); + })) + ], + ), + AppSpaces.verticalMedium, + Expanded( + child: getReportsType(), + ) + ], + ), + ); + })); } generateCsv(String name) async { @@ -254,37 +218,22 @@ class _ReportsVCState extends BaseStatefulState } 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'), - ), - ), - ), + return DropdownSearch( + selectedItem: selectedReport, + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + 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/settings/reportsViews/BestSuppliersVC.dart b/lib/application/views/settings/reportsViews/BestSuppliersVC.dart index cfad5df..6482d83 100644 --- a/lib/application/views/settings/reportsViews/BestSuppliersVC.dart +++ b/lib/application/views/settings/reportsViews/BestSuppliersVC.dart @@ -10,6 +10,7 @@ import 'package:wosull/application/views/settings/viewModels/BestSupplierViewMod 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 BestSupplierVC extends StatelessWidget { @@ -29,9 +30,10 @@ class BestSupplierVC extends StatelessWidget { @override Widget build(BuildContext context) { + _controller = ScrollController()..addListener(_scrollNotification); return OrientationBuilder(builder: (c, orientation) { isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; - _controller = ScrollController()..addListener(_scrollNotification); + return SingleChildScrollView( controller: _controller, child: ChangeNotifierProvider( @@ -72,10 +74,7 @@ class BestSupplierVC extends StatelessWidget { children: [ isPortrait ? Container() - : Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 50, - color: MyColors.containerBackColor, + : ListHeadingContainer( child: Row( children: [ Expanded( @@ -189,10 +188,7 @@ class BestSupplierVC 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('$position')), diff --git a/lib/application/views/settings/reportsViews/POSCompleteVC.dart b/lib/application/views/settings/reportsViews/POSCompleteVC.dart index 37e44c9..bde6a7b 100644 --- a/lib/application/views/settings/reportsViews/POSCompleteVC.dart +++ b/lib/application/views/settings/reportsViews/POSCompleteVC.dart @@ -9,7 +9,10 @@ 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/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'; import '../../../../widgets/EmptyDataWidget.dart'; @@ -75,10 +78,7 @@ class POSComplete extends StatelessWidget { children: [ isPortrait ? Container() - : Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 50, - color: MyColors.containerBackColor, + : ListHeadingContainer( child: Row( children: [ Expanded( @@ -89,6 +89,20 @@ class POSComplete extends StatelessWidget { child: HeadingText( AppLocalizations.of(context)! .store_name)), + Expanded(child: HeadingText('Delivery Type')), + Expanded( + child: HeadingText( + AppLocalizations.of(context)! + .payment_mode)), + Expanded( + child: HeadingText( + AppLocalizations.of(context)!.table)), + Expanded( + child: HeadingText( + AppLocalizations.of(context)!.total)), + Expanded( + child: HeadingText( + AppLocalizations.of(context)!.discount)), Expanded( child: HeadingText( AppLocalizations.of(context)!.status)), @@ -133,24 +147,30 @@ class POSComplete extends StatelessWidget { children: [ HeadingText(AppLocalizations.of(context)! .order_number), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, HeadingText(AppLocalizations.of(context)! .store_name), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, + HeadingText('Delivery Type'), + AppSpaces.verticalMedium, + HeadingText(AppLocalizations.of(context)! + .payment_mode), + AppSpaces.verticalMedium, + HeadingText( + AppLocalizations.of(context)!.table), + AppSpaces.verticalMedium, + HeadingText( + AppLocalizations.of(context)!.total), + AppSpaces.verticalMedium, + HeadingText( + AppLocalizations.of(context)!.discount), + AppSpaces.verticalMedium, HeadingText( AppLocalizations.of(context)!.status), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, HeadingText(AppLocalizations.of(context)! .created_on), - const SizedBox( - height: 8, - ), + AppSpaces.verticalMedium, HeadingText(AppLocalizations.of(context)! .updated_on), ], @@ -163,22 +183,30 @@ class POSComplete extends StatelessWidget { ValueText( completePOS.uniqueId!.toString(), ), - const SizedBox( - height: 12, - ), + AppSpaces.verticalMedium, ValueText(completePOS.storeId!.name ?? ''), - const SizedBox( - height: 12, - ), - ValueText(completePOS.status ?? ''), - const SizedBox( - height: 12, - ), + AppSpaces.verticalMedium, + ValueText(completePOS.orderType ?? ''), + 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 ?? '')), - const SizedBox( - height: 12, - ), + AppSpaces.verticalMedium, ValueText(DataTimeFormat.getFormatDate( completePOS.updatedAt ?? '')), ], @@ -192,10 +220,7 @@ class POSComplete 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( @@ -203,8 +228,25 @@ class POSComplete extends StatelessWidget { completePOS.uniqueId!.toString())), Expanded( child: - ValueText(completePOS.storeId!.name!)), - Expanded(child: ValueText(completePOS.status!)), + ValueText(completePOS.storeId!.name)), + Expanded( + child: ValueText(completePOS.orderType!)), + 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( diff --git a/lib/application/views/settings/reportsViews/POSReturnOrderVC.dart b/lib/application/views/settings/reportsViews/POSReturnOrderVC.dart index 1f83c51..403c8b7 100644 --- a/lib/application/views/settings/reportsViews/POSReturnOrderVC.dart +++ b/lib/application/views/settings/reportsViews/POSReturnOrderVC.dart @@ -160,20 +160,20 @@ class POSReturnOrderVC extends StatelessWidget { children: [ ValueText(returnOrder.uniqueId!.toString()), const SizedBox( - height: 12, + height: 8, ), ValueText(returnOrder.storeId!.name ?? ''), const SizedBox( - height: 12, + height: 8, ), ValueText(returnOrder.status ?? ''), const SizedBox( - height: 12, + height: 8, ), ValueText(DataTimeFormat.getFormatDate( returnOrder.createdAt ?? '')), const SizedBox( - height: 12, + height: 8, ), ValueText(DataTimeFormat.getFormatDate( returnOrder.updatedAt ?? '')), diff --git a/lib/application/views/settings/reportsViews/ReportsCategoryVC.dart b/lib/application/views/settings/reportsViews/ReportsCategoryVC.dart index 7a34215..140b1af 100644 --- a/lib/application/views/settings/reportsViews/ReportsCategoryVC.dart +++ b/lib/application/views/settings/reportsViews/ReportsCategoryVC.dart @@ -7,6 +7,7 @@ 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 'package:wosull/widgets/ListHeadingContainer.dart'; import '../../../../widgets/EmptyDataWidget.dart'; @@ -96,10 +97,7 @@ class _ReportsCategoryVCState extends State { children: [ isPortrait ? Container() - : Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 50, - color: MyColors.containerBackColor, + : ListHeadingContainer( child: Row( children: [ Expanded( @@ -140,92 +138,87 @@ class _ReportsCategoryVCState extends State { elevation: 2, color: MyColors.white, child: Container( - padding: const EdgeInsets.fromLTRB(8, 0, 0, 8), + padding: const EdgeInsets.all(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( + 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)! - .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(), - ), - ], - )), - ], - ), + .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(), + ), + ], + )), + ], )), ], ), @@ -269,7 +262,7 @@ class _ReportsCategoryVCState extends State { child: Center( child: Text( _data[position].isActive()!, - style: const TextStyle( + style: TextStyle( fontStyle: FontStyle.normal, fontFamily: MyFonts.Bold, fontSize: MyFonts.normal, diff --git a/lib/application/views/settings/reportsViews/ReportsCustomerVC.dart b/lib/application/views/settings/reportsViews/ReportsCustomerVC.dart index 49b0dc3..d16eb17 100644 --- a/lib/application/views/settings/reportsViews/ReportsCustomerVC.dart +++ b/lib/application/views/settings/reportsViews/ReportsCustomerVC.dart @@ -1,10 +1,10 @@ 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/Constants.dart'; @@ -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; @@ -349,7 +349,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/reportsViews/ReportsInvoiceVC.dart b/lib/application/views/settings/reportsViews/ReportsInvoiceVC.dart index 0710a73..062aa93 100644 --- a/lib/application/views/settings/reportsViews/ReportsInvoiceVC.dart +++ b/lib/application/views/settings/reportsViews/ReportsInvoiceVC.dart @@ -8,6 +8,7 @@ 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'; +import 'package:wosull/helpers/AppSpaces.dart'; class ReportsInvoiceVC extends StatelessWidget { bool isPortrait = true; @@ -178,7 +179,7 @@ class ReportsInvoiceVC extends StatelessWidget { borderRadius: BorderRadius.circular(8.0), ), child: Container( - padding: const EdgeInsets.fromLTRB(16, 0, 0, 16), + padding: const EdgeInsets.all(8), color: MyColors.containerBackColor, child: Row( crossAxisAlignment: CrossAxisAlignment.start, @@ -186,185 +187,191 @@ class ReportsInvoiceVC extends StatelessWidget { 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), - ), - )) - ], - ), - ], - ), + 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.invoiceFor!.first == + 'Company' + ? storeInvoice.supplier?.name ?? "" + : storeInvoice.customer?.name ?? '', + style: MyColors.textStyleValue(), + ), + )) + ], + ), + AppSpaces.verticalMedium, + 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(), + ), + )) + ], + ), + AppSpaces.verticalMedium, + 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(), + ), + )) + ], + ), + AppSpaces.verticalMedium, + 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(), + ), + )) + ], + ), + AppSpaces.verticalMedium, + 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(), + ), + )) + ], + ), + AppSpaces.verticalMedium, + 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(), + ), + )) + ], + ), + AppSpaces.verticalMedium, + 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(), + ), + )) + ], + ), + AppSpaces.verticalMedium, + 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: TextStyle( + fontFamily: MyFonts.Bold, + fontWeight: FontWeight.w500, + fontSize: MyFonts.normal, + color: MyColors.greenColor), + ), + )) + ], + ), + ], )), ], ), @@ -434,7 +441,7 @@ class ReportsInvoiceVC extends StatelessWidget { child: Center( child: Text( storeInvoice.status!, - style: const TextStyle( + style: TextStyle( fontStyle: FontStyle.normal, fontFamily: MyFonts.Bold, fontSize: MyFonts.normal, diff --git a/lib/application/views/settings/reportsViews/ReportsProductsVC.dart b/lib/application/views/settings/reportsViews/ReportsProductsVC.dart index 308b4e5..9d5718d 100644 --- a/lib/application/views/settings/reportsViews/ReportsProductsVC.dart +++ b/lib/application/views/settings/reportsViews/ReportsProductsVC.dart @@ -7,6 +7,7 @@ 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'; +import 'package:wosull/widgets/ListHeadingContainer.dart'; class ReportsProductsVC extends StatefulWidget { final ReportsCVS delegate; @@ -95,10 +96,7 @@ class _ReportsProductsVCState extends State { children: [ isPortrait ? Container() - : Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 50, - color: MyColors.containerBackColor, + : ListHeadingContainer( child: Row( children: [ Expanded( @@ -144,105 +142,109 @@ class _ReportsProductsVCState extends State { elevation: 2, color: MyColors.white, child: Container( - padding: const EdgeInsets.fromLTRB(8, 0, 0, 8), + padding: const EdgeInsets.all(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( + child: Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(widget.context)! + .item_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)! - .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(), - ), - ], - )), - ], - ), + .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] + .price + ?.toStringAsFixed(2) ?? + '', + 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(), + ), + ], + )), + ], )), ], ), diff --git a/lib/application/views/settings/reportsViews/ReportsQuotationVC.dart b/lib/application/views/settings/reportsViews/ReportsQuotationVC.dart index e2bcb76..e2b0bb1 100644 --- a/lib/application/views/settings/reportsViews/ReportsQuotationVC.dart +++ b/lib/application/views/settings/reportsViews/ReportsQuotationVC.dart @@ -9,6 +9,7 @@ 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'; +import 'package:wosull/widgets/ListHeadingContainer.dart'; class ReportsQuotationVC extends StatefulWidget { final ReportsCVS delegate; @@ -95,10 +96,7 @@ class _ReportsQuotationVCState extends State { children: [ isPortrait ? Container() - : Container( - padding: const EdgeInsets.only(left: 8, right: 8), - height: 50, - color: MyColors.containerBackColor, + : ListHeadingContainer( child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ @@ -202,7 +200,7 @@ class _ReportsQuotationVCState extends State { borderRadius: BorderRadius.circular(8.0), ), child: Container( - padding: const EdgeInsets.fromLTRB(16, 0, 0, 16), + padding: const EdgeInsets.all(8), color: MyColors.containerBackColor, child: Row( crossAxisAlignment: CrossAxisAlignment.start, @@ -211,7 +209,6 @@ class _ReportsQuotationVCState extends State { Expanded( flex: 2, child: Container( - padding: const EdgeInsets.only(top: 16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -395,7 +392,7 @@ class _ReportsQuotationVCState extends State { _data[position] .status! .toString(), - style: const TextStyle( + style: TextStyle( fontFamily: MyFonts.Bold, fontWeight: FontWeight.w500, @@ -484,7 +481,7 @@ class _ReportsQuotationVCState extends State { child: Center( child: Text( _data[position].status!, - style: const TextStyle( + style: TextStyle( fontStyle: FontStyle.normal, fontFamily: MyFonts.Bold, fontSize: MyFonts.normal, diff --git a/lib/application/views/settings/viewModels/POSReturnOrderViewModel.dart b/lib/application/views/settings/viewModels/POSReturnOrderViewModel.dart index 14013cf..ad4d420 100644 --- a/lib/application/views/settings/viewModels/POSReturnOrderViewModel.dart +++ b/lib/application/views/settings/viewModels/POSReturnOrderViewModel.dart @@ -45,7 +45,7 @@ class POSReturnOrderViewModel with ChangeNotifier { await APIManager() .fetchData(Constants.GET_RETURN_ORDER_HISTORY, data) .then((result) { - final value = GetReturnOrderModel.fromJson(result); + final value = GetReturnAndDamageModel.fromJson(result); if (_dataState == DataState.refreshing) { _data.clear(); } @@ -61,6 +61,7 @@ class POSReturnOrderViewModel with ChangeNotifier { _dataState = DataState.fetched; _currentPageNumber += 1; }).onError((error, stackTrace) { + print(stackTrace.toString()); _dataState = DataState.error; }); } diff --git a/lib/application/views/transactions/TransactionInvoicesVC.dart b/lib/application/views/transactions/TransactionInvoicesVC.dart deleted file mode 100644 index 0ab0f47..0000000 --- a/lib/application/views/transactions/TransactionInvoicesVC.dart +++ /dev/null @@ -1,986 +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'; - 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' - ]; - - 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, - '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) { - 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 e4394b9..0000000 --- a/lib/application/views/transactions/TransactionPOSReturnVC.dart +++ /dev/null @@ -1,473 +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; - int limit; - TransactionPOSReturnVC( - {super.key, - required this.delegate, - required this.context, - this.limit = 10}); - - @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, - 'limit': widget.limit - }; - - 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 < widget.limit) { - __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, - 'limit': widget.limit - }; - 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 < widget.limit) { - __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 699da54..c5cc5f9 100644 --- a/lib/application/views/transactions/TransactionVC.dart +++ b/lib/application/views/transactions/TransactionVC.dart @@ -1,19 +1,16 @@ 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/repository/WosulRepository.dart'; import 'package:wosull/application/theme/MyColors.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'; @@ -22,7 +19,7 @@ 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); @@ -37,13 +34,13 @@ class _TransactionVCState extends BaseStatefulState 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 = []; @@ -61,7 +58,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: [ @@ -75,27 +72,19 @@ class _TransactionVCState extends BaseStatefulState AppSpaces.horizontalSmall, SizedBox( height: 38, - width: 120, - child: DropdownSearch( - dropdownButtonProps: ThemeDropDown.dropdownButtonProps, - selectedItem: selectedReport, - popupProps: const PopupProps.menu( - constraints: BoxConstraints(maxHeight: 200), - ), - items: items, - itemAsString: (String u) => u, - onChanged: (String? data) { - setState(() { - selectedReport = data!; - }); - }, - dropdownDecoratorProps: MyColors.dropDownStyle( - hint: 'Choose', fillColor: MyColors.white), - ), + width: 100, + child: getDropdownSearch(), ), - Flexible(child: PageLimitDropdown(onChange: (value) { - limit = int.parse(value!); - })) + AppSpaces.horizontalSmall, + Flexible( + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + PageLimitDropdown(onChange: (value) { + limit = int.parse(value!); + }) + ], + )) ], ), AppSpaces.verticalMedium, @@ -107,46 +96,25 @@ class _TransactionVCState extends BaseStatefulState Widget getReportsType() { if (selectedReport == items[0]) { - return CashierTransactionsVC( + return TransactionCashierVC( limit: limit, - isPortrait: isPortrait, + // isPortrait: isPortrait, context: context, - isOrder: false, delegate: this, ); } else if (selectedReport == items[1]) { - return TransactionPOSReturnVC( - limit: limit, - 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( limit: limit, context: context, delegate: this, ); - } else if (selectedReport == items[4]) { - return ReturnTransactionInvoiceVC( - limit: limit, - filter: 'Return', - context: context, - delegate: this, - ); - } else if (selectedReport == items[5]) { - return TransactionDamageInvoiceVC( - limit: limit, - filter: 'Damage', - context: context, - delegate: this, - ); } else { return Container(); } @@ -200,7 +168,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; @@ -234,4 +202,33 @@ class _TransactionVCState extends BaseStatefulState setState(() {}); } } + + getDropdownSearch() { + return DropdownSearch( + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + selectedItem: selectedReport, + popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return SizedBox( + height: 38, + child: Center( + child: Text(item, style: ThemeDropDown.dropDownTextStyle), + ), + ); + }, + 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/return/ReturnPOS.dart b/lib/application/views/transactions/return/ReturnPOS.dart index 96a0a69..6456a6c 100644 --- a/lib/application/views/transactions/return/ReturnPOS.dart +++ b/lib/application/views/transactions/return/ReturnPOS.dart @@ -5,21 +5,23 @@ import 'package:wosull/application/model/reports/CashierOrderHistory.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/TransprentBorderContainer.dart'; import 'package:wosull/widgets/ValueText.dart'; +import 'package:wosull/widgets/WrapHeightContainer.dart'; class ReturnPOS extends StatefulWidget { bool isReturn = false; @@ -71,6 +73,7 @@ class _ReturnPOSState extends State { ), AppSpaces.verticalMedium, Card( + elevation: 5, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(4.0), ), @@ -88,18 +91,7 @@ class _ReturnPOSState extends State { 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: [ HeadingContainer( @@ -151,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, @@ -184,7 +200,6 @@ class _ReturnPOSState extends State { PortraitContainer( width: double.infinity, - height: 48, child: Align( alignment: Alignment .centerLeft, @@ -197,7 +212,6 @@ class _ReturnPOSState extends State { PortraitContainer( width: double.infinity, - height: 48, child: Align( alignment: Alignment .centerLeft, @@ -210,7 +224,6 @@ class _ReturnPOSState extends State { PortraitContainer( width: double.infinity, - height: 48, child: Align( alignment: Alignment .centerLeft, @@ -224,7 +237,6 @@ class _ReturnPOSState extends State { PortraitContainer( width: double.infinity, - height: 48, child: Align( alignment: Alignment .centerLeft, @@ -237,7 +249,6 @@ class _ReturnPOSState extends State { PortraitContainer( width: double.infinity, - height: 48, child: Align( alignment: Alignment .centerLeft, @@ -256,27 +267,27 @@ class _ReturnPOSState extends State { PortraitContainer( width: double.infinity, - height: 48, child: Center( child: Align( alignment: Alignment .centerLeft, - child: ValueText( - item.name), + child: + CustomTextAddProduct( + item.name), ), ), ), PortraitContainer( - height: 48, width: double.infinity, - child: Center( - child: ValueText(item - .description), + child: Align( + alignment: Alignment + .centerLeft, + child: CustomTextAddProduct( + item.description), ), ), PortraitContainer( - height: 48, width: double.infinity, child: @@ -286,11 +297,13 @@ class _ReturnPOSState extends State { item), ), PortraitContainer( - height: 48, width: double.infinity, - child: Center( - child: ValueText( + child: Align( + alignment: Alignment + .centerLeft, + child: + CustomTextAddProduct( item.price .toStringAsFixed( 2), @@ -298,11 +311,13 @@ class _ReturnPOSState extends State { ), ), PortraitContainer( - height: 48, width: double.infinity, - child: Center( - child: ValueText( + child: Align( + alignment: Alignment + .centerLeft, + child: + CustomTextAddProduct( viewModel .getSingleItemPrice( item), @@ -314,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); - }, - ), - )) ], ), ); @@ -360,26 +361,15 @@ class _ReturnPOSState extends State { ), Expanded( child: ChildContainer( - child: TransparentBorderContainer( - child: Expanded( - child: Align( - alignment: - Alignment.centerLeft, - child: ValueText(item.name), - ), - ), + child: Center( + child: ValueText(item.name), ), )), Expanded( child: ChildContainer( - child: TransparentBorderContainer( - backgroundColor: - MyColors.disableColor, - child: Align( - alignment: Alignment.centerLeft, - child: ValueText( - item.description, - ), + child: Center( + child: ValueText( + item.description, ), ), )), @@ -391,21 +381,15 @@ class _ReturnPOSState extends State { )), Expanded( child: ChildContainer( - child: TransparentBorderContainer( - backgroundColor: - MyColors.disableColor, - child: Align( - alignment: Alignment.centerLeft, - child: ValueText( - item.price.toStringAsFixed(2), - ), + child: Center( + child: ValueText( + item.price.toStringAsFixed(2), ), ), )), ChildContainer( width: 84, - child: Align( - alignment: Alignment.centerLeft, + child: Center( child: ValueText( viewModel .getSingleItemPrice(item), @@ -420,51 +404,35 @@ 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: HeadingContainer( heading: 'Grand Total', )), Expanded( child: HeadingContainer( - height: 48, 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: MyColors.white, child: Row( children: [ HeadingContainer( @@ -484,13 +452,15 @@ class _ReturnPOSState extends State { heading: '', )), Expanded( - child: HeadingContainer( - heading: 'Grand Total', + child: ChildContainer( + child: HeadingText('Grand Total'), )), - HeadingContainer( + ChildContainer( width: 84, - heading: - viewModel.getTotalProductsPrice(), + child: Center( + child: HeadingText(viewModel + .getTotalProductsPrice()), + ), ), ], ), @@ -498,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: [ @@ -507,7 +479,7 @@ class _ReturnPOSState extends State { alignment: Alignment.centerRight, child: Text( AppLocalizations.of(context)!.discount, - style: ThemeText.textStyleHeading, + style: ThemeText.textStyleAmountHeading, ), )), AppSpaces.horizontalMedium, @@ -517,7 +489,7 @@ class _ReturnPOSState extends State { child: Text( widget.cashierOrder.totalDiscount! .toStringAsFixed(2), - style: ThemeText.textStyleHeading, + style: ThemeText.textStyleAmountValue, ), )), ], @@ -527,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: [ @@ -537,7 +511,8 @@ class _ReturnPOSState extends State { child: Text( AppLocalizations.of(context)! .total_amount, - style: ThemeText.textStyleHeading, + style: + ThemeText.textStyleAmountHeadingBlack, ), )), AppSpaces.horizontalMedium, @@ -546,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, ), )), ], @@ -563,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(), + ) + ], ) - ], - ) ], ), ), @@ -660,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 c263785..7ff8f29 100644 --- a/lib/application/views/transactions/return/ReturnReasonPopUp.dart +++ b/lib/application/views/transactions/return/ReturnReasonPopUp.dart @@ -38,7 +38,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( @@ -53,7 +53,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( @@ -97,8 +97,10 @@ class _ReturnReasonPopUpState extends State { return DropdownSearch( clearButtonProps: ThemeDropDown.clearButton, dropdownButtonProps: ThemeDropDown.dropdownButtonProps, - popupProps: const PopupProps.menu( - fit: FlexFit.loose, constraints: BoxConstraints(maxHeight: 250)), + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: BoxConstraints(maxHeight: 250)), items: Constants.paymentMethod, itemAsString: (String u) => u, onChanged: (String? data) { @@ -116,8 +118,10 @@ class _ReturnReasonPopUpState extends State { return DropdownSearch( clearButtonProps: ThemeDropDown.clearButton, dropdownButtonProps: ThemeDropDown.dropdownButtonProps, - popupProps: const PopupProps.menu( - fit: FlexFit.loose, constraints: BoxConstraints(maxHeight: 250)), + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: BoxConstraints(maxHeight: 250)), items: Constants.returnProductReason, itemAsString: (String u) => u, onChanged: (String? data) { diff --git a/lib/application/views/transactions/viewmodels/CashierTransactionViewModel.dart b/lib/application/views/transactions/viewmodels/CashierTransactionViewModel.dart index 94b1fa5..4739a2b 100644 --- a/lib/application/views/transactions/viewmodels/CashierTransactionViewModel.dart +++ b/lib/application/views/transactions/viewmodels/CashierTransactionViewModel.dart @@ -25,6 +25,10 @@ class CashierTransactionViewModel with ChangeNotifier { 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; diff --git a/lib/application/views/transactions/EditOrderVC.dart b/lib/application/views/transactions/views/EditOrderVC.dart similarity index 70% rename from lib/application/views/transactions/EditOrderVC.dart rename to lib/application/views/transactions/views/EditOrderVC.dart index 66183cf..f3bfe6e 100644 --- a/lib/application/views/transactions/EditOrderVC.dart +++ b/lib/application/views/transactions/views/EditOrderVC.dart @@ -17,6 +17,7 @@ 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'; @@ -27,11 +28,13 @@ 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}); + EditOrderVC({super.key, required this.cashierOrder, this.isView = false}); @override State createState() => _EditOrderVCState(); @@ -56,20 +59,24 @@ class _EditOrderVCState extends State { Widget build(BuildContext context) { viewModel = context.watch(); return Scaffold( + backgroundColor: MyColors.fillColor, resizeToAvoidBottomInset: true, appBar: CustomAppBar( - heading: AppLocalizations.of(context)!.edit_order, + 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( - color: MyColors.white, padding: const EdgeInsets.all(8), child: Column( children: [ + AppSpaces.verticalLarge, Card( + elevation: 5, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.0), ), @@ -184,33 +191,24 @@ class _EditOrderVCState extends State { ), 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: [ Text( AppLocalizations.of(context)!.search_and_add_products, - style: ThemeText.textStylePageHeading, + style: ThemeText.textStyleHeadingCart, ), 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( child: Row( children: [ Expanded( @@ -243,10 +241,12 @@ class _EditOrderVCState extends State { heading: AppLocalizations.of(context)! .total_amount, ), - HeadingContainer( - width: 44, - heading: '', - ) + widget.isView + ? Container() + : HeadingContainer( + width: 44, + heading: '', + ) ], ), ), @@ -267,10 +267,7 @@ class _EditOrderVCState extends State { var item = widget.cashierOrder.cart! .orderDetails![position].items![i]; if (viewModel.isPortrait) { - return Container( - padding: - const EdgeInsets.fromLTRB(8, 0, 0, 8), - color: MyColors.containerBackColor, + return WrapHeightContainer( child: Row( crossAxisAlignment: CrossAxisAlignment.start, @@ -279,153 +276,142 @@ class _EditOrderVCState extends State { 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: [ - PortraitContainer( - width: double.infinity, - child: Align( - alignment: Alignment - .centerLeft, - child: HeadingText( - AppLocalizations.of( - context)! - .name_or_barcode, - ), + 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)! + .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)! + .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_cost_price, ), ), - PortraitContainer( - width: double.infinity, - child: Align( - alignment: Alignment - .centerLeft, - child: HeadingText( - AppLocalizations.of( - context)! - .total_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, + ), + ], + )), + 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: - getShowProductsWidget( - item, - position, - i), - ), - PortraitContainer( - width: double.infinity, - child: Center( - child: - getItemNotesWidget( - position, i), - ), + getItemNotesWidget( + position, i), ), - PortraitContainer( - width: double.infinity, - child: Center( - child: - getItemQuantityWidget( - 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: + getItemCostPriceWidget( + position, i), ), - PortraitContainer( - width: double.infinity, + ), + PortraitContainer( + width: double.infinity, + child: Center( child: getItemPriceWidget( item), ), - ], - )), - ], - ), + ), + ], + )), + ], )), - getRemoveItemButton(position, i) + Visibility( + visible: !widget.isView, + child: getRemoveItemButton( + 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, + return BorderContainer( + backgroundColor: MyColors.white, child: Row( children: [ Expanded( @@ -467,7 +453,11 @@ class _EditOrderVCState extends State { ), ), ), - getRemoveItemButton(position, i), + Visibility( + visible: !widget.isView, + child: + getRemoveItemButton(position, i), + ) ], ), ); @@ -480,23 +470,14 @@ class _EditOrderVCState extends State { widget.cashierOrder.cart!.orderDetails!.length, ), 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: [ Expanded( child: ChildContainer( - child: Center( + child: Align( + alignment: Alignment.centerLeft, child: HeadingText( AppLocalizations.of(context)! .total_amount), @@ -510,22 +491,14 @@ class _EditOrderVCState extends State { ), ), )), - getAddItemButton() + Visibility( + visible: !widget.isView, + child: getAddItemButton()) ], ), ) - : 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( @@ -553,7 +526,9 @@ class _EditOrderVCState extends State { heading: viewModel.getItemsPriceWithModifier(), ), - getAddItemButton() + Visibility( + visible: !widget.isView, + child: getAddItemButton()) ], ), ), @@ -563,24 +538,26 @@ class _EditOrderVCState extends State { ), ), AppSpaces.verticalLarge, - 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, - )), - ], - ) + 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, + )), + ], + )) ], ), ), @@ -611,12 +588,14 @@ class _EditOrderVCState extends State { if (s.hasData) { var itemsList = s.data!; return DropdownSearch( + enabled: !widget.isView, selectedItem: viewModel.selectedOrderType, clearButtonProps: ThemeDropDown.clearButton, dropdownButtonProps: ThemeDropDown.dropdownButtonProps, - popupProps: const PopupProps.menu( + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, fit: FlexFit.loose, - constraints: BoxConstraints(maxHeight: 250)), + constraints: const BoxConstraints(maxHeight: 250)), items: itemsList, itemAsString: (StoreServiceModel u) => u.name!, onChanged: (StoreServiceModel? data) { @@ -637,13 +616,15 @@ class _EditOrderVCState extends State { 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: const PopupProps.menu( + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, fit: FlexFit.loose, - constraints: BoxConstraints(maxHeight: 250)), + constraints: const BoxConstraints(maxHeight: 250)), items: itemsList, itemAsString: (StoreTable u) => "${u.tableName} | ${u.noOfOccupants}", @@ -665,12 +646,14 @@ class _EditOrderVCState extends State { if (s.hasData) { var itemsList = s.data!; return DropdownSearch( + enabled: !widget.isView, selectedItem: viewModel.selectedStore, clearButtonProps: ThemeDropDown.clearButton, dropdownButtonProps: ThemeDropDown.dropdownButtonProps, - popupProps: const PopupProps.menu( + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, fit: FlexFit.loose, - constraints: BoxConstraints(maxHeight: 250)), + constraints: const BoxConstraints(maxHeight: 250)), items: itemsList, itemAsString: (WosulStore u) => u.name, onChanged: (WosulStore? data) { @@ -686,11 +669,14 @@ class _EditOrderVCState extends State { Widget getSelectedPaymentMode() { return DropdownSearch( + enabled: !widget.isView, selectedItem: viewModel.selectedPaymentMode ?? "Choose", clearButtonProps: ThemeDropDown.clearButton, dropdownButtonProps: ThemeDropDown.dropdownButtonProps, - popupProps: const PopupProps.menu( - fit: FlexFit.loose, constraints: BoxConstraints(maxHeight: 250)), + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), items: viewModel.items, itemAsString: (String u) => u, onChanged: (String? data) { @@ -702,10 +688,13 @@ class _EditOrderVCState extends State { Widget getStatusDropdown() { return DropdownSearch( + enabled: !widget.isView, clearButtonProps: ThemeDropDown.clearButton, dropdownButtonProps: ThemeDropDown.dropdownButtonProps, - popupProps: const PopupProps.menu( - fit: FlexFit.loose, constraints: BoxConstraints(maxHeight: 250)), + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + constraints: const BoxConstraints(maxHeight: 250)), selectedItem: viewModel.selectedStatus ?? "Choose", items: viewModel.statusItems, itemAsString: (String u) => u, @@ -746,6 +735,7 @@ class _EditOrderVCState extends State { ), AppSpaces.verticalSmall, CustomTextFieldForm( + readOnly: widget.isView, keyboardType: TextInputType.number, hintText: 'Enter Amount', initialValue: viewModel.cashierOrder.amount?.toString() ?? '', @@ -802,6 +792,7 @@ class _EditOrderVCState extends State { ), AppSpaces.verticalSmall, CustomTextFieldForm( + readOnly: widget.isView, hintText: 'Enter Delivery Note', initialValue: viewModel.cashierOrder.deliveryNotes ?? '', onChanged: (String value) { @@ -830,13 +821,16 @@ class _EditOrderVCState extends State { icon: Icons.arrow_drop_down, heading: item.name.isEmpty ? 'Choose' : item.name, onPressed: () { - showSheet(position, i); + 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) { @@ -847,6 +841,7 @@ class _EditOrderVCState extends State { getItemQuantityWidget(int position, int i) { return CustomTextFieldForm( + readOnly: widget.isView, hintText: 'Enter item quantity', keyboardType: TextInputType.number, initialValue: viewModel.itemQuantityController[position][i], @@ -858,6 +853,7 @@ class _EditOrderVCState extends State { getItemCostPriceWidget(int position, int i) { return CustomTextFieldForm( + readOnly: widget.isView, hintText: 'Enter item price', keyboardType: TextInputType.number, initialValue: viewModel.itemCostPriceController[position][i], diff --git a/lib/application/views/transactions/ReturnTransactionInvoiceVC.dart b/lib/application/views/transactions/views/ReturnTransactionInvoiceVC.dart similarity index 99% rename from lib/application/views/transactions/ReturnTransactionInvoiceVC.dart rename to lib/application/views/transactions/views/ReturnTransactionInvoiceVC.dart index 79c33c3..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'; @@ -44,7 +45,7 @@ class _ReturnTransactionInvoiceVCState 'Damage' ]; - var viewModel = InventoryViewModel(); + var viewModel = WosulRepository(); List filteredInvoices = []; @@ -72,9 +73,7 @@ class _ReturnTransactionInvoiceVCState child: Column( children: [ _isFirstLoadRunning - ? const Center( - child: CircularProgressIndicator(), - ) + ? AppLoader() : filteredInvoices.isEmpty ? const EmptyDataWidget() : Column( @@ -455,7 +454,7 @@ class _ReturnTransactionInvoiceVCState position] .status! .toString(), - style: const TextStyle( + style: TextStyle( fontFamily: MyFonts.Bold, fontWeight: @@ -729,7 +728,7 @@ class _ReturnTransactionInvoiceVCState child: Text( filteredInvoices[position] .status!, - style: const TextStyle( + style: TextStyle( fontStyle: FontStyle.normal, fontFamily: diff --git a/lib/application/views/transactions/views/TransactionCashierVC.dart b/lib/application/views/transactions/views/TransactionCashierVC.dart new file mode 100644 index 0000000..1484d33 --- /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/CashierOrderHistory.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 e56a092..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'; @@ -44,7 +44,7 @@ class _TransactionDamageInvoiceVCState 'Damage' ]; - var viewModel = InventoryViewModel(); + var viewModel = WosulRepository(); List filteredInvoices = []; 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 99% rename from lib/application/views/transactions/TransactionQuotationVC.dart rename to lib/application/views/transactions/views/TransactionQuotationVC.dart index 6ceeafc..2bce680 100644 --- a/lib/application/views/transactions/TransactionQuotationVC.dart +++ b/lib/application/views/transactions/views/TransactionQuotationVC.dart @@ -13,7 +13,7 @@ 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; @@ -211,7 +211,7 @@ class _TransactionQuotationVCState const SizedBox( width: 10, ), - Container( + SizedBox( width: 46, child: Text( AppLocalizations.of(widget.context)!.action, @@ -400,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, @@ -594,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, diff --git a/lib/application/views/transactions/views/ViewCashierTransactionVC.dart b/lib/application/views/transactions/views/ViewCashierTransactionVC.dart new file mode 100644 index 0000000..744d383 --- /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/CashierOrderHistory.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/ViewPOSReturnVC.dart b/lib/application/views/transactions/views/ViewPOSReturnVC.dart similarity index 97% rename from lib/application/views/transactions/ViewPOSReturnVC.dart rename to lib/application/views/transactions/views/ViewPOSReturnVC.dart index 9a9b2ab..95f63fd 100644 --- a/lib/application/views/transactions/ViewPOSReturnVC.dart +++ b/lib/application/views/transactions/views/ViewPOSReturnVC.dart @@ -23,13 +23,8 @@ class _ViewPOSReturnVCState extends State { @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) { + return Scaffold( + body: OrientationBuilder(builder: (c, orientation) { isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; return SingleChildScrollView( diff --git a/lib/application/views/transactions/widgets/CashierOrderListView.dart b/lib/application/views/transactions/widgets/CashierOrderListView.dart index f1ff979..90edb21 100644 --- a/lib/application/views/transactions/widgets/CashierOrderListView.dart +++ b/lib/application/views/transactions/widgets/CashierOrderListView.dart @@ -6,6 +6,7 @@ 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'; @@ -104,7 +105,6 @@ class CashierOrderListView extends StatelessWidget { CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ - AppSpaces.verticalMedium, HeadingText( 'Reference Number', ), @@ -130,6 +130,7 @@ class CashierOrderListView extends StatelessWidget { ), AppSpaces.verticalMedium, HeadingText(lang(context).updated_on), + AppSpaces.verticalMedium, ], )), Expanded( @@ -146,6 +147,7 @@ class CashierOrderListView extends StatelessWidget { ValueText( posOrders[position].transactionId ?? '', ), + AppSpaces.verticalMedium, ValueText( posOrders[position] .uniqueId! @@ -156,8 +158,14 @@ class CashierOrderListView extends StatelessWidget { posOrders[position].storeId!.name ?? '', ), AppSpaces.verticalMedium, - ValueText( - posOrders[position].status ?? '', + Text( + posOrders[position] + .status! + .toCapitalized(), + style: posOrders[position].status == + 'completed' + ? ThemeText.textStyleValueGreen + : ThemeText.textStyleValueRed, ), AppSpaces.verticalMedium, ValueText( @@ -168,20 +176,13 @@ class CashierOrderListView extends StatelessWidget { AppSpaces.verticalMedium, ValueText(DataTimeFormat.getFormatDate( posOrders[position].updatedAt ?? '')), + AppSpaces.verticalMedium, ], )), ], ), )), - PopupMenuButton( - icon: const Icon(Icons.more_vert), - itemBuilder: (c) { - return getPopUpMenuButton(); - }, - onSelected: (String value) => - actionPopUpItemSelected( - value, posOrders[position]), - ) + getPopUpMenu(position) ], ), ), @@ -191,10 +192,7 @@ class CashierOrderListView 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( @@ -235,15 +233,7 @@ class CashierOrderListView extends StatelessWidget { child: Align( alignment: Alignment.centerRight, child: ActionPopUpContainer( - child: PopupMenuButton( - icon: const Icon(Icons.more_vert), - itemBuilder: (c) { - return getPopUpMenuButton(); - }, - onSelected: (String value) => - actionPopUpItemSelected( - value, posOrders[position]), - ), + child: getPopUpMenu(position), ), ), ) @@ -259,13 +249,9 @@ class CashierOrderListView extends StatelessWidget { ); } - List> getPopUpMenuButton() { - if (isOrder!) { + List> getPopUpMenuButton(String? status) { + if (isOrder! && status! == 'completed') { return [ - PopupMenuItem( - value: 'edit', - child: ValueText('Edit'), - ), PopupMenuItem( value: 'return', child: ValueText('Return'), @@ -274,25 +260,11 @@ class CashierOrderListView extends StatelessWidget { value: 'damage', child: ValueText('Damage'), ), - PopupMenuItem( - value: 'delete', - child: ValueText('Delete'), - ), - PopupMenuItem( - value: 'view', - child: ValueText('View'), - ), ]; + } else if (isOrder! && status! == 'cancelled') { + return []; } else { return [ - PopupMenuItem( - value: 'return', - child: ValueText('Return'), - ), - PopupMenuItem( - value: 'damage', - child: ValueText('Damage'), - ), PopupMenuItem( value: 'view', child: ValueText('View'), @@ -314,4 +286,12 @@ class CashierOrderListView extends StatelessWidget { 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/TransactionCashierOrderListView.dart b/lib/application/views/transactions/widgets/TransactionCashierOrderListView.dart new file mode 100644 index 0000000..849cff6 --- /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/CashierOrderHistory.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/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/ThemeDropDown.dart b/lib/helpers/ThemeDropDown.dart index de096b2..ab95359 100644 --- a/lib/helpers/ThemeDropDown.dart +++ b/lib/helpers/ThemeDropDown.dart @@ -1,6 +1,7 @@ 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 { @@ -38,6 +39,13 @@ abstract class ThemeDropDown { ); static DropdownButtonProps dropdownButtonProps = const DropdownButtonProps( - padding: EdgeInsets.only(left: 0, right: 4), + 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/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 d3c3d03..25f1f64 100644 --- a/lib/helpers/ThemeText.dart +++ b/lib/helpers/ThemeText.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:sizer/sizer.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/theme/MyFonts.dart'; @@ -31,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, @@ -65,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); @@ -85,23 +92,23 @@ 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); @@ -120,6 +127,11 @@ abstract class ThemeText { 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, @@ -141,7 +153,7 @@ abstract class ThemeText { fontWeight: FontWeight.w100, color: MyColors.fillRed); - static const TextStyle textStyleImageHeading = TextStyle( + static TextStyle textStyleImageHeading = TextStyle( fontSize: MyFonts.normalButton, fontWeight: FontWeight.w600, fontFamily: MyFonts.Medium, @@ -153,25 +165,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); @@ -181,29 +193,46 @@ 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.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 const TextStyle textStyleAmountHeading = TextStyle( + static TextStyle textStyleAmountHeading = TextStyle( fontFamily: MyFonts.Bold, fontWeight: FontWeight.bold, fontSize: MyFonts.normalButton, color: MyColors.textColorBlack); - static const TextStyle textStyleAmountValue = TextStyle( + static TextStyle textStyleAmountValue = TextStyle( fontFamily: MyFonts.Bold, fontWeight: FontWeight.bold, fontSize: MyFonts.normalButton, - color: MyColors.textColorBlack20); + 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, @@ -211,7 +240,7 @@ abstract class ThemeText { fontFamily: MyFonts.Bold, color: MyColors.blueThemeColor); - static TextStyle unSelectedTabLabelStyle = const TextStyle( + static TextStyle unSelectedTabLabelStyle = TextStyle( fontSize: MyFonts.normalButton, fontWeight: FontWeight.w500, fontFamily: MyFonts.Medium, 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/objectbox-model.json b/lib/objectbox-model.json index 5c0237a..9f5a1f1 100644 --- a/lib/objectbox-model.json +++ b/lib/objectbox-model.json @@ -5,7 +5,7 @@ "entities": [ { "id": "1:6932070486419484075", - "lastPropertyId": "33:3192907363118089052", + "lastPropertyId": "45:7417376017248106046", "name": "AddIngredient", "properties": [ { @@ -173,6 +173,66 @@ "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": [] @@ -389,7 +449,7 @@ }, { "id": "4:8500243175982317727", - "lastPropertyId": "8:5336083002345932458", + "lastPropertyId": "9:1843248315901556109", "name": "DeliveryPartner", "properties": [ { @@ -432,6 +492,11 @@ "id": "8:5336083002345932458", "name": "stores", "type": 30 + }, + { + "id": "9:1843248315901556109", + "name": "totalItemCount", + "type": 6 } ], "relations": [] @@ -670,7 +735,7 @@ }, { "id": "9:6750695338800619948", - "lastPropertyId": "7:5534011194632221070", + "lastPropertyId": "9:3549302534716425338", "name": "ModifierOption", "properties": [ { @@ -708,9 +773,25 @@ "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", @@ -1216,7 +1297,7 @@ ], "lastEntityId": "15:1489637104339473454", "lastIndexId": "2:697578080641452147", - "lastRelationId": "12:5672312728119666494", + "lastRelationId": "13:3946042636854669420", "lastSequenceId": "0:0", "modelVersion": 5, "modelVersionParserMinimum": 5, diff --git a/lib/objectbox.g.dart b/lib/objectbox.g.dart index b615dff..59cb63c 100644 --- a/lib/objectbox.g.dart +++ b/lib/objectbox.g.dart @@ -36,7 +36,7 @@ final _entities = [ ModelEntity( id: const IdUid(1, 6932070486419484075), name: 'AddIngredient', - lastPropertyId: const IdUid(33, 3192907363118089052), + lastPropertyId: const IdUid(45, 7417376017248106046), flags: 0, properties: [ ModelProperty( @@ -203,6 +203,66 @@ final _entities = [ 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: [], @@ -419,7 +479,7 @@ final _entities = [ ModelEntity( id: const IdUid(4, 8500243175982317727), name: 'DeliveryPartner', - lastPropertyId: const IdUid(8, 5336083002345932458), + lastPropertyId: const IdUid(9, 1843248315901556109), flags: 0, properties: [ ModelProperty( @@ -461,6 +521,11 @@ final _entities = [ id: const IdUid(8, 5336083002345932458), name: 'stores', type: 30, + flags: 0), + ModelProperty( + id: const IdUid(9, 1843248315901556109), + name: 'totalItemCount', + type: 6, flags: 0) ], relations: [], @@ -698,7 +763,7 @@ final _entities = [ ModelEntity( id: const IdUid(9, 6750695338800619948), name: 'ModifierOption', - lastPropertyId: const IdUid(7, 5534011194632221070), + lastPropertyId: const IdUid(9, 3549302534716425338), flags: 0, properties: [ ModelProperty( @@ -735,9 +800,24 @@ final _entities = [ 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), @@ -1266,7 +1346,7 @@ ModelDefinition getObjectBoxModel() { entities: _entities, lastEntityId: const IdUid(15, 1489637104339473454), lastIndexId: const IdUid(2, 697578080641452147), - lastRelationId: const IdUid(12, 5672312728119666494), + lastRelationId: const IdUid(13, 3946042636854669420), lastSequenceId: const IdUid(0, 0), retiredEntityUids: const [], retiredIndexUids: const [697578080641452147], @@ -1327,7 +1407,7 @@ ModelDefinition getObjectBoxModel() { final measuringUnitOffset = fbb.writeString(object.measuringUnit); final idOffset = fbb.writeString(object.id); final quantityOffset = fbb.writeString(object.quantity); - fbb.startTable(34); + fbb.startTable(46); fbb.addInt64(0, object.obid); fbb.addOffset(1, nameOffset); fbb.addOffset(2, descriptionOffset); @@ -1361,6 +1441,18 @@ ModelDefinition getObjectBoxModel() { 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; }, @@ -1376,6 +1468,12 @@ ModelDefinition getObjectBoxModel() { .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) @@ -1384,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, ''); @@ -1410,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) @@ -1446,11 +1562,20 @@ ModelDefinition getObjectBoxModel() { 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, @@ -1461,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, @@ -1726,7 +1854,7 @@ ModelDefinition getObjectBoxModel() { ? null : fbb.writeList( object.stores!.map(fbb.writeString).toList(growable: false)); - fbb.startTable(9); + fbb.startTable(10); fbb.addInt64(0, object.obid); fbb.addOffset(1, idOffset); fbb.addOffset(2, nameOffset); @@ -1735,6 +1863,7 @@ ModelDefinition getObjectBoxModel() { fbb.addOffset(5, createdAtOffset); fbb.addOffset(6, updatedAtOffset); fbb.addOffset(7, storesOffset); + fbb.addInt64(8, object.totalItemCount); fbb.finish(fbb.endTable()); return object.obid; }, @@ -1757,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, @@ -1764,7 +1895,8 @@ 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; @@ -2037,7 +2169,10 @@ ModelDefinition getObjectBoxModel() { ModifierOption: EntityDefinition( 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; @@ -2046,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); @@ -2054,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; }, @@ -2062,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 = @@ -2075,13 +2219,17 @@ 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( @@ -2814,6 +2962,54 @@ class AddIngredient_ { /// 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. @@ -3007,6 +3203,10 @@ class DeliveryPartner_ { /// see [DeliveryPartner.stores] static final stores = QueryStringVectorProperty(_entities[3].properties[7]); + + /// see [DeliveryPartner.totalItemCount] + static final totalItemCount = + QueryIntegerProperty(_entities[3].properties[8]); } /// [ItemCategory] entity fields to define ObjectBox queries. @@ -3204,6 +3404,18 @@ class ModifierOption_ { /// see [ModifierOption.qtyIdx] static final qtyIdx = 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. diff --git a/lib/widgets/ActionPopUpContainer.dart b/lib/widgets/ActionPopUpContainer.dart index 92c5369..64593f1 100644 --- a/lib/widgets/ActionPopUpContainer.dart +++ b/lib/widgets/ActionPopUpContainer.dart @@ -9,8 +9,8 @@ class ActionPopUpContainer extends StatelessWidget { @override Widget build(BuildContext context) { return Container( - width: 42, - height: 42, + width: 38, + height: 38, decoration: BoxDecoration( borderRadius: const BorderRadius.all(Radius.circular(4)), color: MyColors.backFillColor), diff --git a/lib/widgets/BackButtonWidget.dart b/lib/widgets/BackButtonWidget.dart index 4f815f5..dfb4e8b 100644 --- a/lib/widgets/BackButtonWidget.dart +++ b/lib/widgets/BackButtonWidget.dart @@ -15,12 +15,12 @@ class BackButtonWidget extends StatelessWidget { child: ElevatedButton.icon( onPressed: onPressed, icon: const Icon( - size: 16, + size: 14, Icons.arrow_back_ios, color: MyColors.textColorBlack, ), label: Text( - lang(context)!.back, + lang(context).back, style: const TextStyle( color: MyColors.textColorBlack, fontFamily: MyFonts.Medium, 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/CustomAddButton.dart b/lib/widgets/CustomAddButton.dart index aa7e443..9f1ceb2 100644 --- a/lib/widgets/CustomAddButton.dart +++ b/lib/widgets/CustomAddButton.dart @@ -16,7 +16,7 @@ class CustomAddButton extends StatelessWidget { Widget build(BuildContext context) { return Center( child: Container( - margin: const EdgeInsets.all(5), + margin: const EdgeInsets.all(6), width: 32, height: 32, decoration: BoxDecoration( diff --git a/lib/widgets/CustomCheckBox.dart b/lib/widgets/CustomCheckBox.dart index 62fc8cd..f38bad2 100644 --- a/lib/widgets/CustomCheckBox.dart +++ b/lib/widgets/CustomCheckBox.dart @@ -14,14 +14,23 @@ class CustomCheckBox extends StatelessWidget { @override Widget build(BuildContext context) { return Row(mainAxisAlignment: MainAxisAlignment.end, children: [ - SizedBox( + 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, 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/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 213def8..b699ba1 100644 --- a/lib/widgets/CustomTextButtonIcon.dart +++ b/lib/widgets/CustomTextButtonIcon.dart @@ -14,7 +14,7 @@ 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}); @@ -33,7 +33,7 @@ class CustomTextButtonIcon extends StatelessWidget { color: Colors.transparent, width: 1, ), - color: backgroundColor, + color: backgroundColor ?? MyColors.backFillColor, borderRadius: BorderRadius.circular(8.0), ), child: Row( @@ -48,7 +48,7 @@ class CustomTextButtonIcon extends StatelessWidget { child: Text( heading, textAlign: TextAlign.left, - style: const TextStyle( + style: TextStyle( fontFamily: MyFonts.DMREGULAR, fontSize: MyFonts.normal, color: MyColors.black), 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 9bffb54..62eb175 100644 --- a/lib/widgets/CustomTextFieldForm.dart +++ b/lib/widgets/CustomTextFieldForm.dart @@ -1,6 +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 CustomTextFieldForm extends StatelessWidget { CustomTextFieldForm( @@ -26,26 +26,20 @@ class CustomTextFieldForm extends StatelessWidget { @override Widget build(BuildContext context) { return TextFormField( - // style: ThemeText.textStyleValue, textAlignVertical: TextAlignVertical.center, readOnly: readOnly, keyboardType: keyboardType, initialValue: initialValue, maxLines: maxLines, - style: const TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normal, - color: MyColors.black), + style: ThemeText.textFliedStyleValue, decoration: InputDecoration( constraints: BoxConstraints(maxHeight: height), - fillColor: readOnly ? MyColors.disableColor : MyColors.backFillColor, filled: true, border: InputBorder.none, - // labelStyle: ThemeText.labelStyleTextField, - // hintStyle: ThemeText.labelStyleTextField, hintText: hintText, - isDense: true, // + isDense: true, + // focusedBorder: OutlineInputBorder( borderSide: const BorderSide(color: MyColors.textColorGray, width: 0.5), diff --git a/lib/widgets/CustomTextFieldPassword.dart b/lib/widgets/CustomTextFieldPassword.dart index 2b663c9..9dcbb7c 100644 --- a/lib/widgets/CustomTextFieldPassword.dart +++ b/lib/widgets/CustomTextFieldPassword.dart @@ -27,7 +27,7 @@ class CustomTextFieldPassword extends StatelessWidget { flex: 1, child: TextFormField( obscureText: obscure ?? false, - style: const TextStyle( + style: TextStyle( fontFamily: MyFonts.DMREGULAR, fontSize: MyFonts.normal, color: MyColors.black), 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/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 index 70419b7..a912ecd 100644 --- a/lib/widgets/ItemCategoryDropdown.dart +++ b/lib/widgets/ItemCategoryDropdown.dart @@ -16,6 +16,7 @@ class ItemCategoryDropdown extends StatelessWidget { bool isEdit = false; bool showFirst = false; String categoryId = ''; + List items = []; ItemCategoryDropdown({ super.key, @@ -61,7 +62,7 @@ class ItemCategoryDropdown extends StatelessWidget { Future> getCategoriesData() async { var items = []; - + print('called'); await APIManager() .fetchData(Constants.GET_STORE_CATEGORY, Constants.getStorePayload()) .then((value) { diff --git a/lib/widgets/LanguageDropdown.dart b/lib/widgets/LanguageDropdown.dart index d7ddc23..5180bea 100644 --- a/lib/widgets/LanguageDropdown.dart +++ b/lib/widgets/LanguageDropdown.dart @@ -1,32 +1,72 @@ +import 'package:dropdown_search/dropdown_search.dart'; import 'package:flutter/material.dart'; import 'package:wosull/application/language/AppLanguage.dart'; -import 'package:wosull/helpers/ThemeText.dart'; -import 'package:wosull/widgets/HeadingText.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, required this.dropdownValue, required this.onChange}); + {super.key, + this.fillColor, + required this.dropdownValue, + required this.onChange}); @override Widget build(BuildContext context) { - return DropdownButton( - value: dropdownValue, - iconSize: 12, - style: ThemeText.textStyleHeading, - onChanged: onChange, - underline: DropdownButtonHideUnderline(child: Container()), - items: AppLanguage.languages() - .map>( - (e) => DropdownMenuItem( - value: e, - child: HeadingText( - e.name, - )), - ) - .toList(), + 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/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 index e67780f..1c4fa49 100644 --- a/lib/widgets/PageLimitDropDown.dart +++ b/lib/widgets/PageLimitDropDown.dart @@ -1,46 +1,95 @@ 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/ThemePadding.dart'; import 'package:wosull/helpers/ThemeText.dart'; class PageLimitDropdown extends StatelessWidget { - final void Function(String? language) onChange; + final void Function(String? limit) onChange; + String? value; - const PageLimitDropdown({super.key, required this.onChange}); + PageLimitDropdown({super.key, this.value, required this.onChange}); @override Widget build(BuildContext context) { - return Row( - mainAxisAlignment: MainAxisAlignment.end, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Text( - 'Show', - style: ThemeText.textStyleValue, - ), - AppSpaces.horizontalSmall, - SizedBox( - width: 100, - child: DropdownSearch( - popupProps: const PopupProps.menu( - constraints: BoxConstraints(maxHeight: 220)), - items: Constants.pageLimits, - itemAsString: (String u) => u, - onChanged: onChange, - dropdownDecoratorProps: const DropDownDecoratorProps( - baseStyle: ThemeText.textStyleValue, - textAlignVertical: TextAlignVertical.center, - dropdownSearchDecoration: InputDecoration( - labelStyle: ThemeText.textStyleValue, - hintStyle: ThemeText.textStyleValue, - border: InputBorder.none, - hintText: 'Page Limit', - ), - ), + 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: 90, + child: DropdownSearch( + dropdownButtonProps: ThemeDropDown.dropdownButtonProps, + popupProps: PopupProps.menu( + menuProps: ThemeDropDown.menuProps, + fit: FlexFit.loose, + 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 index a76007a..83ec835 100644 --- a/lib/widgets/PortraitContainer.dart +++ b/lib/widgets/PortraitContainer.dart @@ -7,13 +7,13 @@ class PortraitContainer extends StatelessWidget { double? height; PortraitContainer( - {super.key, required this.child, this.width = 44, this.height = 48}); + {super.key, required this.child, this.width = 44, this.height = 58}); @override Widget build(BuildContext context) { return Container( width: width, - height: 48, + height: height, padding: const EdgeInsets.all(4), decoration: const BoxDecoration( border: Border( 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 3ed22fb..44c94ee 100644 --- a/lib/widgets/SearchBox.dart +++ b/lib/widgets/SearchBox.dart @@ -27,7 +27,7 @@ class SearchBox extends StatelessWidget { onEditingDone(searchController.text); }, onChanged: onChanged, - style: const TextStyle( + style: TextStyle( fontFamily: MyFonts.DMREGULAR, fontSize: MyFonts.normal, color: MyColors.black), diff --git a/pubspec.lock b/pubspec.lock index d591f62..7cf0a89 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -217,6 +217,14 @@ packages: url: "https://pub.dev" source: hosted 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: diff --git a/pubspec.yaml b/pubspec.yaml index ee8b481..6e3658b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -69,6 +69,7 @@ dependencies: pdf: ^3.10.4 screenshot: ^2.1.0 android_path_provider: ^0.3.0 + cross_scroll: ^0.0.76 dev_dependencies: flutter_test: sdk: flutter From 675025c10dd00e0523f89a2f58c7d593b6a77fb1 Mon Sep 17 00:00:00 2001 From: waqasYeepeey Date: Fri, 13 Oct 2023 16:06:38 +0500 Subject: [PATCH 07/11] 'reformat reports' --- .../interfaces/DrawerWidgetSelect.dart | 2 +- .../model/reports/CashierOrder.dart | 107 ++++ .../model/reports/CashierOrderHistory.dart | 151 +----- .../reports/CashierSingleOrderHistory.dart | 16 + .../reports/SearchCashierOrderHistory.dart | 18 + .../model/reports/TopOrderItemsModel.dart | 44 +- lib/application/theme/MyColors.dart | 6 + lib/application/utils/AppError.dart | 1 - lib/application/utils/Constants.dart | 14 + .../authModule/checkinViews/CheckInPopUp.dart | 2 - .../views/TransactionPOSReturnVC.dart | 1 - .../views/TransactionPosDamageVC.dart | 1 - .../create_order_module/HoldOrderVC.dart | 1 - .../views/PrintReceiptVC.dart | 4 +- .../views/TabBarHomeVC.dart | 4 +- .../views/popups/DineInPopup.dart | 1 - .../views/popups/ItemModifiersPopUp.dart | 1 - .../views/popups/PaymentOptionPopUpVC.dart | 16 +- lib/application/views/dashboard/HomeVC.dart | 2 +- .../InventoryCategoriesModule.dart | 1 - .../viewModels/CategoryViewModel.dart | 3 - .../comboviews/CreateComboGroupVC.dart | 1 - .../inventoryAddDeliveryPriceVC.dart | 1 - .../InventoryNewStockTransferVC.dart | 1 - .../InventorySubCategoryVC.dart | 1 - .../viewmodel/ProductViewModel.dart | 27 +- .../views/table/KitchenNewTableVC.dart | 2 - .../views/ordersModule/OrderVC.dart | 2 +- .../viewModel/OrderViewModel.dart | 4 +- .../ordersModule/views/OrderCashierVC.dart | 2 +- lib/application/views/settings/ReportsVC.dart | 43 +- .../settings/repo/ReportsRepository.dart | 67 +++ .../reportsViews/BestSuppliersVC.dart | 165 +----- .../settings/reportsViews/POSCompleteVC.dart | 207 +------- .../reportsViews/POSReturnOrderVC.dart | 160 +----- .../reportsViews/ReportsCategoryVC.dart | 283 ++-------- .../reportsViews/ReportsInvoiceVC.dart | 424 +-------------- .../reportsViews/ReportsProductsVC.dart | 298 ++--------- .../reportsViews/ReportsQuotationVC.dart | 502 ++---------------- .../viewModels/BestSupplierViewModel.dart | 17 +- .../viewModels/POSCompleteViewModel.dart | 17 +- .../viewModels/ReportsInvoiceViewModel.dart | 71 --- .../settings/viewModels/ReportsViewModel.dart | 7 + .../widgets/BestSupplierListView.dart | 152 ++++++ .../settings/widgets/POSCompleteListView.dart | 207 ++++++++ .../widgets/POSReturnOrderListView.dart | 144 +++++ .../widgets/ReportsCategoryListView.dart | 171 ++++++ .../widgets/ReportsInvoiceListView.dart | 336 ++++++++++++ .../widgets/ReportsProductListView.dart | 172 ++++++ .../widgets/ReportsQuotationListView.dart | 330 ++++++++++++ .../views/transactions/TransactionVC.dart | 2 +- .../views/transactions/return/ReturnPOS.dart | 2 +- .../CashierTransactionViewModel.dart | 1 + .../viewmodels/ReturnPOSOrderVM.dart | 3 +- .../views/transactions/views/EditOrderVC.dart | 2 +- .../views/TransactionCashierVC.dart | 2 +- .../views/ViewCashierTransactionVC.dart | 2 +- .../widgets/CashierOrderListView.dart | 2 +- .../widgets/EditOrderViewModel.dart | 4 +- .../TransactionCashierOrderListView.dart | 2 +- lib/helpers/ThemeText.dart | 11 +- 61 files changed, 2014 insertions(+), 2229 deletions(-) create mode 100644 lib/application/model/reports/CashierOrder.dart create mode 100644 lib/application/model/reports/CashierSingleOrderHistory.dart create mode 100644 lib/application/model/reports/SearchCashierOrderHistory.dart create mode 100644 lib/application/views/settings/repo/ReportsRepository.dart delete mode 100644 lib/application/views/settings/viewModels/ReportsInvoiceViewModel.dart create mode 100644 lib/application/views/settings/widgets/BestSupplierListView.dart create mode 100644 lib/application/views/settings/widgets/POSCompleteListView.dart create mode 100644 lib/application/views/settings/widgets/POSReturnOrderListView.dart create mode 100644 lib/application/views/settings/widgets/ReportsCategoryListView.dart create mode 100644 lib/application/views/settings/widgets/ReportsInvoiceListView.dart create mode 100644 lib/application/views/settings/widgets/ReportsProductListView.dart create mode 100644 lib/application/views/settings/widgets/ReportsQuotationListView.dart 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/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 9cf24df..ade7ad0 100644 --- a/lib/application/model/reports/CashierOrderHistory.dart +++ b/lib/application/model/reports/CashierOrderHistory.dart @@ -1,157 +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 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() - : []); - } -} - -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; - 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/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/theme/MyColors.dart b/lib/application/theme/MyColors.dart index ab11569..178e5c8 100644 --- a/lib/application/theme/MyColors.dart +++ b/lib/application/theme/MyColors.dart @@ -63,6 +63,12 @@ class MyColors { 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); diff --git a/lib/application/utils/AppError.dart b/lib/application/utils/AppError.dart index 8527888..14d3e7a 100644 --- a/lib/application/utils/AppError.dart +++ b/lib/application/utils/AppError.dart @@ -9,7 +9,6 @@ class AppError extends StatelessWidget { @override Widget build(BuildContext context) { - // TODO: implement build return Container( height: 42, margin: const EdgeInsets.only(top: 16), diff --git a/lib/application/utils/Constants.dart b/lib/application/utils/Constants.dart index beac531..9d06e84 100644 --- a/lib/application/utils/Constants.dart +++ b/lib/application/utils/Constants.dart @@ -233,6 +233,10 @@ class Constants { static const completed = "completed"; static const cancelled = "cancelled"; + static const dineIn = "dinein"; + static const takeAway = "takeaway"; + static const deliveryPartner = "deliverypartner"; + static const invoiceFilterType = [ 'All', 'Open', @@ -242,6 +246,16 @@ class Constants { 'Return' ]; + static const reportsTypes = [ + 'Best Seller', + 'POS Complete', + 'POS Return & Damage', + 'Invoices', + 'Quotations', + 'Categories', + 'Products' + ]; + static const appliedTypes = [ 'allStores', 'specificStore', diff --git a/lib/application/views/authModule/checkinViews/CheckInPopUp.dart b/lib/application/views/authModule/checkinViews/CheckInPopUp.dart index fc53949..c534bb4 100644 --- a/lib/application/views/authModule/checkinViews/CheckInPopUp.dart +++ b/lib/application/views/authModule/checkinViews/CheckInPopUp.dart @@ -29,13 +29,11 @@ class _CheckInPopUpState extends BaseStatefulState { @override void initState() { - // TODO: implement initState super.initState(); } @override void dispose() { - // TODO: implement dispose super.dispose(); viewModel.disposeData(); } diff --git a/lib/application/views/businessAccounts/views/TransactionPOSReturnVC.dart b/lib/application/views/businessAccounts/views/TransactionPOSReturnVC.dart index 45258e5..e7e1484 100644 --- a/lib/application/views/businessAccounts/views/TransactionPOSReturnVC.dart +++ b/lib/application/views/businessAccounts/views/TransactionPOSReturnVC.dart @@ -30,7 +30,6 @@ class _TransactionPOSReturnVCState @override void initState() { - // TODO: implement initState super.initState(); } diff --git a/lib/application/views/businessAccounts/views/TransactionPosDamageVC.dart b/lib/application/views/businessAccounts/views/TransactionPosDamageVC.dart index c48667e..067182a 100644 --- a/lib/application/views/businessAccounts/views/TransactionPosDamageVC.dart +++ b/lib/application/views/businessAccounts/views/TransactionPosDamageVC.dart @@ -31,7 +31,6 @@ class _TransactionPosDamageVCState @override void initState() { - // TODO: implement initState super.initState(); } diff --git a/lib/application/views/create_order_module/HoldOrderVC.dart b/lib/application/views/create_order_module/HoldOrderVC.dart index 5f82167..2a38dc0 100644 --- a/lib/application/views/create_order_module/HoldOrderVC.dart +++ b/lib/application/views/create_order_module/HoldOrderVC.dart @@ -29,7 +29,6 @@ class _HoldOrderVCState extends BaseStatefulState { @override void initState() { - // TODO: implement initState super.initState(); } diff --git a/lib/application/views/create_order_module/views/PrintReceiptVC.dart b/lib/application/views/create_order_module/views/PrintReceiptVC.dart index 68bf432..84bcc21 100644 --- a/lib/application/views/create_order_module/views/PrintReceiptVC.dart +++ b/lib/application/views/create_order_module/views/PrintReceiptVC.dart @@ -553,7 +553,7 @@ class _PrintReceiptVCState extends State { ], ), Visibility( - visible: orderCompleted, + visible: !orderCompleted, child: getDoneButton(), ) ], @@ -573,7 +573,7 @@ class _PrintReceiptVCState extends State { ), AppSpaces.horizontalSmall, Visibility( - visible: orderCompleted, + visible: !orderCompleted, child: SizedBox( width: 90, child: getDoneButton(), diff --git a/lib/application/views/create_order_module/views/TabBarHomeVC.dart b/lib/application/views/create_order_module/views/TabBarHomeVC.dart index 7def1a6..940ab96 100644 --- a/lib/application/views/create_order_module/views/TabBarHomeVC.dart +++ b/lib/application/views/create_order_module/views/TabBarHomeVC.dart @@ -1030,13 +1030,13 @@ class _TabBarHomeVCState extends BaseStatefulState { .toString() .replaceAll(' ', '') .toLowerCase() == - 'dinein') { + Constants.dineIn) { showDineInTable(); } else if (viewModel.services[i].name .toString() .replaceAll(' ', '') .toLowerCase() == - 'deliverypartner') { + Constants.deliveryPartner) { showDeliveryPartners(); } else { await viewModel.checkLastSelectedService(); 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 fa0b8ff..c7ad48e 100644 --- a/lib/application/views/create_order_module/views/popups/DineInPopup.dart +++ b/lib/application/views/create_order_module/views/popups/DineInPopup.dart @@ -34,7 +34,6 @@ class _DineInPopupState extends State { @override void initState() { - // TODO: implement initState super.initState(); if (isConnected) { getTables(selectedItem); 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 ecfb4b6..1c09971 100644 --- a/lib/application/views/create_order_module/views/popups/ItemModifiersPopUp.dart +++ b/lib/application/views/create_order_module/views/popups/ItemModifiersPopUp.dart @@ -32,7 +32,6 @@ class _ItemModifiersPopUpState extends State { @override void initState() { - // TODO: implement initState super.initState(); setState(() { 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 f074bd2..747eb24 100644 --- a/lib/application/views/create_order_module/views/popups/PaymentOptionPopUpVC.dart +++ b/lib/application/views/create_order_module/views/popups/PaymentOptionPopUpVC.dart @@ -43,14 +43,12 @@ class _PaymentOptionPopUpVCState @override void initState() { - // TODO: implement initState super.initState(); context.read().setAmountValue(widget.cartAmount); } @override void dispose() { - // TODO: implement dispose viewModel.disposeData(); super.dispose(); } @@ -732,16 +730,16 @@ class _PaymentOptionPopUpVCState : MyColors.greenColorDisable, onPressed: () async { var result = await viewModel.sendOrder(widget.status); - Navigator.pop(context, result); + checkState(result); }, - heading: widget.status == "ready" + heading: widget.status == Constants.ready ? AppLocalizations.of(context)!.done : AppLocalizations.of(context)!.send_to_kitchen, ), - viewModel.isCash && widget.status != Constants.ready + widget.status != Constants.ready ? AppSpaces.verticalMedium : Container(), - viewModel.isCash && widget.status != Constants.ready + widget.status != Constants.ready ? CustomSimpleButton( height: 48, radius: 24, @@ -751,7 +749,7 @@ class _PaymentOptionPopUpVCState : MyColors.greenColorDisable, onPressed: () async { var result = await viewModel.sendOrder(Constants.ready); - Navigator.pop(context, result); + checkState(result); }, heading: AppLocalizations.of(context)!.completed, ) @@ -973,4 +971,8 @@ class _PaymentOptionPopUpVCState ), )); } + + void checkState(result) { + Navigator.pop(context, result); + } } diff --git a/lib/application/views/dashboard/HomeVC.dart b/lib/application/views/dashboard/HomeVC.dart index f265834..1491481 100644 --- a/lib/application/views/dashboard/HomeVC.dart +++ b/lib/application/views/dashboard/HomeVC.dart @@ -4,7 +4,7 @@ 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'; diff --git a/lib/application/views/inventorymodule/categoryviews/InventoryCategoriesModule.dart b/lib/application/views/inventorymodule/categoryviews/InventoryCategoriesModule.dart index fa60cd2..9152778 100644 --- a/lib/application/views/inventorymodule/categoryviews/InventoryCategoriesModule.dart +++ b/lib/application/views/inventorymodule/categoryviews/InventoryCategoriesModule.dart @@ -38,7 +38,6 @@ class _InventoryCategoriesModuleState @override void dispose() { - // TODO: implement dispose categoryViewModel.disposeData(); super.dispose(); } diff --git a/lib/application/views/inventorymodule/categoryviews/viewModels/CategoryViewModel.dart b/lib/application/views/inventorymodule/categoryviews/viewModels/CategoryViewModel.dart index 4b107a9..a5455e0 100644 --- a/lib/application/views/inventorymodule/categoryviews/viewModels/CategoryViewModel.dart +++ b/lib/application/views/inventorymodule/categoryviews/viewModels/CategoryViewModel.dart @@ -1,5 +1,3 @@ -import 'dart:convert'; - import 'package:flutter/material.dart'; import 'package:wosull/application/enum/DataState.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; @@ -66,7 +64,6 @@ class CategoryViewModel extends ChangeNotifier { 'page': _currentPageNumber, 'limit': this.limit }; - print(jsonEncode(data)); try { if (_didLastLoad) { _dataState = DataState.noMoreData; diff --git a/lib/application/views/inventorymodule/comboviews/CreateComboGroupVC.dart b/lib/application/views/inventorymodule/comboviews/CreateComboGroupVC.dart index 7580292..bbd2ef2 100644 --- a/lib/application/views/inventorymodule/comboviews/CreateComboGroupVC.dart +++ b/lib/application/views/inventorymodule/comboviews/CreateComboGroupVC.dart @@ -28,7 +28,6 @@ class _CreateComboGroupVCState extends BaseStatefulState { @override void initState() { - // TODO: implement initState context.read().init(); super.initState(); } diff --git a/lib/application/views/inventorymodule/deliveryPartnerViews/inventoryAddDeliveryPriceVC.dart b/lib/application/views/inventorymodule/deliveryPartnerViews/inventoryAddDeliveryPriceVC.dart index a190a10..7292b56 100644 --- a/lib/application/views/inventorymodule/deliveryPartnerViews/inventoryAddDeliveryPriceVC.dart +++ b/lib/application/views/inventorymodule/deliveryPartnerViews/inventoryAddDeliveryPriceVC.dart @@ -44,7 +44,6 @@ class _InventoryAddDeliveryPriceVCState @override void initState() { - // TODO: implement initState super.initState(); context .read() diff --git a/lib/application/views/inventorymodule/stockTransferViews/InventoryNewStockTransferVC.dart b/lib/application/views/inventorymodule/stockTransferViews/InventoryNewStockTransferVC.dart index 9bf841c..ecd3cd1 100644 --- a/lib/application/views/inventorymodule/stockTransferViews/InventoryNewStockTransferVC.dart +++ b/lib/application/views/inventorymodule/stockTransferViews/InventoryNewStockTransferVC.dart @@ -40,7 +40,6 @@ class _InventoryNewStockTransferVCState @override void dispose() { - // TODO: implement dispose viewModel.disposeData(); super.dispose(); } diff --git a/lib/application/views/inventorymodule/subCategoryViews/InventorySubCategoryVC.dart b/lib/application/views/inventorymodule/subCategoryViews/InventorySubCategoryVC.dart index e19f31c..3b63863 100644 --- a/lib/application/views/inventorymodule/subCategoryViews/InventorySubCategoryVC.dart +++ b/lib/application/views/inventorymodule/subCategoryViews/InventorySubCategoryVC.dart @@ -36,7 +36,6 @@ class _InventorySubCategoryVCState @override void dispose() { - // TODO: implement dispose viewModel.disposeData(); super.dispose(); } diff --git a/lib/application/views/inventorymodule/viewmodel/ProductViewModel.dart b/lib/application/views/inventorymodule/viewmodel/ProductViewModel.dart index da963e3..9702bfe 100644 --- a/lib/application/views/inventorymodule/viewmodel/ProductViewModel.dart +++ b/lib/application/views/inventorymodule/viewmodel/ProductViewModel.dart @@ -2,10 +2,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/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; @@ -13,12 +17,13 @@ class ProductViewModel with ChangeNotifier { bool _didLastLoad = false; int limit = 10; DataState get dataState => _dataState; - List _dataList = []; + List _dataList = []; List get dataList => _dataList; fetchReportsProducts({bool isRefresh = false, int limit = 10}) async { this.limit = limit; + _isLoading = true; if (!isRefresh) { _dataState = (_dataState == DataState.uninitialized) ? DataState.initialFetching @@ -28,7 +33,7 @@ class ProductViewModel with ChangeNotifier { _dataState = DataState.refreshing; } notifyListeners(); - Map data = { + Map map = { 'store_id': sharedPrefs.storeId, 'page': _currentPageNumber, 'is_export': false, @@ -38,29 +43,29 @@ class ProductViewModel with ChangeNotifier { 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 < this.limit) { + 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/table/KitchenNewTableVC.dart b/lib/application/views/kitchenmodule/views/table/KitchenNewTableVC.dart index a79e02e..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(); } diff --git a/lib/application/views/salesandordermodule/views/ordersModule/OrderVC.dart b/lib/application/views/salesandordermodule/views/ordersModule/OrderVC.dart index c0831a1..bf5c087 100644 --- a/lib/application/views/salesandordermodule/views/ordersModule/OrderVC.dart +++ b/lib/application/views/salesandordermodule/views/ordersModule/OrderVC.dart @@ -7,7 +7,7 @@ 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'; diff --git a/lib/application/views/salesandordermodule/views/ordersModule/viewModel/OrderViewModel.dart b/lib/application/views/salesandordermodule/views/ordersModule/viewModel/OrderViewModel.dart index c8c74d6..5542a13 100644 --- a/lib/application/views/salesandordermodule/views/ordersModule/viewModel/OrderViewModel.dart +++ b/lib/application/views/salesandordermodule/views/ordersModule/viewModel/OrderViewModel.dart @@ -3,7 +3,9 @@ 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/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'; @@ -120,7 +122,7 @@ class OrderViewModel with ChangeNotifier { await APIManager() .fetchData(Constants.searchCashier, data) .then((result) { - print(result); + print(result); final value = SearchCashierOrderHistory.fromJson(result); _filteredList.clear(); if (value.success!) { diff --git a/lib/application/views/salesandordermodule/views/ordersModule/views/OrderCashierVC.dart b/lib/application/views/salesandordermodule/views/ordersModule/views/OrderCashierVC.dart index c6ef975..75fc310 100644 --- a/lib/application/views/salesandordermodule/views/ordersModule/views/OrderCashierVC.dart +++ b/lib/application/views/salesandordermodule/views/ordersModule/views/OrderCashierVC.dart @@ -2,7 +2,7 @@ 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/CashierOrderHistory.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'; diff --git a/lib/application/views/settings/ReportsVC.dart b/lib/application/views/settings/ReportsVC.dart index 08c65d0..cfb04b5 100644 --- a/lib/application/views/settings/ReportsVC.dart +++ b/lib/application/views/settings/ReportsVC.dart @@ -8,11 +8,11 @@ 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/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/repository/WosulRepository.dart'; import 'package:wosull/application/theme/MyColors.dart'; +import 'package:wosull/application/utils/Constants.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'; @@ -36,7 +36,6 @@ class ReportsVC extends StatefulWidget { class _ReportsVCState extends BaseStatefulState implements ReportsCVS { - final viewModel = WosulRepository(); bool isPortrait = true; bool isLoading = true; @@ -48,22 +47,12 @@ class _ReportsVCState extends BaseStatefulState List customerData = []; List suppliers = []; - var items = [ - 'Best Seller', - 'POS Complete', - 'POS Return & Damage', - 'Invoices', - 'Quotations', - 'Categories', - 'Products' - ]; String selectedReport = ""; @override void initState() { - // TODO: implement initState super.initState(); - selectedReport = items[0]; + selectedReport = Constants.reportsTypes[0]; } @override @@ -128,19 +117,19 @@ class _ReportsVCState extends BaseStatefulState generateCsv(String name) async { List> data = [[]]; - if (selectedReport == items[0]) { + if (selectedReport == Constants.reportsTypes[0]) { data.clear(); data.add(cvsData); - } else if (selectedReport == items[1]) { + } else if (selectedReport == Constants.reportsTypes[1]) { data.clear(); data.add(completedOrders); - } else if (selectedReport == items[2]) { + } else if (selectedReport == Constants.reportsTypes[2]) { data.clear(); data.add(returnOrder); - } else if (selectedReport == items[3]) { + } else if (selectedReport == Constants.reportsTypes[3]) { data.clear(); data.add(customerData); - } else if (selectedReport == items[4]) { + } else if (selectedReport == Constants.reportsTypes[4]) { data.clear(); data.add(suppliers); } @@ -164,43 +153,43 @@ class _ReportsVCState extends BaseStatefulState } Widget getReportsType() { - if (selectedReport == items[0]) { + if (selectedReport == Constants.reportsTypes[0]) { return BestSupplierVC( limit: limit, context: context, delegate: this, ); - } else if (selectedReport == items[1]) { + } else if (selectedReport == Constants.reportsTypes[1]) { return POSComplete( limit: limit, context: context, delegate: this, ); - } else if (selectedReport == items[2]) { + } else if (selectedReport == Constants.reportsTypes[2]) { return POSReturnOrderVC( limit: limit, context: context, delegate: this, ); - } else if (selectedReport == items[3]) { + } else if (selectedReport == Constants.reportsTypes[3]) { return ReportsInvoiceVC( limit: limit, context: context, delegate: this, ); - } else if (selectedReport == items[4]) { + } else if (selectedReport == Constants.reportsTypes[4]) { return ReportsQuotationVC( limit: limit, context: context, delegate: this, ); - } else if (selectedReport == items[5]) { + } else if (selectedReport == Constants.reportsTypes[5]) { return ReportsCategoryVC( limit: limit, context: context, delegate: this, ); - } else if (selectedReport == items[6]) { + } else if (selectedReport == Constants.reportsTypes[6]) { return ReportsProductsVC( limit: limit, context: context, @@ -225,7 +214,7 @@ class _ReportsVCState extends BaseStatefulState fit: FlexFit.loose, constraints: const BoxConstraints(maxHeight: 200), ), - items: items, + items: Constants.reportsTypes, itemAsString: (String u) => u, onChanged: (String? data) { setState(() { 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 index 6482d83..44a27c7 100644 --- a/lib/application/views/settings/reportsViews/BestSuppliersVC.dart +++ b/lib/application/views/settings/reportsViews/BestSuppliersVC.dart @@ -3,15 +3,10 @@ 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/ListHeadingContainer.dart'; -import 'package:wosull/widgets/ValueText.dart'; +import 'package:wosull/application/views/settings/widgets/BestSupplierListView.dart'; class BestSupplierVC extends StatelessWidget { final ReportsCVS delegate; @@ -46,18 +41,18 @@ class BestSupplierVC extends StatelessWidget { Future(() { controller.fetch(limit: limit); }); - return showData(controller.data, true); + return showData(controller.data); case DataState.initialFetching: return AppLoader(); case DataState.moreFetching: case DataState.refreshing: - return showData(controller.data, true); + 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, false); + return showData(controller.data); } }, ), @@ -65,158 +60,10 @@ class BestSupplierVC extends StatelessWidget { }); } - Widget showData(List data, bool isLoading) { + Widget showData(List data) { return Column( children: [ - 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, - ), - 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: ListHeadingContainer( - 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, - ) - ], - ), + BestSupplierListView(isPortrait: isPortrait, data: data), if (viewModel.dataState == DataState.moreFetching) AppLoader(), ], ); diff --git a/lib/application/views/settings/reportsViews/POSCompleteVC.dart b/lib/application/views/settings/reportsViews/POSCompleteVC.dart index bde6a7b..6aea41e 100644 --- a/lib/application/views/settings/reportsViews/POSCompleteVC.dart +++ b/lib/application/views/settings/reportsViews/POSCompleteVC.dart @@ -1,21 +1,12 @@ 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/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/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'; - -import '../../../../widgets/EmptyDataWidget.dart'; +import 'package:wosull/application/views/settings/widgets/POSCompleteListView.dart'; class POSComplete extends StatelessWidget { late ScrollController _controller; @@ -72,199 +63,7 @@ class POSComplete extends StatelessWidget { Widget showData(List data) { return Column( children: [ - data.isEmpty - ? const EmptyDataWidget() - : Column( - children: [ - isPortrait - ? Container() - : ListHeadingContainer( - child: Row( - children: [ - Expanded( - child: HeadingText( - AppLocalizations.of(context)! - .order_number)), - Expanded( - child: HeadingText( - AppLocalizations.of(context)! - .store_name)), - Expanded(child: HeadingText('Delivery Type')), - Expanded( - child: HeadingText( - AppLocalizations.of(context)! - .payment_mode)), - Expanded( - child: HeadingText( - AppLocalizations.of(context)!.table)), - Expanded( - child: HeadingText( - AppLocalizations.of(context)!.total)), - Expanded( - child: HeadingText( - AppLocalizations.of(context)!.discount)), - 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), - AppSpaces.verticalMedium, - HeadingText(AppLocalizations.of(context)! - .store_name), - AppSpaces.verticalMedium, - HeadingText('Delivery Type'), - AppSpaces.verticalMedium, - HeadingText(AppLocalizations.of(context)! - .payment_mode), - AppSpaces.verticalMedium, - HeadingText( - AppLocalizations.of(context)!.table), - AppSpaces.verticalMedium, - HeadingText( - AppLocalizations.of(context)!.total), - AppSpaces.verticalMedium, - HeadingText( - AppLocalizations.of(context)!.discount), - AppSpaces.verticalMedium, - HeadingText( - AppLocalizations.of(context)!.status), - AppSpaces.verticalMedium, - HeadingText(AppLocalizations.of(context)! - .created_on), - AppSpaces.verticalMedium, - HeadingText(AppLocalizations.of(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, - ValueText(completePOS.orderType ?? ''), - 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: ValueText(completePOS.orderType!)), - 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, - ) - ], - ), + POSCompleteListView(isPortrait: isPortrait, data: data), if (viewModel.dataState == DataState.moreFetching) AppLoader(), ], ); diff --git a/lib/application/views/settings/reportsViews/POSReturnOrderVC.dart b/lib/application/views/settings/reportsViews/POSReturnOrderVC.dart index 403c8b7..ac83e6a 100644 --- a/lib/application/views/settings/reportsViews/POSReturnOrderVC.dart +++ b/lib/application/views/settings/reportsViews/POSReturnOrderVC.dart @@ -1,17 +1,12 @@ 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'; +import 'package:wosull/application/views/settings/widgets/POSReturnOrderListView.dart'; class POSReturnOrderVC extends StatelessWidget { late ScrollController _controller; @@ -67,158 +62,7 @@ class POSReturnOrderVC extends StatelessWidget { 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: 8, - ), - ValueText(returnOrder.storeId!.name ?? ''), - const SizedBox( - height: 8, - ), - ValueText(returnOrder.status ?? ''), - const SizedBox( - height: 8, - ), - ValueText(DataTimeFormat.getFormatDate( - returnOrder.createdAt ?? '')), - const SizedBox( - height: 8, - ), - 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, - ) - ], - ), + POSReturnOrderListView(data: data, isPortrait: isPortrait), if (viewModel.dataState == DataState.moreFetching) AppLoader(), ], ); diff --git a/lib/application/views/settings/reportsViews/ReportsCategoryVC.dart b/lib/application/views/settings/reportsViews/ReportsCategoryVC.dart index 140b1af..c5cb291 100644 --- a/lib/application/views/settings/reportsViews/ReportsCategoryVC.dart +++ b/lib/application/views/settings/reportsViews/ReportsCategoryVC.dart @@ -1,15 +1,11 @@ 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/utils/AppLoader.dart'; import 'package:wosull/application/views/inventorymodule/categoryviews/viewModels/CategoryViewModel.dart'; -import 'package:wosull/widgets/ListHeadingContainer.dart'; - -import '../../../../widgets/EmptyDataWidget.dart'; +import 'package:wosull/application/views/settings/widgets/ReportsCategoryListView.dart'; class ReportsCategoryVC extends StatefulWidget { final ReportsCVS delegate; @@ -28,9 +24,10 @@ class ReportsCategoryVC extends StatefulWidget { class _ReportsCategoryVCState extends State { bool isPortrait = true; - bool _isLoading = false; + late ScrollController _controller; - late DataState _dataState; + + // late DataState _dataState; final categoryViewModel = CategoryViewModel(); @override @@ -46,250 +43,56 @@ class _ReportsCategoryVCState extends State { 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(limit: widget.limit); - }); - 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); - } - }, - ), - ), - ], + 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, bool isLoading) { - _isLoading = isLoading; + Widget categoryListViewWidget(List data) { return Column( children: [ - _data.isEmpty - ? const EmptyDataWidget() - : Column( - children: [ - isPortrait - ? Container() - : ListHeadingContainer( - 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.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: [ - 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: 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()), + ReportsCategoryListView( + isPortrait: isPortrait, + data: data, + ), + if (categoryViewModel.dataState == DataState.moreFetching) AppLoader(), ], ); } bool _scrollNotification() { - if (!_isLoading && _controller.position.extentAfter < 300) { - _isLoading = true; + if (!categoryViewModel.isLoading && + _controller.position.extentAfter < 300) { categoryViewModel.fetchCategories(limit: categoryViewModel.limit); } return true; diff --git a/lib/application/views/settings/reportsViews/ReportsInvoiceVC.dart b/lib/application/views/settings/reportsViews/ReportsInvoiceVC.dart index 062aa93..6b8fdc6 100644 --- a/lib/application/views/settings/reportsViews/ReportsInvoiceVC.dart +++ b/lib/application/views/settings/reportsViews/ReportsInvoiceVC.dart @@ -1,21 +1,18 @@ 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'; -import 'package:wosull/helpers/AppSpaces.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 = ReportsInvoiceViewModel(); + final viewModel = InvoiceViewModel(); final ReportsCVS delegate; BuildContext context; @@ -29,29 +26,27 @@ class ReportsInvoiceVC extends StatelessWidget { @override Widget build(BuildContext context) { + _controller = ScrollController()..addListener(_scrollNotification); 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? _) { + child: Consumer( + builder: + (BuildContext context, InvoiceViewModel controller, Widget? _) { switch (controller.dataState) { case DataState.uninitialized: Future(() { - controller.fetchInvoices(limit: limit); + controller.fetch(limit: limit); }); - return showList(controller.invoiceList); + return showList(controller.filteredList); case DataState.initialFetching: - return const Center( - child: CircularProgressIndicator(), - ); + return AppLoader(); case DataState.moreFetching: case DataState.refreshing: - return showList(controller.invoiceList); + return showList(controller.filteredList); case DataState.error: return const Center( child: Text("Error"), @@ -59,7 +54,7 @@ class ReportsInvoiceVC extends StatelessWidget { case DataState.fetched: case DataState.searching: case DataState.noMoreData: - return showList(controller.invoiceList); + return showList(controller.filteredList); } }, ), @@ -71,402 +66,15 @@ class ReportsInvoiceVC extends StatelessWidget { 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.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: Text( - 'Supplier name', - style: MyColors.textStyleHeading(), - ), - )), - Expanded( - child: Align( - alignment: Alignment.centerRight, - child: Text( - storeInvoice.invoiceFor!.first == - 'Company' - ? storeInvoice.supplier?.name ?? "" - : storeInvoice.customer?.name ?? '', - style: MyColors.textStyleValue(), - ), - )) - ], - ), - AppSpaces.verticalMedium, - 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(), - ), - )) - ], - ), - AppSpaces.verticalMedium, - 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(), - ), - )) - ], - ), - AppSpaces.verticalMedium, - 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(), - ), - )) - ], - ), - AppSpaces.verticalMedium, - 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(), - ), - )) - ], - ), - AppSpaces.verticalMedium, - 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(), - ), - )) - ], - ), - AppSpaces.verticalMedium, - 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(), - ), - )) - ], - ), - AppSpaces.verticalMedium, - 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: 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: 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()), + ReportsInvoiceListView(data: data, isPortrait: isPortrait), + if (viewModel.dataState == DataState.moreFetching) AppLoader(), ], ); } bool _scrollNotification() { if (!viewModel.isLoading && _controller.position.extentAfter < 300) { - viewModel.fetchInvoices(limit: viewModel.limit); + viewModel.fetch(limit: viewModel.limit); } return true; } diff --git a/lib/application/views/settings/reportsViews/ReportsProductsVC.dart b/lib/application/views/settings/reportsViews/ReportsProductsVC.dart index 9d5718d..724cf83 100644 --- a/lib/application/views/settings/reportsViews/ReportsProductsVC.dart +++ b/lib/application/views/settings/reportsViews/ReportsProductsVC.dart @@ -1,13 +1,11 @@ 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/utils/AppLoader.dart'; import 'package:wosull/application/views/inventorymodule/viewmodel/ProductViewModel.dart'; -import 'package:wosull/widgets/EmptyDataWidget.dart'; -import 'package:wosull/widgets/ListHeadingContainer.dart'; +import 'package:wosull/application/views/settings/widgets/ReportsProductListView.dart'; class ReportsProductsVC extends StatefulWidget { final ReportsCVS delegate; @@ -28,9 +26,11 @@ class ReportsProductsVC extends StatefulWidget { class _ReportsProductsVCState extends State { final viewModel = ProductViewModel(); bool isPortrait = true; - bool _isLoading = false; + + //bool _isLoading = false; late ScrollController _controller; - late DataState _dataState; + + //late DataState _dataState; @override void initState() { @@ -45,269 +45,53 @@ class _ReportsProductsVCState extends State { 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(limit: widget.limit); - }); - 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); - } - }, - ), - ), - ], + 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, bool isLoading) { - _isLoading = isLoading; + Widget showList(List data) { + //_isLoading = isLoading; return Column( children: [ - _data.isEmpty - ? const EmptyDataWidget() - : Column( - children: [ - isPortrait - ? Container() - : ListHeadingContainer( - 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.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: [ - Text( - AppLocalizations.of(widget.context)! - .item_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] - .price - ?.toStringAsFixed(2) ?? - '', - 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()), + ReportsProductListView(data: data, isPortrait: isPortrait), + if (viewModel.dataState == DataState.moreFetching) AppLoader(), ], ); } bool _scrollNotification() { - if (!_isLoading && _controller.position.extentAfter < 300) { - _isLoading = true; + if (!viewModel.isLoading && _controller.position.extentAfter < 300) { viewModel.fetchReportsProducts(limit: viewModel.limit); } return true; diff --git a/lib/application/views/settings/reportsViews/ReportsQuotationVC.dart b/lib/application/views/settings/reportsViews/ReportsQuotationVC.dart index e2b0bb1..977767f 100644 --- a/lib/application/views/settings/reportsViews/ReportsQuotationVC.dart +++ b/lib/application/views/settings/reportsViews/ReportsQuotationVC.dart @@ -1,15 +1,11 @@ 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/utils/AppLoader.dart'; import 'package:wosull/application/views/settings/viewModels/ReportsViewModel.dart'; -import 'package:wosull/widgets/EmptyDataWidget.dart'; -import 'package:wosull/widgets/ListHeadingContainer.dart'; +import 'package:wosull/application/views/settings/widgets/ReportsQuotationListView.dart'; class ReportsQuotationVC extends StatefulWidget { final ReportsCVS delegate; @@ -28,9 +24,11 @@ class ReportsQuotationVC extends StatefulWidget { class _ReportsQuotationVCState extends State { bool isPortrait = true; - bool _isLoading = false; + + // bool _isLoading = false; late ScrollController _controller; - late DataState _dataState; + + // late DataState _dataState; final viewModel = ReportsViewModel(); @override @@ -46,469 +44,55 @@ class _ReportsQuotationVCState extends State { 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(limit: widget.limit); - }); - 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); - } - }, - ), - ), - ], + 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, bool isLoading) { + Widget showList(List data) { return Column( children: [ - _data.isEmpty - ? const EmptyDataWidget() - : Column( - children: [ - isPortrait - ? Container() - : ListHeadingContainer( - 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.all(8), - color: MyColors.containerBackColor, - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Expanded( - flex: 2, - child: Container( - 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: 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: 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()), + ReportsQuotationListView( + data: data, + isPortrait: isPortrait, + ), + if (viewModel.dataState == DataState.moreFetching) AppLoader(), ], ); } bool _scrollNotification() { - if (!_isLoading && _controller.position.extentAfter < 300) { - _isLoading = true; + if (!viewModel.isLoading && _controller.position.extentAfter < 300) { viewModel.fetchQuotations(limit: viewModel.limit); } return true; diff --git a/lib/application/views/settings/viewModels/BestSupplierViewModel.dart b/lib/application/views/settings/viewModels/BestSupplierViewModel.dart index f08ef9e..832674d 100644 --- a/lib/application/views/settings/viewModels/BestSupplierViewModel.dart +++ b/lib/application/views/settings/viewModels/BestSupplierViewModel.dart @@ -1,12 +1,11 @@ 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; @@ -50,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 < this.limit) { + if (result.isNotEmpty) { + _data.addAll(result); + if (result.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; diff --git a/lib/application/views/settings/viewModels/POSCompleteViewModel.dart b/lib/application/views/settings/viewModels/POSCompleteViewModel.dart index 79d6ca7..bbca3b6 100644 --- a/lib/application/views/settings/viewModels/POSCompleteViewModel.dart +++ b/lib/application/views/settings/viewModels/POSCompleteViewModel.dart @@ -1,11 +1,11 @@ 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/reports/CashierOrder.dart'; +import 'package:wosull/application/views/settings/repo/ReportsRepository.dart'; class POSCompleteViewModel with ChangeNotifier { + final repository = ReportsRepository(); int _currentPageNumber = 1; DataState _dataState = DataState.uninitialized; bool _didLastLoad = false; @@ -41,16 +41,13 @@ class POSCompleteViewModel with ChangeNotifier { 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 < this.limit) { + if (result.isNotEmpty) { + _data.addAll(result); + if (result.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; diff --git a/lib/application/views/settings/viewModels/ReportsInvoiceViewModel.dart b/lib/application/views/settings/viewModels/ReportsInvoiceViewModel.dart deleted file mode 100644 index 486d5d7..0000000 --- a/lib/application/views/settings/viewModels/ReportsInvoiceViewModel.dart +++ /dev/null @@ -1,71 +0,0 @@ -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/StoreInvoice.dart'; -import 'package:wosull/application/model/store/StoreInvoicesModel.dart'; -import 'package:wosull/application/network/APIManager.dart'; -import 'package:wosull/application/utils/Constants.dart'; - -class ReportsInvoiceViewModel with ChangeNotifier { - int _currentPageNumber = 1; - DataState _dataState = DataState.uninitialized; - bool _didLastLoad = false; - int limit = 10; - bool _isLoading = false; - - bool get isLoading => _isLoading; - - DataState get dataState => _dataState; - - List _invoiceList = []; - - List get invoiceList => _invoiceList; - - fetchInvoices({bool isRefresh = false, int limit = 10}) async { - this.limit = limit; - if (!isRefresh) { - _dataState = (_dataState == DataState.uninitialized) - ? DataState.initialFetching - : DataState.moreFetching; - } else { - _currentPageNumber = 1; - _dataState = DataState.refreshing; - } - notifyListeners(); - 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); - if (_dataState == DataState.refreshing) { - _invoiceList.clear(); - } - if (value.success!) { - _invoiceList.addAll(value.invoices!); - if (value.invoices!.length < this.limit) { - _didLastLoad = true; - } else { - _didLastLoad = false; - } - } - _dataState = DataState.fetched; - _currentPageNumber += 1; - }).onError((error, stackTrace) { - _dataState = DataState.error; - }); - } - notifyListeners(); - } catch (e) { - _dataState = DataState.error; - notifyListeners(); - } - } -} diff --git a/lib/application/views/settings/viewModels/ReportsViewModel.dart b/lib/application/views/settings/viewModels/ReportsViewModel.dart index 1d84530..111b8fa 100644 --- a/lib/application/views/settings/viewModels/ReportsViewModel.dart +++ b/lib/application/views/settings/viewModels/ReportsViewModel.dart @@ -10,6 +10,9 @@ 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; @@ -23,6 +26,7 @@ class ReportsViewModel with ChangeNotifier { fetchInvoices({bool isRefresh = false, int limit = 10}) async { this.limit = limit; + _isLoading = true; if (!isRefresh) { _dataState = (_dataState == DataState.uninitialized) ? DataState.initialFetching @@ -56,14 +60,17 @@ class ReportsViewModel with ChangeNotifier { _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(); } 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/TransactionVC.dart b/lib/application/views/transactions/TransactionVC.dart index c5cc5f9..e9650d3 100644 --- a/lib/application/views/transactions/TransactionVC.dart +++ b/lib/application/views/transactions/TransactionVC.dart @@ -3,6 +3,7 @@ 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/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/views/salesandordermodule/views/invoiceModule/views/AddInvoiceAndPrintVC.dart'; @@ -18,7 +19,6 @@ import 'package:wosull/helpers/ThemeText.dart'; import 'package:wosull/widgets/PageLimitDropDown.dart'; import '../../model/cart/GetHoldOrderModel.dart'; -import '../../model/reports/CashierOrderHistory.dart'; import '../salesandordermodule/views/invoiceModule/views/NewInvoiceVC.dart'; class TransactionVC extends StatefulWidget { diff --git a/lib/application/views/transactions/return/ReturnPOS.dart b/lib/application/views/transactions/return/ReturnPOS.dart index 6456a6c..de8244c 100644 --- a/lib/application/views/transactions/return/ReturnPOS.dart +++ b/lib/application/views/transactions/return/ReturnPOS.dart @@ -1,7 +1,7 @@ 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'; diff --git a/lib/application/views/transactions/viewmodels/CashierTransactionViewModel.dart b/lib/application/views/transactions/viewmodels/CashierTransactionViewModel.dart index 4739a2b..a19631c 100644 --- a/lib/application/views/transactions/viewmodels/CashierTransactionViewModel.dart +++ b/lib/application/views/transactions/viewmodels/CashierTransactionViewModel.dart @@ -3,6 +3,7 @@ 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/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'; diff --git a/lib/application/views/transactions/viewmodels/ReturnPOSOrderVM.dart b/lib/application/views/transactions/viewmodels/ReturnPOSOrderVM.dart index cdb1252..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'; diff --git a/lib/application/views/transactions/views/EditOrderVC.dart b/lib/application/views/transactions/views/EditOrderVC.dart index f3bfe6e..740082e 100644 --- a/lib/application/views/transactions/views/EditOrderVC.dart +++ b/lib/application/views/transactions/views/EditOrderVC.dart @@ -3,7 +3,7 @@ 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/CashierOrderHistory.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'; diff --git a/lib/application/views/transactions/views/TransactionCashierVC.dart b/lib/application/views/transactions/views/TransactionCashierVC.dart index 1484d33..e3bd5f5 100644 --- a/lib/application/views/transactions/views/TransactionCashierVC.dart +++ b/lib/application/views/transactions/views/TransactionCashierVC.dart @@ -2,7 +2,7 @@ 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/CashierOrderHistory.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'; diff --git a/lib/application/views/transactions/views/ViewCashierTransactionVC.dart b/lib/application/views/transactions/views/ViewCashierTransactionVC.dart index 744d383..6e6a67e 100644 --- a/lib/application/views/transactions/views/ViewCashierTransactionVC.dart +++ b/lib/application/views/transactions/views/ViewCashierTransactionVC.dart @@ -1,7 +1,7 @@ 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/CashierOrderHistory.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'; diff --git a/lib/application/views/transactions/widgets/CashierOrderListView.dart b/lib/application/views/transactions/widgets/CashierOrderListView.dart index 90edb21..eb516f0 100644 --- a/lib/application/views/transactions/widgets/CashierOrderListView.dart +++ b/lib/application/views/transactions/widgets/CashierOrderListView.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:wosull/application/model/converters/DataTimeFormat.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/helpers/AppSpaces.dart'; import 'package:wosull/helpers/ThemeText.dart'; diff --git a/lib/application/views/transactions/widgets/EditOrderViewModel.dart b/lib/application/views/transactions/widgets/EditOrderViewModel.dart index 57282ea..c17cd4f 100644 --- a/lib/application/views/transactions/widgets/EditOrderViewModel.dart +++ b/lib/application/views/transactions/widgets/EditOrderViewModel.dart @@ -5,7 +5,7 @@ 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/CashierOrderHistory.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'; @@ -318,7 +318,7 @@ class EditOrderViewModel with ChangeNotifier { void setSelectedOrderType(StoreServiceModel? data) { selectedOrderType = data; if (data != null) { - cashierOrder.orderType = data.name; + cashierOrder.orderType = data.name!; } else { cashierOrder.orderType = ''; } diff --git a/lib/application/views/transactions/widgets/TransactionCashierOrderListView.dart b/lib/application/views/transactions/widgets/TransactionCashierOrderListView.dart index 849cff6..4c8ed53 100644 --- a/lib/application/views/transactions/widgets/TransactionCashierOrderListView.dart +++ b/lib/application/views/transactions/widgets/TransactionCashierOrderListView.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:wosull/application/model/converters/DataTimeFormat.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/helpers/AppSpaces.dart'; import 'package:wosull/helpers/ThemeText.dart'; diff --git a/lib/helpers/ThemeText.dart b/lib/helpers/ThemeText.dart index 25f1f64..068d847 100644 --- a/lib/helpers/ThemeText.dart +++ b/lib/helpers/ThemeText.dart @@ -144,14 +144,21 @@ 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 TextStyle textStyleImageHeading = TextStyle( fontSize: MyFonts.normalButton, From bd83346b1ce4449f090817063cf8ce98842ca8bb Mon Sep 17 00:00:00 2001 From: waqasYeepeey Date: Fri, 13 Oct 2023 16:06:47 +0500 Subject: [PATCH 08/11] 'reformat reports' --- lib/application/model/inventory/Item.dart | 32 +++++++++---------- .../viewModels/POSReturnOrderViewModel.dart | 22 ++++++------- 2 files changed, 25 insertions(+), 29 deletions(-) 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/views/settings/viewModels/POSReturnOrderViewModel.dart b/lib/application/views/settings/viewModels/POSReturnOrderViewModel.dart index ad4d420..a0dc7bf 100644 --- a/lib/application/views/settings/viewModels/POSReturnOrderViewModel.dart +++ b/lib/application/views/settings/viewModels/POSReturnOrderViewModel.dart @@ -2,10 +2,11 @@ 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; @@ -42,32 +43,29 @@ class POSReturnOrderViewModel with ChangeNotifier { if (_didLastLoad) { _dataState = DataState.noMoreData; } else { - await APIManager() - .fetchData(Constants.GET_RETURN_ORDER_HISTORY, data) - .then((result) { - final value = GetReturnAndDamageModel.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 < this.limit) { + 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) { - print(stackTrace.toString()); + _isLoading = false; _dataState = DataState.error; }); } notifyListeners(); } catch (e) { - _isLoading = true; + _isLoading = false; _dataState = DataState.error; notifyListeners(); } From 8178e1ae5a7d5dd782fdf3aa44e7c7778553786f Mon Sep 17 00:00:00 2001 From: waqasYeepeey Date: Sat, 14 Oct 2023 20:18:09 +0500 Subject: [PATCH 09/11] 'payment method' --- lib/application/MyApp.dart | 3 + .../model/invoice/PaymentMethod.dart | 36 ++- .../model/store/StoreInvoicesModel.dart | 14 +- .../repository/WosulRepository.dart | 15 +- lib/application/utils/Constants.dart | 6 + .../BillingCounterDashBoard.dart | 10 +- .../views/ViewPOSOrderVC.dart | 8 + .../views/create_order_module/CartVC.dart | 3 +- .../create_order_module/HoldOrderVC.dart | 2 + .../viewModels/CartViewModel.dart | 19 ++ .../viewModels/PaymentOptionViewModel.dart | 2 +- .../views/PrintReceiptVC.dart | 54 ++-- .../views/TabBarHomeVC.dart | 2 +- .../views/popups/PaymentOptionPopUpVC.dart | 41 +-- lib/application/views/dashboard/HomeVC.dart | 2 +- .../dashboard/widgets/InvoiceStatusGraph.dart | 2 +- .../dashboard/widgets/POSStatusGraph.dart | 2 +- .../views/dashboard/widgets/RevenueGraph.dart | 2 +- .../dashboard/widgets/TodayPOSSales.dart | 26 +- .../dashboard/widgets/TodaySaleGraph.dart | 4 +- .../discountModule/views/NewDiscountVC.dart | 4 + .../comboviews/InventoryNewComboVC.dart | 19 ++ .../AddProductIngredientVC.dart | 16 ++ .../InventoryAddMeasurementVC.dart | 4 + .../viewModels/AddMeasurementUnitVM.dart | 5 +- .../views/NewModifierOptionVC.dart | 10 + .../AddNewInventoryProductVC.dart | 25 ++ .../stockReturn/views/NewStockReturnVC.dart | 25 ++ .../InventoryNewStockTransferVC.dart | 10 + .../InventorySubCategoryVC.dart | 4 + .../subCategoryViews/SubCategoryVC.dart | 5 + .../views/InvoiceMakePaymentVC.dart | 13 +- .../views/invoiceModule/views/InvoicesVC.dart | 4 + .../invoiceModule/views/NewInvoiceVC.dart | 28 ++ .../views/ordersModule/OrderVC.dart | 4 + .../quotataionModule/NewQuotationsVC.dart | 28 ++ .../views/quotataionModule/QuotationsVC.dart | 8 +- .../views/settings/SettingsMainVC.dart | 11 +- .../repo/PaymentMethodRepository.dart | 24 ++ .../viewModel/NewPaymentMethodViewModel.dart | 72 ++++++ .../viewModel/PaymentMethodViewModel.dart | 124 +++++++++ .../views/NewPaymentMethodVC.dart | 202 +++++++++++++++ .../paymentMethods/views/PaymentMethodVC.dart | 224 ++++++++++++++++ .../widgets/PaymentMethodListView.dart | 242 ++++++++++++++++++ .../{ => views/reports}/ReportsVC.dart | 20 +- .../reportsViews/BestSuppliersVC.dart | 0 .../reportsViews/POSCompleteVC.dart | 0 .../reportsViews/POSReturnOrderVC.dart | 0 .../reportsViews/ReportsCategoryVC.dart | 0 .../reportsViews/ReportsCustomerVC.dart | 8 +- .../reportsViews/ReportsInvoiceVC.dart | 0 .../reportsViews/ReportsProductsVC.dart | 0 .../reportsViews/ReportsQuotationVC.dart | 0 .../reportsViews/ReportsSupplierVC.dart | 0 .../views/transactions/TransactionVC.dart | 8 +- .../return/ReturnReasonPopUp.dart | 7 + .../views/transactions/views/EditOrderVC.dart | 16 ++ lib/widgets/DiscountDropdown.dart | 11 +- lib/widgets/DropdownItemBuilder.dart | 21 ++ lib/widgets/ItemCategoryDropdown.dart | 4 + lib/widgets/PageLimitDropDown.dart | 4 + 61 files changed, 1354 insertions(+), 109 deletions(-) create mode 100644 lib/application/views/settings/views/paymentMethods/repo/PaymentMethodRepository.dart create mode 100644 lib/application/views/settings/views/paymentMethods/viewModel/NewPaymentMethodViewModel.dart create mode 100644 lib/application/views/settings/views/paymentMethods/viewModel/PaymentMethodViewModel.dart create mode 100644 lib/application/views/settings/views/paymentMethods/views/NewPaymentMethodVC.dart create mode 100644 lib/application/views/settings/views/paymentMethods/views/PaymentMethodVC.dart create mode 100644 lib/application/views/settings/views/paymentMethods/widgets/PaymentMethodListView.dart rename lib/application/views/settings/{ => views/reports}/ReportsVC.dart (89%) rename lib/application/views/settings/{ => views}/reportsViews/BestSuppliersVC.dart (100%) rename lib/application/views/settings/{ => views}/reportsViews/POSCompleteVC.dart (100%) rename lib/application/views/settings/{ => views}/reportsViews/POSReturnOrderVC.dart (100%) rename lib/application/views/settings/{ => views}/reportsViews/ReportsCategoryVC.dart (100%) rename lib/application/views/settings/{ => views}/reportsViews/ReportsCustomerVC.dart (99%) rename lib/application/views/settings/{ => views}/reportsViews/ReportsInvoiceVC.dart (100%) rename lib/application/views/settings/{ => views}/reportsViews/ReportsProductsVC.dart (100%) rename lib/application/views/settings/{ => views}/reportsViews/ReportsQuotationVC.dart (100%) rename lib/application/views/settings/{ => views}/reportsViews/ReportsSupplierVC.dart (100%) create mode 100644 lib/widgets/DropdownItemBuilder.dart diff --git a/lib/application/MyApp.dart b/lib/application/MyApp.dart index 612ca4d..fede9b1 100644 --- a/lib/application/MyApp.dart +++ b/lib/application/MyApp.dart @@ -35,6 +35,7 @@ import 'package:wosull/application/views/salesandordermodule/views/invoiceModule 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/views/paymentMethods/viewModel/NewPaymentMethodViewModel.dart'; import 'package:wosull/application/views/transactions/viewmodels/TransactionQuotationViewModel.dart'; import 'package:wosull/application/views/transactions/widgets/EditOrderViewModel.dart'; @@ -55,6 +56,8 @@ class MyApp extends StatelessWidget { Widget build(BuildContext context) { return MultiProvider( providers: [ + ChangeNotifierProvider( + create: (context) => NewPaymentMethodViewModel()), ChangeNotifierProvider( create: (context) => MakePaymentViewModel()), ChangeNotifierProvider( diff --git a/lib/application/model/invoice/PaymentMethod.dart b/lib/application/model/invoice/PaymentMethod.dart index c75b9a8..6fc58c8 100644 --- a/lib/application/model/invoice/PaymentMethod.dart +++ b/lib/application/model/invoice/PaymentMethod.dart @@ -1,15 +1,35 @@ +import 'package:wosull/application/localdb/SharedPrefs.dart'; + class PaymentMethod { - String id; - String paymentMethod; - bool status; + String? id; + String? paymentMethod; + bool? status; + String? updatedAt; + String? description; - PaymentMethod(this.id, this.paymentMethod, this.status); + PaymentMethod( + {this.id, + this.paymentMethod, + this.status, + this.description, + this.updatedAt}); factory PaymentMethod.fromJson(Map json) { return PaymentMethod( - json['_id'] ?? '', - json['paymentMethod'] ?? '', - json['status'] ?? false, - ); + 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, + 'store_id': sharedPrefs.storeId, + 'payment_id': id + }; } } 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/repository/WosulRepository.dart b/lib/application/repository/WosulRepository.dart index 7f2c3ac..2b3639b 100644 --- a/lib/application/repository/WosulRepository.dart +++ b/lib/application/repository/WosulRepository.dart @@ -21,20 +21,19 @@ import 'package:wosull/application/repo/AuthRepository.dart'; import 'package:wosull/application/utils/Constants.dart'; class WosulRepository { - Future> getPaymentMethods() async { + Future> getPaymentMethods( + {Map? map}) async { var items = []; - var data = {'page': 1, 'is_pagination_included': false}; + map ??= {'page': 1, 'is_pagination_included': false}; await APIManager() .getResponseAuth( - "${Constants.getPaymentMethods}/${sharedPrefs.storeId}", data) + "${Constants.getPaymentMethods}/${sharedPrefs.storeId}", map) .then((result) { final value = PaymentMethodResponse.fromJson(result); if (value.status) { items.addAll(value.paymentMethods); } - }).onError((error, stackTrace) { - print(stackTrace.toString()); - }); + }).onError((error, stackTrace) {}); return items; } @@ -202,9 +201,7 @@ class WosulRepository { .then((response) { final value = ProductItemCategoryModel.fromJson(response); items.addAll(value.categories); - }).onError((error, stackTrace) { - print(stackTrace.toString()); - }); + }).onError((error, stackTrace) {}); return items; } diff --git a/lib/application/utils/Constants.dart b/lib/application/utils/Constants.dart index 9d06e84..22bbc78 100644 --- a/lib/application/utils/Constants.dart +++ b/lib/application/utils/Constants.dart @@ -191,9 +191,11 @@ class Constants { 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'; @@ -201,6 +203,10 @@ class Constants { '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'; diff --git a/lib/application/views/billingCounterDashboard/BillingCounterDashBoard.dart b/lib/application/views/billingCounterDashboard/BillingCounterDashBoard.dart index c025c76..8ad9c14 100644 --- a/lib/application/views/billingCounterDashboard/BillingCounterDashBoard.dart +++ b/lib/application/views/billingCounterDashboard/BillingCounterDashBoard.dart @@ -11,6 +11,7 @@ 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}); @@ -120,8 +121,13 @@ class _BillingCounterDashBoardState extends State { return DropdownSearch( dropdownButtonProps: ThemeDropDown.dropdownButtonProps, selectedItem: Constants.counterTypes.first, - popupProps: - const PopupProps.menu(constraints: BoxConstraints(maxHeight: 180)), + 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) { diff --git a/lib/application/views/businessAccounts/views/ViewPOSOrderVC.dart b/lib/application/views/businessAccounts/views/ViewPOSOrderVC.dart index 4e9e87c..ed55a4d 100644 --- a/lib/application/views/businessAccounts/views/ViewPOSOrderVC.dart +++ b/lib/application/views/businessAccounts/views/ViewPOSOrderVC.dart @@ -15,6 +15,7 @@ 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'; @@ -550,6 +551,13 @@ class ViewPOSOrderVC extends StatelessWidget { 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) {}, diff --git a/lib/application/views/create_order_module/CartVC.dart b/lib/application/views/create_order_module/CartVC.dart index d546914..909ac51 100644 --- a/lib/application/views/create_order_module/CartVC.dart +++ b/lib/application/views/create_order_module/CartVC.dart @@ -52,6 +52,7 @@ class _CartVCState extends BaseStatefulState { Widget build(BuildContext context) { homeViewModel = context.watch(); return Scaffold( + backgroundColor: MyColors.white, body: Padding( padding: const EdgeInsets.all(12), child: Column( @@ -309,7 +310,7 @@ 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(); diff --git a/lib/application/views/create_order_module/HoldOrderVC.dart b/lib/application/views/create_order_module/HoldOrderVC.dart index 2a38dc0..f1c5fd0 100644 --- a/lib/application/views/create_order_module/HoldOrderVC.dart +++ b/lib/application/views/create_order_module/HoldOrderVC.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; import 'package:wosull/application/interfaces/DrawerWidgetSelect.dart'; import 'package:wosull/application/model/CreateAndUpdateOrder.dart'; import 'package:wosull/application/theme/MyColors.dart'; @@ -34,6 +35,7 @@ class _HoldOrderVCState extends BaseStatefulState { @override Widget build(BuildContext context) { + viewModel = context.watch(); return Scaffold( backgroundColor: MyColors.white, body: Padding( diff --git a/lib/application/views/create_order_module/viewModels/CartViewModel.dart b/lib/application/views/create_order_module/viewModels/CartViewModel.dart index 8ee6364..8a975ab 100644 --- a/lib/application/views/create_order_module/viewModels/CartViewModel.dart +++ b/lib/application/views/create_order_module/viewModels/CartViewModel.dart @@ -50,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 = { diff --git a/lib/application/views/create_order_module/viewModels/PaymentOptionViewModel.dart b/lib/application/views/create_order_module/viewModels/PaymentOptionViewModel.dart index 75eaee9..940695f 100644 --- a/lib/application/views/create_order_module/viewModels/PaymentOptionViewModel.dart +++ b/lib/application/views/create_order_module/viewModels/PaymentOptionViewModel.dart @@ -235,7 +235,7 @@ class PaymentOptionViewModel with ChangeNotifier { if (data == null) { selectedPaymentMethod = ''; } else { - selectedPaymentMethod = data.paymentMethod; + selectedPaymentMethod = data.paymentMethod!; } } } diff --git a/lib/application/views/create_order_module/views/PrintReceiptVC.dart b/lib/application/views/create_order_module/views/PrintReceiptVC.dart index 84bcc21..9ea9c0f 100644 --- a/lib/application/views/create_order_module/views/PrintReceiptVC.dart +++ b/lib/application/views/create_order_module/views/PrintReceiptVC.dart @@ -157,14 +157,22 @@ class _PrintReceiptVCState extends State { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( + Flexible( + child: Text( + overflow: TextOverflow.ellipsis, + softWrap: false, + maxLines: 3, 'Billed by: ${sharedPrefs.billingCounterName}', style: ThemeText.textStyleMediumDJMono, - ), - Text( + )), + Flexible( + child: Text( '${viewModel.itemQuantity} Items : (${viewModel.allItemsQuantity} Qty)', + overflow: TextOverflow.ellipsis, + softWrap: false, + maxLines: 3, style: ThemeText.textStyleMediumDJMono, - ), + )), ], ), AppSpaces.verticalLarge, @@ -178,6 +186,9 @@ class _PrintReceiptVCState extends State { Flexible( child: Text( 'Description', + overflow: TextOverflow.ellipsis, + softWrap: false, + maxLines: 3, style: ThemeText.textStyleBOLDDJMono, )), Row( @@ -351,6 +362,7 @@ class _PrintReceiptVCState extends State { AppSpaces.verticalSmall, Text( 'Address: ${order.storeId!.address}', + textAlign: TextAlign.center, style: ThemeText.textStyleSmallDJMono, ), AppSpaces.verticalLarge, @@ -385,14 +397,23 @@ class _PrintReceiptVCState extends State { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( + Flexible( + child: Text( 'Billed by: ${sharedPrefs.billingCounterName}', + overflow: TextOverflow.ellipsis, + softWrap: false, + maxLines: 3, style: ThemeText.textStyleMediumDJMono, - ), - Text( - '${viewModel.itemQuantity} Items : (${viewModel.allItemsQuantity} Qty)', - style: ThemeText.textStyleMediumDJMono, - ), + )), + Flexible( + child: Text( + '${viewModel.itemQuantity} Items : (${viewModel.allItemsQuantity} Qty)', + overflow: TextOverflow.ellipsis, + softWrap: false, + maxLines: 3, + style: ThemeText.textStyleMediumDJMono, + ), + ) ], ), AppSpaces.verticalLarge, @@ -552,10 +573,7 @@ class _PrintReceiptVCState extends State { ), ], ), - Visibility( - visible: !orderCompleted, - child: getDoneButton(), - ) + getDoneButton() ], ) : Row( @@ -572,13 +590,7 @@ class _PrintReceiptVCState extends State { child: getDownloadButton(), ), AppSpaces.horizontalSmall, - Visibility( - visible: !orderCompleted, - child: SizedBox( - width: 90, - child: getDoneButton(), - ), - ) + getDoneButton() ], ), ); diff --git a/lib/application/views/create_order_module/views/TabBarHomeVC.dart b/lib/application/views/create_order_module/views/TabBarHomeVC.dart index 940ab96..78670fa 100644 --- a/lib/application/views/create_order_module/views/TabBarHomeVC.dart +++ b/lib/application/views/create_order_module/views/TabBarHomeVC.dart @@ -996,7 +996,7 @@ 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(); 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 747eb24..76fc2f1 100644 --- a/lib/application/views/create_order_module/views/popups/PaymentOptionPopUpVC.dart +++ b/lib/application/views/create_order_module/views/popups/PaymentOptionPopUpVC.dart @@ -19,6 +19,7 @@ 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 { @@ -123,7 +124,9 @@ class _PaymentOptionPopUpVCState crossAxisAlignment: CrossAxisAlignment.center, children: [ - Icon(Icons.money, + Icon( + Icons + .monetization_on_outlined, color: MyColors.blueThemeColor, size: 18), @@ -172,7 +175,7 @@ class _PaymentOptionPopUpVCState crossAxisAlignment: CrossAxisAlignment.center, children: [ - Icon(Icons.money, + Icon(Icons.card_membership, color: MyColors.blueThemeColor, size: 18), @@ -293,7 +296,7 @@ class _PaymentOptionPopUpVCState .monetization_on_outlined, color: MyColors.blueThemeColor, - size: 24), + size: 18), const SizedBox( width: 8, ), @@ -346,7 +349,7 @@ class _PaymentOptionPopUpVCState Icon(Icons.card_membership, color: MyColors.blueThemeColor, - size: 24), + size: 18), const SizedBox( width: 8, ), @@ -576,19 +579,16 @@ class _PaymentOptionPopUpVCState )); } - Widget getDiscounts(BuildContext context) { - return SizedBox( - height: 48, - child: DiscountDropdown( - onChanged: (data) { - if (isConnected) { - viewModel.applyDiscount(sharedPrefs.cartID, data); - } else { - viewModel.calculateDiscount(data); - } - }, - fillColor: MyColors.fillColor2), - ); + Widget getDiscounts() { + return DiscountDropdown( + onChanged: (data) { + if (isConnected) { + viewModel.applyDiscount(sharedPrefs.cartID, data); + } else { + viewModel.calculateDiscount(data); + } + }, + fillColor: MyColors.fillColor2); } Widget getDiscountAndCalculation() { @@ -614,7 +614,7 @@ class _PaymentOptionPopUpVCState hint: AppLocalizations.of(context)!.discount_code, ), AppSpaces.verticalSmall, - getDiscounts(context), + getDiscounts(), ], )), AppSpaces.horizontalMedium, @@ -762,11 +762,14 @@ class _PaymentOptionPopUpVCState 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, + itemAsString: (PaymentMethod u) => u.paymentMethod!, onChanged: (PaymentMethod? data) { viewModel.setPaymentMethod(data); }, diff --git a/lib/application/views/dashboard/HomeVC.dart b/lib/application/views/dashboard/HomeVC.dart index 1491481..57dbe08 100644 --- a/lib/application/views/dashboard/HomeVC.dart +++ b/lib/application/views/dashboard/HomeVC.dart @@ -22,7 +22,7 @@ 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'; diff --git a/lib/application/views/dashboard/widgets/InvoiceStatusGraph.dart b/lib/application/views/dashboard/widgets/InvoiceStatusGraph.dart index 08d1407..3b144ae 100644 --- a/lib/application/views/dashboard/widgets/InvoiceStatusGraph.dart +++ b/lib/application/views/dashboard/widgets/InvoiceStatusGraph.dart @@ -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/POSStatusGraph.dart b/lib/application/views/dashboard/widgets/POSStatusGraph.dart index 6dceb9c..3d0f1d2 100644 --- a/lib/application/views/dashboard/widgets/POSStatusGraph.dart +++ b/lib/application/views/dashboard/widgets/POSStatusGraph.dart @@ -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 fb0f3f2..813e6ad 100644 --- a/lib/application/views/dashboard/widgets/RevenueGraph.dart +++ b/lib/application/views/dashboard/widgets/RevenueGraph.dart @@ -56,7 +56,7 @@ class RevenueGraph extends StatelessWidget { borderData: FlBorderData( show: false, ), - sectionsSpace: 0, + sectionsSpace: 2, centerSpaceRadius: 40, sections: showingSections(), ), diff --git a/lib/application/views/dashboard/widgets/TodayPOSSales.dart b/lib/application/views/dashboard/widgets/TodayPOSSales.dart index 2689fac..1f9d5a1 100644 --- a/lib/application/views/dashboard/widgets/TodayPOSSales.dart +++ b/lib/application/views/dashboard/widgets/TodayPOSSales.dart @@ -10,10 +10,11 @@ import 'package:wosull/helpers/ThemeText.dart'; class TodayPOSSales extends StatelessWidget { List gradientColors = [ - MyColors.blueThemeColor, + MyColors.backColorBlue50, MyColors.blueThemeColor, ]; List todaySales = []; + TodayPOSSales({super.key, required this.todaySales}); @override @@ -86,6 +87,29 @@ class TodayPOSSales extends StatelessWidget { LineChartData mainData() { return LineChartData( + minY: 0, + minX: 0, + gridData: FlGridData( + show: true, + getDrawingHorizontalLine: (value) => const FlLine( + color: MyColors.fillColorGray, + strokeWidth: 1, + ), + getDrawingVerticalLine: (value) { + return const FlLine( + 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, rightTitles: const AxisTitles( diff --git a/lib/application/views/dashboard/widgets/TodaySaleGraph.dart b/lib/application/views/dashboard/widgets/TodaySaleGraph.dart index 063ea88..7ff2587 100644 --- a/lib/application/views/dashboard/widgets/TodaySaleGraph.dart +++ b/lib/application/views/dashboard/widgets/TodaySaleGraph.dart @@ -107,7 +107,7 @@ class TodaySaleGraph extends StatelessWidget { horizontalInterval: 1, verticalInterval: 1, ), - lineTouchData: LineTouchData(enabled: true), + lineTouchData: const LineTouchData(enabled: true), borderData: FlBorderData( show: true, border: Border.all(color: MyColors.fillColorGray2), @@ -133,7 +133,7 @@ class TodaySaleGraph extends StatelessWidget { LineChartBarData( show: true, spots: getSpots(), - isCurved: true, + isCurved: false, gradient: LinearGradient( colors: gradientColors, ), diff --git a/lib/application/views/discountModule/views/NewDiscountVC.dart b/lib/application/views/discountModule/views/NewDiscountVC.dart index 4a78ff3..4c684f4 100644 --- a/lib/application/views/discountModule/views/NewDiscountVC.dart +++ b/lib/application/views/discountModule/views/NewDiscountVC.dart @@ -24,6 +24,7 @@ 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'; @@ -388,6 +389,9 @@ class _NewDiscountVCState extends BaseStatefulState { 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)), diff --git a/lib/application/views/inventorymodule/comboviews/InventoryNewComboVC.dart b/lib/application/views/inventorymodule/comboviews/InventoryNewComboVC.dart index 8954d07..2345ca6 100644 --- a/lib/application/views/inventorymodule/comboviews/InventoryNewComboVC.dart +++ b/lib/application/views/inventorymodule/comboviews/InventoryNewComboVC.dart @@ -22,6 +22,7 @@ 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'; @@ -140,6 +141,9 @@ class _InventoryNewComboVCState extends BaseStatefulState { 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)), @@ -417,6 +421,9 @@ class _InventoryNewComboVCState extends BaseStatefulState { 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)), @@ -435,6 +442,9 @@ class _InventoryNewComboVCState extends BaseStatefulState { 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)), @@ -453,6 +463,9 @@ class _InventoryNewComboVCState extends BaseStatefulState { 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)), @@ -471,6 +484,9 @@ class _InventoryNewComboVCState extends BaseStatefulState { 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)), @@ -489,6 +505,9 @@ class _InventoryNewComboVCState extends BaseStatefulState { 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)), diff --git a/lib/application/views/inventorymodule/ingredientsViews/AddProductIngredientVC.dart b/lib/application/views/inventorymodule/ingredientsViews/AddProductIngredientVC.dart index 8f94d0f..99bcd73 100644 --- a/lib/application/views/inventorymodule/ingredientsViews/AddProductIngredientVC.dart +++ b/lib/application/views/inventorymodule/ingredientsViews/AddProductIngredientVC.dart @@ -24,6 +24,7 @@ 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 { @@ -568,6 +569,9 @@ class _AddProductIngredientVCState 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)), @@ -596,6 +600,9 @@ class _AddProductIngredientVCState 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)), @@ -625,6 +632,9 @@ class _AddProductIngredientVCState 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)), @@ -651,6 +661,9 @@ class _AddProductIngredientVCState 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)), @@ -678,6 +691,9 @@ class _AddProductIngredientVCState 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)), diff --git a/lib/application/views/inventorymodule/measurementviews/InventoryAddMeasurementVC.dart b/lib/application/views/inventorymodule/measurementviews/InventoryAddMeasurementVC.dart index f1eae26..8b022f4 100644 --- a/lib/application/views/inventorymodule/measurementviews/InventoryAddMeasurementVC.dart +++ b/lib/application/views/inventorymodule/measurementviews/InventoryAddMeasurementVC.dart @@ -14,6 +14,7 @@ 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'; @@ -148,6 +149,9 @@ class _InventoryAddMeasurementVCState 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)), diff --git a/lib/application/views/inventorymodule/measurementviews/viewModels/AddMeasurementUnitVM.dart b/lib/application/views/inventorymodule/measurementviews/viewModels/AddMeasurementUnitVM.dart index 63a7ecf..6279657 100644 --- a/lib/application/views/inventorymodule/measurementviews/viewModels/AddMeasurementUnitVM.dart +++ b/lib/application/views/inventorymodule/measurementviews/viewModels/AddMeasurementUnitVM.dart @@ -10,13 +10,12 @@ class AddMeasurementUnitVM with ChangeNotifier { bool _isLoading = false; bool get isLoading => _isLoading; - - String unitName = ''; - var _crudOperation = CRUDOperationState.uninitialized; CRUDOperationState get crudOperation => _crudOperation; + String unitName = ''; + void disposeData() { unitName = ''; } diff --git a/lib/application/views/inventorymodule/modiferOption/views/NewModifierOptionVC.dart b/lib/application/views/inventorymodule/modiferOption/views/NewModifierOptionVC.dart index 400bf7a..ad66d49 100644 --- a/lib/application/views/inventorymodule/modiferOption/views/NewModifierOptionVC.dart +++ b/lib/application/views/inventorymodule/modiferOption/views/NewModifierOptionVC.dart @@ -19,6 +19,7 @@ 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'; @@ -176,6 +177,9 @@ class _NewModifierOptionVCState extends State { 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), @@ -201,6 +205,9 @@ class _NewModifierOptionVCState extends State { 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), @@ -363,6 +370,9 @@ class _NewModifierOptionVCState extends State { 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), diff --git a/lib/application/views/inventorymodule/productviews/AddNewInventoryProductVC.dart b/lib/application/views/inventorymodule/productviews/AddNewInventoryProductVC.dart index 2d608ff..8106292 100644 --- a/lib/application/views/inventorymodule/productviews/AddNewInventoryProductVC.dart +++ b/lib/application/views/inventorymodule/productviews/AddNewInventoryProductVC.dart @@ -33,6 +33,7 @@ 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'; @@ -502,6 +503,9 @@ class _AddNewInventoryProductVCState extends State 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)), @@ -531,6 +535,9 @@ class _AddNewInventoryProductVCState extends State 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)), @@ -559,6 +566,9 @@ class _AddNewInventoryProductVCState extends State 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)), @@ -587,6 +597,9 @@ class _AddNewInventoryProductVCState extends State 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)), @@ -615,6 +628,9 @@ class _AddNewInventoryProductVCState extends State 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)), @@ -642,6 +658,9 @@ class _AddNewInventoryProductVCState extends State 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)), @@ -782,6 +801,9 @@ class _AddNewInventoryProductVCState extends State 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)), @@ -811,6 +833,9 @@ class _AddNewInventoryProductVCState extends State 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)), diff --git a/lib/application/views/inventorymodule/stockReturn/views/NewStockReturnVC.dart b/lib/application/views/inventorymodule/stockReturn/views/NewStockReturnVC.dart index c009579..12df54e 100644 --- a/lib/application/views/inventorymodule/stockReturn/views/NewStockReturnVC.dart +++ b/lib/application/views/inventorymodule/stockReturn/views/NewStockReturnVC.dart @@ -28,6 +28,7 @@ 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'; @@ -680,6 +681,9 @@ class _NewStockReturnVCState extends State { 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)), @@ -709,6 +713,9 @@ class _NewStockReturnVCState extends State { 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)), @@ -735,6 +742,9 @@ class _NewStockReturnVCState extends State { 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)), @@ -791,6 +801,9 @@ class _NewStockReturnVCState extends State { 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)), @@ -854,6 +867,9 @@ class _NewStockReturnVCState extends State { 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, @@ -927,6 +943,9 @@ class _NewStockReturnVCState extends State { 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)), @@ -951,6 +970,9 @@ class _NewStockReturnVCState extends State { 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)), @@ -989,6 +1011,9 @@ class _NewStockReturnVCState extends State { 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)), diff --git a/lib/application/views/inventorymodule/stockTransferViews/InventoryNewStockTransferVC.dart b/lib/application/views/inventorymodule/stockTransferViews/InventoryNewStockTransferVC.dart index ecd3cd1..82d8132 100644 --- a/lib/application/views/inventorymodule/stockTransferViews/InventoryNewStockTransferVC.dart +++ b/lib/application/views/inventorymodule/stockTransferViews/InventoryNewStockTransferVC.dart @@ -15,6 +15,7 @@ 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'; @@ -182,6 +183,9 @@ class _InventoryNewStockTransferVCState 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, @@ -210,6 +214,9 @@ class _InventoryNewStockTransferVCState 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), @@ -355,6 +362,9 @@ class _InventoryNewStockTransferVCState 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), diff --git a/lib/application/views/inventorymodule/subCategoryViews/InventorySubCategoryVC.dart b/lib/application/views/inventorymodule/subCategoryViews/InventorySubCategoryVC.dart index 3b63863..9c129dc 100644 --- a/lib/application/views/inventorymodule/subCategoryViews/InventorySubCategoryVC.dart +++ b/lib/application/views/inventorymodule/subCategoryViews/InventorySubCategoryVC.dart @@ -15,6 +15,7 @@ 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'; class InventorySubCategoryVC extends StatefulWidget { @@ -250,6 +251,9 @@ class _InventorySubCategoryVCState 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)), diff --git a/lib/application/views/inventorymodule/subCategoryViews/SubCategoryVC.dart b/lib/application/views/inventorymodule/subCategoryViews/SubCategoryVC.dart index 173195a..b108980 100644 --- a/lib/application/views/inventorymodule/subCategoryViews/SubCategoryVC.dart +++ b/lib/application/views/inventorymodule/subCategoryViews/SubCategoryVC.dart @@ -23,6 +23,8 @@ 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}); @@ -214,6 +216,9 @@ class _SubCategoryVCState extends State { 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)), diff --git a/lib/application/views/salesandordermodule/views/invoiceModule/views/InvoiceMakePaymentVC.dart b/lib/application/views/salesandordermodule/views/invoiceModule/views/InvoiceMakePaymentVC.dart index 8015eb6..c7e85a8 100644 --- a/lib/application/views/salesandordermodule/views/invoiceModule/views/InvoiceMakePaymentVC.dart +++ b/lib/application/views/salesandordermodule/views/invoiceModule/views/InvoiceMakePaymentVC.dart @@ -19,6 +19,7 @@ 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'; @@ -220,9 +221,12 @@ class _InvoiceMakePaymentVCState extends State { 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: BoxConstraints(maxHeight: 250)), + constraints: const BoxConstraints(maxHeight: 250)), items: viewModel.accounts, itemAsString: (Account u) => u.name, onChanged: (Account? data) { @@ -258,11 +262,14 @@ class _InvoiceMakePaymentVCState extends State { DropdownSearch( dropdownButtonProps: ThemeDropDown.dropdownButtonProps, popupProps: PopupProps.menu( + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.paymentMethod!); + }, menuProps: ThemeDropDown.menuProps, fit: FlexFit.loose, - constraints: BoxConstraints(maxHeight: 250)), + constraints: const BoxConstraints(maxHeight: 250)), items: viewModel.paymentMethod, - itemAsString: (PaymentMethod u) => u.paymentMethod, + itemAsString: (PaymentMethod u) => u.paymentMethod!, onChanged: (PaymentMethod? data) { viewModel.setPaymentMethod(data); }, diff --git a/lib/application/views/salesandordermodule/views/invoiceModule/views/InvoicesVC.dart b/lib/application/views/salesandordermodule/views/invoiceModule/views/InvoicesVC.dart index f3f4d9e..8de5b6c 100644 --- a/lib/application/views/salesandordermodule/views/invoiceModule/views/InvoicesVC.dart +++ b/lib/application/views/salesandordermodule/views/invoiceModule/views/InvoicesVC.dart @@ -20,6 +20,7 @@ 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'; @@ -273,6 +274,9 @@ class _InvoicesVCState extends BaseStatefulState { 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), ), diff --git a/lib/application/views/salesandordermodule/views/invoiceModule/views/NewInvoiceVC.dart b/lib/application/views/salesandordermodule/views/invoiceModule/views/NewInvoiceVC.dart index d9e46d8..7b42031 100644 --- a/lib/application/views/salesandordermodule/views/invoiceModule/views/NewInvoiceVC.dart +++ b/lib/application/views/salesandordermodule/views/invoiceModule/views/NewInvoiceVC.dart @@ -28,6 +28,7 @@ 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'; @@ -957,6 +958,9 @@ class _NewInvoiceVCState extends BaseStatefulState { 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], @@ -975,6 +979,9 @@ class _NewInvoiceVCState extends BaseStatefulState { 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], @@ -995,6 +1002,9 @@ class _NewInvoiceVCState extends BaseStatefulState { 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, @@ -1015,6 +1025,9 @@ class _NewInvoiceVCState extends BaseStatefulState { 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: @@ -1065,6 +1078,9 @@ class _NewInvoiceVCState extends BaseStatefulState { 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], @@ -1090,6 +1106,9 @@ class _NewInvoiceVCState extends BaseStatefulState { 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, @@ -1195,6 +1214,9 @@ class _NewInvoiceVCState extends BaseStatefulState { 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, @@ -1226,6 +1248,9 @@ class _NewInvoiceVCState extends BaseStatefulState { 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, @@ -1376,6 +1401,9 @@ class _NewInvoiceVCState extends BaseStatefulState { showSearchBox: true, isFilterOnline: false, menuProps: ThemeDropDown.menuProps, + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name ?? ''); + }, fit: FlexFit.loose, constraints: const BoxConstraints(maxHeight: 200), ), diff --git a/lib/application/views/salesandordermodule/views/ordersModule/OrderVC.dart b/lib/application/views/salesandordermodule/views/ordersModule/OrderVC.dart index bf5c087..915550b 100644 --- a/lib/application/views/salesandordermodule/views/ordersModule/OrderVC.dart +++ b/lib/application/views/salesandordermodule/views/ordersModule/OrderVC.dart @@ -19,6 +19,7 @@ import 'package:wosull/application/views/transactions/widgets/CashierOrderListVi 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'; @@ -250,6 +251,9 @@ class _OrderVCState extends State implements TransactionCVS { 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, diff --git a/lib/application/views/salesandordermodule/views/quotataionModule/NewQuotationsVC.dart b/lib/application/views/salesandordermodule/views/quotataionModule/NewQuotationsVC.dart index d64c528..8e4fccb 100644 --- a/lib/application/views/salesandordermodule/views/quotataionModule/NewQuotationsVC.dart +++ b/lib/application/views/salesandordermodule/views/quotataionModule/NewQuotationsVC.dart @@ -26,6 +26,7 @@ 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'; @@ -939,6 +940,9 @@ class _NewQuotationsVCState extends BaseStatefulState { showSearchBox: true, isFilterOnline: false, menuProps: ThemeDropDown.menuProps, + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item.name ?? ''); + }, fit: FlexFit.loose, constraints: const BoxConstraints(maxHeight: 200), ), @@ -959,6 +963,9 @@ class _NewQuotationsVCState extends BaseStatefulState { // 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), ), @@ -1009,6 +1016,9 @@ class _NewQuotationsVCState extends BaseStatefulState { 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), ), @@ -1028,6 +1038,9 @@ class _NewQuotationsVCState extends BaseStatefulState { 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), ), @@ -1047,6 +1060,9 @@ class _NewQuotationsVCState extends BaseStatefulState { 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), ), @@ -1068,6 +1084,9 @@ class _NewQuotationsVCState extends BaseStatefulState { 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), ), @@ -1095,6 +1114,9 @@ class _NewQuotationsVCState extends BaseStatefulState { 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), ), @@ -1127,6 +1149,9 @@ class _NewQuotationsVCState extends BaseStatefulState { 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), ), @@ -1217,6 +1242,9 @@ class _NewQuotationsVCState extends BaseStatefulState { 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), ), diff --git a/lib/application/views/salesandordermodule/views/quotataionModule/QuotationsVC.dart b/lib/application/views/salesandordermodule/views/quotataionModule/QuotationsVC.dart index 0945c17..9eb048c 100644 --- a/lib/application/views/salesandordermodule/views/quotataionModule/QuotationsVC.dart +++ b/lib/application/views/salesandordermodule/views/quotataionModule/QuotationsVC.dart @@ -19,6 +19,7 @@ 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'; @@ -257,7 +258,12 @@ class _QuotationsVCState extends BaseStatefulState { return DropdownSearch( dropdownButtonProps: ThemeDropDown.dropdownButtonProps, popupProps: PopupProps.menu( - menuProps: ThemeDropDown.menuProps, fit: FlexFit.loose), + menuProps: ThemeDropDown.menuProps, + itemBuilder: (context, item, value) { + return DropdownItemBuilder(title: item); + }, + fit: FlexFit.loose, + ), items: Constants.quotationStatus, itemAsString: (String u) => u, onChanged: (String? data) { diff --git a/lib/application/views/settings/SettingsMainVC.dart b/lib/application/views/settings/SettingsMainVC.dart index d53e136..fa41e78 100644 --- a/lib/application/views/settings/SettingsMainVC.dart +++ b/lib/application/views/settings/SettingsMainVC.dart @@ -3,12 +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 @@ -19,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, @@ -94,6 +96,9 @@ class _SettingsMainVCState extends State { Tab( text: AppLocalizations.of(context)!.reports, ), + const Tab( + text: 'Payment Methods', + ), ], ) ], @@ -101,7 +106,7 @@ class _SettingsMainVCState extends State { ), const Expanded( child: TabBarView( - children: [ReportsVC()], + children: [ReportsVC(), PaymentMethodVC()], )) ], ), 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..006858c --- /dev/null +++ b/lib/application/views/settings/views/paymentMethods/repo/PaymentMethodRepository.dart @@ -0,0 +1,24 @@ +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.searchCashier, 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..ae8c719 --- /dev/null +++ b/lib/application/views/settings/views/paymentMethods/viewModel/NewPaymentMethodViewModel.dart @@ -0,0 +1,72 @@ +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 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..e6e20c0 --- /dev/null +++ b/lib/application/views/settings/views/paymentMethods/views/NewPaymentMethodVC.dart @@ -0,0 +1,202 @@ +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 + 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..2856173 --- /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: 150, + 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/ReportsVC.dart b/lib/application/views/settings/views/reports/ReportsVC.dart similarity index 89% rename from lib/application/views/settings/ReportsVC.dart rename to lib/application/views/settings/views/reports/ReportsVC.dart index cfb04b5..96a8d99 100644 --- a/lib/application/views/settings/ReportsVC.dart +++ b/lib/application/views/settings/views/reports/ReportsVC.dart @@ -13,20 +13,20 @@ 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/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/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'; -import 'reportsViews/POSCompleteVC.dart'; -import 'reportsViews/ReportsProductsVC.dart'; - class ReportsVC extends StatefulWidget { const ReportsVC({super.key}); @@ -209,7 +209,11 @@ class _ReportsVCState extends BaseStatefulState 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), diff --git a/lib/application/views/settings/reportsViews/BestSuppliersVC.dart b/lib/application/views/settings/views/reportsViews/BestSuppliersVC.dart similarity index 100% rename from lib/application/views/settings/reportsViews/BestSuppliersVC.dart rename to lib/application/views/settings/views/reportsViews/BestSuppliersVC.dart diff --git a/lib/application/views/settings/reportsViews/POSCompleteVC.dart b/lib/application/views/settings/views/reportsViews/POSCompleteVC.dart similarity index 100% rename from lib/application/views/settings/reportsViews/POSCompleteVC.dart rename to lib/application/views/settings/views/reportsViews/POSCompleteVC.dart diff --git a/lib/application/views/settings/reportsViews/POSReturnOrderVC.dart b/lib/application/views/settings/views/reportsViews/POSReturnOrderVC.dart similarity index 100% rename from lib/application/views/settings/reportsViews/POSReturnOrderVC.dart rename to lib/application/views/settings/views/reportsViews/POSReturnOrderVC.dart diff --git a/lib/application/views/settings/reportsViews/ReportsCategoryVC.dart b/lib/application/views/settings/views/reportsViews/ReportsCategoryVC.dart similarity index 100% rename from lib/application/views/settings/reportsViews/ReportsCategoryVC.dart rename to lib/application/views/settings/views/reportsViews/ReportsCategoryVC.dart diff --git a/lib/application/views/settings/reportsViews/ReportsCustomerVC.dart b/lib/application/views/settings/views/reportsViews/ReportsCustomerVC.dart similarity index 99% rename from lib/application/views/settings/reportsViews/ReportsCustomerVC.dart rename to lib/application/views/settings/views/reportsViews/ReportsCustomerVC.dart index d16eb17..0ed9ac0 100644 --- a/lib/application/views/settings/reportsViews/ReportsCustomerVC.dart +++ b/lib/application/views/settings/views/reportsViews/ReportsCustomerVC.dart @@ -7,9 +7,9 @@ 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; @@ -50,9 +50,7 @@ class _ReportsCustomerVCState extends State { child: Column( children: [ isLoading - ? const Center( - child: CircularProgressIndicator(), - ) + ? AppLoader() : customers.isEmpty ? const EmptyDataWidget() : Column( diff --git a/lib/application/views/settings/reportsViews/ReportsInvoiceVC.dart b/lib/application/views/settings/views/reportsViews/ReportsInvoiceVC.dart similarity index 100% rename from lib/application/views/settings/reportsViews/ReportsInvoiceVC.dart rename to lib/application/views/settings/views/reportsViews/ReportsInvoiceVC.dart diff --git a/lib/application/views/settings/reportsViews/ReportsProductsVC.dart b/lib/application/views/settings/views/reportsViews/ReportsProductsVC.dart similarity index 100% rename from lib/application/views/settings/reportsViews/ReportsProductsVC.dart rename to lib/application/views/settings/views/reportsViews/ReportsProductsVC.dart diff --git a/lib/application/views/settings/reportsViews/ReportsQuotationVC.dart b/lib/application/views/settings/views/reportsViews/ReportsQuotationVC.dart similarity index 100% rename from lib/application/views/settings/reportsViews/ReportsQuotationVC.dart rename to lib/application/views/settings/views/reportsViews/ReportsQuotationVC.dart 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/transactions/TransactionVC.dart b/lib/application/views/transactions/TransactionVC.dart index e9650d3..6f24103 100644 --- a/lib/application/views/transactions/TransactionVC.dart +++ b/lib/application/views/transactions/TransactionVC.dart @@ -16,6 +16,7 @@ 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'; @@ -209,12 +210,7 @@ class _TransactionVCState extends BaseStatefulState selectedItem: selectedReport, popupProps: PopupProps.menu( itemBuilder: (context, item, value) { - return SizedBox( - height: 38, - child: Center( - child: Text(item, style: ThemeDropDown.dropDownTextStyle), - ), - ); + return DropdownItemBuilder(title: item); }, fit: FlexFit.loose, menuProps: ThemeDropDown.menuProps, diff --git a/lib/application/views/transactions/return/ReturnReasonPopUp.dart b/lib/application/views/transactions/return/ReturnReasonPopUp.dart index 7ff8f29..6fc6cba 100644 --- a/lib/application/views/transactions/return/ReturnReasonPopUp.dart +++ b/lib/application/views/transactions/return/ReturnReasonPopUp.dart @@ -7,6 +7,7 @@ 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 { @@ -100,6 +101,9 @@ class _ReturnReasonPopUpState extends State { 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, @@ -119,6 +123,9 @@ class _ReturnReasonPopUpState extends State { 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)), diff --git a/lib/application/views/transactions/views/EditOrderVC.dart b/lib/application/views/transactions/views/EditOrderVC.dart index 740082e..3bc1030 100644 --- a/lib/application/views/transactions/views/EditOrderVC.dart +++ b/lib/application/views/transactions/views/EditOrderVC.dart @@ -24,6 +24,7 @@ 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'; @@ -594,6 +595,9 @@ class _EditOrderVCState extends State { 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, @@ -623,6 +627,9 @@ class _EditOrderVCState extends State { 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, @@ -652,6 +659,9 @@ class _EditOrderVCState extends State { 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, @@ -675,6 +685,9 @@ class _EditOrderVCState extends State { 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, @@ -693,6 +706,9 @@ class _EditOrderVCState extends State { 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", diff --git a/lib/widgets/DiscountDropdown.dart b/lib/widgets/DiscountDropdown.dart index 451cafd..5e585b4 100644 --- a/lib/widgets/DiscountDropdown.dart +++ b/lib/widgets/DiscountDropdown.dart @@ -7,6 +7,7 @@ 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; @@ -51,12 +52,16 @@ class DiscountDropdown extends StatelessWidget { Widget dropDown(List itemsList) { return SizedBox( - height: 42, width: double.infinity, child: DropdownSearch( dropdownButtonProps: ThemeDropDown.dropdownButtonProps, - popupProps: const PopupProps.menu( - fit: FlexFit.loose, constraints: BoxConstraints(maxHeight: 200)), + 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!, diff --git a/lib/widgets/DropdownItemBuilder.dart b/lib/widgets/DropdownItemBuilder.dart new file mode 100644 index 0000000..952db2b --- /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: 38, + 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/ItemCategoryDropdown.dart b/lib/widgets/ItemCategoryDropdown.dart index a912ecd..2f0bd57 100644 --- a/lib/widgets/ItemCategoryDropdown.dart +++ b/lib/widgets/ItemCategoryDropdown.dart @@ -7,6 +7,7 @@ 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; @@ -45,6 +46,9 @@ class ItemCategoryDropdown extends StatelessWidget { 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, diff --git a/lib/widgets/PageLimitDropDown.dart b/lib/widgets/PageLimitDropDown.dart index 1c4fa49..eeb15a5 100644 --- a/lib/widgets/PageLimitDropDown.dart +++ b/lib/widgets/PageLimitDropDown.dart @@ -5,6 +5,7 @@ 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; @@ -44,6 +45,9 @@ class PageLimitDropdown extends StatelessWidget { 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, From c3766c6b735fa94edca38c08ede71568931e1808 Mon Sep 17 00:00:00 2001 From: waqasYeepeey Date: Mon, 20 Nov 2023 15:07:26 +0500 Subject: [PATCH 10/11] last --- lib/application/model/home/DrawerItem.dart | 0 .../views/authModule/repo/AuthRepository.dart | 0 .../repo/BillingCounterRepository.dart | 0 .../viewModels/DineInViewModel.dart | 0 .../viewModels/ItemModifiersViewModel.dart | 0 .../dashboard/repo/DashBoardRepository.dart | 0 .../repo/DiscountRepository.dart | 0 .../DownloadBestSellerReportViewModel.dart | 0 .../DownloadCategoryReportViewModel.dart | 0 .../DownloadPOSCompleteReportViewModel.dart | 0 .../DownloadPOSReturnDamageViewModel.dart | 0 .../viewModel/DownloadProductViewModel.dart | 0 .../views/DownloadReportMainVC.dart | 0 .../dowloadReports/views/DownloadReports.dart | 0 .../widgets/BestSellerReportView.dart | 0 .../widgets/DownloadCategoriesView.dart | 0 .../widgets/DownloadDiscountView.dart | 0 .../widgets/DownloadInventoryReport.dart | 0 .../widgets/DownloadInvoiceView.dart | 0 .../widgets/DownloadOrderReportView.dart | 0 .../widgets/DownloadPOSCompleteView.dart | 0 .../widgets/DownloadPOSReturnAndDamage.dart | 0 .../widgets/DownloadProductsView.dart | 0 .../widgets/DownloadQuotationView.dart | 0 .../widgets/DownloadReportView.dart | 0 .../widgets/DownloadStockStatusView.dart | 0 .../comboviews/repo/ComboRepository.dart | 0 .../repo/IngredientRepository.dart | 0 .../repo/MeasurementsRepository.dart | 0 .../repo/ModifierOptionRepository.dart | 23 +++++++++++++++++++ .../repo/ModifierRepository.dart | 0 .../productviews/repo/ProductRepository.dart | 0 .../repo/StockReturnRepository.dart | 0 .../repo/StockTransferRepository.dart | 0 .../repo/SubCategoryRepository.dart | 0 .../views/kitchen/repo/KitchenRepository.dart | 0 .../kitchen}/viewModel/KitchenViewModel.dart | 0 .../views/table/repo/TableRepository.dart | 0 .../table/viewModels}/TablesViewModel.dart | 0 .../ordersModule/repo/OrderRepository.dart | 0 .../CustomControllerTextFieldForm.dart | 0 lib/widgets/CustomIconButton.dart | 0 42 files changed, 23 insertions(+) create mode 100644 lib/application/model/home/DrawerItem.dart create mode 100644 lib/application/views/authModule/repo/AuthRepository.dart create mode 100644 lib/application/views/billingCounterDashboard/repo/BillingCounterRepository.dart create mode 100644 lib/application/views/create_order_module/viewModels/DineInViewModel.dart create mode 100644 lib/application/views/create_order_module/viewModels/ItemModifiersViewModel.dart create mode 100644 lib/application/views/dashboard/repo/DashBoardRepository.dart create mode 100644 lib/application/views/discountModule/repo/DiscountRepository.dart create mode 100644 lib/application/views/dowloadReports/viewModel/DownloadBestSellerReportViewModel.dart create mode 100644 lib/application/views/dowloadReports/viewModel/DownloadCategoryReportViewModel.dart create mode 100644 lib/application/views/dowloadReports/viewModel/DownloadPOSCompleteReportViewModel.dart create mode 100644 lib/application/views/dowloadReports/viewModel/DownloadPOSReturnDamageViewModel.dart create mode 100644 lib/application/views/dowloadReports/viewModel/DownloadProductViewModel.dart create mode 100644 lib/application/views/dowloadReports/views/DownloadReportMainVC.dart create mode 100644 lib/application/views/dowloadReports/views/DownloadReports.dart create mode 100644 lib/application/views/dowloadReports/widgets/BestSellerReportView.dart create mode 100644 lib/application/views/dowloadReports/widgets/DownloadCategoriesView.dart create mode 100644 lib/application/views/dowloadReports/widgets/DownloadDiscountView.dart create mode 100644 lib/application/views/dowloadReports/widgets/DownloadInventoryReport.dart create mode 100644 lib/application/views/dowloadReports/widgets/DownloadInvoiceView.dart create mode 100644 lib/application/views/dowloadReports/widgets/DownloadOrderReportView.dart create mode 100644 lib/application/views/dowloadReports/widgets/DownloadPOSCompleteView.dart create mode 100644 lib/application/views/dowloadReports/widgets/DownloadPOSReturnAndDamage.dart create mode 100644 lib/application/views/dowloadReports/widgets/DownloadProductsView.dart create mode 100644 lib/application/views/dowloadReports/widgets/DownloadQuotationView.dart create mode 100644 lib/application/views/dowloadReports/widgets/DownloadReportView.dart create mode 100644 lib/application/views/dowloadReports/widgets/DownloadStockStatusView.dart create mode 100644 lib/application/views/inventorymodule/comboviews/repo/ComboRepository.dart create mode 100644 lib/application/views/inventorymodule/ingredientsViews/repo/IngredientRepository.dart create mode 100644 lib/application/views/inventorymodule/measurementviews/repo/MeasurementsRepository.dart create mode 100644 lib/application/views/inventorymodule/modiferOption/repo/ModifierOptionRepository.dart create mode 100644 lib/application/views/inventorymodule/modifierviews/repo/ModifierRepository.dart create mode 100644 lib/application/views/inventorymodule/productviews/repo/ProductRepository.dart create mode 100644 lib/application/views/inventorymodule/stockReturn/repo/StockReturnRepository.dart create mode 100644 lib/application/views/inventorymodule/stockTransferViews/repo/StockTransferRepository.dart create mode 100644 lib/application/views/inventorymodule/subCategoryViews/repo/SubCategoryRepository.dart create mode 100644 lib/application/views/kitchenmodule/views/kitchen/repo/KitchenRepository.dart rename lib/application/views/kitchenmodule/{ => views/kitchen}/viewModel/KitchenViewModel.dart (100%) create mode 100644 lib/application/views/kitchenmodule/views/table/repo/TableRepository.dart rename lib/application/views/kitchenmodule/{viewModel => views/table/viewModels}/TablesViewModel.dart (100%) create mode 100644 lib/application/views/salesandordermodule/views/ordersModule/repo/OrderRepository.dart create mode 100644 lib/widgets/CustomControllerTextFieldForm.dart create mode 100644 lib/widgets/CustomIconButton.dart diff --git a/lib/application/model/home/DrawerItem.dart b/lib/application/model/home/DrawerItem.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/application/views/authModule/repo/AuthRepository.dart b/lib/application/views/authModule/repo/AuthRepository.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/application/views/billingCounterDashboard/repo/BillingCounterRepository.dart b/lib/application/views/billingCounterDashboard/repo/BillingCounterRepository.dart new file mode 100644 index 0000000..e69de29 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..e69de29 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..e69de29 diff --git a/lib/application/views/dashboard/repo/DashBoardRepository.dart b/lib/application/views/dashboard/repo/DashBoardRepository.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/application/views/discountModule/repo/DiscountRepository.dart b/lib/application/views/discountModule/repo/DiscountRepository.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/application/views/dowloadReports/viewModel/DownloadBestSellerReportViewModel.dart b/lib/application/views/dowloadReports/viewModel/DownloadBestSellerReportViewModel.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/application/views/dowloadReports/viewModel/DownloadCategoryReportViewModel.dart b/lib/application/views/dowloadReports/viewModel/DownloadCategoryReportViewModel.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/application/views/dowloadReports/viewModel/DownloadPOSCompleteReportViewModel.dart b/lib/application/views/dowloadReports/viewModel/DownloadPOSCompleteReportViewModel.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/application/views/dowloadReports/viewModel/DownloadPOSReturnDamageViewModel.dart b/lib/application/views/dowloadReports/viewModel/DownloadPOSReturnDamageViewModel.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/application/views/dowloadReports/viewModel/DownloadProductViewModel.dart b/lib/application/views/dowloadReports/viewModel/DownloadProductViewModel.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/application/views/dowloadReports/views/DownloadReportMainVC.dart b/lib/application/views/dowloadReports/views/DownloadReportMainVC.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/application/views/dowloadReports/views/DownloadReports.dart b/lib/application/views/dowloadReports/views/DownloadReports.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/application/views/dowloadReports/widgets/BestSellerReportView.dart b/lib/application/views/dowloadReports/widgets/BestSellerReportView.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/application/views/dowloadReports/widgets/DownloadCategoriesView.dart b/lib/application/views/dowloadReports/widgets/DownloadCategoriesView.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/application/views/dowloadReports/widgets/DownloadDiscountView.dart b/lib/application/views/dowloadReports/widgets/DownloadDiscountView.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/application/views/dowloadReports/widgets/DownloadInventoryReport.dart b/lib/application/views/dowloadReports/widgets/DownloadInventoryReport.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/application/views/dowloadReports/widgets/DownloadInvoiceView.dart b/lib/application/views/dowloadReports/widgets/DownloadInvoiceView.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/application/views/dowloadReports/widgets/DownloadOrderReportView.dart b/lib/application/views/dowloadReports/widgets/DownloadOrderReportView.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/application/views/dowloadReports/widgets/DownloadPOSCompleteView.dart b/lib/application/views/dowloadReports/widgets/DownloadPOSCompleteView.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/application/views/dowloadReports/widgets/DownloadPOSReturnAndDamage.dart b/lib/application/views/dowloadReports/widgets/DownloadPOSReturnAndDamage.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/application/views/dowloadReports/widgets/DownloadProductsView.dart b/lib/application/views/dowloadReports/widgets/DownloadProductsView.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/application/views/dowloadReports/widgets/DownloadQuotationView.dart b/lib/application/views/dowloadReports/widgets/DownloadQuotationView.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/application/views/dowloadReports/widgets/DownloadReportView.dart b/lib/application/views/dowloadReports/widgets/DownloadReportView.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/application/views/dowloadReports/widgets/DownloadStockStatusView.dart b/lib/application/views/dowloadReports/widgets/DownloadStockStatusView.dart new file mode 100644 index 0000000..e69de29 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..e69de29 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..e69de29 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..e69de29 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..8b994bf --- /dev/null +++ b/lib/application/views/inventorymodule/modiferOption/repo/ModifierOptionRepository.dart @@ -0,0 +1,23 @@ +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 ModifierRepository { + Future> fetch(Map map) async { + await APIManager() + .getResponseAuth( + Constants.getModifierOptions + sharedPrefs.storeId, map) + .then((result) { + final value = ModifierOptionsResponse.fromJson(result); + if (value.status!) {} + }).onError((error, stackTrace) {}); + } + + Future addUpdateModifierOption( + Map map) async { + return await APIManager().fetchData(Constants.addModifierOptions, map); + } +} 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..e69de29 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..e69de29 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..e69de29 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..e69de29 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..e69de29 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..e69de29 diff --git a/lib/application/views/kitchenmodule/viewModel/KitchenViewModel.dart b/lib/application/views/kitchenmodule/views/kitchen/viewModel/KitchenViewModel.dart similarity index 100% rename from lib/application/views/kitchenmodule/viewModel/KitchenViewModel.dart rename to lib/application/views/kitchenmodule/views/kitchen/viewModel/KitchenViewModel.dart 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..e69de29 diff --git a/lib/application/views/kitchenmodule/viewModel/TablesViewModel.dart b/lib/application/views/kitchenmodule/views/table/viewModels/TablesViewModel.dart similarity index 100% rename from lib/application/views/kitchenmodule/viewModel/TablesViewModel.dart rename to lib/application/views/kitchenmodule/views/table/viewModels/TablesViewModel.dart 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..e69de29 diff --git a/lib/widgets/CustomControllerTextFieldForm.dart b/lib/widgets/CustomControllerTextFieldForm.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/widgets/CustomIconButton.dart b/lib/widgets/CustomIconButton.dart new file mode 100644 index 0000000..e69de29 From 349af75da0386b8fe3e5a53c6759cc315b66e04e Mon Sep 17 00:00:00 2001 From: waqasYeepeey Date: Mon, 20 Nov 2023 15:10:00 +0500 Subject: [PATCH 11/11] first commit --- ios/Podfile.lock | 6 + ios/Runner/Info.plist | 4 + lib/application/MyApp.dart | 15 + .../model/Products/ItemProductModel.dart | 10 +- .../model/auth/AccessTokenModel.dart | 4 +- .../model/discount/StoreDiscountModel.dart | 11 +- lib/application/model/home/DrawerItem.dart | 8 + .../model/invoice/PaymentMethod.dart | 2 +- lib/application/repo/AuthRepository.dart | 1 + .../repository/WosulRepository.dart | 110 ++++++ lib/application/utils/Constants.dart | 13 + .../viewModel/CheckInViewModel.dart | 1 + .../loginViews/viewModel/LoginViewModel.dart | 37 +- .../registerViews/CategoryPopUp.dart | 2 +- .../authModule/registerViews/CityPopUp.dart | 2 +- .../authModule/registerViews/RegisterVC.dart | 334 +++++------------- .../viewModel/AuthViewModel.dart | 211 ++++++++--- .../viewModel/CityViewModel.dart | 2 +- .../views/authModule/repo/AuthRepository.dart | 70 ++++ .../BillingCounterDashBoard.dart | 8 +- .../BillingCounterMainVC.dart | 78 +--- .../repo/BillingCounterRepository.dart | 12 + .../viewModels/BillingCounterViewModel.dart | 13 +- .../views/create_order_module/CartVC.dart | 6 +- .../viewModels/CounterCloseViewMdoel.dart | 2 + .../viewModels/DineInViewModel.dart | 79 +++++ .../viewModels/ItemModifiersViewModel.dart | 97 +++++ .../views/PrintReceiptVC.dart | 5 +- .../views/TabBarHomeVC.dart | 2 +- .../views/popups/DineInPopup.dart | 125 ++----- .../views/popups/ItemModifiersPopUp.dart | 269 +++----------- lib/application/views/dashboard/HomeVC.dart | 3 - .../dashboard/repo/DashBoardRepository.dart | 34 ++ .../viewModel/DashboardViewModel.dart | 31 +- .../dashboard/widgets/TodayPOSSales.dart | 2 +- .../dashboard/widgets/TodaySaleGraph.dart | 1 - .../repo/DiscountRepository.dart | 67 ++++ .../viewModels/DiscountViewModel.dart | 39 +- .../viewModels/NewDiscountViewModel.dart | 46 +-- .../discountModule/views/DiscountVC.dart | 5 +- .../DownloadBestSellerReportViewModel.dart | 144 ++++++++ .../DownloadCategoryReportViewModel.dart | 25 ++ .../DownloadPOSCompleteReportViewModel.dart | 3 + .../DownloadPOSReturnDamageViewModel.dart | 25 ++ .../viewModel/DownloadProductViewModel.dart | 25 ++ .../views/DownloadReportMainVC.dart | 56 +++ .../dowloadReports/views/DownloadReports.dart | 96 +++++ .../widgets/BestSellerReportView.dart | 110 ++++++ .../widgets/DownloadCategoriesView.dart | 143 ++++++++ .../widgets/DownloadDiscountView.dart | 139 ++++++++ .../widgets/DownloadInventoryReport.dart | 139 ++++++++ .../widgets/DownloadInvoiceView.dart | 139 ++++++++ .../widgets/DownloadOrderReportView.dart | 173 +++++++++ .../widgets/DownloadPOSCompleteView.dart | 108 ++++++ .../widgets/DownloadPOSReturnAndDamage.dart | 143 ++++++++ .../widgets/DownloadProductsView.dart | 204 +++++++++++ .../widgets/DownloadQuotationView.dart | 138 ++++++++ .../widgets/DownloadReportView.dart | 180 ++++++++++ .../widgets/DownloadStockStatusView.dart | 173 +++++++++ lib/application/views/home/HomePage.dart | 288 +++++---------- .../views/home/HomePageViewModel.dart | 17 +- .../InventoryCategoriesModule.dart | 5 - .../comboviews/InventoryComboVC.dart | 19 +- .../comboviews/InventoryNewComboVC.dart | 1 + .../comboviews/repo/ComboRepository.dart | 44 +++ .../viewModels/AddComboGroupViewModel.dart | 13 +- .../viewModels/AddComboSizeViewModel.dart | 20 +- .../viewModels/AddNewComboViewModel.dart | 61 ++-- .../comboviews/viewModels/ComboViewModel.dart | 22 +- .../InventoryDeliveryPartnerPriceVC.dart | 17 +- .../AddProductIngredientVC.dart | 2 +- .../ingredientsViews/IngredientsVC.dart | 14 +- .../repo/IngredientRepository.dart | 71 ++++ .../viewModels/AddIngredientViewModel.dart | 218 +++--------- .../viewModels/IngredientViewModel.dart | 41 +-- .../repo/MeasurementsRepository.dart | 43 +++ .../viewModels/AddMeasurementUnitVM.dart | 15 +- .../viewModels/AddMeasurementViewModel.dart | 36 +- .../viewModels/MeasurementViewModel.dart | 29 +- .../repo/ModifierOptionRepository.dart | 20 +- .../viewModels/ModifierOptionsViewModel.dart | 29 +- .../NewModifierOptionViewModel.dart | 56 ++- .../views/NewModifierOptionVC.dart | 6 + .../repo/ModifierRepository.dart | 55 +++ .../viewModels/ModiferViewModel.dart | 44 +-- .../viewModels/NewModifierVM.dart | 22 +- .../productviews/InventoryProductVC.dart | 15 +- .../productviews/repo/ProductRepository.dart | 60 ++++ .../viewModels/AddProductViewModel.dart | 212 +++-------- .../viewModels/ProductViewModel.dart | 121 +++---- .../repo/StockReturnRepository.dart | 30 ++ .../viewmodels/NewStockReturnViewModel.dart | 44 +-- .../viewmodels/StockReturnViewModel.dart | 22 +- .../stockReturn/views/StockReturnVC.dart | 5 +- .../InventoryStockTransferVC.dart | 5 +- .../repo/StockTransferRepository.dart | 65 ++++ .../viewModels/NewStockTransferVM.dart | 33 +- .../viewModels/StockTransferViewModel.dart | 46 +-- .../repo/SubCategoryRepository.dart | 60 ++++ .../viewModels/AddSubCategoryViewModel.dart | 40 +-- .../viewModels/SubCategoryViewModel.dart | 54 +-- .../views/kitchen/KitchenViewVC.dart | 2 +- .../views/kitchen/repo/KitchenRepository.dart | 29 ++ .../kitchen/viewModel/KitchenViewModel.dart | 47 +-- .../views/kitchen/widgets/ItemsListView.dart | 2 +- .../kitchen/widgets/KitchenListView.dart | 2 +- .../offline/KitchenOfflineItemListView.dart | 2 +- .../offline/KitchenOfflineListView.dart | 2 +- .../views/table/KitchenTableVC.dart | 2 +- .../views/table/repo/TableRepository.dart | 46 +++ .../table/viewModels/NewTableViewModel.dart | 15 +- .../table/viewModels/TablesViewModel.dart | 37 +- .../views/ReturnInvoiceVC.dart | 6 +- .../views/invoiceModule/views/InvoicesVC.dart | 6 +- .../widgets/InvoiceListView.dart | 79 +++-- .../ordersModule/repo/OrderRepository.dart | 39 ++ .../viewModel/OrderViewModel.dart | 46 +-- .../ordersModule/views/OrderCashierVC.dart | 1 - .../quotataionModule/NewQuotationsVC.dart | 5 +- .../views/quotataionModule/QuotationsVC.dart | 6 +- .../repo/QuotationRepository.dart | 15 +- .../viewModels/NewQuotationViewModel.dart | 3 +- .../viewModels/POSCompleteViewModel.dart | 22 ++ .../repo/PaymentMethodRepository.dart | 4 +- .../viewModel/NewPaymentMethodViewModel.dart | 8 + .../views/NewPaymentMethodVC.dart | 6 + .../paymentMethods/views/PaymentMethodVC.dart | 2 +- .../settings/views/reports/ReportsVC.dart | 15 +- .../CashierTransactionViewModel.dart | 13 +- lib/helpers/ThemeImage.dart | 10 + lib/main.dart | 2 - .../CustomControllerTextFieldForm.dart | 58 +++ lib/widgets/CustomIconButton.dart | 39 ++ lib/widgets/DropdownItemBuilder.dart | 2 +- lib/widgets/PageLimitDropDown.dart | 3 +- lib/widgets/SearchBox.dart | 6 +- pubspec.lock | 72 ++++ pubspec.yaml | 1 + 138 files changed, 4518 insertions(+), 2087 deletions(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 47e5c87..cbfff2c 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -36,6 +36,8 @@ PODS: - file_picker (0.0.1): - DKImagePickerController/PhotoGallery - Flutter + - file_saver (0.0.1): + - Flutter - Flutter (1.0.0) - fluttertoast (0.0.2): - Flutter @@ -68,6 +70,7 @@ PODS: 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`) @@ -93,6 +96,8 @@ EXTERNAL SOURCES: :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: @@ -117,6 +122,7 @@ SPEC CHECKSUMS: DKImagePickerController: b512c28220a2b8ac7419f21c491fc8534b7601ac DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179 file_picker: ce3938a0df3cc1ef404671531facef740d03f920 + file_saver: 503e386464dbe118f630e17b4c2e1190fa0cf808 Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 fluttertoast: fafc4fa4d01a6a9e4f772ecd190ffa525e9e2d9c image_picker_ios: 4a8aadfbb6dc30ad5141a2ce3832af9214a705b5 diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index b2cd6e8..86fc99f 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -12,6 +12,10 @@ $(DEVELOPMENT_LANGUAGE) CFBundleDisplayName Wosul + LSSupportsOpeningDocumentsInPlace + + UIFileSharingEnabled + CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier diff --git a/lib/application/MyApp.dart b/lib/application/MyApp.dart index fede9b1..2ac1abd 100644 --- a/lib/application/MyApp.dart +++ b/lib/application/MyApp.dart @@ -7,14 +7,18 @@ 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/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'; @@ -35,6 +39,7 @@ import 'package:wosull/application/views/salesandordermodule/views/invoiceModule 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'; @@ -56,6 +61,16 @@ 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( 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/auth/AccessTokenModel.dart b/lib/application/model/auth/AccessTokenModel.dart index 98f4838..5d9dad3 100644 --- a/lib/application/model/auth/AccessTokenModel.dart +++ b/lib/application/model/auth/AccessTokenModel.dart @@ -9,6 +9,8 @@ class AccessTokenModel { factory AccessTokenModel.fromJson(Map json) { return AccessTokenModel( success: json['success'] ?? false, - access: AccessToken.fromJson(json['access_token'])); + access: json['access_token'] != null + ? AccessToken.fromJson(json['access_token']) + : AccessToken()); } } diff --git a/lib/application/model/discount/StoreDiscountModel.dart b/lib/application/model/discount/StoreDiscountModel.dart index a009481..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( diff --git a/lib/application/model/home/DrawerItem.dart b/lib/application/model/home/DrawerItem.dart index e69de29..b5b01b8 100644 --- a/lib/application/model/home/DrawerItem.dart +++ 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/invoice/PaymentMethod.dart b/lib/application/model/invoice/PaymentMethod.dart index 6fc58c8..0d074d2 100644 --- a/lib/application/model/invoice/PaymentMethod.dart +++ b/lib/application/model/invoice/PaymentMethod.dart @@ -27,7 +27,7 @@ class PaymentMethod { return { 'description': description, 'paymentMethod': paymentMethod, - 'status': status, + 'status': status ?? true, 'store_id': sharedPrefs.storeId, 'payment_id': id }; 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 index 2b3639b..e1d6cde 100644 --- a/lib/application/repository/WosulRepository.dart +++ b/lib/application/repository/WosulRepository.dart @@ -1,13 +1,20 @@ 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'; @@ -16,6 +23,7 @@ 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'; @@ -54,6 +62,12 @@ class WosulRepository { 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() @@ -133,6 +147,34 @@ class WosulRepository { 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() @@ -223,4 +265,72 @@ class WosulRepository { 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/utils/Constants.dart b/lib/application/utils/Constants.dart index 22bbc78..c391b77 100644 --- a/lib/application/utils/Constants.dart +++ b/lib/application/utils/Constants.dart @@ -243,6 +243,9 @@ class Constants { static const takeAway = "takeaway"; static const deliveryPartner = "deliverypartner"; + static const statusReturn = "return"; + static const statusDamage = "damage"; + static const invoiceFilterType = [ 'All', 'Open', @@ -252,6 +255,16 @@ class Constants { 'Return' ]; + static const posStatus = [ + 'Return', + 'Damage', + ]; + + static const activeStatus = [ + 'Active', + 'Inactive', + ]; + static const reportsTypes = [ 'Best Seller', 'POS Complete', diff --git a/lib/application/views/authModule/checkinViews/viewModel/CheckInViewModel.dart b/lib/application/views/authModule/checkinViews/viewModel/CheckInViewModel.dart index e499c9e..7cf0cb0 100644 --- a/lib/application/views/authModule/checkinViews/viewModel/CheckInViewModel.dart +++ b/lib/application/views/authModule/checkinViews/viewModel/CheckInViewModel.dart @@ -37,6 +37,7 @@ class CheckInViewModel with ChangeNotifier { double actualBalanceInHand = 0.0; void disposeData() { + _crudOperationState = CRUDOperationState.uninitialized; _isGettingData = true; _isLoading = false; cashAmount = ''; diff --git a/lib/application/views/authModule/loginViews/viewModel/LoginViewModel.dart b/lib/application/views/authModule/loginViews/viewModel/LoginViewModel.dart index a448db5..fd515cb 100644 --- a/lib/application/views/authModule/loginViews/viewModel/LoginViewModel.dart +++ b/lib/application/views/authModule/loginViews/viewModel/LoginViewModel.dart @@ -4,18 +4,15 @@ 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/auth/AccessTokenModel.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; @@ -117,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(); @@ -132,7 +126,6 @@ class LoginViewModel with ChangeNotifier { setLoading(false); } }).onError((error, stackTrace) { - Utils.showMessage("login " + error.toString()); _dataState = LoginState.error; setLoading(false); }); @@ -149,35 +142,27 @@ 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.error; setLoading(false); }); } Future checkAccessAccount() async { - await APIManager() - .getResponseAuth('${Constants.getAccessToken}/${sharedPrefs.storeId}') - .then((value) async { - final response = AccessTokenModel.fromJson(value); + await repository.checkAccessAccount().then((response) async { if (response.success!) { sharedPrefs.token = response.access!.accessToken ?? ''; _dataState = LoginState.showAccessAccount; - setLoading(false); } else { _dataState = LoginState.toHome; } + setLoading(false); }).onError((error, stackTrace) async { - print(stackTrace.toString()); _dataState = LoginState.error; setLoading(false); }); @@ -185,17 +170,10 @@ class LoginViewModel with ChangeNotifier { Future createAccessToken(String token) async { setLoading(true); - Map data = { - 'token': token, - }; - await APIManager() - .fetchData(Constants.CREATE_ACCESS_TOKEN, data) - .then((value) async { - final response = SimpleResponseModel.fromJson(value); + await repository.createAccessToken(token).then((response) async { await checkResponse(response); setLoading(false); }).onError((error, stackTrace) async { - print(stackTrace.toString()); _dataState = LoginState.error; setLoading(false); }); @@ -206,7 +184,6 @@ class LoginViewModel with ChangeNotifier { sharedPrefs.storeid = result.store.id; sharedPrefs.currency = result.currency; sharedPrefs.token = result.token; - print(sharedPrefs.token); } checkResponse(SimpleResponseModel response) { diff --git a/lib/application/views/authModule/registerViews/CategoryPopUp.dart b/lib/application/views/authModule/registerViews/CategoryPopUp.dart index 72c1973..d6c88c0 100644 --- a/lib/application/views/authModule/registerViews/CategoryPopUp.dart +++ b/lib/application/views/authModule/registerViews/CategoryPopUp.dart @@ -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 4da82e8..58f946a 100644 --- a/lib/application/views/authModule/registerViews/CityPopUp.dart +++ b/lib/application/views/authModule/registerViews/CityPopUp.dart @@ -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 1cd6204..beafd85 100644 --- a/lib/application/views/authModule/registerViews/RegisterVC.dart +++ b/lib/application/views/authModule/registerViews/RegisterVC.dart @@ -5,29 +5,20 @@ 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/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/registerViews/viewModel/AuthViewModel.dart'; -import 'package:wosull/application/views/home/HomePage.dart'; import 'package:wosull/application/views/popups/CountryPopUp.dart'; import 'package:wosull/base/BaseStatefulState.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/CustomSimpleButton.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'; @@ -44,67 +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; - - bool obscureText = true; - - 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; - - void showHidePassword() { - setState(() { - obscureText = !obscureText; - }); - } - - 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( @@ -117,40 +52,38 @@ 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(ThemeImage.wosulLogo, height: 80), - AppSpaces.verticalLarge, - Text( - AppLocalizations.of(context)!.register, - style: ThemeText.bigHeader, - ), - Container( - margin: const EdgeInsets.all(16), - child: Center( - child: getMainDesign(), - ), - ), - ], - ) /* add child content here */, - ) - ], - ), - )), + ], + ) /* add child content here */, + ) + ], + ), + ), )); } @@ -180,7 +113,8 @@ class _RegisterVCState extends BaseStatefulState { ), ), components: [ - Component(Component.country, selectedCountry.countryCode ?? "AE") + Component( + Component.country, authView.selectedCountry.countryCode ?? "AE") ], ); @@ -194,12 +128,7 @@ 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!; - }); + authView.updateAddress(detail, p.description ?? ''); } Widget getMandatoryTextField( @@ -208,32 +137,12 @@ class _RegisterVCState extends BaseStatefulState { children: [ MandatoryTitleText(hint: title), AppSpaces.verticalSmall, - TextFormField( + CustomControllerTextFieldForm( controller: controller, - style: TextStyle( - fontFamily: MyFonts.DMREGULAR, - fontSize: MyFonts.normal, - color: MyColors.black), - decoration: InputDecoration( - constraints: const BoxConstraints(maxHeight: 48, minHeight: 48), - fillColor: MyColors.backFillColor, - filled: true, - border: InputBorder.none, - hintText: hint, - 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: (String value) { + // controller.text = value; + }, + hintText: hint, ), ], ); @@ -251,11 +160,11 @@ class _RegisterVCState extends BaseStatefulState { child: Column( children: [ getMandatoryTextField( - nameController, + authView.nameController, AppLocalizations.of(context)!.company_name, 'Enter Company name'), AppSpaces.verticalMedium, - getMandatoryTextField(emailController, + getMandatoryTextField(authView.emailController, AppLocalizations.of(context)!.company_email, 'Company email'), AppSpaces.verticalMedium, getMandatoryPopUpButton(context, @@ -278,14 +187,17 @@ class _RegisterVCState extends BaseStatefulState { AppSpaces.verticalMedium, buildPassword(), AppSpaces.verticalLarge, - CustomSimpleButton( - backGroundColor: MyColors.primary, + LoginButton( + isLoading: authView.isInAsyncCall, textColor: MyColors.white, - onPressed: () { - validate(); + backGroundColor: MyColors.blueThemeColor, + onPressed: () async { + await authView.validate(); + checkState(); }, heading: AppLocalizations.of(context)!.register, ), + AppSpaces.verticalMedium, GestureDetector( onTap: () { Navigator.pop(context); @@ -336,9 +248,9 @@ class _RegisterVCState extends BaseStatefulState { AppSpaces.verticalSmall, CustomTextButtonIcon( icon: Icons.arrow_drop_down_outlined, - heading: selectedCountry.countryName!.isEmpty + heading: authView.selectedCountry.countryName!.isEmpty ? hint - : selectedCountry.countryName!, + : authView.selectedCountry.countryName!, onPressed: () { _navigateAndDisplayCountry(context); }, @@ -355,10 +267,11 @@ class _RegisterVCState extends BaseStatefulState { AppSpaces.verticalSmall, CustomTextButtonIcon( icon: Icons.arrow_drop_down_outlined, - heading: - selectedCity.cityName!.isEmpty ? hint : selectedCity.cityName!, + heading: authView.selectedCity.cityName!.isEmpty + ? hint + : authView.selectedCity.cityName!, onPressed: () { - if (selectedCountry.id!.isNotEmpty) { + if (authView.selectedCountry.id!.isNotEmpty) { _navigateAndDisplayCity(context); } else { showMessage('Select country'); @@ -377,10 +290,11 @@ class _RegisterVCState extends BaseStatefulState { AppSpaces.verticalSmall, CustomTextButtonIcon( icon: Icons.arrow_drop_down_outlined, - heading: - addressController.isEmpty ? 'Enter Address' : addressController, + heading: authView.addressController.isEmpty + ? 'Enter Address' + : authView.addressController, onPressed: () { - if (selectedCountry.id!.isNotEmpty) { + if (authView.selectedCountry.id!.isNotEmpty) { _handlePressButton(); } else { showMessage('Select city'); @@ -399,11 +313,11 @@ class _RegisterVCState extends BaseStatefulState { AppSpaces.verticalSmall, CustomTextButtonIcon( icon: Icons.arrow_drop_down_outlined, - heading: selectedCategory.deliveryName!.isEmpty + heading: authView.selectedCategory.deliveryName!.isEmpty ? hint - : selectedCategory.deliveryName!, + : authView.selectedCategory.deliveryName!, onPressed: () { - if (selectedCity.id!.isNotEmpty) { + if (authView.selectedCity.id!.isNotEmpty) { _navigateAndDisplayDelivery(context); } else { showMessage('Select City'); @@ -444,7 +358,7 @@ class _RegisterVCState extends BaseStatefulState { mainAxisAlignment: MainAxisAlignment.start, children: [ Text( - selectedCountry.phoneCode!, + authView.selectedCountry.phoneCode!, style: TextStyle( fontFamily: MyFonts.DMREGULAR, fontSize: MyFonts.normal, @@ -465,7 +379,7 @@ class _RegisterVCState extends BaseStatefulState { flex: 1, child: TextFormField( keyboardType: TextInputType.phone, - controller: phoneController, + controller: authView.phoneController, style: TextStyle( fontFamily: MyFonts.DMREGULAR, fontSize: MyFonts.normal, @@ -493,13 +407,13 @@ class _RegisterVCState extends BaseStatefulState { borderRadius: BorderRadius.circular(8.0), ), child: CustomTextFieldPassword( - obscure: obscureText, + obscure: authView.obscureText, hint: 'Enter your password', onChanged: (value) { - passwordController.text = value; + authView.passwordController.text = value; }, onPressed: () { - showHidePassword(); + authView.showHidePassword(); }, )); } @@ -523,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 { @@ -535,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 { @@ -552,98 +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); - - final storeResponse = await authView.loginRegisterUser(map); - if (storeResponse.success) { - addAccount(storeResponse.store); - } else { - hideProgressBar(); - showMessage('Try Again'); - // showMessage(error); - // showMessage(AppLocalizations.of(context)![error]); - } - } - - 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(() {}); + if (city != null) { + authView.updateCity(city); } } - void validate() { - 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); + 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 index 3f1a5d3..9f8655b 100644 --- a/lib/application/views/authModule/registerViews/viewModel/AuthViewModel.dart +++ b/lib/application/views/authModule/registerViews/viewModel/AuthViewModel.dart @@ -1,68 +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/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'; +import 'package:wosull/application/utils/CRUDOperatoinState.dart'; +import 'package:wosull/application/views/authModule/repo/AuthRepository.dart'; +import 'package:wosull/helpers/Utils.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(); - } +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; } - Future getStoreService(Map data) async { - try { - dynamic response = await AuthRepository() - .postResponse(Constants.Store_services_URL, data); - return StoreServiceResponse.fromJson(response); - } catch (e) { - return StoreServiceResponse(); - } + void setLoading(bool value) { + isInAsyncCall = value; + notifyListeners(); } - 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: ''), - ); - } + void showHidePassword() { + obscureText = !obscureText; + notifyListeners(); } - Future getData(String url, Map data) async { - try { - dynamic response = await AuthRepository().postResponseAuth(url, data); - return response; - } catch (e) { - return e; + 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 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: ''), - ); + 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/registerViews/viewModel/CityViewModel.dart b/lib/application/views/authModule/registerViews/viewModel/CityViewModel.dart index 67b5b7d..4dfeda2 100644 --- a/lib/application/views/authModule/registerViews/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/repo/AuthRepository.dart b/lib/application/views/authModule/repo/AuthRepository.dart index e69de29..8259bab 100644 --- a/lib/application/views/authModule/repo/AuthRepository.dart +++ 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/billingCounterDashboard/BillingCounterDashBoard.dart b/lib/application/views/billingCounterDashboard/BillingCounterDashBoard.dart index 8ad9c14..f96cc68 100644 --- a/lib/application/views/billingCounterDashboard/BillingCounterDashBoard.dart +++ b/lib/application/views/billingCounterDashboard/BillingCounterDashBoard.dart @@ -1,7 +1,6 @@ import 'package:dropdown_search/dropdown_search.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:wosull/application/model/billingCounter/CounterDashboard.dart'; import 'package:wosull/application/theme/MyColors.dart'; import 'package:wosull/application/utils/AppLoader.dart'; import 'package:wosull/application/utils/Constants.dart'; @@ -105,7 +104,8 @@ class _BillingCounterDashBoardState extends State { AppSpaces.verticalLarge, viewModel.isLoading ? AppLoader() - : showList(viewModel.filteredList) + : BillingCounterGrid( + isPortrait: isPortrait, data: viewModel.filteredList) ], ), ), @@ -113,10 +113,6 @@ class _BillingCounterDashBoardState extends State { })); } - Widget showList(List counters) { - return BillingCounterGrid(isPortrait: isPortrait, data: counters); - } - Widget getCounterTypeDropdown() { return DropdownSearch( dropdownButtonProps: ThemeDropDown.dropdownButtonProps, diff --git a/lib/application/views/billingCounterDashboard/BillingCounterMainVC.dart b/lib/application/views/billingCounterDashboard/BillingCounterMainVC.dart index 0bc007f..39cb6f4 100644 --- a/lib/application/views/billingCounterDashboard/BillingCounterMainVC.dart +++ b/lib/application/views/billingCounterDashboard/BillingCounterMainVC.dart @@ -1,10 +1,8 @@ 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/billingCounterDashboard/BillingCounterDashBoard.dart'; -import 'package:wosull/helpers/ThemeText.dart'; +import 'package:wosull/widgets/BackTabBarContainer.dart'; class BillingCounterMainVC extends StatefulWidget { final DrawerWidgetSelect delegateDrawer; @@ -31,71 +29,15 @@ class _BillingCounterMainVCState 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, - ), - TabBar( - indicatorColor: Colors.white, - labelStyle: ThemeText.tabLabelStyle, - isScrollable: true, - unselectedLabelStyle: ThemeText.unSelectedTabLabelStyle, - unselectedLabelColor: MyColors.textColorBlack, - labelColor: MyColors.blueThemeColor, - tabs: const [ - Tab( - text: 'Billing Counter Dashboard', - ), - ], - ) - ], - ), + BackTabBarContainer( + onPressed: () { + widget.delegateDrawer.goToHome(); + }, + tabs: const [ + Tab( + text: 'Billing Counter Dashboard', + ), + ], ), const Expanded( child: TabBarView( diff --git a/lib/application/views/billingCounterDashboard/repo/BillingCounterRepository.dart b/lib/application/views/billingCounterDashboard/repo/BillingCounterRepository.dart index e69de29..a399260 100644 --- a/lib/application/views/billingCounterDashboard/repo/BillingCounterRepository.dart +++ 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 index 4927efa..503550e 100644 --- a/lib/application/views/billingCounterDashboard/viewModels/BillingCounterViewModel.dart +++ b/lib/application/views/billingCounterDashboard/viewModels/BillingCounterViewModel.dart @@ -1,11 +1,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/billingCounter/BillingCounterDashboard.dart'; import 'package:wosull/application/model/billingCounter/CounterDashboard.dart'; import 'package:wosull/application/model/converters/DataTimeFormat.dart'; -import 'package:wosull/application/network/APIManager.dart'; import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/billingCounterDashboard/repo/BillingCounterRepository.dart'; class BillingCounterViewModel with ChangeNotifier { String startDate = ""; @@ -15,6 +14,8 @@ class BillingCounterViewModel with ChangeNotifier { bool get isLoading => _isLoading; + final repository = BillingCounterRepository(); + //using this state to handle for get data and pagination DataState _dataState = DataState.uninitialized; @@ -38,7 +39,7 @@ class BillingCounterViewModel 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(), @@ -80,10 +81,7 @@ class BillingCounterViewModel with ChangeNotifier { 'start_date': startDate, 'end_date': endDate }; - await APIManager() - .getResponseAuth(Constants.billingDashboardData, data) - .then((value) { - final response = BillingCounterDashboard.fromJson(value); + await repository.fetchCounters(data).then((response) { if (response.success) { _allCounters.clear(); _filteredCounters.clear(); @@ -95,7 +93,6 @@ class BillingCounterViewModel with ChangeNotifier { } setLoading(false); }).onError((error, stackTrace) { - print(stackTrace.toString()); _dataState = DataState.error; setLoading(false); }); diff --git a/lib/application/views/create_order_module/CartVC.dart b/lib/application/views/create_order_module/CartVC.dart index 909ac51..865acaf 100644 --- a/lib/application/views/create_order_module/CartVC.dart +++ b/lib/application/views/create_order_module/CartVC.dart @@ -11,7 +11,7 @@ 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/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'; @@ -39,7 +39,7 @@ class CartVC extends StatefulWidget { } class _CartVCState extends BaseStatefulState { - var homeViewModel = CartViewModel(); + var homeViewModel = CreateOrderViewModel(); String createOrderId = ''; @@ -50,7 +50,7 @@ class _CartVCState extends BaseStatefulState { @override Widget build(BuildContext context) { - homeViewModel = context.watch(); + homeViewModel = context.watch(); return Scaffold( backgroundColor: MyColors.white, body: Padding( diff --git a/lib/application/views/create_order_module/viewModels/CounterCloseViewMdoel.dart b/lib/application/views/create_order_module/viewModels/CounterCloseViewMdoel.dart index dfcb68c..b33bb27 100644 --- a/lib/application/views/create_order_module/viewModels/CounterCloseViewMdoel.dart +++ b/lib/application/views/create_order_module/viewModels/CounterCloseViewMdoel.dart @@ -53,6 +53,8 @@ class CounterCloseViewModel with ChangeNotifier { 'creditAmount': double.parse(creditAmount), }; await repository.updateBusinessRegister(data).then((value) { + sharedPrefs.billingCounterId = ''; + sharedPrefs.billingCounterName = ''; if (value.success) { setState(CRUDOperationState.add); } else { diff --git a/lib/application/views/create_order_module/viewModels/DineInViewModel.dart b/lib/application/views/create_order_module/viewModels/DineInViewModel.dart index e69de29..4cee466 100644 --- a/lib/application/views/create_order_module/viewModels/DineInViewModel.dart +++ 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 index e69de29..0cac18d 100644 --- a/lib/application/views/create_order_module/viewModels/ItemModifiersViewModel.dart +++ 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/views/PrintReceiptVC.dart b/lib/application/views/create_order_module/views/PrintReceiptVC.dart index 9ea9c0f..8b4d351 100644 --- a/lib/application/views/create_order_module/views/PrintReceiptVC.dart +++ b/lib/application/views/create_order_module/views/PrintReceiptVC.dart @@ -590,7 +590,10 @@ class _PrintReceiptVCState extends State { child: getDownloadButton(), ), AppSpaces.horizontalSmall, - getDoneButton() + SizedBox( + width: 100, + child: getDoneButton(), + ), ], ), ); diff --git a/lib/application/views/create_order_module/views/TabBarHomeVC.dart b/lib/application/views/create_order_module/views/TabBarHomeVC.dart index 78670fa..6a2ae07 100644 --- a/lib/application/views/create_order_module/views/TabBarHomeVC.dart +++ b/lib/application/views/create_order_module/views/TabBarHomeVC.dart @@ -66,7 +66,7 @@ class _TabBarHomeVCState extends BaseStatefulState { @override void initState() { context.read().getStoreDetails(); - Future.delayed(const Duration(seconds: 3), () { + Future.delayed(const Duration(seconds: 2), () { if (sharedPrefs.billingCounterId.isEmpty) { showCounters(); } 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 c7ad48e..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,12 +1,12 @@ 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/model/tables/GetStoreTable.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/create_order_module/viewModels/DineInViewModel.dart'; import 'package:wosull/helpers/AppSpaces.dart'; import 'package:wosull/main.dart'; import 'package:wosull/widgets/BoxContainer.dart'; @@ -24,26 +24,21 @@ 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() { 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( @@ -80,7 +75,9 @@ class _DineInPopupState extends State { textColor: MyColors.white, onPressed: () { Navigator.pop( - context, filteredTables[selectedItem]); + context, + viewModel.filteredTables[ + viewModel.selectedItem]); }, heading: AppLocalizations.of(context)!.apply, ), @@ -101,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(); } @@ -114,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(); @@ -140,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, @@ -149,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), @@ -163,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( @@ -181,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), @@ -195,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, )), @@ -209,40 +202,6 @@ class _DineInPopupState extends State { ); } - Future> getTables(int selectedItem) async { - // = await (Connectivity().checkConnectivity()); - var items = []; - if (isConnected) { - final viewModel = WosulRepository(); - 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, @@ -250,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), @@ -277,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, @@ -297,29 +243,14 @@ 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()); - } - - tablesSeats = tablesSeats.toSet().toList(); - } - tables.addAll(storeTables); - filteredTables.addAll(storeTables); - isLoading = false; - } - Widget availableDetails() { return Column( children: [ - isPortrait + viewModel.isPortrait ? Column( children: [ Row( @@ -464,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 1c09971..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,14 +1,14 @@ 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/Modifier.dart'; -import 'package:wosull/application/model/Modifiers/ModifierOption.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'; @@ -23,31 +23,23 @@ class ItemModifiersPopUp extends StatefulWidget { } class _ItemModifiersPopUpState extends State { - bool isPortrait = true; - int selectedItem = -1; - List selectedModifier = []; - List? selectedOption = []; - - var noteController = ''; + var viewModel = ItemModifiersViewModel(); @override void 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( @@ -57,13 +49,13 @@ class _ItemModifiersPopUpState extends State { 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, @@ -80,19 +72,14 @@ class _ItemModifiersPopUpState extends State { mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( + HeadingText( AppLocalizations.of(context)!.note, - style: TextStyle( - fontSize: MyFonts.normalButton, - fontWeight: FontWeight.w600, - fontFamily: MyFonts.DMREGULAR, - color: MyColors.textColorPopUp), ), AppSpaces.verticalSmall, CustomTextFieldForm( hintText: 'Enter Note', onChanged: (String value) { - noteController = value; + viewModel.noteController = value; }, ), AppSpaces.verticalMedium, @@ -100,30 +87,33 @@ class _ItemModifiersPopUpState extends State { physics: const NeverScrollableScrollPhysics(), shrinkWrap: true, itemBuilder: (context, position) { - if (widget.item.modifiers[position].options + if (viewModel.item.modifiers[position].options .isNotEmpty) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - HeadingText( - widget.item.modifiers[position].name), + HeadingText(viewModel + .item.modifiers[position].name), AppSpaces.verticalSmall, GridView.builder( shrinkWrap: true, - itemCount: widget.item + itemCount: viewModel.item .modifiers[position].options.length, physics: const NeverScrollableScrollPhysics(), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: widget + crossAxisCount: viewModel .item .modifiers[position] .options .isEmpty ? 1 - : widget.item.modifiers[position] - .options.length, + : viewModel + .item + .modifiers[position] + .options + .length, mainAxisExtent: SizerUtil.deviceType == DeviceType.mobile @@ -135,153 +125,16 @@ class _ItemModifiersPopUpState extends State { 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 - .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 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 - .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); - } - } - }); + viewModel + .onSelectModifierOption( + position, i); }, child: Container( margin: const EdgeInsets.all(4), padding: const EdgeInsets.all(4), decoration: BoxDecoration( - color: widget + color: viewModel .item .modifiers[position] .options[i] @@ -291,7 +144,7 @@ class _ItemModifiersPopUpState extends State { : Colors.transparent, border: Border.all( width: 1, - color: widget + color: viewModel .item .modifiers[ position] @@ -314,7 +167,7 @@ class _ItemModifiersPopUpState extends State { .center, children: [ Text( - widget + viewModel .item .modifiers[ position] @@ -325,7 +178,7 @@ class _ItemModifiersPopUpState extends State { MyFonts.H2, fontFamily: MyFonts.Bold, - color: widget + color: viewModel .item .modifiers[ position] @@ -342,13 +195,13 @@ class _ItemModifiersPopUpState extends State { ), AppSpaces.verticalSmall, Text( - '${widget.item.modifiers[position].options[i].price.toString()} ${sharedPrefs.currency}', + '${viewModel.item.modifiers[position].options[i].price.toString()} ${sharedPrefs.currency}', style: TextStyle( fontSize: MyFonts.normal, fontFamily: MyFonts.Medium, - color: widget + color: viewModel .item .modifiers[ position] @@ -367,9 +220,11 @@ class _ItemModifiersPopUpState extends State { }) ], ); + } else { + return Container(); } }, - itemCount: widget.item.modifiers.length, + itemCount: viewModel.item.modifiers.length, ), AppSpaces.verticalMedium, Row( @@ -378,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 + viewModel.selectedModifier, + viewModel.noteController ]; Navigator.pop(context, result); }, - child: Text( - AppLocalizations.of(context)!.apply, - style: TextStyle( - fontSize: MyFonts.normalButton, - color: MyColors.white, - fontFamily: MyFonts.Bold), - ), + heading: AppLocalizations.of(context)!.apply, ), ), ], diff --git a/lib/application/views/dashboard/HomeVC.dart b/lib/application/views/dashboard/HomeVC.dart index 57dbe08..f4ce2f6 100644 --- a/lib/application/views/dashboard/HomeVC.dart +++ b/lib/application/views/dashboard/HomeVC.dart @@ -55,9 +55,6 @@ class _HomeVCState extends BaseStatefulState implements ReportsCVS { super.dispose(); } - @override - void didChangeDependencies() {} - @override Widget build(BuildContext context) { viewModel = context.watch(); diff --git a/lib/application/views/dashboard/repo/DashBoardRepository.dart b/lib/application/views/dashboard/repo/DashBoardRepository.dart index e69de29..a23989e 100644 --- a/lib/application/views/dashboard/repo/DashBoardRepository.dart +++ 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 61af6f9..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,6 +13,9 @@ class DashBoardViewModel with ChangeNotifier { var saleCancelOrder = TotalSalesCancelledOrderModel(); var invoiceSale = InvoiceStatusModel(); var graphData = GraphData(); + + var repository = DashBoardRepository(); + bool isPortrait = true; String startDate = ""; @@ -44,10 +46,7 @@ class DashBoardViewModel with ChangeNotifier { 'end_date': endDate }; - await APIManager() - .fetchData(Constants.GET_ADMIN_DASHBOARD, data) - .then((value) async { - final response = AdminDashboardModel.fromJson(value); + await repository.getDashboard(data).then((response) async { if (!loading) { await getAdminDashBoardGraph(); } @@ -70,10 +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); + await repository.getAdminDashBoardGraph(data).then((value) { + graphData = value; }).onError((error, stackTrace) { setLoading(false); }); @@ -81,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; } @@ -94,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; } @@ -112,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/TodayPOSSales.dart b/lib/application/views/dashboard/widgets/TodayPOSSales.dart index 1f9d5a1..891e78a 100644 --- a/lib/application/views/dashboard/widgets/TodayPOSSales.dart +++ b/lib/application/views/dashboard/widgets/TodayPOSSales.dart @@ -130,7 +130,7 @@ class TodayPOSSales extends StatelessWidget { lineBarsData: [ LineChartBarData( spots: getSpots(), - isCurved: true, + isCurved: false, gradient: LinearGradient( colors: gradientColors, ), diff --git a/lib/application/views/dashboard/widgets/TodaySaleGraph.dart b/lib/application/views/dashboard/widgets/TodaySaleGraph.dart index 7ff2587..38bf81c 100644 --- a/lib/application/views/dashboard/widgets/TodaySaleGraph.dart +++ b/lib/application/views/dashboard/widgets/TodaySaleGraph.dart @@ -72,7 +72,6 @@ class TodaySaleGraph extends StatelessWidget { Widget text; if (value.toInt() <= todaySales.length) { - print(value.toInt()); text = Text( DataTimeFormat.getTimeFormat( todaySales[value.toInt()].id!.createdAt!), diff --git a/lib/application/views/discountModule/repo/DiscountRepository.dart b/lib/application/views/discountModule/repo/DiscountRepository.dart index e69de29..d892092 100644 --- a/lib/application/views/discountModule/repo/DiscountRepository.dart +++ 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 f6af84c..632637c 100644 --- a/lib/application/views/discountModule/viewModels/DiscountViewModel.dart +++ b/lib/application/views/discountModule/viewModels/DiscountViewModel.dart @@ -2,8 +2,7 @@ import 'package:flutter/cupertino.dart'; import 'package:wosull/application/enum/DataState.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; import 'package:wosull/application/model/discount/StoreDiscountModel.dart'; -import 'package:wosull/application/network/APIManager.dart'; -import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/discountModule/repo/DiscountRepository.dart'; class DiscountViewModel with ChangeNotifier { int _currentPageNumber = 1; @@ -22,6 +21,7 @@ class DiscountViewModel with ChangeNotifier { List get dataList => _dataList; List get filteredList => _filteredList; + final repository = DiscountRepository(); fetch({bool isRefresh = false, int limit = 10}) async { this.limit = limit; @@ -46,18 +46,15 @@ class DiscountViewModel with ChangeNotifier { 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 < this.limit) { + if (discounts.isNotEmpty) { + _filteredList.addAll(discounts); + _dataList.addAll(discounts); + if (discounts.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; @@ -92,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) { @@ -113,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(); @@ -126,13 +117,7 @@ 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); diff --git a/lib/application/views/discountModule/viewModels/NewDiscountViewModel.dart b/lib/application/views/discountModule/viewModels/NewDiscountViewModel.dart index 13b3433..3e481c7 100644 --- a/lib/application/views/discountModule/viewModels/NewDiscountViewModel.dart +++ b/lib/application/views/discountModule/viewModels/NewDiscountViewModel.dart @@ -1,16 +1,12 @@ -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/converters/DataTimeFormat.dart'; import 'package:wosull/application/model/discount/StoreDiscountModel.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/GetItemsByStoreId.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/discountModule/repo/DiscountRepository.dart'; import 'package:wosull/helpers/DatePicker.dart'; import 'package:wosull/helpers/Utils.dart'; @@ -35,6 +31,8 @@ class NewDiscountViewModel with ChangeNotifier { List filteredItems = []; List data = []; + final repository = DiscountRepository(); + disposeData() { isLoading = false; isGettingItems = false; @@ -82,8 +80,6 @@ class NewDiscountViewModel with ChangeNotifier { } 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) { @@ -137,11 +133,7 @@ class NewDiscountViewModel with ChangeNotifier { 'discountId': storeDiscount.id ?? '' }; - print(jsonEncode(data)); - await APIManager() - .fetchData(Constants.ADD_STORE_DISCOUNT, data) - .then((value) { - final response = SimpleResponseModel.fromJson(value); + await repository.addDiscount(data).then((response) { if (response.success) { Utils.showMessage(response.message); _crudOperation = CRUDOperationState.add; @@ -184,30 +176,26 @@ class NewDiscountViewModel with ChangeNotifier { data.clear(); } else if (verticalGroupValue == Constants.discountFilters.elementAt(2)) { type = "3"; - final response = await APIManager().fetchData( - Constants.GET_STORE_CATEGORY_LIST, Constants.getStorePayload()); - final itemsResponse = ItemCategoryResponse.fromJson(response); - if (itemsResponse.success && itemsResponse.categories.isNotEmpty) { - filteredItems.clear(); - data.clear(); - filteredItems.addAll(itemsResponse.categories); - data.addAll(itemsResponse.categories); - } + 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 response = await APIManager().fetchData( - Constants.GET_STORE_CATEGORY_LIST_ID, Constants.getStorePayload()); - final getItemsByStoreId = GetItemsByStoreId.fromJson(response); - if (getItemsByStoreId.success! && - getItemsByStoreId.categories!.isNotEmpty) { + final categories = await repository.getCategoriesListById(); + if (categories.isNotEmpty) { filteredItems.clear(); data.clear(); - filteredItems.addAll(getItemsByStoreId.categories!); - data.addAll(getItemsByStoreId.categories!); + filteredItems.addAll(categories); + data.addAll(categories); } } setIsGettingData(false); diff --git a/lib/application/views/discountModule/views/DiscountVC.dart b/lib/application/views/discountModule/views/DiscountVC.dart index e66bc59..0ff8038 100644 --- a/lib/application/views/discountModule/views/DiscountVC.dart +++ b/lib/application/views/discountModule/views/DiscountVC.dart @@ -83,7 +83,8 @@ class _DiscountVCState extends BaseStatefulState { ), AppSpaces.horizontalSmall, getSearchBar(), - Row( + Flexible( + child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ PageLimitDropdown(onChange: (value) { @@ -92,7 +93,7 @@ class _DiscountVCState extends BaseStatefulState { limit: int.parse(value!)); }) ], - ) + )) ], ), AppSpaces.verticalMedium, diff --git a/lib/application/views/dowloadReports/viewModel/DownloadBestSellerReportViewModel.dart b/lib/application/views/dowloadReports/viewModel/DownloadBestSellerReportViewModel.dart index e69de29..9b8441a 100644 --- a/lib/application/views/dowloadReports/viewModel/DownloadBestSellerReportViewModel.dart +++ 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 index e69de29..273cdbc 100644 --- a/lib/application/views/dowloadReports/viewModel/DownloadCategoryReportViewModel.dart +++ 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 index e69de29..28a833f 100644 --- a/lib/application/views/dowloadReports/viewModel/DownloadPOSCompleteReportViewModel.dart +++ 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 index e69de29..1d26428 100644 --- a/lib/application/views/dowloadReports/viewModel/DownloadPOSReturnDamageViewModel.dart +++ 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 index e69de29..1fe850a 100644 --- a/lib/application/views/dowloadReports/viewModel/DownloadProductViewModel.dart +++ 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 index e69de29..f46578e 100644 --- a/lib/application/views/dowloadReports/views/DownloadReportMainVC.dart +++ 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 index e69de29..4633de5 100644 --- a/lib/application/views/dowloadReports/views/DownloadReports.dart +++ 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 index e69de29..dd080ca 100644 --- a/lib/application/views/dowloadReports/widgets/BestSellerReportView.dart +++ 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 index e69de29..594a0de 100644 --- a/lib/application/views/dowloadReports/widgets/DownloadCategoriesView.dart +++ 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 index e69de29..c6e8a90 100644 --- a/lib/application/views/dowloadReports/widgets/DownloadDiscountView.dart +++ 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 index e69de29..0f9593d 100644 --- a/lib/application/views/dowloadReports/widgets/DownloadInventoryReport.dart +++ 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 index e69de29..c41a99c 100644 --- a/lib/application/views/dowloadReports/widgets/DownloadInvoiceView.dart +++ 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 index e69de29..ddd878d 100644 --- a/lib/application/views/dowloadReports/widgets/DownloadOrderReportView.dart +++ 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 index e69de29..8b30566 100644 --- a/lib/application/views/dowloadReports/widgets/DownloadPOSCompleteView.dart +++ 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 index e69de29..012b256 100644 --- a/lib/application/views/dowloadReports/widgets/DownloadPOSReturnAndDamage.dart +++ 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 index e69de29..8992d20 100644 --- a/lib/application/views/dowloadReports/widgets/DownloadProductsView.dart +++ 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 index e69de29..e2efe92 100644 --- a/lib/application/views/dowloadReports/widgets/DownloadQuotationView.dart +++ 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 index e69de29..e749c10 100644 --- a/lib/application/views/dowloadReports/widgets/DownloadReportView.dart +++ 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 index e69de29..00df180 100644 --- a/lib/application/views/dowloadReports/widgets/DownloadStockStatusView.dart +++ 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 5ec710b..ebe0f7c 100644 --- a/lib/application/views/home/HomePage.dart +++ b/lib/application/views/home/HomePage.dart @@ -33,17 +33,11 @@ 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/LanguageDropdown.dart'; import 'package:wosull/widgets/ValueText.dart'; -class DrawerItem { - String title; - IconData icon; - - DrawerItem(this.title, this.icon); -} - class HomePage extends StatefulWidget { const HomePage({Key? key}) : super(key: key); @@ -58,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 @@ -70,7 +68,7 @@ class _HomePageState extends BaseStatefulState @override Widget build(BuildContext context) { viewModel = context.watch(); - viewModel.setContext(context); + // viewModel.setContext(context); viewModel.setHomeMenus(); viewModel.setDropDownValue(); return StreamProvider( @@ -96,152 +94,41 @@ class _HomePageState extends BaseStatefulState children: [ getLangDropdown(), AppSpaces.horizontalMedium, - // 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, - // ), - // ), getSyncButton(), AppSpaces.horizontalMedium, SizedBox( width: 110, - child: ElevatedButton.icon( - style: ElevatedButton.styleFrom( - elevation: 0, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - backgroundColor: MyColors.backFillColor, - minimumSize: const Size.fromHeight(38), // NEW - ), + child: CustomIconButton( onPressed: () { viewModel.setSelectedDrawer(0); }, - label: Text( - AppLocalizations.of(context)!.cashier, - style: ThemeText.textStyleBlueMedium, - ), - icon: ImageIcon( - color: MyColors.blueThemeColor, - const AssetImage('images/cashier.png'), - size: 18, - ), + heading: AppLocalizations.of(context)!.cashier, + svgIconPath: ThemeImage.cashierImage, ), ), AppSpaces.horizontalMedium, SizedBox( width: 110, - 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: () { - showCloseCounter(); - }, - label: Text( - 'Counter', - style: ThemeText.textStyleBlueMedium, - ), - icon: ImageIcon( - color: MyColors.blueThemeColor, - const AssetImage('images/cashier.png'), - size: 18, - ), - ), + child: CustomIconButton( + onPressed: () { + showCloseCounter(); + }, + heading: 'Counter', + svgIconPath: ThemeImage.cashierImage), ), AppSpaces.horizontalMedium, SizedBox( width: 110, - 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: ThemeText.textStyleBlueMedium, - ), - icon: ImageIcon( - color: MyColors.blueThemeColor, - const AssetImage('images/kitchen.png'), - size: 18, - ), - ), + child: CustomIconButton( + onPressed: () { + viewModel.setSelectedDrawer(7); + }, + heading: + AppLocalizations.of(context)!.kitchen, + svgIconPath: ThemeImage.kitchenImage), ), AppSpaces.horizontalMedium, - 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( - 'images/account_profile.svg'), - )), - ), - ), - ), - 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), - ), + getPopupButton(), AppSpaces.horizontalMedium, ], )) @@ -254,57 +141,7 @@ class _HomePageState extends BaseStatefulState AppSpaces.horizontalSmall, getSyncButton(), AppSpaces.horizontalSmall, - 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( - 'images/account_profile.svg'), - )), - ), - ), - ), - Text( - sharedPrefs.store_name, - style: 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), - ), + getPopupButton(), AppSpaces.horizontalSmall, ], )) @@ -519,56 +356,56 @@ class _HomePageState extends BaseStatefulState ), CustomListTile( wasTaped: viewModel.isTaped[0], - path: 'images/home_icon.svg', + path: ThemeImage.homeImage, title: 'Master Dashboard', onTap: () { viewModel.onSelectItem(0); }), CustomListTile( wasTaped: viewModel.isTaped[1], - path: 'images/create-order.svg', + path: ThemeImage.createOrderImage, title: 'Billing Counter Dashboard', onTap: () { viewModel.onSelectItem(1); }), CustomListTile( wasTaped: viewModel.isTaped[2], - path: 'images/create-order.svg', + path: ThemeImage.createOrderImage, title: AppLocalizations.of(context)!.create_order, onTap: () { viewModel.onSelectItem(2); }), CustomListTile( wasTaped: viewModel.isTaped[3], - path: 'images/inven.svg', + path: ThemeImage.inventoryImage, title: AppLocalizations.of(context)!.inventory, onTap: () { viewModel.onSelectItem(3); }), CustomListTile( wasTaped: viewModel.isTaped[4], - path: 'images/dis.svg', + path: ThemeImage.discountImage, title: AppLocalizations.of(context)!.discount, onTap: () { viewModel.onSelectItem(4); }), CustomListTile( wasTaped: viewModel.isTaped[5], - path: 'images/sales_order.svg', + path: ThemeImage.salesImage, title: 'Business Accounts', onTap: () { viewModel.onSelectItem(5); }), CustomListTile( wasTaped: viewModel.isTaped[6], - path: 'images/sales_order.svg', + path: ThemeImage.salesImage, title: AppLocalizations.of(context)!.sales_and_orders, onTap: () { viewModel.onSelectItem(6); }), CustomListTile( wasTaped: viewModel.isTaped[7], - path: 'images/kitchen.svg', + path: ThemeImage.kitchenIcon, title: AppLocalizations.of(context)!.kitchen, onTap: () { viewModel.tableIndex = 0; @@ -578,7 +415,7 @@ class _HomePageState extends BaseStatefulState alignment: FractionalOffset.bottomCenter, child: CustomListTile( wasTaped: viewModel.isTaped[8], - path: 'images/setting.svg', + path: ThemeImage.settingIcon, title: AppLocalizations.of(context)!.settings, onTap: () { viewModel.onSelectItem(8); @@ -596,11 +433,6 @@ class _HomePageState extends BaseStatefulState @override void changeBottomNavigation(int index) { - // if (viewModel.isCashier) { - // viewModel.onItemTapped(1); - // } else { - // - // } viewModel.onItemTapped(index); } @@ -648,7 +480,7 @@ class _HomePageState extends BaseStatefulState return SettingsMainVC(delegateDrawer: this); case 9: return HomeVC(delegateDrawer: this); - case 12: + case 10: return CartVC(delegateDrawer: this); case 11: return HoldOrderVC( @@ -707,4 +539,54 @@ class _HomePageState extends BaseStatefulState 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 684d3fc..f92f744 100644 --- a/lib/application/views/home/HomePageViewModel.dart +++ b/lib/application/views/home/HomePageViewModel.dart @@ -15,11 +15,7 @@ class HomePageViewModel with ChangeNotifier { List homeItems = []; - // List cashierItems = []; var _appLocale; - - //late String currentDefaultSystemLocale; - bool _isInSync = false; bool get isInSync => _isInSync; @@ -67,7 +63,6 @@ class HomePageViewModel with ChangeNotifier { _appLocale.changeLocale(Locale(locale.languageCode)); dropdownValue = AppLanguage.languages().firstWhere( (element) => element.languageCode == locale.languageCode); - // setFlag(); }); } } @@ -161,11 +156,6 @@ class HomePageViewModel with ChangeNotifier { currentIndex = 1; } } - // if (index == 12) { - // isCashier = false; - // currentIndex = 0; - // } - // currentIndex = index; setSelectedDrawer(index); Navigator.of(context).pop(); // close the drawer } @@ -173,14 +163,11 @@ class HomePageViewModel with ChangeNotifier { void onItemTapped(int index) async { currentIndex = index; if (index == 0) { - // isCashier = false; setSelectedDrawer(0); } else if (index == 1) { - // isCashier = true; - // currentIndex = 1; setSelectedDrawer(2); } else if (index == 2) { - setSelectedDrawer(12); + setSelectedDrawer(10); } else if (index == 3) { setSelectedDrawer(11); } @@ -230,7 +217,5 @@ class HomePageViewModel with ChangeNotifier { sharedPrefs.isLoggedIn = false; sharedPrefs.storeId = ''; sharedPrefs.store_name = ''; - // sharedPrefs.businessRegisterId = ''; - // sharedPrefs.billingCounterId = ''; } } diff --git a/lib/application/views/inventorymodule/categoryviews/InventoryCategoriesModule.dart b/lib/application/views/inventorymodule/categoryviews/InventoryCategoriesModule.dart index 9152778..a64bb42 100644 --- a/lib/application/views/inventorymodule/categoryviews/InventoryCategoriesModule.dart +++ b/lib/application/views/inventorymodule/categoryviews/InventoryCategoriesModule.dart @@ -44,11 +44,6 @@ class _InventoryCategoriesModuleState @override Widget build(BuildContext context) { - //not doing watch because using state to get the data - //and listener - //categoryViewModel = CategoryViewModel(); - //scroll state for pagination - print('here ${categoryViewModel.limit}'); _controller = ScrollController()..addListener(_scrollNotification); return Scaffold( backgroundColor: MyColors.fillColor, diff --git a/lib/application/views/inventorymodule/comboviews/InventoryComboVC.dart b/lib/application/views/inventorymodule/comboviews/InventoryComboVC.dart index 159db29..ca9ecbd 100644 --- a/lib/application/views/inventorymodule/comboviews/InventoryComboVC.dart +++ b/lib/application/views/inventorymodule/comboviews/InventoryComboVC.dart @@ -147,11 +147,18 @@ class _InventoryComboVCState extends BaseStatefulState { hint: AppLocalizations.of(context)!.search, ), ), - Flexible(child: PageLimitDropdown( - onChange: (value) { - viewModel.fetch( - isRefresh: true, limit: int.parse(value!)); - }, + Flexible( + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + PageLimitDropdown( + onChange: (value) { + viewModel.fetch( + isRefresh: true, + limit: int.parse(value!)); + }, + ) + ], )) ], ), @@ -228,7 +235,7 @@ class _InventoryComboVCState extends BaseStatefulState { Future _delete(String id) async { progressDialogue(context); - viewModel.delete(id); + await viewModel.delete(id); hideProgressBar(); } diff --git a/lib/application/views/inventorymodule/comboviews/InventoryNewComboVC.dart b/lib/application/views/inventorymodule/comboviews/InventoryNewComboVC.dart index 2345ca6..1364c02 100644 --- a/lib/application/views/inventorymodule/comboviews/InventoryNewComboVC.dart +++ b/lib/application/views/inventorymodule/comboviews/InventoryNewComboVC.dart @@ -533,6 +533,7 @@ class _InventoryNewComboVCState extends BaseStatefulState { Widget getPriceTextField(int position) { return CustomTextFieldForm( + key: Key(viewModel.priceController[position]), onChanged: (value) { viewModel.priceController[position] = value; }, diff --git a/lib/application/views/inventorymodule/comboviews/repo/ComboRepository.dart b/lib/application/views/inventorymodule/comboviews/repo/ComboRepository.dart index e69de29..eb24ba7 100644 --- a/lib/application/views/inventorymodule/comboviews/repo/ComboRepository.dart +++ 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 index 50a7d1c..1509e7a 100644 --- a/lib/application/views/inventorymodule/comboviews/viewModels/AddComboGroupViewModel.dart +++ b/lib/application/views/inventorymodule/comboviews/viewModels/AddComboGroupViewModel.dart @@ -1,9 +1,7 @@ import 'package:flutter/material.dart'; import 'package:wosull/application/model/Combo/GetComboModel.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/comboviews/repo/ComboRepository.dart'; import 'package:wosull/helpers/Utils.dart'; class AddComboGroupViewModel with ChangeNotifier { @@ -12,7 +10,7 @@ class AddComboGroupViewModel with ChangeNotifier { bool get isLoading => _isLoading; var addComboGroup = AddComboGroup(); - //List subGroupNameController = []; + final repository = ComboRepository(); var groupName = ''; var _crudOperation = CRUDOperationState.uninitialized; @@ -25,7 +23,6 @@ class AddComboGroupViewModel with ChangeNotifier { } void disposeData() { - // subGroupNameController.clear(); _isLoading = false; groupName = ''; } @@ -51,10 +48,7 @@ class AddComboGroupViewModel with ChangeNotifier { setLoading(true); addComboGroup.groupName = groupName; - await APIManager() - .fetchData(Constants.ADD_COMBO_GROUP, addComboGroup.toJson()) - .then((value) { - final response = SimpleResponseModel.fromJson(value); + await repository.addGroup(addComboGroup.toJson()).then((response) { if (response.success) { Utils.showMessage(response.message); _crudOperation = CRUDOperationState.add; @@ -70,7 +64,6 @@ class AddComboGroupViewModel with ChangeNotifier { } void removeGroup(int position) { - // subGroupNameController.removeAt(position); addComboGroup.subGroups!.removeAt(position); notifyListeners(); } diff --git a/lib/application/views/inventorymodule/comboviews/viewModels/AddComboSizeViewModel.dart b/lib/application/views/inventorymodule/comboviews/viewModels/AddComboSizeViewModel.dart index 10944c4..8661aa2 100644 --- a/lib/application/views/inventorymodule/comboviews/viewModels/AddComboSizeViewModel.dart +++ b/lib/application/views/inventorymodule/comboviews/viewModels/AddComboSizeViewModel.dart @@ -1,9 +1,7 @@ import 'package:flutter/cupertino.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/CRUDOperatoinState.dart'; -import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/inventorymodule/comboviews/repo/ComboRepository.dart'; import 'package:wosull/helpers/Utils.dart'; class AddComboSizeViewModel with ChangeNotifier { @@ -20,6 +18,8 @@ class AddComboSizeViewModel with ChangeNotifier { CRUDOperationState get crudOperation => _crudOperation; + final repository = ComboRepository(); + void disposeData() { controller.clear(); _crudOperation = CRUDOperationState.uninitialized; @@ -36,10 +36,7 @@ class AddComboSizeViewModel with ChangeNotifier { _crudOperation = CRUDOperationState.update; setLoading(true); var comboSizes = ComboSize(id: '', sizes: controller); - await APIManager() - .fetchData(Constants.ADD_COMBO_SIZES, comboSizes.toJson()) - .then((value) { - final response = SimpleResponseModel.fromJson(value); + await repository.addUpdateSize(comboSizes.toJson()).then((response) { if (response.success) { _crudOperation = CRUDOperationState.add; Utils.showMessage(response.message); @@ -82,10 +79,7 @@ class AddComboSizeViewModel with ChangeNotifier { } void getComboSizes() async { - await APIManager() - .fetchData(Constants.GET_COMBO_SIZES, Constants.getStorePayload()) - .then((value) { - final response = GetComboSizes.fromJson(value); + await repository.getComboSizes().then((response) { if (response.success!) { if (response.comboSizes != null) { for (var size in response.comboSizes!.sizes!) { @@ -96,8 +90,8 @@ class AddComboSizeViewModel with ChangeNotifier { _crudOperation = CRUDOperationState.update; notifyListeners(); }).onError((error, stackTrace) { - print(stackTrace.toString()); _crudOperation = CRUDOperationState.error; - }).timeout(const Duration(minutes: 1)); + notifyListeners(); + }); } } diff --git a/lib/application/views/inventorymodule/comboviews/viewModels/AddNewComboViewModel.dart b/lib/application/views/inventorymodule/comboviews/viewModels/AddNewComboViewModel.dart index 06aed3f..a6646b8 100644 --- a/lib/application/views/inventorymodule/comboviews/viewModels/AddNewComboViewModel.dart +++ b/lib/application/views/inventorymodule/comboviews/viewModels/AddNewComboViewModel.dart @@ -5,15 +5,11 @@ 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/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/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/comboviews/repo/ComboRepository.dart'; import 'package:wosull/helpers/Utils.dart'; class AddNewComboViewModel with ChangeNotifier { @@ -45,12 +41,23 @@ class AddNewComboViewModel with ChangeNotifier { 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(); @@ -84,15 +91,13 @@ class AddNewComboViewModel with ChangeNotifier { categoriesList.addAll(response); if (categoriesList.isNotEmpty) { selectedItemCategory = categoriesList.first; + addCombo.categoryId = categoriesList.first.id; } loadSizes(); } Future loadSizes() async { - await APIManager() - .fetchData(Constants.GET_COMBO_SIZES, Constants.getStorePayload()) - .then((value) { - final response = GetComboSizes.fromJson(value); + await repository.getComboSizes().then((response) { if (response.success!) { comboSize.addAll(response.comboSizes!.sizes!); loadGroups(); @@ -100,35 +105,27 @@ class AddNewComboViewModel with ChangeNotifier { setLoadingFirst(false); } }).onError((error, stackTrace) { - print('size' + error.toString()); setLoading(false); }); } Future loadGroups() async { - await APIManager() - .fetchData(Constants.GET_COMBO_GROUPS, Constants.getStorePayload()) - .then((value) { - final response = GetComboGroupModel.fromJson(value); - if (response.success!) { - comboGroups.addAll(response.comboGroup!); + await wosulRepository.loadGroups().then((value) { + if (value.isNotEmpty) { + comboGroups.addAll(value); loadMeasurement(); } else { setLoadingFirst(false); } }).onError((error, stackTrace) { setLoadingFirst(false); - print(error.toString()); }); } Future loadMeasurement() async { - await APIManager() - .fetchData(Constants.GET_MEASUREMENT, Constants.getStorePayload()) - .then((value) { - final response = GetComboMeasurementModel.fromJson(value); - if (response.success!) { - comboMeasurement.addAll(response.measurements!); + await wosulRepository.loadMeasurement().then((value) { + if (value.isNotEmpty) { + comboMeasurement.addAll(value); if (categoriesList.isNotEmpty) { loadProduct(); } @@ -142,18 +139,14 @@ class AddNewComboViewModel with ChangeNotifier { Future loadProduct() async { ItemCategory itemCategory = selectedItemCategory; - Map data = { + Map map = { 'store_id': sharedPrefs.storeId, 'category_id': itemCategory.id, }; - await APIManager() - .fetchData(Constants.GET_PRODUCT_ITEM_BY_CATEGORY, data) - .then((value) { - final response = GetComboProductItem.fromJson(value); - if (response.success!) { + await wosulRepository.loadProduct(map).then((value) { + if (value.isNotEmpty) { comboProduct.clear(); - comboProduct.addAll(response.products!); - + comboProduct.addAll(value); setLoadingFirst(false); } else { setLoadingFirst(false); @@ -182,12 +175,8 @@ class AddNewComboViewModel with ChangeNotifier { Future addUpdateCombo() async { addCombo.comboPrice = double.parse(comboTotalPriceController); addCombo.comboName = comboNameController; - setLoading(true); - await APIManager() - .fetchData(Constants.NEW_COMBO, addCombo.toJson()) - .then((value) { - final response = SimpleResponseModel.fromJson(value); + await repository.addUpdateCombo(addCombo.toJson()).then((response) { if (response.success) { _crudOperation = CRUDOperationState.add; Utils.showMessage(response.message); diff --git a/lib/application/views/inventorymodule/comboviews/viewModels/ComboViewModel.dart b/lib/application/views/inventorymodule/comboviews/viewModels/ComboViewModel.dart index a91c8c0..337ace0 100644 --- a/lib/application/views/inventorymodule/comboviews/viewModels/ComboViewModel.dart +++ b/lib/application/views/inventorymodule/comboviews/viewModels/ComboViewModel.dart @@ -1,13 +1,11 @@ -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/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; @@ -43,13 +41,11 @@ class ComboViewModel with ChangeNotifier { 'page': _currentPageNumber, 'limit': this.limit }; - print(jsonEncode(data)); 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(); @@ -66,8 +62,6 @@ class ComboViewModel with ChangeNotifier { _dataState = DataState.fetched; _currentPageNumber += 1; }).onError((error, stackTrace) { - print(error.toString()); - print(stackTrace.toString()); _dataState = DataState.error; }); } @@ -94,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!); @@ -115,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/deliveryPartnerViews/InventoryDeliveryPartnerPriceVC.dart b/lib/application/views/inventorymodule/deliveryPartnerViews/InventoryDeliveryPartnerPriceVC.dart index c5aa39d..b7b8e54 100644 --- a/lib/application/views/inventorymodule/deliveryPartnerViews/InventoryDeliveryPartnerPriceVC.dart +++ b/lib/application/views/inventorymodule/deliveryPartnerViews/InventoryDeliveryPartnerPriceVC.dart @@ -122,11 +122,18 @@ class _InventoryDeliveryPartnerPriceVCState hint: AppLocalizations.of(context)!.search, ), ), - Flexible(child: PageLimitDropdown( - onChange: (value) { - viewModel.fetch( - isRefresh: true, limit: int.parse(value!)); - }, + Flexible( + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + PageLimitDropdown( + onChange: (value) { + viewModel.fetch( + isRefresh: true, + limit: int.parse(value!)); + }, + ) + ], )) ], ), diff --git a/lib/application/views/inventorymodule/ingredientsViews/AddProductIngredientVC.dart b/lib/application/views/inventorymodule/ingredientsViews/AddProductIngredientVC.dart index 99bcd73..0fc22d0 100644 --- a/lib/application/views/inventorymodule/ingredientsViews/AddProductIngredientVC.dart +++ b/lib/application/views/inventorymodule/ingredientsViews/AddProductIngredientVC.dart @@ -574,7 +574,7 @@ class _AddProductIngredientVCState }, menuProps: ThemeDropDown.menuProps, fit: FlexFit.loose, - constraints: const BoxConstraints(maxHeight: 250)), + constraints: const BoxConstraints(maxHeight: 200)), items: itemsList, itemAsString: (Brand u) => u.name!, onChanged: (Brand? data) { diff --git a/lib/application/views/inventorymodule/ingredientsViews/IngredientsVC.dart b/lib/application/views/inventorymodule/ingredientsViews/IngredientsVC.dart index 8af2429..1a1ffb7 100644 --- a/lib/application/views/inventorymodule/ingredientsViews/IngredientsVC.dart +++ b/lib/application/views/inventorymodule/ingredientsViews/IngredientsVC.dart @@ -79,10 +79,16 @@ class _IngredientsVCState extends State { hint: AppLocalizations.of(context)!.search, ), ), - Flexible(child: PageLimitDropdown(onChange: (value) { - viewModel.fetch( - isRefresh: true, limit: int.parse(value!)); - })) + Flexible( + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + PageLimitDropdown(onChange: (value) { + viewModel.fetch( + isRefresh: true, limit: int.parse(value!)); + }) + ], + )), ], ), isPortrait diff --git a/lib/application/views/inventorymodule/ingredientsViews/repo/IngredientRepository.dart b/lib/application/views/inventorymodule/ingredientsViews/repo/IngredientRepository.dart index e69de29..aa2e9c4 100644 --- a/lib/application/views/inventorymodule/ingredientsViews/repo/IngredientRepository.dart +++ 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 index 34cb875..ac91b2d 100644 --- a/lib/application/views/inventorymodule/ingredientsViews/viewModels/AddIngredientViewModel.dart +++ b/lib/application/views/inventorymodule/ingredientsViews/viewModels/AddIngredientViewModel.dart @@ -1,41 +1,21 @@ -import 'dart:convert'; - import 'package:flutter/material.dart'; -import 'package:wosull/application/localdb/SharedPrefs.dart'; import 'package:wosull/application/model/Measurement/InventoryMeasurementModel.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/ingredients/AddIngredient.dart'; -import 'package:wosull/application/model/ingredients/AddIngredientModel.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/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/helpers/DatePicker.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; @@ -48,6 +28,8 @@ class AddIngredientViewModel with ChangeNotifier { CRUDOperationState get crudOperationState => _crudOperationState; + final repository = IngredientRepository(); + void setInStock(bool value) { addIngredient.isItemInStock = value; notifyListeners(); @@ -61,16 +43,6 @@ class AddIngredientViewModel with ChangeNotifier { selectedSupplier = null; selectedDiscount = null; selectedBrand = null; - // nameController = ''; - // productCode = ''; - // salePriceExclTax = ''; - // salePriceIncludeTax = ''; - // purchasePriceExclTax = ''; - // stockAlertQuantity = ''; - // quantityController = ''; - // descriptionController = ''; - // descriptionArabic = ''; - // barCodeController = ''; } void setData(AddIngredient ingredient) { @@ -90,21 +62,15 @@ class AddIngredientViewModel with ChangeNotifier { 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); + await repository.getSubProducts(categoryID).then((values) { if (values.success) { - id = values.product.id; + if (values.product.isNotEmpty) { + id = values.product.first.id; + } } else { Utils.showMessage('Product not found against selected category'); } }).onError((error, stackTrace) {}); - return id; } @@ -114,21 +80,10 @@ class AddIngredientViewModel with ChangeNotifier { } 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); setLoading(true); - print(jsonEncode(addIngredient.toJson())); - await APIManager() - .fetchData(Constants.ADD_INGREDIENTS, addIngredient.toJson()) - .then((value) { - final response = AddIngredientModel.fromJson(value); + await repository + .addIngredientToServer(addIngredient.toJson()) + .then((response) { if (response.success) { _crudOperationState = CRUDOperationState.add; setLoading(false); @@ -143,110 +98,50 @@ class AddIngredientViewModel with ChangeNotifier { }); } - // 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(); addIngredient.uniqueIdForStoreData = number; - // 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.formatDateFromPicketINVOICE(pickedDate); - } else { - addIngredient.expiryDate = - DataTimeFormat.formatDateFromPicketINVOICE(pickedDate); - } - 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 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'); - } - } + 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); } - }) - .onError((error, stackTrace) {}) - .timeout(const Duration(minutes: 1)); - + } + } + selectedBrand ??= Brand(name: 'Choose'); + }).onError((error, stackTrace) {}); 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); + await WosulRepository().getStoreCategoriesData().then((categories) { + if (categories.isNotEmpty) { + items.addAll(categories); if (isEditView) { if (addIngredient.categoryId.isNotEmpty) { selectedCategory = items.singleWhere( @@ -260,22 +155,15 @@ class AddIngredientViewModel with ChangeNotifier { addIngredient.categoryId = selectedCategory.id; } } - }).onError((error, stackTrace) { - print(error.toString()); - }); - + }).onError((error, stackTrace) {}); 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!); + await WosulRepository().getSuppliersData().then((suppliers) { + if (suppliers.isNotEmpty) { + items.addAll(suppliers); if (isEditView) { if (addIngredient.supplier.isNotEmpty) { selectedSupplier = items.singleWhere( @@ -292,12 +180,9 @@ class AddIngredientViewModel 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!); + await WosulRepository().getDiscount().then((discounts) { + if (discounts.isNotEmpty) { + items.addAll(discounts); if (isEditView) { if (addIngredient.discount.isNotEmpty) { selectedDiscount = items.singleWhere( @@ -314,12 +199,9 @@ class AddIngredientViewModel with ChangeNotifier { Future> getMeasurement() async { var items = []; - await APIManager() - .fetchData(Constants.GET_MEASUREMENT, Constants.getStorePayload()) - .then((value) { - final response = ProductMeasurementModel.fromJson(value); - if (response.success!) { - items.addAll(response.measurements!); + await WosulRepository().getMeasurement().then((measurements) { + if (measurements.isNotEmpty) { + items.addAll(measurements); if (isEditView) { final name = items .singleWhere( diff --git a/lib/application/views/inventorymodule/ingredientsViews/viewModels/IngredientViewModel.dart b/lib/application/views/inventorymodule/ingredientsViews/viewModels/IngredientViewModel.dart index 89a5a52..fb7e98d 100644 --- a/lib/application/views/inventorymodule/ingredientsViews/viewModels/IngredientViewModel.dart +++ b/lib/application/views/inventorymodule/ingredientsViews/viewModels/IngredientViewModel.dart @@ -2,12 +2,12 @@ import 'package:flutter/material.dart'; import 'package:wosull/application/enum/DataState.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; import 'package:wosull/application/model/ingredients/AddIngredient.dart'; -import 'package:wosull/application/model/ingredients/GetIngredientModel.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/ingredientsViews/repo/IngredientRepository.dart'; class IngredientViewModel with ChangeNotifier { + final repository = IngredientRepository(); + List _filteredList = []; List get filteredList => _filteredList; @@ -54,18 +54,15 @@ class IngredientViewModel with ChangeNotifier { 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); - _dataList.addAll(value.ingredient); - if (value.ingredient.length < this.limit) { + if (ingredient.isNotEmpty) { + _filteredList.addAll(ingredient); + _dataList.addAll(ingredient); + if (ingredient.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; @@ -102,13 +99,10 @@ class IngredientViewModel with ChangeNotifier { _dataState = DataState.searching; notifyListeners(); try { - await APIManager() - .fetchData(Constants.searchIngredients, data) - .then((result) { - final value = GetIngredientModel.fromJson(result); + await repository.search(data).then((ingredients) { _filteredList.clear(); - if (value.success) { - _filteredList.addAll(value.ingredient); + if (ingredients.isNotEmpty) { + _filteredList.addAll(ingredients); } _dataState = DataState.fetched; }).onError((error, stackTrace) { @@ -123,10 +117,7 @@ class IngredientViewModel with ChangeNotifier { } 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; @@ -141,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/measurementviews/repo/MeasurementsRepository.dart b/lib/application/views/inventorymodule/measurementviews/repo/MeasurementsRepository.dart index e69de29..afbdac8 100644 --- a/lib/application/views/inventorymodule/measurementviews/repo/MeasurementsRepository.dart +++ 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 6279657..dcc08d3 100644 --- a/lib/application/views/inventorymodule/measurementviews/viewModels/AddMeasurementUnitVM.dart +++ b/lib/application/views/inventorymodule/measurementviews/viewModels/AddMeasurementUnitVM.dart @@ -1,9 +1,7 @@ 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 { @@ -16,6 +14,8 @@ class AddMeasurementUnitVM with ChangeNotifier { String unitName = ''; + final repository = MeasurementRepository(); + void disposeData() { unitName = ''; } @@ -35,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 997f4b7..a0bc267 100644 --- a/lib/application/views/inventorymodule/measurementviews/viewModels/AddMeasurementViewModel.dart +++ b/lib/application/views/inventorymodule/measurementviews/viewModels/AddMeasurementViewModel.dart @@ -2,21 +2,12 @@ import 'package:flutter/material.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; import 'package:wosull/application/model/Measurement/InventoryMeasurementModel.dart'; import 'package:wosull/application/model/Measurement/MeasurementUnitModel.dart'; -import 'package:wosull/application/model/SimpleResponsModel.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/measurementviews/repo/MeasurementsRepository.dart'; import 'package:wosull/helpers/Utils.dart'; class AddMeasurementViewModel with ChangeNotifier { - void disposeData() { - _isLoading = false; - measurementUnits.clear(); - dropdownValue = null; - measurement = Measurement(); - } - bool _isLoading = false; bool get isLoading => _isLoading; @@ -30,11 +21,20 @@ class AddMeasurementViewModel with ChangeNotifier { CRUDOperationState get crudOperation => _crudOperation; var measurement = Measurement(); + final repository = MeasurementRepository(); + void setLoading(bool value) { _isLoading = value; notifyListeners(); } + void disposeData() { + _isLoading = false; + measurementUnits.clear(); + dropdownValue = null; + measurement = Measurement(); + } + Future fillValueOnEdit(bool isEdit, Measurement measurement) async { this.isEdit = isEdit; this.measurement = measurement; @@ -44,9 +44,6 @@ class AddMeasurementViewModel with ChangeNotifier { dropdownValue ??= measurementUnits .singleWhere((element) => element.name == measurement.measurement); } - print(measurement.measurement); - - print(dropdownValue); dropdownValue ??= MeasurementUnit(id: '', name: 'Choose'); notifyListeners(); } @@ -57,15 +54,14 @@ 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, @@ -73,10 +69,7 @@ class AddMeasurementViewModel with ChangeNotifier { '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; @@ -99,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 a17035d..bc4029b 100644 --- a/lib/application/views/inventorymodule/measurementviews/viewModels/MeasurementViewModel.dart +++ b/lib/application/views/inventorymodule/measurementviews/viewModels/MeasurementViewModel.dart @@ -1,12 +1,10 @@ -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/Measurement/GetStoreMeasurementModel.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; @@ -24,6 +22,8 @@ class MeasurementViewModel extends ChangeNotifier { List get filteredList => _filteredList; + final repository = MeasurementRepository(); + void disposeData() { _filteredList.clear(); _dataState = DataState.uninitialized; @@ -52,16 +52,13 @@ class MeasurementViewModel extends ChangeNotifier { if (_didLastLoad) { _dataState = DataState.noMoreData; } else { - await APIManager() - .fetchData(Constants.GET_INVENTORY_MEASUREMENTS, data) - .then((result) { - final value = GetStoreMeasurementModel.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 < this.limit) { + if (measurements.isNotEmpty) { + _filteredList.addAll(measurements); + if (measurements.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; @@ -89,21 +86,17 @@ class MeasurementViewModel extends ChangeNotifier { _filteredList.clear(); notifyListeners(); } else { - Map data = { + Map map = { 'store_id': sharedPrefs.storeId, 'searchTerm': searchValue }; - print(jsonEncode(data)); _dataState = DataState.searching; notifyListeners(); try { - await APIManager() - .fetchData(Constants.SEARCH_MEASUREMENT, data) - .then((result) { - final value = GetStoreMeasurementModel.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/modiferOption/repo/ModifierOptionRepository.dart b/lib/application/views/inventorymodule/modiferOption/repo/ModifierOptionRepository.dart index 8b994bf..2cdd291 100644 --- a/lib/application/views/inventorymodule/modiferOption/repo/ModifierOptionRepository.dart +++ b/lib/application/views/inventorymodule/modiferOption/repo/ModifierOptionRepository.dart @@ -5,15 +5,31 @@ import 'package:wosull/application/model/modifierOptions/ModifierOptionsResponse import 'package:wosull/application/network/APIManager.dart'; import 'package:wosull/application/utils/Constants.dart'; -class ModifierRepository { +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!) {} + if (value.status!) { + options.addAll(value.modifierOptions ?? []); + } }).onError((error, stackTrace) {}); + return options; } Future addUpdateModifierOption( diff --git a/lib/application/views/inventorymodule/modiferOption/viewModels/ModifierOptionsViewModel.dart b/lib/application/views/inventorymodule/modiferOption/viewModels/ModifierOptionsViewModel.dart index a070ee6..c2b32b6 100644 --- a/lib/application/views/inventorymodule/modiferOption/viewModels/ModifierOptionsViewModel.dart +++ b/lib/application/views/inventorymodule/modiferOption/viewModels/ModifierOptionsViewModel.dart @@ -1,10 +1,7 @@ import 'package:flutter/material.dart'; import 'package:wosull/application/enum/DataState.dart'; -import 'package:wosull/application/localdb/SharedPrefs.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'; +import 'package:wosull/application/views/inventorymodule/modiferOption/repo/ModifierOptionRepository.dart'; class ModifierOptionsViewModel with ChangeNotifier { bool _isLoading = false; @@ -22,6 +19,8 @@ class ModifierOptionsViewModel with ChangeNotifier { List get filteredList => _filteredList; + final repository = ModifierOptionRepository(); + void setLoading(bool value) { _isLoading = value; notifyListeners(); @@ -49,17 +48,13 @@ class ModifierOptionsViewModel with ChangeNotifier { if (_didLastLoad) { _dataState = DataState.noMoreData; } else { - await APIManager() - .getResponseAuth( - Constants.getModifierOptions + sharedPrefs.storeId, data) - .then((result) { - final value = ModifierOptionsResponse.fromJson(result); + await repository.fetch(data).then((value) { if (_dataState == DataState.refreshing) { _filteredList.clear(); } - if (value.status!) { - _filteredList.addAll(value.modifierOptions!); - if (value.modifierOptions!.length < this.limit) { + if (value.isNotEmpty) { + _filteredList.addAll(value); + if (value.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; @@ -81,10 +76,7 @@ class ModifierOptionsViewModel with ChangeNotifier { } Future delete(String id) async { - Map data = {'modifier_option_id': id}; - await APIManager() - .getResponsePatch(Constants.deleteModifierOption, data) - .then((result) { + await repository.delete(id).then((result) { filteredList.removeWhere((element) => element.id! == id); notifyListeners(); }).onError((error, stackTrace) { @@ -93,10 +85,7 @@ class ModifierOptionsViewModel with ChangeNotifier { } Future update(String id, bool value) async { - Map data = {'modifier_option_id': id, 'status': value}; - await APIManager() - .getResponsePatch(Constants.updateModifierOption, data) - .then((result) { + await repository.update(id, value).then((result) { _filteredList.singleWhere((element) => element.id == id).status = value; notifyListeners(); }).onError((error, stackTrace) { diff --git a/lib/application/views/inventorymodule/modiferOption/viewModels/NewModifierOptionViewModel.dart b/lib/application/views/inventorymodule/modiferOption/viewModels/NewModifierOptionViewModel.dart index 2122531..88bf935 100644 --- a/lib/application/views/inventorymodule/modiferOption/viewModels/NewModifierOptionViewModel.dart +++ b/lib/application/views/inventorymodule/modiferOption/viewModels/NewModifierOptionViewModel.dart @@ -1,22 +1,18 @@ import 'package:flutter/material.dart'; import 'package:objectbox/objectbox.dart'; -import 'package:wosull/application/localdb/SharedPrefs.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/ingredients/AddIngredient.dart'; -import 'package:wosull/application/model/ingredients/GetIngredientModel.dart'; import 'package:wosull/application/model/modifierOptions/ModifierId.dart'; import 'package:wosull/application/model/modifierOptions/ModifierOption.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/modiferOption/repo/ModifierOptionRepository.dart'; import 'package:wosull/helpers/Utils.dart'; class NewModifierOptionViewModel with ChangeNotifier { + final repository = ModifierOptionRepository(); + bool _isLoading = false; bool get isLoading => _isLoading; @@ -30,6 +26,15 @@ class NewModifierOptionViewModel with ChangeNotifier { 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; } @@ -58,13 +63,10 @@ class NewModifierOptionViewModel with ChangeNotifier { Future> getModifiers() async { var modifiers = []; - await APIManager() - .getResponseAuth(Constants.getModifiers + sharedPrefs.storeId) - .then((value) { - final response = GetModifiersModel.fromJson(value); - if (response.success!) { + await WosulRepository().getModifiers().then((data) { + if (data.isNotEmpty) { modifiers.clear(); - modifiers.addAll(response.modifiers!); + modifiers.addAll(data); } }).onError((error, stackTrace) {}); return modifiers; @@ -86,10 +88,9 @@ class NewModifierOptionViewModel with ChangeNotifier { Future addUpdateModifierOption() async { setLoading(true); - await APIManager() - .fetchData(Constants.addModifierOptions, modifierOption.toJson()) - .then((value) { - final response = SimpleResponseModel.fromJson(value); + await repository + .addUpdateModifierOption(modifierOption.toJson()) + .then((response) { Utils.showMessage(response.message); if (response.success) { setState(CRUDOperationState.add); @@ -99,7 +100,6 @@ class NewModifierOptionViewModel with ChangeNotifier { setLoading(false); }).onError((error, stackTrace) { setState(CRUDOperationState.error); - print(stackTrace.toString()); setLoading(false); }); } @@ -116,27 +116,19 @@ class NewModifierOptionViewModel with ChangeNotifier { 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); + await WosulRepository().getMeasurements().then((data) { + if (data.isNotEmpty) { + items.addAll(data); } }).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); + await WosulRepository().getIngredients().then((data) { + if (data.isNotEmpty) { + ingredients.addAll(data); } }).onError((error, stackTrace) {}); return ingredients; diff --git a/lib/application/views/inventorymodule/modiferOption/views/NewModifierOptionVC.dart b/lib/application/views/inventorymodule/modiferOption/views/NewModifierOptionVC.dart index ad66d49..8ee0cac 100644 --- a/lib/application/views/inventorymodule/modiferOption/views/NewModifierOptionVC.dart +++ b/lib/application/views/inventorymodule/modiferOption/views/NewModifierOptionVC.dart @@ -55,6 +55,12 @@ class _NewModifierOptionVCState extends State { super.initState(); } + @override + void dispose() { + viewModel.disposeData(); + super.dispose(); + } + @override Widget build(BuildContext context) { viewModel = context.watch(); diff --git a/lib/application/views/inventorymodule/modifierviews/repo/ModifierRepository.dart b/lib/application/views/inventorymodule/modifierviews/repo/ModifierRepository.dart index e69de29..2cdc5e5 100644 --- a/lib/application/views/inventorymodule/modifierviews/repo/ModifierRepository.dart +++ 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 eb9b73d..3a2baa5 100644 --- a/lib/application/views/inventorymodule/modifierviews/viewModels/ModiferViewModel.dart +++ b/lib/application/views/inventorymodule/modifierviews/viewModels/ModiferViewModel.dart @@ -1,10 +1,8 @@ -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/model/Modifiers/Modifier.dart'; -import 'package:wosull/application/network/APIManager.dart'; -import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/inventorymodule/modifierviews/repo/ModifierRepository.dart'; class ModifierViewModel extends ChangeNotifier { bool _isLoading = false; @@ -25,6 +23,8 @@ class ModifierViewModel extends ChangeNotifier { List get filteredList => _filteredList; + final repository = ModifierRepository(); + void setLoading(bool value) { _isLoading = value; notifyListeners(); @@ -53,18 +53,15 @@ class ModifierViewModel extends ChangeNotifier { 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 < this.limit) { + if (value.isNotEmpty) { + _filteredList.addAll(value); + _dataList.addAll(value); + if (value.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; @@ -99,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) { @@ -120,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(); @@ -139,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 3317e8c..c01e02c 100644 --- a/lib/application/views/inventorymodule/modifierviews/viewModels/NewModifierVM.dart +++ b/lib/application/views/inventorymodule/modifierviews/viewModels/NewModifierVM.dart @@ -1,13 +1,9 @@ -import 'dart:convert'; - 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/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/modifierviews/repo/ModifierRepository.dart'; import 'package:wosull/helpers/Utils.dart'; class NewModifierVM with ChangeNotifier { @@ -23,6 +19,8 @@ class NewModifierVM with ChangeNotifier { CRUDOperationState get crudOperationState => _crudOperationState; + final repository = ModifierRepository(); + void disposeData() { _isLoading = false; modifier = @@ -55,12 +53,7 @@ class NewModifierVM with ChangeNotifier { 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 { @@ -85,18 +78,11 @@ class NewModifierVM with ChangeNotifier { } void removeModifierOption(int position) { - // controllersName.removeAt(position); - // controllersArabic.removeAt(position); - // controllersPrice.removeAt(position); modifier.options.removeAt(position); notifyListeners(); } void addNewModifierOption() { - // controllersName.add(''); - // controllersArabic.add(''); - // controllersPrice.add(''); - modifier.options.add(ModifierOption( name: '', arabicName: '', ingredients: ToMany(items: []))); notifyListeners(); diff --git a/lib/application/views/inventorymodule/productviews/InventoryProductVC.dart b/lib/application/views/inventorymodule/productviews/InventoryProductVC.dart index 9657e1a..8d22a12 100644 --- a/lib/application/views/inventorymodule/productviews/InventoryProductVC.dart +++ b/lib/application/views/inventorymodule/productviews/InventoryProductVC.dart @@ -132,10 +132,17 @@ class _InventoryProductVCState extends BaseStatefulState { ), ), Flexible( - child: PageLimitDropdown(onChange: (value) { - viewModel.fetch( - isRefresh: true, limit: int.parse(value!)); - })) + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + PageLimitDropdown(onChange: (value) { + viewModel.fetch( + isRefresh: true, + limit: int.parse(value!)); + }) + ], + )) ], ), ChangeNotifierProvider( diff --git a/lib/application/views/inventorymodule/productviews/repo/ProductRepository.dart b/lib/application/views/inventorymodule/productviews/repo/ProductRepository.dart index e69de29..eabf59e 100644 --- a/lib/application/views/inventorymodule/productviews/repo/ProductRepository.dart +++ 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/AddProductViewModel.dart b/lib/application/views/inventorymodule/productviews/viewModels/AddProductViewModel.dart index b93cea7..75c85eb 100644 --- a/lib/application/views/inventorymodule/productviews/viewModels/AddProductViewModel.dart +++ b/lib/application/views/inventorymodule/productviews/viewModels/AddProductViewModel.dart @@ -11,29 +11,26 @@ import 'package:wosull/application/model/DeliveryPartner/GetDeliveryPartner.dart import 'package:wosull/application/model/DeliveryPartner/ItemsDeliveryPartner.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/Products/AddProduct.dart'; -import 'package:wosull/application/model/Products/ItemProductModel.dart'; -import 'package:wosull/application/model/Products/ProductById.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/ingredients/AddIngredient.dart'; -import 'package:wosull/application/model/ingredients/AddProdcutModel.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/store/GetStoreSupplier.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/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 { - // List unitsController = []; + final repository = ProductRepository(); List selectedMod = []; List selectedPartners = []; @@ -118,8 +115,6 @@ class AddProductViewModel with ChangeNotifier { } else { storeItem.deliveryPartners[position].price = 0; } - - // notifyListeners(); } void addNewDeliveryPartner() { @@ -182,30 +177,19 @@ 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.formatDateFromPicketINVOICE(pickedDate); - } else { - storeItem.expireDate = - DataTimeFormat.formatDateFromPicketINVOICE(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(); } Future isValidate(BuildContext context, bool isEdit) async { @@ -239,9 +223,8 @@ class AddProductViewModel with ChangeNotifier { productId.productId = await getSubProducts(selected.id); storeItem.productId = productId; - await APIManager() - .getResponsePatch( - Constants.UPDATE_PRODUCT_ITEM, storeItem.toJsonUpdateProduct()) + await repository + .updateProduct(storeItem.toJsonUpdateProduct()) .then((value) { if (value.success) { Utils.showMessage(value.message); @@ -264,11 +247,7 @@ class AddProductViewModel with ChangeNotifier { notifyListeners(); storeItem.productIdSt = await getSubProducts(storeItem.productIdSt); - await APIManager() - .fetchData(Constants.ADD_PRODUCT_ITEM, storeItem.toJsonProduct()) - .then((value) { - final response = AddProductModel.fromJson(value); - + await repository.addProduct(storeItem.toJsonProduct()).then((response) { if (response.success) { if (response.product.id.isNotEmpty) { if (isImageUploaded) { @@ -300,17 +279,11 @@ class AddProductViewModel with ChangeNotifier { 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); + 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(); @@ -320,7 +293,6 @@ class AddProductViewModel with ChangeNotifier { isLoadingData = false; notifyListeners(); }); - return id; } @@ -350,7 +322,6 @@ class AddProductViewModel with ChangeNotifier { 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(); final result = jsonDecode(response.body) as Map; if (result['success']) { Utils.showMessage('Product Added Successfully'); @@ -365,7 +336,6 @@ class AddProductViewModel with ChangeNotifier { generateCode() { String number = Utils.generateCode(); - // barCodeController = number; storeItem.uniqueIdForStoreData = number; notifyListeners(); } @@ -377,12 +347,9 @@ class AddProductViewModel with ChangeNotifier { Future> getIngredients() async { var items = []; - await APIManager() - .getResponseAuth("${Constants.GET_INGREDIENTS}/${sharedPrefs.storeId}") - .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; @@ -391,12 +358,9 @@ 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!); + await WosulRepository().getDiscount().then((value) { + if (value.isNotEmpty) { + items.addAll(value); if (isEdit) { for (var item in items) { if (item.name == storeItem.discount) { @@ -414,13 +378,9 @@ 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!); + await WosulRepository().getSuppliersData().then((value) { + if (value.isNotEmpty) { + items.addAll(value); if (isEdit) { selectedSupplier ??= items.singleWhere((element) => element.id! == storeItem.supplier); @@ -428,23 +388,14 @@ class AddProductViewModel with ChangeNotifier { selectedSupplier ??= Supplier(name: 'Choose'); } }).onError((error, stackTrace) {}); - 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); - + await WosulRepository().getStoreCategoriesData().then((data) { + if (data.isNotEmpty) { + items.addAll(data); if (isEdit) { if (selectedCategory == null) { selectedCategory = items.singleWhere( @@ -458,23 +409,15 @@ class AddProductViewModel with ChangeNotifier { storeItem.productIdSt = items.first.id; } } - }).onError((error, stackTrace) { - print(error.toString()); - }); - + }).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) @@ -489,32 +432,19 @@ 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(bool isIngredient) async { var items = []; - - await APIManager() - .getResponseAuth( - Constants.getMeasuringUnit, Constants.getStorePayload()) - .then((value) { - final response = MeasuringUnit.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( @@ -529,7 +459,6 @@ class AddProductViewModel with ChangeNotifier { } } }).onError((error, stackTrace) {}); - return items; } @@ -538,18 +467,11 @@ 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; } @@ -563,7 +485,6 @@ class AddProductViewModel with ChangeNotifier { selectedIngredientsMeasurement[position] = MeasurementUnit(id: '', name: ''); } - notifyListeners(); } @@ -590,7 +511,6 @@ class AddProductViewModel with ChangeNotifier { void setIngredient(AddIngredient? data) { if (data != null) { - // unitsController.add(data.defaultSalePrice.toString()); selectedIngredientsMeasurement .add(MeasurementUnit(id: '', name: 'Choose')); storeItem.ingredients.add(data); @@ -618,7 +538,6 @@ class AddProductViewModel with ChangeNotifier { } void removeUnit(int position) { - // unitsController.removeAt(position); selectedIngredientsMeasurement.removeAt(position); storeItem.ingredients.removeAt(position); notifyListeners(); @@ -628,49 +547,33 @@ class AddProductViewModel with ChangeNotifier { if (value.isEmpty) { 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 APIManager() - .getResponseAuth("${Constants.GET_PRODUCT_BY_ID}/$itemId") - .then((value) { - final response = ProductById.fromJson(value); - + 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)); } - // for (var item in storeItem.ingredients) { - // unitsController.add(item.defaultSalePrice!.toString()); - // } isLoadingFirst = false; } }).onError((error, stackTrace) { @@ -679,7 +582,6 @@ class AddProductViewModel with ChangeNotifier { } void removeIngredient(int position) { - //unitsController.removeAt(position); storeItem.ingredients.removeAt(position); notifyListeners(); } diff --git a/lib/application/views/inventorymodule/productviews/viewModels/ProductViewModel.dart b/lib/application/views/inventorymodule/productviews/viewModels/ProductViewModel.dart index 2031f6b..d6ada7c 100644 --- a/lib/application/views/inventorymodule/productviews/viewModels/ProductViewModel.dart +++ b/lib/application/views/inventorymodule/productviews/viewModels/ProductViewModel.dart @@ -1,17 +1,12 @@ -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/Products/GetProductResponse.dart'; -import 'package:wosull/application/model/Products/ItemProductModel.dart'; -import 'package:wosull/application/model/Products/SearchProductResponse.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 = false; @@ -35,6 +30,7 @@ class ProductViewModel with ChangeNotifier { bool _didLastLoad = false; bool _isLoading = true; + final repository = ProductRepository(); bool get isLoading => _isLoading; String productId = ""; @@ -46,61 +42,37 @@ 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, int limit = 10}) async { @@ -124,23 +96,20 @@ class ProductViewModel with ChangeNotifier { 'page': _currentPageNumber, 'limit': this.limit }; - print(jsonEncode(data)); + try { if (_didLastLoad) { _dataState = DataState.noMoreData; } else { - await APIManager() - .fetchData(Constants.GET_ITEMS_URL, data) - .then((result) { - final value = GetProductResponse.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 < this.limit) { + if (storeItems.isNotEmpty) { + _filteredList.addAll(storeItems); + _dataList.addAll(storeItems); + if (storeItems.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; @@ -151,7 +120,6 @@ class ProductViewModel with ChangeNotifier { _isLoading = false; notifyListeners(); }).onError((error, stackTrace) { - print(stackTrace.toString()); _dataState = DataState.error; _isLoading = false; notifyListeners(); @@ -180,13 +148,10 @@ class ProductViewModel with ChangeNotifier { _dataState = DataState.searching; notifyListeners(); try { - await APIManager() - .fetchData(Constants.SEARCH_PRODUCT, 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) { @@ -201,10 +166,7 @@ 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.itemId == id); _dataList.removeWhere((element) => element.itemId == id); @@ -221,10 +183,7 @@ 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.itemId == id); _filteredList[index].status = status; diff --git a/lib/application/views/inventorymodule/stockReturn/repo/StockReturnRepository.dart b/lib/application/views/inventorymodule/stockReturn/repo/StockReturnRepository.dart index e69de29..cc68080 100644 --- a/lib/application/views/inventorymodule/stockReturn/repo/StockReturnRepository.dart +++ 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 index 9359574..646bba9 100644 --- a/lib/application/views/inventorymodule/stockReturn/viewmodels/NewStockReturnViewModel.dart +++ b/lib/application/views/inventorymodule/stockReturn/viewmodels/NewStockReturnViewModel.dart @@ -2,16 +2,14 @@ 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/SimpleResponsModel.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/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/stockReturn/repo/StockReturnRepository.dart'; import 'package:wosull/helpers/Utils.dart'; class NewStockReturnViewModel with ChangeNotifier { @@ -34,6 +32,8 @@ class NewStockReturnViewModel with ChangeNotifier { CRUDOperationState get crudOperation => _crudOperation; + final repository = StockReturnRepository(); + void setState(CRUDOperationState state) { _crudOperation = state; } @@ -100,10 +100,9 @@ class NewStockReturnViewModel with ChangeNotifier { Future addUpdateStockReturn() async { setLoading(true); - await APIManager() - .fetchData(Constants.addStockReturn, stockReturn.toJson()) - .then((value) { - final response = SimpleResponseModel.fromJson(value); + await repository + .addUpdateStockReturn(stockReturn.toJson()) + .then((response) { Utils.showMessage(response.message); if (response.success) { setState(CRUDOperationState.add); @@ -205,13 +204,8 @@ class NewStockReturnViewModel 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!); - } + await WosulRepository().getDiscount().then((discounts) { + items.addAll(discounts); }).onError((error, stackTrace) {}); return items; @@ -219,16 +213,9 @@ class NewStockReturnViewModel with ChangeNotifier { 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)); + await WosulRepository().getTax().then((vats) { + items.addAll(vats); + }).onError((error, stackTrace) {}); return items; } @@ -236,13 +223,8 @@ class NewStockReturnViewModel with ChangeNotifier { 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!); - } + await WosulRepository().getMeasurement().then((measurements) { + items.addAll(measurements); }).onError((error, stackTrace) {}); return items; diff --git a/lib/application/views/inventorymodule/stockReturn/viewmodels/StockReturnViewModel.dart b/lib/application/views/inventorymodule/stockReturn/viewmodels/StockReturnViewModel.dart index f73b083..0e919e7 100644 --- a/lib/application/views/inventorymodule/stockReturn/viewmodels/StockReturnViewModel.dart +++ b/lib/application/views/inventorymodule/stockReturn/viewmodels/StockReturnViewModel.dart @@ -2,9 +2,7 @@ import 'package:flutter/material.dart'; import 'package:wosull/application/enum/DataState.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; import 'package:wosull/application/model/ReturnStock/ReturnStock.dart'; -import 'package:wosull/application/model/ReturnStock/ReturnStockResponse.dart'; -import 'package:wosull/application/network/APIManager.dart'; -import 'package:wosull/application/utils/Constants.dart'; +import 'package:wosull/application/views/inventorymodule/stockReturn/repo/StockReturnRepository.dart'; class StockReturnViewModel with ChangeNotifier { bool _isLoading = false; @@ -22,6 +20,8 @@ class StockReturnViewModel with ChangeNotifier { List get filteredList => _filteredList; + final repository = StockReturnRepository(); + void setLoading(bool value) { _isLoading = value; notifyListeners(); @@ -50,16 +50,13 @@ class StockReturnViewModel with ChangeNotifier { if (_didLastLoad) { _dataState = DataState.noMoreData; } else { - await APIManager() - .fetchData(Constants.getReturnStock, data) - .then((result) { - final value = ReturnStockResponse.fromJson(result); + await repository.fetch(data).then((stock) { if (_dataState == DataState.refreshing) { _filteredList.clear(); } - if (value.success) { - _filteredList.addAll(value.returnStock); - if (value.returnStock.length < this.limit) { + if (stock.isNotEmpty) { + _filteredList.addAll(stock); + if (stock.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; @@ -81,10 +78,7 @@ class StockReturnViewModel with ChangeNotifier { } Future delete(String id) async { - Map data = {'modifier_option_id': id}; - await APIManager() - .getResponsePatch(Constants.deleteModifierOption, data) - .then((result) { + await repository.delete(id).then((result) { filteredList.removeWhere((element) => element.id == id); notifyListeners(); }).onError((error, stackTrace) { diff --git a/lib/application/views/inventorymodule/stockReturn/views/StockReturnVC.dart b/lib/application/views/inventorymodule/stockReturn/views/StockReturnVC.dart index 376b3dc..7b55019 100644 --- a/lib/application/views/inventorymodule/stockReturn/views/StockReturnVC.dart +++ b/lib/application/views/inventorymodule/stockReturn/views/StockReturnVC.dart @@ -76,7 +76,8 @@ class _StockReturnVCState extends BaseStatefulState { width: 150, child: newStock(), ), - Row( + Flexible( + child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ PageLimitDropdown(onChange: (value) { @@ -85,7 +86,7 @@ class _StockReturnVCState extends BaseStatefulState { limit: int.parse(value!)); }) ], - ) + )) ], ), AppSpaces.verticalMedium, diff --git a/lib/application/views/inventorymodule/stockTransferViews/InventoryStockTransferVC.dart b/lib/application/views/inventorymodule/stockTransferViews/InventoryStockTransferVC.dart index e32fb71..21dfc7f 100644 --- a/lib/application/views/inventorymodule/stockTransferViews/InventoryStockTransferVC.dart +++ b/lib/application/views/inventorymodule/stockTransferViews/InventoryStockTransferVC.dart @@ -122,7 +122,8 @@ class _InventoryStockTransferVCState hint: AppLocalizations.of(context)!.search, ), ), - Row( + Flexible( + child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ PageLimitDropdown(onChange: (value) { @@ -131,7 +132,7 @@ class _InventoryStockTransferVCState limit: int.parse(value!)); }) ], - ) + )) ], ), AppSpaces.verticalMedium, diff --git a/lib/application/views/inventorymodule/stockTransferViews/repo/StockTransferRepository.dart b/lib/application/views/inventorymodule/stockTransferViews/repo/StockTransferRepository.dart index e69de29..b710ba7 100644 --- a/lib/application/views/inventorymodule/stockTransferViews/repo/StockTransferRepository.dart +++ 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 82e6fae..bc13f77 100644 --- a/lib/application/views/inventorymodule/stockTransferViews/viewModels/NewStockTransferVM.dart +++ b/lib/application/views/inventorymodule/stockTransferViews/viewModels/NewStockTransferVM.dart @@ -1,18 +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; @@ -57,10 +53,7 @@ class NewStockTransferVM with ChangeNotifier { '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( @@ -95,16 +88,12 @@ class NewStockTransferVM with ChangeNotifier { '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); @@ -120,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); @@ -162,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(); diff --git a/lib/application/views/inventorymodule/stockTransferViews/viewModels/StockTransferViewModel.dart b/lib/application/views/inventorymodule/stockTransferViews/viewModels/StockTransferViewModel.dart index 737343d..8f348e3 100644 --- a/lib/application/views/inventorymodule/stockTransferViews/viewModels/StockTransferViewModel.dart +++ b/lib/application/views/inventorymodule/stockTransferViews/viewModels/StockTransferViewModel.dart @@ -1,13 +1,9 @@ -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/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'; +import 'package:wosull/application/views/inventorymodule/stockTransferViews/repo/StockTransferRepository.dart'; class StockTransferViewModel with ChangeNotifier { bool _isLoading = false; @@ -28,6 +24,7 @@ class StockTransferViewModel with ChangeNotifier { List _dataList = []; List get dataList => _dataList; + final repository = StockTransferRepository(); fetch({bool isRefresh = false, int limit = 10}) async { this.limit = limit; @@ -52,18 +49,15 @@ class StockTransferViewModel with ChangeNotifier { 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); - _dataList.addAll(value.stockTransfers); - if (value.stockTransfers.length < this.limit) { + if (stockTransfers.isNotEmpty) { + _filteredList.addAll(stockTransfers); + _dataList.addAll(stockTransfers); + if (stockTransfers.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; @@ -73,7 +67,6 @@ class StockTransferViewModel with ChangeNotifier { _dataState = DataState.fetched; _currentPageNumber += 1; }).onError((error, stackTrace) { - print(stackTrace.toString()); _isLoading = false; _dataState = DataState.error; }); @@ -100,13 +93,10 @@ class StockTransferViewModel with ChangeNotifier { _dataState = DataState.searching; notifyListeners(); try { - await APIManager() - .fetchData(Constants.searchStockTransfer, data) - .then((result) { - final value = SearchStockTransferResponse.fromJson(result); + await repository.search(data).then((stockTransfers) { _filteredList.clear(); - if (value.success) { - _filteredList.addAll(value.stockTransfers); + if (stockTransfers.isNotEmpty) { + _filteredList.addAll(stockTransfers); } _dataState = DataState.fetched; }).onError((error, stackTrace) { @@ -122,9 +112,7 @@ class StockTransferViewModel with ChangeNotifier { 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) { @@ -139,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/subCategoryViews/repo/SubCategoryRepository.dart b/lib/application/views/inventorymodule/subCategoryViews/repo/SubCategoryRepository.dart index e69de29..710b014 100644 --- a/lib/application/views/inventorymodule/subCategoryViews/repo/SubCategoryRepository.dart +++ 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 58f9a17..0ef0626 100644 --- a/lib/application/views/inventorymodule/subCategoryViews/viewModels/AddSubCategoryViewModel.dart +++ b/lib/application/views/inventorymodule/subCategoryViews/viewModels/AddSubCategoryViewModel.dart @@ -1,13 +1,11 @@ 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/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 { @@ -22,6 +20,8 @@ class AddSubCategoryViewModel with ChangeNotifier { List itemsList = []; List storeIds = []; + final repository = SubCategoryRepository(); + var nameController = ''; var arabicController = ''; @@ -112,10 +112,7 @@ class AddSubCategoryViewModel with ChangeNotifier { 'is_visible_in_store': activeInActiveStatus, }; - 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; } @@ -146,20 +143,21 @@ class AddSubCategoryViewModel with ChangeNotifier { } 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); - } - - notifyListeners(); + 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 62724ae..120cb33 100644 --- a/lib/application/views/inventorymodule/subCategoryViews/viewModels/SubCategoryViewModel.dart +++ b/lib/application/views/inventorymodule/subCategoryViews/viewModels/SubCategoryViewModel.dart @@ -1,16 +1,12 @@ -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/ViewItemCategory.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/repository/WosulRepository.dart'; import 'package:wosull/application/utils/CRUDOperatoinState.dart'; -import 'package:wosull/application/utils/Constants.dart'; - -import '../../../../repository/WosulRepository.dart'; +import 'package:wosull/application/views/inventorymodule/subCategoryViews/repo/SubCategoryRepository.dart'; class SubCategoryViewModel with ChangeNotifier { int _currentPageNumber = 1; @@ -47,6 +43,8 @@ class SubCategoryViewModel with ChangeNotifier { List get filteredList => _filteredList; late ViewItemCategory category; + final repository = SubCategoryRepository(); + Future initData() async { final response = await WosulRepository().getCategoriesData(); itemsList.addAll(response); @@ -87,18 +85,15 @@ class SubCategoryViewModel with ChangeNotifier { if (_didLastLoad) { _dataState = DataState.noMoreData; } else { - await APIManager() - .fetchData(Constants.GET_SUBCATEGORIES_URL, data) - .then((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 < this.limit) { + if (categories.isNotEmpty) { + _filteredList.addAll(categories); + _dataList.addAll(categories); + if (categories.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; @@ -135,13 +130,10 @@ class SubCategoryViewModel with ChangeNotifier { _dataState = DataState.searching; notifyListeners(); try { - await APIManager() - .fetchData(Constants.SEARCH_SUB_CATEGORY, data) - .then((result) { - final value = SearchSubCategoryResponse.fromJson(result); + await repository.search(data).then((categories) { _filteredList.clear(); - if (value.success) { - _filteredList.addAll(value.categories); + if (categories.isNotEmpty) { + _filteredList.addAll(categories); } _dataState = DataState.fetched; }).onError((error, stackTrace) { @@ -156,10 +148,7 @@ class SubCategoryViewModel with ChangeNotifier { } Future viewCategory(String id) async { - await APIManager() - .getResponseAuth('${Constants.GET_SUB_CATEGORY_BY_ID}$id') - .then((response) { - final value = SubCategoryResponse.fromJson(response); + await repository.viewCategory(id).then((value) { if (value.success) { category = value.subCategory; _crudOperationState = CRUDOperationState.view; @@ -172,10 +161,7 @@ class SubCategoryViewModel with ChangeNotifier { } 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); @@ -191,13 +177,7 @@ 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); @@ -207,10 +187,8 @@ class SubCategoryViewModel with ChangeNotifier { } else { _crudOperationState = CRUDOperationState.error; } - notifyListeners(); }).onError((error, stackTrace) { - print(stackTrace.toString()); _crudOperationState == CRUDOperationState.error; notifyListeners(); }); diff --git a/lib/application/views/kitchenmodule/views/kitchen/KitchenViewVC.dart b/lib/application/views/kitchenmodule/views/kitchen/KitchenViewVC.dart index 44fc037..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'; diff --git a/lib/application/views/kitchenmodule/views/kitchen/repo/KitchenRepository.dart b/lib/application/views/kitchenmodule/views/kitchen/repo/KitchenRepository.dart index e69de29..7e04170 100644 --- a/lib/application/views/kitchenmodule/views/kitchen/repo/KitchenRepository.dart +++ 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/views/kitchen/viewModel/KitchenViewModel.dart b/lib/application/views/kitchenmodule/views/kitchen/viewModel/KitchenViewModel.dart index 38e12dc..35298d4 100644 --- a/lib/application/views/kitchenmodule/views/kitchen/viewModel/KitchenViewModel.dart +++ b/lib/application/views/kitchenmodule/views/kitchen/viewModel/KitchenViewModel.dart @@ -1,5 +1,4 @@ import 'dart:async'; -import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:wosull/application/enum/DataState.dart'; @@ -7,11 +6,11 @@ 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/ModifierOption.dart'; -import 'package:wosull/application/model/SimpleResponsModel.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 { @@ -33,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; @@ -67,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; @@ -100,18 +86,7 @@ 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); + await repository.update(id).then((response) { if (response.success) { _filteredList.removeWhere((element) => element.id! == id); _dataList.removeWhere((element) => element.id! == id); @@ -188,7 +163,6 @@ class KitchenViewModel with ChangeNotifier { Future setItemStatusOffline( int index, int parent, int child, bool? value) async { - print(value); if (value == null) { dbOrder[index].orderDetails[parent].items[child].status = false; } else { @@ -201,8 +175,5 @@ class KitchenViewModel with ChangeNotifier { dbOrder.removeWhere((element) => element.obid == order.obid); order.orderStatus = Constants.ready; await objectbox.updateOrder(order); - // Future.delayed(const Duration(milliseconds: 500), () { - // notifyListeners(); // Here you can write your code - // }); } } diff --git a/lib/application/views/kitchenmodule/views/kitchen/widgets/ItemsListView.dart b/lib/application/views/kitchenmodule/views/kitchen/widgets/ItemsListView.dart index f14adfa..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'; diff --git a/lib/application/views/kitchenmodule/views/kitchen/widgets/KitchenListView.dart b/lib/application/views/kitchenmodule/views/kitchen/widgets/KitchenListView.dart index 0cbf658..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'; 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 c38940d..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'; 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 9117c71..084feec 100644 --- a/lib/application/views/kitchenmodule/views/kitchen/widgets/offline/KitchenOfflineListView.dart +++ b/lib/application/views/kitchenmodule/views/kitchen/widgets/offline/KitchenOfflineListView.dart @@ -8,7 +8,7 @@ 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'; diff --git a/lib/application/views/kitchenmodule/views/table/KitchenTableVC.dart b/lib/application/views/kitchenmodule/views/table/KitchenTableVC.dart index c385fe9..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'; diff --git a/lib/application/views/kitchenmodule/views/table/repo/TableRepository.dart b/lib/application/views/kitchenmodule/views/table/repo/TableRepository.dart index e69de29..0eccdec 100644 --- a/lib/application/views/kitchenmodule/views/table/repo/TableRepository.dart +++ 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/views/table/viewModels/TablesViewModel.dart b/lib/application/views/kitchenmodule/views/table/viewModels/TablesViewModel.dart index 2ce2920..53e936f 100644 --- a/lib/application/views/kitchenmodule/views/table/viewModels/TablesViewModel.dart +++ b/lib/application/views/kitchenmodule/views/table/viewModels/TablesViewModel.dart @@ -2,8 +2,7 @@ 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; @@ -23,6 +22,8 @@ class TablesViewModel with ChangeNotifier { List get filteredList => _filteredList; + final repository = TableRepository(); + fetch({bool isRefresh = false, int limit = 10}) async { this.limit = limit; _isLoading = true; @@ -46,18 +47,15 @@ class TablesViewModel with ChangeNotifier { 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 < this.limit) { + if (tables.isNotEmpty) { + _filteredList.addAll(tables); + _dataList.addAll(tables); + if (tables.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; @@ -92,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) { @@ -113,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(); @@ -132,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/salesandordermodule/views/ReturnInvoiceVC.dart b/lib/application/views/salesandordermodule/views/ReturnInvoiceVC.dart index 9cdfbb1..3105ed6 100644 --- a/lib/application/views/salesandordermodule/views/ReturnInvoiceVC.dart +++ b/lib/application/views/salesandordermodule/views/ReturnInvoiceVC.dart @@ -647,8 +647,7 @@ class _ReturnInvoiceVCState extends BaseStatefulState { await viewModel.returnInvoice(); checkState(); }, - heading: - viewModel.isReturn ? 'Return Only order' : "Damage Only order"); + heading: viewModel.isReturn ? 'Return Items' : "Damage Items"); } getWholeOrderButton() { @@ -659,7 +658,6 @@ class _ReturnInvoiceVCState extends BaseStatefulState { await viewModel.update(); checkState(); }, - heading: - viewModel.isReturn ? 'Return whole order' : "Damage whole order"); + heading: viewModel.isReturn ? 'Return Invoice' : "Damage Invoice"); } } diff --git a/lib/application/views/salesandordermodule/views/invoiceModule/views/InvoicesVC.dart b/lib/application/views/salesandordermodule/views/invoiceModule/views/InvoicesVC.dart index 8de5b6c..b7b6e7b 100644 --- a/lib/application/views/salesandordermodule/views/invoiceModule/views/InvoicesVC.dart +++ b/lib/application/views/salesandordermodule/views/invoiceModule/views/InvoicesVC.dart @@ -126,7 +126,11 @@ class _InvoicesVCState extends BaseStatefulState { height: 48, child: getSearchBox(), ), - Flexible(child: getPageLimit()) + Flexible( + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [getPageLimit()], + )) ], ), AppSpaces.verticalLarge, diff --git a/lib/application/views/salesandordermodule/views/invoiceModule/widgets/InvoiceListView.dart b/lib/application/views/salesandordermodule/views/invoiceModule/widgets/InvoiceListView.dart index d4be514..79e20bd 100644 --- a/lib/application/views/salesandordermodule/views/invoiceModule/widgets/InvoiceListView.dart +++ b/lib/application/views/salesandordermodule/views/invoiceModule/widgets/InvoiceListView.dart @@ -2,6 +2,7 @@ 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'; @@ -492,38 +493,56 @@ class InvoiceListView extends StatelessWidget { Widget getPopUpMenuButton(BuildContext context, StoreInvoice invoice) { return CustomPopupMenuButton( onSelected: (String value) => actionPopUpItemSelected(value, invoice), - items: [ - // PopupMenuItem( - // value: 'edit', - // child: ValueText( - // lang(context).edit, - // ), - // ), - PopupMenuItem( - value: 'return', - child: ValueText( - lang(context).return_txt, - ), + 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, ), - PopupMenuItem( - value: 'damage', - child: ValueText( - "Damage", - ), + ), + ]; + } + + getAllMenuOptions(BuildContext context) { + return [ + // PopupMenuItem( + // value: 'edit', + // child: ValueText( + // lang(context).edit, + // ), + // ), + PopupMenuItem( + value: 'return', + child: ValueText( + lang(context).return_txt, ), - PopupMenuItem( - value: 'view', - child: ValueText( - lang(context).print_or_download, - ), + ), + PopupMenuItem( + value: 'damage', + child: ValueText( + "Damage", ), - PopupMenuItem( - value: 'delete', - child: ValueText( - lang(context).delete, - ), - ) - ], - ); + ), + 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/repo/OrderRepository.dart b/lib/application/views/salesandordermodule/views/ordersModule/repo/OrderRepository.dart index e69de29..2798236 100644 --- a/lib/application/views/salesandordermodule/views/ordersModule/repo/OrderRepository.dart +++ 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 5542a13..2505e5e 100644 --- a/lib/application/views/salesandordermodule/views/ordersModule/viewModel/OrderViewModel.dart +++ b/lib/application/views/salesandordermodule/views/ordersModule/viewModel/OrderViewModel.dart @@ -1,13 +1,8 @@ -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/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'; +import 'package:wosull/application/views/salesandordermodule/views/ordersModule/repo/OrderRepository.dart'; class OrderViewModel with ChangeNotifier { String selectedFilter = 'All'; @@ -15,12 +10,10 @@ class OrderViewModel with ChangeNotifier { void setSelectedFilter(String filter) { selectedFilter = filter; - // notifyListeners(); } void setLimit(int parse) { limit = parse; - //notifyListeners(); } int _currentPageNumber = 1; @@ -40,6 +33,8 @@ class OrderViewModel with ChangeNotifier { List get filteredList => _filteredList; + final repository = OrderRepository(); + void setDataState(DataState state) { _dataState = state; } @@ -64,23 +59,19 @@ class OrderViewModel with ChangeNotifier { 'limit': limit, 'order_status': selectedFilter.toLowerCase() }; - print(jsonEncode(data)); 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.fetch(data).then((orders) { 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) { + if (orders.isNotEmpty) { + _filteredList.addAll(orders); + _dataList.addAll(orders); + if (orders.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; @@ -89,14 +80,12 @@ class OrderViewModel with ChangeNotifier { _dataState = DataState.fetched; _currentPageNumber += 1; }).onError((error, stackTrace) { - print(stackTrace.toString()); _dataState = DataState.error; }); } _isLoading = false; notifyListeners(); } catch (e) { - print(e.toString()); _isLoading = false; _dataState = DataState.error; notifyListeners(); @@ -119,18 +108,13 @@ class OrderViewModel with ChangeNotifier { _dataState = DataState.searching; notifyListeners(); try { - await APIManager() - .fetchData(Constants.searchCashier, data) - .then((result) { - print(result); - final value = SearchCashierOrderHistory.fromJson(result); + await repository.search(data).then((orders) { _filteredList.clear(); - if (value.success!) { - _filteredList.addAll(value.topOrders!); + if (orders.isNotEmpty) { + _filteredList.addAll(orders); } _dataState = DataState.fetched; }).onError((error, stackTrace) { - print(stackTrace.toString()); _dataState = DataState.error; }); notifyListeners(); @@ -142,13 +126,7 @@ class OrderViewModel with ChangeNotifier { } Future deleteOrder(String? id) async { - Map data = { - 'orderId': id!, - }; - - await APIManager() - .getResponsePatch(Constants.DELETE_ORDER, data) - .then((value) { + await repository.deleteOrder(id).then((value) { if (value.success) { _filteredList.removeWhere((element) => element.id == id); _dataList.removeWhere((element) => element.id == id); diff --git a/lib/application/views/salesandordermodule/views/ordersModule/views/OrderCashierVC.dart b/lib/application/views/salesandordermodule/views/ordersModule/views/OrderCashierVC.dart index 75fc310..b48f2b1 100644 --- a/lib/application/views/salesandordermodule/views/ordersModule/views/OrderCashierVC.dart +++ b/lib/application/views/salesandordermodule/views/ordersModule/views/OrderCashierVC.dart @@ -43,7 +43,6 @@ class _OrderCashierVCState extends BaseStatefulState { @override Widget build(BuildContext context) { - print(viewModel.dataState); return SingleChildScrollView( controller: _controller, child: ChangeNotifierProvider( diff --git a/lib/application/views/salesandordermodule/views/quotataionModule/NewQuotationsVC.dart b/lib/application/views/salesandordermodule/views/quotataionModule/NewQuotationsVC.dart index 8e4fccb..ee57799 100644 --- a/lib/application/views/salesandordermodule/views/quotataionModule/NewQuotationsVC.dart +++ b/lib/application/views/salesandordermodule/views/quotataionModule/NewQuotationsVC.dart @@ -167,8 +167,8 @@ class _NewQuotationsVCState extends BaseStatefulState { getQuotationFor(), AppSpaces.verticalLarge, getQuotationDueDate(), - AppSpaces.verticalLarge, - getCurrencyWidget() + // AppSpaces.verticalLarge, + // getCurrencyWidget() ], )), AppSpaces.horizontalMedium, @@ -1357,6 +1357,7 @@ class _NewQuotationsVCState extends BaseStatefulState { } 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 9eb048c..417c5b4 100644 --- a/lib/application/views/salesandordermodule/views/quotataionModule/QuotationsVC.dart +++ b/lib/application/views/salesandordermodule/views/quotataionModule/QuotationsVC.dart @@ -124,7 +124,11 @@ class _QuotationsVCState extends BaseStatefulState { height: 48, child: getSearchBox(), ), - Flexible(child: getPageLimitDropdown()) + Flexible( + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [getPageLimitDropdown()], + )) ], ), AppSpaces.verticalMedium, diff --git a/lib/application/views/salesandordermodule/views/quotataionModule/repo/QuotationRepository.dart b/lib/application/views/salesandordermodule/views/quotataionModule/repo/QuotationRepository.dart index 966a188..7d17e54 100644 --- a/lib/application/views/salesandordermodule/views/quotataionModule/repo/QuotationRepository.dart +++ b/lib/application/views/salesandordermodule/views/quotataionModule/repo/QuotationRepository.dart @@ -3,7 +3,6 @@ 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'; -import 'package:wosull/helpers/Utils.dart'; class QuotationRepository { Future getQuotationById(String id) async { @@ -69,16 +68,8 @@ class QuotationRepository { return false; } - Future addUpdateQuotation(map) async { - await APIManager().fetchData(Constants.ADD_QUOTATION, map).then((value) { - final response = SimpleResponseModel.fromJson(value); - if (response.success) { - Utils.showMessage(response.message); - } - 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 index c472aff..0aeb1ab 100644 --- a/lib/application/views/salesandordermodule/views/quotataionModule/viewModels/NewQuotationViewModel.dart +++ b/lib/application/views/salesandordermodule/views/quotataionModule/viewModels/NewQuotationViewModel.dart @@ -147,7 +147,8 @@ class NewQuotationViewModel with ChangeNotifier { setLoading(true); var map = addQuotation.toJson(); await repository.addUpdateQuotation(map).then((value) { - if (value) { + if (value.success) { + Utils.showMessage(value.message); setState(CRUDOperationState.add); } setLoading(false); diff --git a/lib/application/views/settings/viewModels/POSCompleteViewModel.dart b/lib/application/views/settings/viewModels/POSCompleteViewModel.dart index bbca3b6..781ecef 100644 --- a/lib/application/views/settings/viewModels/POSCompleteViewModel.dart +++ b/lib/application/views/settings/viewModels/POSCompleteViewModel.dart @@ -1,8 +1,10 @@ import 'package:flutter/cupertino.dart'; import 'package:wosull/application/enum/DataState.dart'; import 'package:wosull/application/localdb/SharedPrefs.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(); @@ -18,6 +20,26 @@ class POSCompleteViewModel with ChangeNotifier { List get data => _data; + 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; diff --git a/lib/application/views/settings/views/paymentMethods/repo/PaymentMethodRepository.dart b/lib/application/views/settings/views/paymentMethods/repo/PaymentMethodRepository.dart index 006858c..0551c78 100644 --- a/lib/application/views/settings/views/paymentMethods/repo/PaymentMethodRepository.dart +++ b/lib/application/views/settings/views/paymentMethods/repo/PaymentMethodRepository.dart @@ -5,7 +5,9 @@ import 'package:wosull/application/utils/Constants.dart'; class PaymentMethodRepository { Future addPaymentMethod( Map data) async { - final result = await APIManager().fetchData(Constants.searchCashier, data); + final result = + await APIManager().fetchData(Constants.addPaymentMethod, data); + return SimpleResponseModel.fromJson(result); } diff --git a/lib/application/views/settings/views/paymentMethods/viewModel/NewPaymentMethodViewModel.dart b/lib/application/views/settings/views/paymentMethods/viewModel/NewPaymentMethodViewModel.dart index ae8c719..1f591a5 100644 --- a/lib/application/views/settings/views/paymentMethods/viewModel/NewPaymentMethodViewModel.dart +++ b/lib/application/views/settings/views/paymentMethods/viewModel/NewPaymentMethodViewModel.dart @@ -19,6 +19,14 @@ class NewPaymentMethodViewModel with ChangeNotifier { 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; diff --git a/lib/application/views/settings/views/paymentMethods/views/NewPaymentMethodVC.dart b/lib/application/views/settings/views/paymentMethods/views/NewPaymentMethodVC.dart index e6e20c0..7481337 100644 --- a/lib/application/views/settings/views/paymentMethods/views/NewPaymentMethodVC.dart +++ b/lib/application/views/settings/views/paymentMethods/views/NewPaymentMethodVC.dart @@ -39,6 +39,12 @@ class _NewPaymentMethodVCState extends State { super.initState(); } + @override + void dispose() { + viewModel.disposeData(); + super.dispose(); + } + @override Widget build(BuildContext context) { viewModel = context.watch(); diff --git a/lib/application/views/settings/views/paymentMethods/views/PaymentMethodVC.dart b/lib/application/views/settings/views/paymentMethods/views/PaymentMethodVC.dart index 2856173..fc217fb 100644 --- a/lib/application/views/settings/views/paymentMethods/views/PaymentMethodVC.dart +++ b/lib/application/views/settings/views/paymentMethods/views/PaymentMethodVC.dart @@ -82,7 +82,7 @@ class _PaymentMethodVCState extends State { AppSpaces.horizontalSmall, SizedBox( height: 38, - width: 150, + width: 170, child: newPaymentMethod()), AppSpaces.horizontalSmall, Flexible( diff --git a/lib/application/views/settings/views/reports/ReportsVC.dart b/lib/application/views/settings/views/reports/ReportsVC.dart index 96a8d99..61ea125 100644 --- a/lib/application/views/settings/views/reports/ReportsVC.dart +++ b/lib/application/views/settings/views/reports/ReportsVC.dart @@ -100,9 +100,15 @@ class _ReportsVCState extends BaseStatefulState width: 150, child: getReportsTypeButton(), ), - Flexible(child: PageLimitDropdown(onChange: (value) { - limit = int.parse(value!); - })) + Flexible( + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + PageLimitDropdown(onChange: (value) { + limit = int.parse(value!); + }) + ], + )) ], ), AppSpaces.verticalMedium, @@ -138,7 +144,8 @@ class _ReportsVCState extends BaseStatefulState final path = "$directory/${name.trim()}${DateTime.now()}.csv"; print(path); final File file = File(path); - await file.writeAsString("csvData"); + await file.writeAsString(csvData); + // FileStorage.writeCounter( // csvData, '$name${DateTime.now()}.csv'); diff --git a/lib/application/views/transactions/viewmodels/CashierTransactionViewModel.dart b/lib/application/views/transactions/viewmodels/CashierTransactionViewModel.dart index a19631c..10276a4 100644 --- a/lib/application/views/transactions/viewmodels/CashierTransactionViewModel.dart +++ b/lib/application/views/transactions/viewmodels/CashierTransactionViewModel.dart @@ -1,5 +1,3 @@ -import 'dart:convert'; - import 'package:flutter/cupertino.dart'; import 'package:wosull/application/enum/DataState.dart'; import 'package:wosull/application/localdb/SharedPrefs.dart'; @@ -50,7 +48,6 @@ class CashierTransactionViewModel with ChangeNotifier { 'limit': limit, 'order_status': filter }; - print(jsonEncode(data)); try { if (_didLastLoad) { _dataState = DataState.noMoreData; @@ -63,10 +60,10 @@ class CashierTransactionViewModel with ChangeNotifier { _filteredList.clear(); _dataList.clear(); } - if (value.success!) { - _filteredList.addAll(value.topOrders!); - _dataList.addAll(value.topOrders!); - if (value.topOrders!.length < this.limit) { + if (value.success) { + _filteredList.addAll(value.topOrders); + _dataList.addAll(value.topOrders); + if (value.topOrders.length < this.limit) { _didLastLoad = true; } else { _didLastLoad = false; @@ -75,14 +72,12 @@ class CashierTransactionViewModel with ChangeNotifier { _dataState = DataState.fetched; _currentPageNumber += 1; }).onError((error, stackTrace) { - print(stackTrace.toString()); _dataState = DataState.error; }); } _isLoading = false; notifyListeners(); } catch (e) { - print(e.toString()); _isLoading = false; _dataState = DataState.error; notifyListeners(); 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/main.dart b/lib/main.dart index 0345e31..1feff5e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -26,11 +26,9 @@ 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; } diff --git a/lib/widgets/CustomControllerTextFieldForm.dart b/lib/widgets/CustomControllerTextFieldForm.dart index e69de29..d222847 100644 --- a/lib/widgets/CustomControllerTextFieldForm.dart +++ 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 index e69de29..56f3753 100644 --- a/lib/widgets/CustomIconButton.dart +++ 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/DropdownItemBuilder.dart b/lib/widgets/DropdownItemBuilder.dart index 952db2b..b8ee943 100644 --- a/lib/widgets/DropdownItemBuilder.dart +++ b/lib/widgets/DropdownItemBuilder.dart @@ -9,7 +9,7 @@ class DropdownItemBuilder extends StatelessWidget { @override Widget build(BuildContext context) { return Container( - height: 38, + height: 42, padding: const EdgeInsets.only(left: 8, right: 8), child: Align( alignment: Alignment.centerLeft, diff --git a/lib/widgets/PageLimitDropDown.dart b/lib/widgets/PageLimitDropDown.dart index eeb15a5..b6164fa 100644 --- a/lib/widgets/PageLimitDropDown.dart +++ b/lib/widgets/PageLimitDropDown.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/MyColors.dart'; import 'package:wosull/application/utils/Constants.dart'; import 'package:wosull/helpers/ThemeDropDown.dart'; @@ -39,7 +40,7 @@ class PageLimitDropdown extends StatelessWidget { width: 2, ), SizedBox( - width: 90, + width: SizerUtil.deviceType == DeviceType.mobile ? 90 : 105, child: DropdownSearch( dropdownButtonProps: ThemeDropDown.dropdownButtonProps, popupProps: PopupProps.menu( diff --git a/lib/widgets/SearchBox.dart b/lib/widgets/SearchBox.dart index 44c94ee..2444f27 100644 --- a/lib/widgets/SearchBox.dart +++ b/lib/widgets/SearchBox.dart @@ -38,7 +38,11 @@ class SearchBox extends StatelessWidget { states.contains(MaterialState.focused) ? MyColors.textColorBlack20 : MyColors.textColorBlack20), - prefixIcon: const Icon(Icons.search), + prefixIcon: const Icon( + Icons.search, + size: 18, + color: MyColors.textColorBlack20, + ), focusedBorder: OutlineInputBorder( borderSide: const BorderSide(color: MyColors.textColorGray, width: 0.5), diff --git a/pubspec.lock b/pubspec.lock index 7cf0a89..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: @@ -49,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: @@ -281,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: @@ -289,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: @@ -337,6 +369,14 @@ packages: url: "https://pub.dev" source: hosted 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: @@ -677,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: @@ -693,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: @@ -997,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: @@ -1154,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: diff --git a/pubspec.yaml b/pubspec.yaml index 6e3658b..3c4d027 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -70,6 +70,7 @@ dependencies: 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