From 7790a4017e9372a2ac2ac8f5abbf9491d43159aa Mon Sep 17 00:00:00 2001 From: "mr.mojtaba" Date: Thu, 17 Jul 2025 15:44:40 +0330 Subject: [PATCH] fix : ui fix after release 1.3.3 --- assets/icons/empty.svg | 22 +- assets/icons/place_holder.svg | 2 +- assets/vec/empty.svg.vec | Bin 12776 -> 12776 bytes .../datasource/remote/chicken_remote_imp.dart | 2 +- .../segmentation_model.dart | 10 +- .../segmentation_model.freezed.dart | 27 +- .../segmentation_model.g.dart | 2 + .../lib/presentation/pages/home/logic.dart | 32 +- .../lib/presentation/pages/home/view.dart | 89 ++-- .../lib/presentation/pages/profile/view.dart | 21 +- .../pages/sales_out_of_province/logic.dart | 197 +++++++- .../pages/sales_out_of_province/view.dart | 478 +++++++++++++++++- .../sales_out_of_province_buyers/logic.dart | 65 +-- .../sales_out_of_province_buyers/view.dart | 79 +-- .../pages/segmentation/logic.dart | 18 +- .../presentation/pages/segmentation/view.dart | 2 +- .../presentation/widget/base_page/view.dart | 47 +- .../lib/infrastructure/remote/dio_remote.dart | 12 +- 18 files changed, 898 insertions(+), 207 deletions(-) diff --git a/assets/icons/empty.svg b/assets/icons/empty.svg index ffff199..b7bb9ce 100644 --- a/assets/icons/empty.svg +++ b/assets/icons/empty.svg @@ -27,19 +27,19 @@ - - + + - - - - - - + + + + + + @@ -47,9 +47,9 @@ - - - + + + diff --git a/assets/icons/place_holder.svg b/assets/icons/place_holder.svg index f76a0bf..5a0c1d4 100644 --- a/assets/icons/place_holder.svg +++ b/assets/icons/place_holder.svg @@ -1,4 +1,4 @@ - diff --git a/assets/vec/empty.svg.vec b/assets/vec/empty.svg.vec index 5fcf9c8644ffc1b01bd2f506b9410f2256fa8abb..f0a85a0d0a84ff59b1bf93dd706f0d3d0ebc0eff 100644 GIT binary patch delta 34 ocmaEn{33aRviOzW^8d_C4FCVjSQx4OXJ!VmRu;r;v|48f02a9qMF0Q* delta 34 ocmaEn{33aRviSda-T%x?4FCVjSQx4OXJ!Vm_Bo1gv|48f01bQ&nE(I) diff --git a/packages/chicken/lib/data/datasource/remote/chicken_remote_imp.dart b/packages/chicken/lib/data/datasource/remote/chicken_remote_imp.dart index 5d72f8a..d0ecd35 100644 --- a/packages/chicken/lib/data/datasource/remote/chicken_remote_imp.dart +++ b/packages/chicken/lib/data/datasource/remote/chicken_remote_imp.dart @@ -63,7 +63,7 @@ class ChickenRemoteDatasourceImp implements ChickenRemoteDatasource { Map? queryParameters, }) async { var res = await _httpClient.get( - '/bars_for_kill_house_dashboard/?role=Steward', + '/bars_for_kill_house_dashboard/', queryParameters: queryParameters, headers: {'Authorization': 'Bearer $token'}, fromJson: BarInformation.fromJson, diff --git a/packages/chicken/lib/data/models/response/segmentation_model/segmentation_model.dart b/packages/chicken/lib/data/models/response/segmentation_model/segmentation_model.dart index 86122c3..6226831 100644 --- a/packages/chicken/lib/data/models/response/segmentation_model/segmentation_model.dart +++ b/packages/chicken/lib/data/models/response/segmentation_model/segmentation_model.dart @@ -6,8 +6,14 @@ part 'segmentation_model.g.dart'; @freezed abstract class SegmentationModel with _$SegmentationModel { - const factory SegmentationModel({String? key, Buyer? buyer, DateTime? date, int? weight,String? result}) = - _SegmentationModel; + const factory SegmentationModel({ + String? key, + String? productKey, + Buyer? buyer, + DateTime? date, + int? weight, + String? result, + }) = _SegmentationModel; factory SegmentationModel.fromJson(Map json) => _$SegmentationModelFromJson(json); diff --git a/packages/chicken/lib/data/models/response/segmentation_model/segmentation_model.freezed.dart b/packages/chicken/lib/data/models/response/segmentation_model/segmentation_model.freezed.dart index 2f106c3..ef5569d 100644 --- a/packages/chicken/lib/data/models/response/segmentation_model/segmentation_model.freezed.dart +++ b/packages/chicken/lib/data/models/response/segmentation_model/segmentation_model.freezed.dart @@ -16,7 +16,7 @@ T _$identity(T value) => value; /// @nodoc mixin _$SegmentationModel { - String? get key; Buyer? get buyer; DateTime? get date; int? get weight; String? get result; + String? get key; String? get productKey; Buyer? get buyer; DateTime? get date; int? get weight; String? get result; /// Create a copy of SegmentationModel /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @@ -29,16 +29,16 @@ $SegmentationModelCopyWith get copyWith => _$SegmentationMode @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is SegmentationModel&&(identical(other.key, key) || other.key == key)&&(identical(other.buyer, buyer) || other.buyer == buyer)&&(identical(other.date, date) || other.date == date)&&(identical(other.weight, weight) || other.weight == weight)&&(identical(other.result, result) || other.result == result)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is SegmentationModel&&(identical(other.key, key) || other.key == key)&&(identical(other.productKey, productKey) || other.productKey == productKey)&&(identical(other.buyer, buyer) || other.buyer == buyer)&&(identical(other.date, date) || other.date == date)&&(identical(other.weight, weight) || other.weight == weight)&&(identical(other.result, result) || other.result == result)); } @JsonKey(includeFromJson: false, includeToJson: false) @override -int get hashCode => Object.hash(runtimeType,key,buyer,date,weight,result); +int get hashCode => Object.hash(runtimeType,key,productKey,buyer,date,weight,result); @override String toString() { - return 'SegmentationModel(key: $key, buyer: $buyer, date: $date, weight: $weight, result: $result)'; + return 'SegmentationModel(key: $key, productKey: $productKey, buyer: $buyer, date: $date, weight: $weight, result: $result)'; } @@ -49,7 +49,7 @@ abstract mixin class $SegmentationModelCopyWith<$Res> { factory $SegmentationModelCopyWith(SegmentationModel value, $Res Function(SegmentationModel) _then) = _$SegmentationModelCopyWithImpl; @useResult $Res call({ - String? key, Buyer? buyer, DateTime? date, int? weight, String? result + String? key, String? productKey, Buyer? buyer, DateTime? date, int? weight, String? result }); @@ -66,9 +66,10 @@ class _$SegmentationModelCopyWithImpl<$Res> /// Create a copy of SegmentationModel /// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') @override $Res call({Object? key = freezed,Object? buyer = freezed,Object? date = freezed,Object? weight = freezed,Object? result = freezed,}) { +@pragma('vm:prefer-inline') @override $Res call({Object? key = freezed,Object? productKey = freezed,Object? buyer = freezed,Object? date = freezed,Object? weight = freezed,Object? result = freezed,}) { return _then(_self.copyWith( key: freezed == key ? _self.key : key // ignore: cast_nullable_to_non_nullable +as String?,productKey: freezed == productKey ? _self.productKey : productKey // ignore: cast_nullable_to_non_nullable as String?,buyer: freezed == buyer ? _self.buyer : buyer // ignore: cast_nullable_to_non_nullable as Buyer?,date: freezed == date ? _self.date : date // ignore: cast_nullable_to_non_nullable as DateTime?,weight: freezed == weight ? _self.weight : weight // ignore: cast_nullable_to_non_nullable @@ -96,10 +97,11 @@ $BuyerCopyWith<$Res>? get buyer { @JsonSerializable() class _SegmentationModel implements SegmentationModel { - const _SegmentationModel({this.key, this.buyer, this.date, this.weight, this.result}); + const _SegmentationModel({this.key, this.productKey, this.buyer, this.date, this.weight, this.result}); factory _SegmentationModel.fromJson(Map json) => _$SegmentationModelFromJson(json); @override final String? key; +@override final String? productKey; @override final Buyer? buyer; @override final DateTime? date; @override final int? weight; @@ -118,16 +120,16 @@ Map toJson() { @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _SegmentationModel&&(identical(other.key, key) || other.key == key)&&(identical(other.buyer, buyer) || other.buyer == buyer)&&(identical(other.date, date) || other.date == date)&&(identical(other.weight, weight) || other.weight == weight)&&(identical(other.result, result) || other.result == result)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is _SegmentationModel&&(identical(other.key, key) || other.key == key)&&(identical(other.productKey, productKey) || other.productKey == productKey)&&(identical(other.buyer, buyer) || other.buyer == buyer)&&(identical(other.date, date) || other.date == date)&&(identical(other.weight, weight) || other.weight == weight)&&(identical(other.result, result) || other.result == result)); } @JsonKey(includeFromJson: false, includeToJson: false) @override -int get hashCode => Object.hash(runtimeType,key,buyer,date,weight,result); +int get hashCode => Object.hash(runtimeType,key,productKey,buyer,date,weight,result); @override String toString() { - return 'SegmentationModel(key: $key, buyer: $buyer, date: $date, weight: $weight, result: $result)'; + return 'SegmentationModel(key: $key, productKey: $productKey, buyer: $buyer, date: $date, weight: $weight, result: $result)'; } @@ -138,7 +140,7 @@ abstract mixin class _$SegmentationModelCopyWith<$Res> implements $SegmentationM factory _$SegmentationModelCopyWith(_SegmentationModel value, $Res Function(_SegmentationModel) _then) = __$SegmentationModelCopyWithImpl; @override @useResult $Res call({ - String? key, Buyer? buyer, DateTime? date, int? weight, String? result + String? key, String? productKey, Buyer? buyer, DateTime? date, int? weight, String? result }); @@ -155,9 +157,10 @@ class __$SegmentationModelCopyWithImpl<$Res> /// Create a copy of SegmentationModel /// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $Res call({Object? key = freezed,Object? buyer = freezed,Object? date = freezed,Object? weight = freezed,Object? result = freezed,}) { +@override @pragma('vm:prefer-inline') $Res call({Object? key = freezed,Object? productKey = freezed,Object? buyer = freezed,Object? date = freezed,Object? weight = freezed,Object? result = freezed,}) { return _then(_SegmentationModel( key: freezed == key ? _self.key : key // ignore: cast_nullable_to_non_nullable +as String?,productKey: freezed == productKey ? _self.productKey : productKey // ignore: cast_nullable_to_non_nullable as String?,buyer: freezed == buyer ? _self.buyer : buyer // ignore: cast_nullable_to_non_nullable as Buyer?,date: freezed == date ? _self.date : date // ignore: cast_nullable_to_non_nullable as DateTime?,weight: freezed == weight ? _self.weight : weight // ignore: cast_nullable_to_non_nullable diff --git a/packages/chicken/lib/data/models/response/segmentation_model/segmentation_model.g.dart b/packages/chicken/lib/data/models/response/segmentation_model/segmentation_model.g.dart index d10cb35..745602a 100644 --- a/packages/chicken/lib/data/models/response/segmentation_model/segmentation_model.g.dart +++ b/packages/chicken/lib/data/models/response/segmentation_model/segmentation_model.g.dart @@ -9,6 +9,7 @@ part of 'segmentation_model.dart'; _SegmentationModel _$SegmentationModelFromJson(Map json) => _SegmentationModel( key: json['key'] as String?, + productKey: json['product_key'] as String?, buyer: json['buyer'] == null ? null : Buyer.fromJson(json['buyer'] as Map), @@ -22,6 +23,7 @@ _SegmentationModel _$SegmentationModelFromJson(Map json) => Map _$SegmentationModelToJson(_SegmentationModel instance) => { 'key': instance.key, + 'product_key': instance.productKey, 'buyer': instance.buyer, 'date': instance.date?.toIso8601String(), 'weight': instance.weight, diff --git a/packages/chicken/lib/presentation/pages/home/logic.dart b/packages/chicken/lib/presentation/pages/home/logic.dart index 5c0e315..d1b89f9 100644 --- a/packages/chicken/lib/presentation/pages/home/logic.dart +++ b/packages/chicken/lib/presentation/pages/home/logic.dart @@ -1,41 +1,56 @@ import 'package:rasadyar_auth/data/utils/safe_call.dart'; import 'package:rasadyar_chicken/chicken.dart'; import 'package:rasadyar_chicken/data/models/response/bar_information/bar_information.dart'; -import 'package:rasadyar_chicken/data/models/response/inventory/inventory_model.dart'; import 'package:rasadyar_chicken/data/models/response/kill_house_distribution_info/kill_house_distribution_info.dart'; -import 'package:rasadyar_chicken/presentation/utils/utils.dart'; import 'package:rasadyar_core/core.dart'; class HomeLogic extends GetxController { RootLogic rootLogic = Get.find(); RxnInt totalWeightTodayBars = RxnInt(); Rxn killHouseDistributionInfo = Rxn(); + Rxn barInformation = Rxn(); RxBool isExpanded = false.obs; - @override void onReady() { super.onReady(); + getGeneralBarsInformation(); getTodayBars(); getDistributionInformation(); } + Future getGeneralBarsInformation() async { + await safeCall( + call: () async => await rootLogic.chickenRepository.getGeneralBarInformation( + token: rootLogic.tokenService.accessToken.value!, + queryParameters: buildQueryParams(role: 'Steward'), + ), + onSuccess: (result) { + if (result != null) { + barInformation.value = result; + } + }, + onError: (error, stackTrace) {}, + ); + } Future getTodayBars() async { await safeCall( call: () async => await rootLogic.chickenRepository.getGeneralBarInformation( token: rootLogic.tokenService.accessToken.value!, - queryParameters: buildQueryParams(fromDate: DateTime.now(), toDate: DateTime.now()), + queryParameters: buildQueryParams( + fromDate: DateTime.now(), + toDate: DateTime.now(), + role: 'Steward', + ), ), onSuccess: (result) { if (result != null) { totalWeightTodayBars.value = result.totalBarsWeight?.toInt(); } }, - onError: (error, stackTrace) { - - }, + onError: (error, stackTrace) {}, ); } @@ -52,7 +67,4 @@ class HomeLogic extends GetxController { onError: (error, stackTrace) {}, ); } - - - } diff --git a/packages/chicken/lib/presentation/pages/home/view.dart b/packages/chicken/lib/presentation/pages/home/view.dart index 4fba960..d02fd50 100644 --- a/packages/chicken/lib/presentation/pages/home/view.dart +++ b/packages/chicken/lib/presentation/pages/home/view.dart @@ -280,61 +280,44 @@ class HomePage extends GetView { } Widget _todayShipmentWidget() { - return ObxValue((data) { - return Container( - height: 70, - width: Get.width / 2, - decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8)), - clipBehavior: Clip.hardEdge, - child: Row( - children: [ - Expanded( - child: Container( - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [const Color(0xFFEAEFFF), Colors.white], - ), - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - spacing: 4, - children: [ - Assets.icons.cubeScan.svg(width: 30, height: 30), - Text( - 'بارهای امروز', - textAlign: TextAlign.right, - style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal), - ), - ], - ), + return Padding( + padding: const EdgeInsets.fromLTRB(0, 10, 0, 13), + child: Row( + spacing: 8, + children: [ + Expanded( + child: ObxValue( + (data) => _informationLabelCard( + title: 'بارهای امروز', + isLoading: data.value == null, + description: data.value?.separatedByComma ?? '0', + iconPath: Assets.vec.cubeSearchSvg.path, + iconColor: AppColor.blueNormal, + bgDescriptionColor: Colors.white, + bgLabelColor: Color(0xFFEAEFFF), ), + controller.totalWeightTodayBars, ), - Expanded( - child: data.value == null - ? CupertinoActivityIndicator() - : Column( - mainAxisAlignment: MainAxisAlignment.center, - spacing: 4, - children: [ - Text( - data.value.separatedByComma, - textAlign: TextAlign.right, - style: AppFonts.yekan16.copyWith(color: AppColor.textColor), - ), - Text( - 'کیلوگرم', - textAlign: TextAlign.center, - style: AppFonts.yekan12.copyWith(color: AppColor.textColor), - ), - ], - ), - ), - ], - ), - ); - }, controller.totalWeightTodayBars); + ), + + Expanded( + child: ObxValue((data) { + return _informationLabelCard( + title: 'درانتظار تایید', + isLoading: data.value == null, + description: '(${data.value?.totalNotEnteredBars.separatedByComma ?? '0'})', + unit: '(${data.value?.totalNotEnteredKillHouseRequestsWeight.separatedByComma})کیلوگرم', + iconPath: Assets.vec.cubeRotateSvg.path, + iconColor: Color(0xFF8F4124), + bgLabelColor: Color(0xFFF59770), + bgDescriptionColor: Color(0xFFF6DFD8), + ); + }, controller.barInformation), + ), + ], + ), + ); + } Container _informationLabelCard({ diff --git a/packages/chicken/lib/presentation/pages/profile/view.dart b/packages/chicken/lib/presentation/pages/profile/view.dart index 3805a4a..f0cef35 100644 --- a/packages/chicken/lib/presentation/pages/profile/view.dart +++ b/packages/chicken/lib/presentation/pages/profile/view.dart @@ -74,6 +74,9 @@ class ProfilePage extends GetView { cardActionWidget( title: 'خروج', selected: true, + color: ColorFilter.mode(Colors.redAccent, BlendMode.srcIn), + cardColor:AppColor.error.withValues(alpha: 0.24), + textColor: Colors.red, onPressed: () { Get.bottomSheet(exitBottomSheet(), isScrollControlled: true); }, @@ -83,7 +86,6 @@ class ProfilePage extends GetView { ), ), - SizedBox(height: 100), ], ), @@ -214,6 +216,9 @@ class ProfilePage extends GetView { required VoidCallback onPressed, required String icon, bool selected = false, + ColorFilter? color, + Color? cardColor, + Color? textColor, }) { return GestureDetector( onTap: onPressed, @@ -225,23 +230,25 @@ class ProfilePage extends GetView { height: 52, padding: EdgeInsets.all(8), decoration: ShapeDecoration( - color: AppColor.blueLight, + color: cardColor??AppColor.blueLight, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), ), child: SvgGenImage.vec(icon).svg( width: 40, height: 40, - colorFilter: ColorFilter.mode( - selected ? AppColor.blueNormal : AppColor.whiteLight, - BlendMode.srcIn, - ), + colorFilter: + color ?? + ColorFilter.mode( + selected ? AppColor.blueNormal : AppColor.whiteLight, + BlendMode.srcIn, + ), ), ), SizedBox(height: 2), Text( title, style: AppFonts.yekan10.copyWith( - color: selected ? AppColor.blueNormal : AppColor.blueLightActive, + color: textColor ?? (selected ? AppColor.blueNormal : AppColor.blueLightActive), ), textAlign: TextAlign.center, ), diff --git a/packages/chicken/lib/presentation/pages/sales_out_of_province/logic.dart b/packages/chicken/lib/presentation/pages/sales_out_of_province/logic.dart index f1df06f..1f8e19e 100644 --- a/packages/chicken/lib/presentation/pages/sales_out_of_province/logic.dart +++ b/packages/chicken/lib/presentation/pages/sales_out_of_province/logic.dart @@ -1,7 +1,15 @@ +import 'package:flutter/material.dart'; +import 'package:rasadyar_auth/data/utils/safe_call.dart'; +import 'package:rasadyar_chicken/data/models/request/steward_free_sale_bar/steward_free_sale_bar_request.dart'; +import 'package:rasadyar_chicken/data/models/response/iran_province_city/iran_province_city_model.dart'; +import 'package:rasadyar_chicken/data/models/response/out_province_carcasses_buyer/out_province_carcasses_buyer.dart'; +import 'package:rasadyar_chicken/data/models/response/roles_products/roles_products.dart'; +import 'package:rasadyar_chicken/data/models/response/steward_free_sale_bar/steward_free_sale_bar.dart'; import 'package:rasadyar_chicken/presentation/pages/root/logic.dart'; import 'package:rasadyar_chicken/presentation/pages/sale/logic.dart'; import 'package:rasadyar_chicken/presentation/pages/sales_out_of_province_buyers/logic.dart'; import 'package:rasadyar_chicken/presentation/pages/sales_out_of_province_sales_list/logic.dart'; +import 'package:rasadyar_chicken/presentation/utils/utils.dart'; import 'package:rasadyar_core/core.dart'; class SalesOutOfProvinceLogic extends GetxController { @@ -9,58 +17,199 @@ class SalesOutOfProvinceLogic extends GetxController { SaleLogic get saleLogic => Get.find(); - SalesOutOfProvinceBuyersLogic get buyersLogic => - Get.find(); + SalesOutOfProvinceBuyersLogic get buyersLogic => Get.find(); SalesOutOfProvinceSalesListLogic get saleListLogic => Get.find(); - RxInt selectedSegmentIndex = 0.obs; - RxBool isExpanded = false.obs; + SalesOutOfProvinceBuyersLogic get buyerLogic => Get.find(); + RxBool isExpanded = false.obs; + RxInt currentPage = 1.obs; + RxBool isSaleSubmitButtonEnabled = false.obs; RxList isExpandedList = [].obs; Rx fromDateFilter = Jalali.now().obs; Rx toDateFilter = Jalali.now().obs; RxnString searchedValue = RxnString(); RxList routesName = RxList(); + RxBool isLoadingMoreAllocationsMade = false.obs; + Rxn selectedCity = Rxn(); + + //TODO add this to Di + ImagePicker imagePicker = ImagePicker(); + + GlobalKey formKey = GlobalKey(); + TextEditingController quarantineCodeController = TextEditingController(); + TextEditingController saleWeightController = TextEditingController(); + Rx saleDate = Jalali.now().obs; + String? key; + + Rx>> salesList = + Resource>.loading().obs; + + Rxn selectedProduct = Rxn(); + Rxn selectedBuyer = Rxn(); @override void onInit() { super.onInit(); routesName.value = [...saleLogic.routesName, 'خارج استان'].toList(); - - routesName.add(selectedSegmentIndex.value == 0 ? 'فروش' : 'خریداران'); - ever(selectedSegmentIndex, (callback) { - routesName.removeLast(); - routesName.add(callback == 0 ? 'فروش' : 'خریداران'); - }); } @override void onReady() { super.onReady(); - - + getOutProvinceSales(); + selectedProduct.value = rootLogic.rolesProductsModel.first; + debounce( + searchedValue, + (callback) => getOutProvinceSales(), + time: Duration(milliseconds: timeDebounce), + ); } void setSearchValue(String? value) { searchedValue.value = value?.trim(); - if (selectedSegmentIndex.value == 0) { - saleListLogic.searchedValue.value = value?.trim(); - } else { - buyersLogic.searchedValue.value = value?.trim(); - } } void submitFilter() { - if (selectedSegmentIndex.value == 0) { - saleListLogic.fromDateFilter.value = fromDateFilter.value; - saleListLogic.toDateFilter.value = toDateFilter.value; - saleListLogic.getOutProvinceSales(); + fromDateFilter.value = fromDateFilter.value; + toDateFilter.value = toDateFilter.value; + getOutProvinceSales(); + } + + Future getOutProvinceSales([bool isLoadingMore = false]) async { + if (isLoadingMore) { + isLoadingMoreAllocationsMade.value = true; } else { - buyersLogic.fromDateFilter.value = fromDateFilter.value; - buyersLogic.toDateFilter.value = toDateFilter.value; - buyersLogic.getOutProvinceCarcassesBuyer(); + salesList.value = Resource>.loading(); } + await safeCall( + call: () => rootLogic.chickenRepository.getStewardFreeSaleBar( + token: rootLogic.tokenService.accessToken.value!, + queryParameters: buildQueryParams( + pageSize: 20, + page: currentPage.value, + state: 'buyer-list', + search: 'filter', + role: 'Steward', + value: searchedValue.value ?? '', + fromDate: fromDateFilter.value.toDateTime(), + toDate: toDateFilter.value.toDateTime(), + ), + ), + onSuccess: (res) { + if ((res?.count ?? 0) == 0) { + salesList.value = Resource>.empty(); + } else { + salesList.value = Resource>.success( + PaginationModel( + count: res?.count ?? 0, + next: res?.next, + previous: res?.previous, + results: [...(salesList.value.data?.results ?? []), ...(res?.results ?? [])], + ), + ); + + isLoadingMoreAllocationsMade.value = false; + } + }, + ); + } + + void setupListeners() { + saleWeightController.addListener(checkSalesFormValid); + quarantineCodeController.addListener(checkSalesFormValid); + ever(selectedBuyer, (_) => checkSalesFormValid); + ever(selectedProduct, (_) => checkSalesFormValid); + ever(saleDate, (_) => checkSalesFormValid()); + } + + void checkSalesFormValid() { + isSaleSubmitButtonEnabled.value = + saleDate.value.toString().isNotEmpty && + selectedProduct.value != null && + selectedBuyer.value != null && + saleWeightController.text.isNotEmpty && + quarantineCodeController.text.isNotEmpty; + } + + void setEditDataSales(StewardFreeSaleBar item) { + quarantineCodeController.text = item.clearanceCode ?? ''; + saleWeightController.text = item.weightOfCarcasses?.toInt().toString() ?? ''; + saleDate.value = Jalali.fromDateTime(DateTime.parse(item.date!)); + selectedCity.value = IranProvinceCityModel(name: item.city); + selectedBuyer.value = buyerLogic.buyerList.value.data?.results?.firstWhere( + (element) => element.key == item.buyer?.key, + ); + selectedProduct.value = rootLogic.rolesProductsModel.first; + key = item.key; + isSaleSubmitButtonEnabled.value = true; + } + + Future deleteStewardPurchaseOutOfProvince(String key) async { + await safeCall( + call: () => rootLogic.chickenRepository.deleteStewardPurchasesOutSideOfTheProvince( + token: rootLogic.tokenService.accessToken.value!, + stewardFreeBarKey: key, + ), + ); + } + + Future createSale() async { + bool res = false; + StewardFreeSaleBarRequest requestBody = StewardFreeSaleBarRequest( + buyerKey: selectedBuyer.value?.key, + numberOfCarcasses: 0, + weightOfCarcasses: int.tryParse(saleWeightController.text.clearComma), + date: saleDate.value.toDateTime().formattedDashedGregorian, + clearanceCode: quarantineCodeController.text, + productKey: selectedProduct.value?.key, + ); + await safeCall( + call: () => rootLogic.chickenRepository.createOutProvinceStewardFreeBar( + token: rootLogic.tokenService.accessToken.value!, + body: requestBody, + ), + onSuccess: (_) { + res = true; + }, + ); + return res; + } + + void clearSaleForm() { + quarantineCodeController.clear(); + saleWeightController.clear(); + saleDate.value = Jalali.now(); + selectedBuyer.value = null; + selectedProduct.value = null; + } + + Future editSale() async { + bool res = false; + StewardFreeSaleBarRequest requestBody = StewardFreeSaleBarRequest( + numberOfCarcasses: 0, + weightOfCarcasses: int.tryParse(saleWeightController.text.clearComma), + date: saleDate.value.toDateTime().formattedDashedGregorian, + clearanceCode: quarantineCodeController.text, + key: key, + ); + await safeCall( + call: () => rootLogic.chickenRepository.updateOutProvinceStewardFreeBar( + token: rootLogic.tokenService.accessToken.value!, + body: requestBody, + ), + onSuccess: (_) { + res = true; + }, + ); + return res; + } + + void resetSubmitForm() { + selectedCity.value = null; + selectedProduct.value = null; + key = null; } } diff --git a/packages/chicken/lib/presentation/pages/sales_out_of_province/view.dart b/packages/chicken/lib/presentation/pages/sales_out_of_province/view.dart index ba334bb..d33e434 100644 --- a/packages/chicken/lib/presentation/pages/sales_out_of_province/view.dart +++ b/packages/chicken/lib/presentation/pages/sales_out_of_province/view.dart @@ -1,8 +1,16 @@ +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:rasadyar_chicken/data/models/response/out_province_carcasses_buyer/out_province_carcasses_buyer.dart'; +import 'package:rasadyar_chicken/data/models/response/roles_products/roles_products.dart'; +import 'package:rasadyar_chicken/data/models/response/steward_free_sale_bar/steward_free_sale_bar.dart'; import 'package:rasadyar_chicken/presentation/pages/sales_out_of_province_sales_list/view.dart'; +import 'package:rasadyar_chicken/presentation/routes/routes.dart'; import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart'; import 'package:rasadyar_chicken/presentation/widget/filter_bottom_sheet.dart'; import 'package:rasadyar_chicken/presentation/widget/inventory_widget.dart'; +import 'package:rasadyar_chicken/presentation/widget/list_item/list_item.dart'; +import 'package:rasadyar_chicken/presentation/widget/list_row_item.dart'; import 'package:rasadyar_chicken/presentation/widget/page_route.dart'; import 'package:rasadyar_core/core.dart'; @@ -20,13 +28,61 @@ class SalesOutOfProvincePage extends GetView { filteringWidget: filterBottomSheet(), widgets: [ inventoryWidget(controller.rootLogic), - - Expanded(child: SalesOutOfProvinceSalesListPage()), + Expanded( + child: ObxValue((data) { + return RPaginatedListView( + onLoadMore: () async => controller.getOutProvinceSales(true), + onRefresh: () async { + controller.currentPage.value = 1; + await controller.getOutProvinceSales(); + }, + hasMore: data.value.data?.next != null, + listType: ListType.separated, + resource: data.value, + padding: EdgeInsets.fromLTRB(8, 8, 8, 80), + itemBuilder: (context, index) { + var item = data.value.data!.results![index]; + return ObxValue((val) { + return ListItem2( + selected: val.contains(index), + onTap: () => controller.isExpandedList.toggle(index), + index: index, + child: itemListWidget(item), + secondChild: itemListExpandedWidget(item, index), + labelColor: AppColor.blueLight, + labelIcon: Assets.vec.timerSvg.path, + ); + }, controller.isExpandedList); + }, + itemCount: data.value.data?.results?.length ?? 0, + separatorBuilder: (context, index) => SizedBox(height: 8.h), + ); + }, controller.salesList), + ), ], + floatingActionButton: Row( + children: [ + RFab.add( + onPressed: () { + Get.bottomSheet(addOrEditSaleBottomSheet(), isScrollControlled: true); + }, + ), + Spacer(), + RFab( + icon: Icon(CupertinoIcons.person_add_solid, color: Colors.white, size: 35.w), + backgroundColor: AppColor.blueNormal, + onPressed: () { + Get.toNamed(ChickenRoutes.salesOutOfProvinceBuyer, id: 1); + }, + ), + SizedBox(width: 25), + ], + ), + floatingActionButtonLocation: FloatingActionButtonLocation.startFloat, ); } - Padding segmentWidget() { + /* Padding segmentWidget() { return Padding( padding: const EdgeInsets.fromLTRB(8, 0, 8, 8), child: Row( @@ -45,7 +101,7 @@ class SalesOutOfProvincePage extends GetView { ], ), ); - } + }*/ Widget filterBottomSheet() => filterBottomSheetWidget( fromDate: controller.fromDateFilter, @@ -54,4 +110,418 @@ class SalesOutOfProvincePage extends GetView { onChangedToDate: (jalali) => controller.toDateFilter.value = jalali, onSubmit: () => controller.submitFilter(), ); + + itemListWidget(StewardFreeSaleBar item) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + SizedBox(width: 12), + Expanded( + flex: 3, + child: Text( + item.date?.formattedJalaliDate ?? 'N/A', + textAlign: TextAlign.center, + style: AppFonts.yekan12.copyWith(color: AppColor.bgDark), + ), + ), + SizedBox(width: 4), + Expanded( + flex: 5, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + item.buyer?.fullname ?? 'N/A', + textAlign: TextAlign.center, + style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal), + ), + + SizedBox(height: 2), + Text( + item.buyer?.mobile ?? 'N/A', + textAlign: TextAlign.center, + style: AppFonts.yekan14.copyWith(color: AppColor.bgDark), + ), + ], + ), + ), + SizedBox(width: 4), + Expanded( + flex: 4, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + spacing: 8, + children: [ + Text( + item.buyer?.unitName ?? 'N/A', + textAlign: TextAlign.center, + style: AppFonts.yekan12.copyWith(color: AppColor.bgDark), + ), + Text( + '${item.weightOfCarcasses?.separatedByComma ?? 0}KG', + textAlign: TextAlign.center, + style: AppFonts.yekan12.copyWith(color: AppColor.bgDark), + ), + ], + ), + ), + Expanded( + flex: 2, + child: Text( + '${item.buyer?.province}\n${item.buyer?.city}', + textAlign: TextAlign.center, + style: AppFonts.yekan12.copyWith(color: AppColor.bgDark), + ), + ), + ], + ); + } + + itemListExpandedWidget(StewardFreeSaleBar item, int index) { + return Container( + padding: EdgeInsets.symmetric(horizontal: 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, + style: AppFonts.yekan16.copyWith(color: AppColor.greenDark), + ), + ], + ), + Container( + height: 32, + padding: EdgeInsets.symmetric(horizontal: 8), + decoration: ShapeDecoration( + color: AppColor.blueLight, + shape: RoundedRectangleBorder( + side: BorderSide(width: 1, color: AppColor.blueLightHover), + borderRadius: BorderRadius.circular(8), + ), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + spacing: 3, + children: [ + Text( + item.date?.toJalali.formatter.wN ?? 'N/A', + style: AppFonts.yekan14.copyWith(color: AppColor.textColor), + ), + + Text( + '${item.date?.toJalali.formatter.d} ${item.date?.toJalali.formatter.mN ?? 'N/A'}', + style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal), + ), + ], + ), + + Text( + '${item.date?.toJalali.formatter.y}', + style: AppFonts.yekan20.copyWith(color: AppColor.textColor), + ), + + Text( + '${item.date?.toJalali.formatter.tHH}:${item.date?.toJalali.formatter.tMM ?? 'N/A'}', + style: AppFonts.yekan14.copyWith(color: AppColor.textColor), + ), + ], + ), + ), + buildRow(title: 'مشخصات خریدار', value: item.buyer?.fullname ?? 'N/A'), + buildRow(title: 'تلفن خریدار', value: item.buyer?.mobile ?? 'N/A'), + buildRow(title: 'نام واحد', value: item.buyer?.unitName ?? 'N/A'), + buildRow(title: 'وزن لاشه', value: '${item.weightOfCarcasses?.separatedByComma}'), + + Row( + mainAxisAlignment: MainAxisAlignment.center, + spacing: 16.w, + children: [ + RElevated( + text: 'ویرایش', + width: 150.w, + height: 40.h, + onPressed: () { + controller.setEditDataSales(item); + Get.bottomSheet( + addOrEditSaleBottomSheet(true), + isScrollControlled: true, + ).whenComplete(() { + controller.resetSubmitForm(); + }); + }, + textStyle: AppFonts.yekan20.copyWith(color: Colors.white), + backgroundColor: AppColor.greenNormal, + ), + ROutlinedElevated( + text: 'حذف', + textStyle: AppFonts.yekan20.copyWith(color: AppColor.redNormal), + width: 150.w, + height: 40.h, + onPressed: () { + buildDeleteDialog( + onConfirm: () async { + controller.isExpandedList.remove(index); + controller.deleteStewardPurchaseOutOfProvince(item.key!); + }, + onRefresh: () => controller.getOutProvinceSales(), + ); + }, + borderColor: AppColor.redNormal, + ), + ], + ), + ], + ), + ); + } + + Widget addOrEditSaleBottomSheet([bool isOnEdit = false]) { + return BaseBottomSheet( + height: 500.h, + child: SingleChildScrollView( + child: Form( + key: controller.formKey, + child: Column( + spacing: 16, + children: [ + Text( + isOnEdit ? 'ویرایش فروش' : 'افزودن فروش', + style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal), + ), + _productDropDown(), + + 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(), + ], + + 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(), + ], + ), + ), + ), + ); + } + + Widget submitButtonWidget(bool isOnEdit) { + return ObxValue((data) { + return RElevated( + isFullWidth: true, + backgroundColor: AppColor.greenNormal, + text: isOnEdit ? 'ویرایش' : 'ثبت', + onPressed: data.value + ? () async { + var res = isOnEdit ? await controller.editSale() : await controller.createSale(); + if (res) { + controller.getOutProvinceSales(); + controller.clearSaleForm(); + Get.back(); + } + } + : null, + height: 40, + ); + }, controller.isSaleSubmitButtonEnabled); + } + + Widget _buyerWidget() { + return Obx(() { + return OverlayDropdownWidget( + items: controller.buyerLogic.buyerList.value.data?.results ?? [], + onChanged: (value) { + controller.selectedBuyer.value = value; + }, + selectedItem: controller.selectedBuyer.value, + itemBuilder: (item) => Text(item.buyer?.fullname ?? 'بدون نام'), + labelBuilder: (item) => Text(item?.buyer?.fullname ?? 'انتخاب خریدار'), + ); + }); + } + + Widget _productDropDown() { + return Obx(() { + return OverlayDropdownWidget( + items: controller.rootLogic.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) => 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}', + ), + ], + ), + ); + }); + } + + GestureDetector timeFilterWidget({ + isFrom = true, + required Rx date, + required Function(Jalali jalali) onChanged, + }) { + return GestureDetector( + onTap: () { + Get.bottomSheet(modalDatePicker((value) => onChanged(value))); + }, + child: Container( + height: 40, + decoration: BoxDecoration( + color: AppColor.bgLight, + borderRadius: BorderRadius.circular(8), + border: Border.all(width: 1, color: AppColor.darkGreyLight), + ), + padding: EdgeInsets.symmetric(horizontal: 11, vertical: 4), + child: Row( + spacing: 8, + children: [ + Assets.vec.calendarSvg.svg( + width: 24, + height: 24, + colorFilter: const ColorFilter.mode(AppColor.bgDark, BlendMode.srcIn), + ), + Text('تاریخ', style: AppFonts.yekan16.copyWith(color: AppColor.bgDark)), + Expanded( + child: ObxValue((data) { + return Text( + date.value.formatCompactDate(), + textAlign: TextAlign.center, + style: AppFonts.yekan16.copyWith(color: AppColor.darkGreyDark), + ); + }, date), + ), + ], + ), + ), + ); + } + + Container modalDatePicker(ValueChanged onDateSelected) { + Jalali? tempPickedDate; + return Container( + height: 250, + color: Colors.white, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + child: Row( + children: [ + SizedBox(width: 20), + RElevated( + height: 35, + width: 70, + textStyle: AppFonts.yekan14.copyWith(color: Colors.white), + onPressed: () { + onDateSelected(tempPickedDate ?? Jalali.now()); + Get.back(); + }, + text: 'تایید', + ), + Spacer(), + RElevated( + height: 35, + width: 70, + backgroundColor: AppColor.error, + textStyle: AppFonts.yekan14.copyWith(color: Colors.white), + onPressed: () { + onDateSelected(tempPickedDate ?? Jalali.now()); + Get.back(); + }, + text: 'لغو', + ), + SizedBox(width: 20), + ], + ), + ), + Divider(height: 0, thickness: 1), + Expanded( + child: Container( + child: PersianCupertinoDatePicker( + initialDateTime: controller.saleDate.value, + mode: PersianCupertinoDatePickerMode.date, + onDateTimeChanged: (dateTime) { + tempPickedDate = dateTime; + }, + ), + ), + ), + ], + ), + ); + } } diff --git a/packages/chicken/lib/presentation/pages/sales_out_of_province_buyers/logic.dart b/packages/chicken/lib/presentation/pages/sales_out_of_province_buyers/logic.dart index 79c2df0..39344b8 100644 --- a/packages/chicken/lib/presentation/pages/sales_out_of_province_buyers/logic.dart +++ b/packages/chicken/lib/presentation/pages/sales_out_of_province_buyers/logic.dart @@ -13,8 +13,7 @@ class SalesOutOfProvinceBuyersLogic extends GetxController { SaleLogic get saleLogic => Get.find(); - SalesOutOfProvinceLogic get saleOutOfProvince => - Get.find(); + SalesOutOfProvinceLogic get saleOutOfProvince => Get.find(); RxInt currentPage = 1.obs; RxList isExpandedList = [].obs; @@ -39,9 +38,12 @@ class SalesOutOfProvinceBuyersLogic extends GetxController { Rx>> buyerList = Resource>.loading().obs; + RxList routesName = RxList(); + @override void onInit() { super.onInit(); + routesName.value = [...saleLogic.routesName, 'خریداران'].toList(); getOutProvinceCarcassesBuyer(); } @@ -56,6 +58,8 @@ class SalesOutOfProvinceBuyersLogic extends GetxController { (callback) => getOutProvinceCarcassesBuyer(), time: Duration(milliseconds: timeDebounce), ); + + setupListeners(); } @override @@ -70,14 +74,11 @@ class SalesOutOfProvinceBuyersLogic extends GetxController { super.onClose(); } - Future getOutProvinceCarcassesBuyer([ - bool isLoadingMore = false, - ]) async { + Future getOutProvinceCarcassesBuyer([bool isLoadingMore = false]) async { if (isLoadingMore) { isLoadingMoreAllocationsMade.value = true; } else { - buyerList.value = - Resource>.loading(); + buyerList.value = Resource>.loading(); } if (searchedValue.value != null && @@ -98,25 +99,19 @@ class SalesOutOfProvinceBuyersLogic extends GetxController { value: searchedValue.value ?? '', ), ), - onError: (error, stackTrace) => - isLoadingMoreAllocationsMade.value = false, + onError: (error, stackTrace) => isLoadingMoreAllocationsMade.value = false, onSuccess: (res) { if ((res?.count ?? 0) == 0) { - buyerList.value = - Resource>.empty(); + buyerList.value = Resource>.empty(); } else { - buyerList.value = - Resource>.success( - PaginationModel( - count: res?.count ?? 0, - next: res?.next, - previous: res?.previous, - results: [ - ...(buyerList.value.data?.results ?? []), - ...(res?.results ?? []), - ], - ), - ); + buyerList.value = Resource>.success( + PaginationModel( + count: res?.count ?? 0, + next: res?.next, + previous: res?.previous, + results: [...(buyerList.value.data?.results ?? []), ...(res?.results ?? [])], + ), + ); isLoadingMoreAllocationsMade.value = false; } @@ -135,9 +130,8 @@ class SalesOutOfProvinceBuyersLogic extends GetxController { Future getCites() async { await safeCall( - call: () => rootLogic.chickenRepository.getCity( - provinceName: selectedProvince.value?.name ?? '', - ), + call: () => + rootLogic.chickenRepository.getCity(provinceName: selectedProvince.value?.name ?? ''), onSuccess: (result) { if (result != null && result.isNotEmpty) { cites.value = result; @@ -181,11 +175,10 @@ class SalesOutOfProvinceBuyersLogic extends GetxController { mobile: buyerPhoneController.text, role: 'Steward', ); - final res = await rootLogic.chickenRepository - .createOutProvinceCarcassesBuyer( - token: rootLogic.tokenService.accessToken.value!, - body: buyer, - ); + final res = await rootLogic.chickenRepository.createOutProvinceCarcassesBuyer( + token: rootLogic.tokenService.accessToken.value!, + body: buyer, + ); }, onSuccess: (result) { getOutProvinceCarcassesBuyer(); @@ -205,4 +198,14 @@ class SalesOutOfProvinceBuyersLogic extends GetxController { selectedCity.value = IranProvinceCityModel(name: item.city); isBuyerSubmitButtonEnabled.value = true; } + + void setSearchValue(String? value) { + searchedValue.value = value?.trim(); + } + + void submitFilter() { + fromDateFilter.value = fromDateFilter.value; + toDateFilter.value = toDateFilter.value; + getOutProvinceCarcassesBuyer(); + } } 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 0ec6714..23b0a04 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 @@ -1,8 +1,11 @@ import 'package:flutter/material.dart'; import 'package:rasadyar_chicken/data/models/response/iran_province_city/iran_province_city_model.dart'; import 'package:rasadyar_chicken/data/models/response/out_province_carcasses_buyer/out_province_carcasses_buyer.dart'; +import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart'; +import 'package:rasadyar_chicken/presentation/widget/filter_bottom_sheet.dart'; import 'package:rasadyar_chicken/presentation/widget/list_item/list_item.dart'; import 'package:rasadyar_chicken/presentation/widget/list_row_item.dart'; +import 'package:rasadyar_chicken/presentation/widget/page_route.dart'; import 'package:rasadyar_core/core.dart'; import 'logic.dart'; @@ -12,36 +15,44 @@ class SalesOutOfProvinceBuyersPage extends GetView controller.getOutProvinceCarcassesBuyer(true), - onRefresh: () async { - controller.currentPage.value = 1; - await controller.getOutProvinceCarcassesBuyer(); - }, - hasMore: data.value.data?.next!= null, - listType: ListType.separated, - resource: data.value, - padding: EdgeInsets.fromLTRB(8, 8, 8, 80), - itemBuilder: (context, index) { - var item = data.value.data!.results![index]; - return ObxValue((val) { - return ListItem2( - selected: val.contains(index), - onTap: () => controller.isExpandedList.toggle(index), - index: index, - child: itemListWidget(item), - secondChild: itemListExpandedWidget(item), - labelColor: AppColor.blueLight, - labelIcon: Assets.vec.userRaduisSvg.path, - ); - }, controller.isExpandedList); - }, - itemCount: data.value.data?.results?.length ?? 0, - separatorBuilder: (context, index) => SizedBox(height: 8.h), - ); - }, controller.buyerList), + return BasePage( + routesWidget: ObxValue((route) => buildPageRoute(route), controller.routesName), + onBackPressed: () => Get.back(id: 1), + onSearchChanged: (data) => controller.setSearchValue(data), + filteringWidget: filterBottomSheet(), + widgets: [ + Expanded( + child: ObxValue((data) { + return RPaginatedListView( + onLoadMore: () async => controller.getOutProvinceCarcassesBuyer(true), + onRefresh: () async { + controller.currentPage.value = 1; + await controller.getOutProvinceCarcassesBuyer(); + }, + hasMore: data.value.data?.next != null, + listType: ListType.separated, + resource: data.value, + padding: EdgeInsets.fromLTRB(8, 8, 8, 80), + itemBuilder: (context, index) { + var item = data.value.data!.results![index]; + return ObxValue((val) { + return ListItem2( + selected: val.contains(index), + onTap: () => controller.isExpandedList.toggle(index), + index: index, + child: itemListWidget(item), + secondChild: itemListExpandedWidget(item), + labelColor: AppColor.blueLight, + labelIcon: Assets.vec.userRaduisSvg.path, + ); + }, controller.isExpandedList); + }, + itemCount: data.value.data?.results?.length ?? 0, + separatorBuilder: (context, index) => SizedBox(height: 8.h), + ); + }, controller.buyerList), + ), + ], floatingActionButton: RFab.add( onPressed: () { Get.bottomSheet(addOrEditBuyerBottomSheet(), isScrollControlled: true); @@ -296,4 +307,12 @@ class SalesOutOfProvinceBuyersPage extends GetView filterBottomSheetWidget( + fromDate: controller.fromDateFilter, + onChangedFromDate: (jalali) => controller.fromDateFilter.value = jalali, + toDate: controller.toDateFilter, + onChangedToDate: (jalali) => controller.toDateFilter.value = jalali, + onSubmit: () => controller.submitFilter(), + ); } diff --git a/packages/chicken/lib/presentation/pages/segmentation/logic.dart b/packages/chicken/lib/presentation/pages/segmentation/logic.dart index 1c4ed0d..9247a90 100644 --- a/packages/chicken/lib/presentation/pages/segmentation/logic.dart +++ b/packages/chicken/lib/presentation/pages/segmentation/logic.dart @@ -82,10 +82,7 @@ class SegmentationLogic extends GetxController { void validateForm() { var weight = int.tryParse(weightController.text.clearComma.trim()); isSubmitButtonEnabled.value = - selectedProduct.value != null && - weightController.text.isNotEmpty && - weight! > 0 - ; + selectedProduct.value != null && weightController.text.isNotEmpty && weight! > 0; } Future getAllSegmentation([bool isLoadingMore = false]) async { @@ -155,7 +152,7 @@ class SegmentationLogic extends GetxController { token: rootLogic.tokenService.accessToken.value!, model: SegmentationModel( key: selectedSegment.value?.key, - weight: int.tryParse(weightController.text) ?? 0, + weight: int.tryParse(weightController.text.clearComma) ?? 0, ), ), onSuccess: (result) { @@ -170,13 +167,16 @@ class SegmentationLogic extends GetxController { Future createSegment() async { var res = true; + SegmentationModel segmentationModel = SegmentationModel( + productKey: selectedProduct.value?.key, + + weight: int.tryParse(weightController.text.clearComma) ?? 0, + ); + iLog(segmentationModel.toString()); safeCall( call: () async => await rootLogic.chickenRepository.createSegmentation( token: rootLogic.tokenService.accessToken.value!, - model: SegmentationModel( - key: selectedProduct.value?.key, - weight: int.tryParse(weightController.text) ?? 0, - ), + model: segmentationModel, ), onSuccess: (result) { res = true; diff --git a/packages/chicken/lib/presentation/pages/segmentation/view.dart b/packages/chicken/lib/presentation/pages/segmentation/view.dart index c0cf686..efbe797 100644 --- a/packages/chicken/lib/presentation/pages/segmentation/view.dart +++ b/packages/chicken/lib/presentation/pages/segmentation/view.dart @@ -283,7 +283,7 @@ class SegmentationPage extends GetView { ? await controller.editSegment() : await controller.createSegment(); if (res) { - controller.getAllSegmentation(); + await controller.getAllSegmentation(); controller.clearForm(); Get.back(); } diff --git a/packages/chicken/lib/presentation/widget/base_page/view.dart b/packages/chicken/lib/presentation/widget/base_page/view.dart index 3a98885..4159fc2 100644 --- a/packages/chicken/lib/presentation/widget/base_page/view.dart +++ b/packages/chicken/lib/presentation/widget/base_page/view.dart @@ -50,22 +50,41 @@ class BasePage extends StatefulWidget { class _BasePageState extends State { BaseLogic get controller => Get.find(); Worker? filterWorker; - + bool _isBottomSheetOpen = false; @override void initState() { super.initState(); - filterWorker = ever(controller.isFilterSelected, (bool isSelected) { + /* filterWorker = ever(controller.isFilterSelected, (bool isSelected) { + if (!mounted) return; + if (isSelected && widget.filteringWidget != null) { + // بررسی اینکه آیا bottomSheet از قبل باز است یا نه + if (_isBottomSheetOpen) { + controller.isFilterSelected.value = false; + return; + } + + // بررسی اینکه آیا route فعلی current است یا نه + if (ModalRoute.of(context)?.isCurrent != true) { + controller.isFilterSelected.value = false; + return; + } + + _isBottomSheetOpen = true; Get.bottomSheet( widget.filteringWidget!, isScrollControlled: true, isDismissible: true, enableDrag: true, ).then((_) { - controller.isFilterSelected.value = false; + // تنظیم مقدار به false بعد از بسته شدن bottomSheet + if (mounted) { + _isBottomSheetOpen = false; + controller.isFilterSelected.value = false; + } }); } - }); + });*/ } @override @@ -73,6 +92,24 @@ class _BasePageState extends State { filterWorker?.dispose(); super.dispose(); } + void _onFilterTap() { + if (widget.hasFilter && widget.filteringWidget != null) { + // بررسی اینکه آیا این route در top است یا نه + final currentRoute = ModalRoute.of(context); + if (currentRoute?.isCurrent != true) { + return; + } + + // مستقیماً bottomSheet را باز کنید + Get.bottomSheet( + widget.filteringWidget!, + isScrollControlled: true, + isDismissible: true, + enableDrag: true, + ); + } + } + @override Widget build(BuildContext context) { @@ -87,7 +124,7 @@ class _BasePageState extends State { hasFilter: widget.hasFilter, hasSearch: widget.hasSearch, isBase: widget.isBase, - onFilterTap: widget.hasFilter ? () => controller.toggleFilter() : null, + onFilterTap: widget.hasFilter ? _onFilterTap : null, onSearchTap: widget.hasSearch ? () => Get.find().toggleSearch() : null, ), body: Column( diff --git a/packages/core/lib/infrastructure/remote/dio_remote.dart b/packages/core/lib/infrastructure/remote/dio_remote.dart index a4f7459..e1d9d73 100644 --- a/packages/core/lib/infrastructure/remote/dio_remote.dart +++ b/packages/core/lib/infrastructure/remote/dio_remote.dart @@ -15,12 +15,12 @@ class DioRemote implements IHttpClient { if (kDebugMode) { dio.interceptors.add( PrettyDioLogger( - request: false, - enabled: false, - requestHeader: false, - responseHeader: false, - requestBody: false, - responseBody: false, + request: true, + enabled: true, + requestHeader: true, + responseHeader: true, + requestBody: true, + responseBody: true, ), ); }