diff --git a/packages/chicken/lib/presentation/pages/buy_in_province_waiting/logic.dart b/packages/chicken/lib/presentation/pages/buy_in_province_waiting/logic.dart index f4c0fbd..9be6f7b 100644 --- a/packages/chicken/lib/presentation/pages/buy_in_province_waiting/logic.dart +++ b/packages/chicken/lib/presentation/pages/buy_in_province_waiting/logic.dart @@ -15,7 +15,8 @@ class BuyInProvinceWaitingLogic extends GetxController { RxnString searchedValue = RxnString(); RxMap isLoadingConfirmMap = RxMap(); Rx bgConfirmAllColor = AppColor.blueNormal.obs; - + RxInt currentPage = 1.obs; + final RxBool isLoadingMoreAllocationsMade = false.obs; RootLogic rootLogic = Get.find(); Rx>> waitingProduct = Resource>.loading().obs; @@ -45,14 +46,26 @@ class BuyInProvinceWaitingLogic extends GetxController { searchedValue.value = data?.trim(); } - Future getWaitingArrivals() async { + Future getWaitingArrivals([bool isLoadingMore = false]) async { + if (isLoadingMore) { + isLoadingMoreAllocationsMade.value = true; + } else { + waitingProduct.value = Resource>.loading(); + } + + if (searchedValue.value != null && + searchedValue.value!.trim().isNotEmpty && + currentPage.value > 1) { + currentPage.value = 1; // Reset to first page if search value is set + } + safeCall( call: () async => await rootLogic.chickenRepository.getWaitingArrivals( token: rootLogic.tokenService.accessToken.value!, queryParameters: buildQueryParams( queryParams: {'type': 'not_entered'}, - pageSize: 10, - page: 1, + pageSize: 20, + page: currentPage.value, search: 'filter', role: 'Steward', value: searchedValue.value, diff --git a/packages/chicken/lib/presentation/pages/buy_in_province_waiting/view.dart b/packages/chicken/lib/presentation/pages/buy_in_province_waiting/view.dart index d5657fb..8e94937 100644 --- a/packages/chicken/lib/presentation/pages/buy_in_province_waiting/view.dart +++ b/packages/chicken/lib/presentation/pages/buy_in_province_waiting/view.dart @@ -35,7 +35,11 @@ class BuyInProvinceWaitingPage extends GetView { }, itemCount: data.value.data?.results?.length ?? 0, separatorBuilder: (context, index) => SizedBox(height: 8.h), - onLoadMore: () async {}, + onLoadMore: () async => controller.getWaitingArrivals(true), + onRefresh: () async { + controller.currentPage.value = 1; + await controller.getWaitingArrivals(); + }, ); }, controller.waitingProduct), ), diff --git a/packages/chicken/lib/presentation/pages/buy_out_of_province/logic.dart b/packages/chicken/lib/presentation/pages/buy_out_of_province/logic.dart index c8ad281..2b29ed0 100644 --- a/packages/chicken/lib/presentation/pages/buy_out_of_province/logic.dart +++ b/packages/chicken/lib/presentation/pages/buy_out_of_province/logic.dart @@ -7,14 +7,16 @@ import 'package:rasadyar_chicken/data/models/response/steward_free_bar/steward_f import 'package:rasadyar_chicken/presentation/pages/buy/logic.dart'; import 'package:rasadyar_chicken/presentation/pages/root/logic.dart'; import 'package:rasadyar_chicken/presentation/pages/sale/logic.dart'; +import 'package:rasadyar_chicken/presentation/utils/utils.dart'; import 'package:rasadyar_core/core.dart'; class BuyOutOfProvinceLogic extends GetxController { + late List routesName; RxBool isExpanded = false.obs; RxBool isSubmitButtonEnabled = false.obs; RxList isExpandedList = [].obs; - - late List routesName; + final RxInt currentPage = 1.obs; + final RxBool isLoadingMoreAllocationsMade = false.obs; //TODO add this to Di ImagePicker imagePicker = ImagePicker(); @@ -61,6 +63,12 @@ class BuyOutOfProvinceLogic extends GetxController { }); setupListeners(); + + debounce( + searchedValue, + (callback) => getStewardPurchaseOutOfProvince(), + time: Duration(milliseconds: timeDebounce), + ); } @override @@ -75,17 +83,26 @@ class BuyOutOfProvinceLogic extends GetxController { void setSearchValue(String? data) { searchedValue.value = data?.trim(); - getStewardPurchaseOutOfProvince(); } - Future getStewardPurchaseOutOfProvince() async { - purchaseOutOfProvinceList.value = Resource>.loading(); + Future getStewardPurchaseOutOfProvince([bool isLoadingMore = false]) async { + if (isLoadingMore) { + isLoadingMoreAllocationsMade.value = true; + } else { + purchaseOutOfProvinceList.value = Resource>.loading(); + } + + if (searchedValue.value != null && + searchedValue.value!.trim().isNotEmpty && + currentPage.value > 1) { + currentPage.value = 1; // Reset to first page if search value is set + } await safeCall( call: () => rootLogic.chickenRepository.getStewardPurchasesOutSideOfTheProvince( token: rootLogic.tokenService.accessToken.value!, queryParameters: buildQueryParams( pageSize: 10, - page: 1, + page: currentPage.value, search: 'filter', role: 'Steward', value: searchedValue.value, diff --git a/packages/chicken/lib/presentation/pages/buy_out_of_province/view.dart b/packages/chicken/lib/presentation/pages/buy_out_of_province/view.dart index c2b6c11..329dc27 100644 --- a/packages/chicken/lib/presentation/pages/buy_out_of_province/view.dart +++ b/packages/chicken/lib/presentation/pages/buy_out_of_province/view.dart @@ -47,7 +47,11 @@ class BuyOutOfProvincePage extends GetView { }, itemCount: data.value.data?.results?.length ?? 0, separatorBuilder: (context, index) => SizedBox(height: 8.h), - onLoadMore: () async {}, + onLoadMore: () async => controller.getStewardPurchaseOutOfProvince(true), + onRefresh: () async { + controller.currentPage.value = 1; + await controller.getStewardPurchaseOutOfProvince(); + }, ); }, controller.purchaseOutOfProvinceList), ), @@ -561,10 +565,7 @@ class BuyOutOfProvincePage extends GetView { width: Get.width, height: 39, margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4), - decoration: BoxDecoration( - color: AppColor.greenLight, - borderRadius: BorderRadius.circular(8), - ), + decoration: BoxDecoration(color: AppColor.greenLight, borderRadius: BorderRadius.circular(8)), alignment: Alignment.center, child: ObxValue((data) { return Text( @@ -574,4 +575,5 @@ class BuyOutOfProvincePage extends GetView { }, controller.rootLogic.inventoryModel), ); } + } diff --git a/packages/chicken/lib/presentation/pages/sales_out_of_province_buyers/view.dart b/packages/chicken/lib/presentation/pages/sales_out_of_province_buyers/view.dart index f6bc1de..47ab8cd 100644 --- a/packages/chicken/lib/presentation/pages/sales_out_of_province_buyers/view.dart +++ b/packages/chicken/lib/presentation/pages/sales_out_of_province_buyers/view.dart @@ -7,8 +7,7 @@ import 'package:rasadyar_core/core.dart'; import 'logic.dart'; -class SalesOutOfProvinceBuyersPage - extends GetView { +class SalesOutOfProvinceBuyersPage extends GetView { const SalesOutOfProvinceBuyersPage({super.key}); @override @@ -44,10 +43,7 @@ class SalesOutOfProvinceBuyersPage }, controller.buyerList), floatingActionButton: RFab.add( onPressed: () { - Get.bottomSheet( - addOrEditBuyerBottomSheet(), - isScrollControlled: true, - ); + Get.bottomSheet(addOrEditBuyerBottomSheet(), isScrollControlled: true); }, ), floatingActionButtonLocation: FloatingActionButtonLocation.startFloat, @@ -61,55 +57,82 @@ class SalesOutOfProvinceBuyersPage child: Form( key: controller.formKey, child: Column( - spacing: 16, + spacing: 8, children: [ Text( isOnEdit ? 'ویرایش خریدار' : 'افزودن خریدار', - style: AppFonts.yekan16Bold.copyWith( - color: AppColor.darkGreyDarkHover, + style: AppFonts.yekan16Bold.copyWith(color: AppColor.darkGreyDarkHover), + ), + + Container( + padding: EdgeInsets.all(8), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(8), + border: Border.all(color: AppColor.darkGreyLight, width: 1), + ), + child: Column(spacing: 12, children: [_provinceWidget(), _cityWidget()]), + ), + + Container( + padding: EdgeInsets.all(8), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(8), + border: Border.all(color: AppColor.darkGreyLight, width: 1), + ), + child: Column( + spacing: 12, + children: [ + RTextField( + controller: controller.buyerNameController, + label: 'نام خریدار', + borderColor: AppColor.darkGreyLight, + filledColor: AppColor.bgLight, + filled: true, + ), + RTextField( + controller: controller.buyerLastNameController, + label: 'نام خانوادگی خریدار', + borderColor: AppColor.darkGreyLight, + filledColor: AppColor.bgLight, + filled: true, + ), + RTextField( + controller: controller.buyerPhoneController, + label: 'تلفن خریدار', + keyboardType: TextInputType.phone, + borderColor: AppColor.darkGreyLight, + filledColor: AppColor.bgLight, + filled: true, + maxLength: 11, + validator: (value) { + if (value == null || value.isEmpty) { + return 'لطفاً شماره موبایل را وارد کنید'; + } + // حذف کاماها برای اعتبارسنجی + String cleaned = value.replaceAll(',', ''); + if (cleaned.length != 11) { + return 'شماره موبایل باید ۱۱ رقم باشد'; + } + if (!cleaned.startsWith('09')) { + return 'شماره موبایل باید با 09 شروع شود'; + } + return null; + }, + ), + RTextField( + controller: controller.buyerUnitNameController, + label: 'نام واحد', + borderColor: AppColor.darkGreyLight, + filledColor: AppColor.bgLight, + filled: true, + ), + + submitButtonWidget(isOnEdit), + ], ), ), - - RTextField( - controller: controller.buyerPhoneController, - label: 'تلفن خریدار', - keyboardType: TextInputType.phone, - borderColor: AppColor.darkGreyLight, - maxLength: 11, - validator: (value) { - if (value == null || value.isEmpty) { - return 'لطفاً شماره موبایل را وارد کنید'; - } - // حذف کاماها برای اعتبارسنجی - String cleaned = value.replaceAll(',', ''); - if (cleaned.length != 11) { - return 'شماره موبایل باید ۱۱ رقم باشد'; - } - if (!cleaned.startsWith('09')) { - return 'شماره موبایل باید با 09 شروع شود'; - } - return null; - }, - ), - RTextField( - controller: controller.buyerNameController, - label: 'نام خریدار', - borderColor: AppColor.darkGreyLight, - ), - RTextField( - controller: controller.buyerLastNameController, - label: 'نام خانوادگی خریدار', - borderColor: AppColor.darkGreyLight, - ), - - RTextField( - controller: controller.buyerUnitNameController, - label: 'نام واحد', - borderColor: AppColor.darkGreyLight, - ), - _provinceWidget(), - _cityWidget(), - submitButtonWidget(isOnEdit), SizedBox(), ], ), @@ -139,7 +162,7 @@ class SalesOutOfProvinceBuyersPage Widget _provinceWidget() { return Obx(() { - return OverlayDropdownWidget2( + return OverlayDropdownWidget( items: controller.rootLogic.provinces, onChanged: (value) { controller.selectedProvince.value = value; @@ -217,17 +240,13 @@ class SalesOutOfProvinceBuyersPage return Container( padding: EdgeInsets.fromLTRB(8, 12, 14, 12), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - ), + decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8)), child: Column( spacing: 8, children: [ Row( mainAxisAlignment: MainAxisAlignment.start, children: [ - Text( '${item.province}-${item.city}', textAlign: TextAlign.center, @@ -244,10 +263,7 @@ class SalesOutOfProvinceBuyersPage title: 'تعداد درخواست ها', value: '${item.requestsInfo?.numberOfRequests.separatedByComma}', ), - buildRow( - title: 'وزن', - value: '${item.requestsInfo?.totalWeight.separatedByComma}', - ), + buildRow(title: 'وزن', value: '${item.requestsInfo?.totalWeight.separatedByComma}'), Row( mainAxisAlignment: MainAxisAlignment.center, diff --git a/packages/chicken/lib/presentation/pages/sales_out_of_province_sales_list/logic.dart b/packages/chicken/lib/presentation/pages/sales_out_of_province_sales_list/logic.dart index b3d2716..ea1223b 100644 --- a/packages/chicken/lib/presentation/pages/sales_out_of_province_sales_list/logic.dart +++ b/packages/chicken/lib/presentation/pages/sales_out_of_province_sales_list/logic.dart @@ -56,6 +56,7 @@ class SalesOutOfProvinceSalesListLogic extends GetxController { void onReady() { super.onReady(); + selectedProduct.value = saleLogic.rolesProductsModel.first; debounce( searchedValue, (callback) => getOutProvinceSales(), diff --git a/packages/chicken/lib/presentation/pages/sales_out_of_province_sales_list/view.dart b/packages/chicken/lib/presentation/pages/sales_out_of_province_sales_list/view.dart index 8bcfeaa..f86edb3 100644 --- a/packages/chicken/lib/presentation/pages/sales_out_of_province_sales_list/view.dart +++ b/packages/chicken/lib/presentation/pages/sales_out_of_province_sales_list/view.dart @@ -211,7 +211,7 @@ class SalesOutOfProvinceSalesListPage Widget addOrEditSaleBottomSheet([bool isOnEdit = false]) { return BaseBottomSheet( - height: 600, + height: 500.h, child: SingleChildScrollView( child: Form( key: controller.formKey, @@ -224,51 +224,67 @@ class SalesOutOfProvinceSalesListPage color: AppColor.darkGreyDarkHover, ), ), - _productWidget(), - _buyerWidget(), - RTextField( - controller: controller.saleWeightController, - label: 'وزن لاشه', - keyboardType: TextInputType.number, - borderColor: AppColor.darkGreyLight, + _productDropDown(), - inputFormatters: [ - FilteringTextInputFormatter.digitsOnly, - SeparatorInputFormatter(), - ], - validator: (value) { - if (value == null) { - return 'لطفاً وزن لاشه را وارد کنید'; - } - return null; - }, - ), - RTextField( - controller: controller.quarantineCodeController, - label: 'کد قرنطینه', - borderColor: AppColor.darkGreyLight, - validator: (value) { - if (value == null) { - return 'لطفاً کد قرنطینه را وارد کنید'; - } - return null; - }, - ), - - Row( - spacing: 8, - children: [ - Expanded( - child: timeFilterWidget( - date: controller.saleDate, - onChanged: (jalali) => controller.saleDate.value = jalali, + Container( + padding: EdgeInsets.all(8), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(8), + border: Border.all(color: AppColor.darkGreyLight, width: 1), + ), + child: Column( + spacing: 12, + children: [ + Row( + spacing: 8, + children: [ + Expanded( + child: timeFilterWidget( + date: controller.saleDate, + onChanged: (jalali) => controller.saleDate.value = jalali, + ), + ), + ], ), - ), - ], - ), + _buyerWidget(), + RTextField( + controller: controller.saleWeightController, + label: 'وزن لاشه', + keyboardType: TextInputType.number, + borderColor: AppColor.darkGreyLight, + filledColor: AppColor.bgLight, + filled: true, + inputFormatters: [ + FilteringTextInputFormatter.digitsOnly, + SeparatorInputFormatter(), + ], - submitButtonWidget(isOnEdit), + validator: (value) { + if (value == null) { + return 'لطفاً وزن لاشه را وارد کنید'; + } + return null; + }, + ), + RTextField( + controller: controller.quarantineCodeController, + label: 'کد قرنطینه', + borderColor: AppColor.darkGreyLight, + filledColor: AppColor.bgLight, + filled: true, + validator: (value) { + if (value == null) { + return 'لطفاً کد قرنطینه را وارد کنید'; + } + return null; + }, + ), + submitButtonWidget(isOnEdit), + ], + ), + ), SizedBox(), ], ), @@ -314,21 +330,39 @@ class SalesOutOfProvinceSalesListPage }); } - Widget _productWidget() { - return ObxValue((data) { + + Widget _productDropDown() { + return Obx(() { return OverlayDropdownWidget( items: controller.saleLogic.rolesProductsModel, + height: 56, + hasDropIcon: false, + background: Colors.white, onChanged: (value) { controller.selectedProduct.value = value; }, selectedItem: controller.selectedProduct.value, initialValue: controller.selectedProduct.value, itemBuilder: (item) => Text(item.name ?? 'بدون نام'), - labelBuilder: (item) => Text(item?.name ?? 'انتخاب محصول'), + labelBuilder: (item) => Row( + spacing: 8, + children: [ + (item?.name?.contains('مرغ گرم') ?? false) + ? Assets.images.chicken.image(width: 40, height: 40) + : Assets.vec.placeHolderSvg.svg(width: 40, height: 40), + + Text(item?.name ?? 'انتخاب محصول'), + Spacer(), + Text( + 'موجودی:${controller.rootLogic.inventoryModel.value?.totalRemainWeight.separatedByComma ?? 0}', + ), + ], + ), ); - }, controller.selectedProduct); + }); } + GestureDetector timeFilterWidget({ isFrom = true, required Rx date, @@ -339,10 +373,11 @@ class SalesOutOfProvinceSalesListPage Get.bottomSheet(modalDatePicker((value) => onChanged(value))); }, child: Container( - height: 35, + height: 40, decoration: BoxDecoration( + color:AppColor.bgLight, borderRadius: BorderRadius.circular(8), - border: Border.all(width: 1, color: AppColor.bgDark), + border: Border.all(width: 1, color: AppColor.darkGreyLight), ), padding: EdgeInsets.symmetric(horizontal: 11, vertical: 4), child: Row(