feat : sale in provence

This commit is contained in:
2025-07-07 16:07:52 +03:30
parent eede1f4b29
commit 93ec5774c8
23 changed files with 529 additions and 713 deletions

View File

@@ -71,6 +71,7 @@ abstract class AllocatedMadeModel with _$AllocatedMadeModel {
abstract class Product with _$Product {
factory Product({
int? weightAverage,
String? name,
}) = _Product;
factory Product.fromJson(Map<String, dynamic> json) =>

View File

@@ -383,7 +383,7 @@ $StewardCopyWith<$Res>? get toGuilds {
/// @nodoc
mixin _$Product {
int? get weightAverage;
int? get weightAverage; String? get name;
/// Create a copy of Product
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@@ -396,16 +396,16 @@ $ProductCopyWith<Product> get copyWith => _$ProductCopyWithImpl<Product>(this as
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is Product&&(identical(other.weightAverage, weightAverage) || other.weightAverage == weightAverage));
return identical(this, other) || (other.runtimeType == runtimeType&&other is Product&&(identical(other.weightAverage, weightAverage) || other.weightAverage == weightAverage)&&(identical(other.name, name) || other.name == name));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,weightAverage);
int get hashCode => Object.hash(runtimeType,weightAverage,name);
@override
String toString() {
return 'Product(weightAverage: $weightAverage)';
return 'Product(weightAverage: $weightAverage, name: $name)';
}
@@ -416,7 +416,7 @@ abstract mixin class $ProductCopyWith<$Res> {
factory $ProductCopyWith(Product value, $Res Function(Product) _then) = _$ProductCopyWithImpl;
@useResult
$Res call({
int? weightAverage
int? weightAverage, String? name
});
@@ -433,10 +433,11 @@ class _$ProductCopyWithImpl<$Res>
/// Create a copy of Product
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? weightAverage = freezed,}) {
@pragma('vm:prefer-inline') @override $Res call({Object? weightAverage = freezed,Object? name = freezed,}) {
return _then(_self.copyWith(
weightAverage: freezed == weightAverage ? _self.weightAverage : weightAverage // ignore: cast_nullable_to_non_nullable
as int?,
as int?,name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
as String?,
));
}
@@ -447,10 +448,11 @@ as int?,
@JsonSerializable()
class _Product implements Product {
_Product({this.weightAverage});
_Product({this.weightAverage, this.name});
factory _Product.fromJson(Map<String, dynamic> json) => _$ProductFromJson(json);
@override final int? weightAverage;
@override final String? name;
/// Create a copy of Product
/// with the given fields replaced by the non-null parameter values.
@@ -465,16 +467,16 @@ Map<String, dynamic> toJson() {
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _Product&&(identical(other.weightAverage, weightAverage) || other.weightAverage == weightAverage));
return identical(this, other) || (other.runtimeType == runtimeType&&other is _Product&&(identical(other.weightAverage, weightAverage) || other.weightAverage == weightAverage)&&(identical(other.name, name) || other.name == name));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,weightAverage);
int get hashCode => Object.hash(runtimeType,weightAverage,name);
@override
String toString() {
return 'Product(weightAverage: $weightAverage)';
return 'Product(weightAverage: $weightAverage, name: $name)';
}
@@ -485,7 +487,7 @@ abstract mixin class _$ProductCopyWith<$Res> implements $ProductCopyWith<$Res> {
factory _$ProductCopyWith(_Product value, $Res Function(_Product) _then) = __$ProductCopyWithImpl;
@override @useResult
$Res call({
int? weightAverage
int? weightAverage, String? name
});
@@ -502,10 +504,11 @@ class __$ProductCopyWithImpl<$Res>
/// Create a copy of Product
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? weightAverage = freezed,}) {
@override @pragma('vm:prefer-inline') $Res call({Object? weightAverage = freezed,Object? name = freezed,}) {
return _then(_Product(
weightAverage: freezed == weightAverage ? _self.weightAverage : weightAverage // ignore: cast_nullable_to_non_nullable
as int?,
as int?,name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
as String?,
));
}

View File

@@ -134,11 +134,14 @@ Map<String, dynamic> _$AllocatedMadeModelToJson(
'dispenser': instance.dispenser,
};
_Product _$ProductFromJson(Map<String, dynamic> json) =>
_Product(weightAverage: (json['weight_average'] as num?)?.toInt());
_Product _$ProductFromJson(Map<String, dynamic> json) => _Product(
weightAverage: (json['weight_average'] as num?)?.toInt(),
name: json['name'] as String?,
);
Map<String, dynamic> _$ProductToJson(_Product instance) => <String, dynamic>{
'weight_average': instance.weightAverage,
'name': instance.name,
};
_Steward _$StewardFromJson(Map<String, dynamic> json) => _Steward(

View File

@@ -11,16 +11,16 @@ import 'package:rasadyar_chicken/data/models/response/inventory/inventory_model.
import 'package:rasadyar_chicken/data/models/response/iran_province_city/iran_province_city_model.dart';
import 'package:rasadyar_chicken/data/models/response/kill_house_distribution_info/kill_house_distribution_info.dart';
import 'package:rasadyar_chicken/data/models/response/out_province_carcasses_buyer/out_province_carcasses_buyer.dart';
import 'package:rasadyar_chicken/data/models/response/pagination_model/pagination_model.dart';
import 'package:rasadyar_chicken/data/models/response/roles_products/roles_products.dart';
import 'package:rasadyar_chicken/data/models/response/steward_free_bar/steward_free_bar.dart';
import 'package:rasadyar_chicken/data/models/response/steward_free_bar_dashboard/steward_free_bar_dashboard.dart';
import 'package:rasadyar_chicken/data/models/response/steward_free_sale_bar/steward_free_sale_bar.dart';
import 'package:rasadyar_chicken/data/models/response/waiting_arrival/waiting_arrival.dart'
hide ProductModel;
import 'package:rasadyar_core/core.dart';
import '../models/request/create_steward_free_bar/create_steward_free_bar.dart';
abstract class ChickenRepository {
Future<List<InventoryModel>?> getInventory({required String token});

View File

@@ -12,7 +12,6 @@ import 'package:rasadyar_chicken/data/models/response/inventory/inventory_model.
import 'package:rasadyar_chicken/data/models/response/iran_province_city/iran_province_city_model.dart';
import 'package:rasadyar_chicken/data/models/response/kill_house_distribution_info/kill_house_distribution_info.dart';
import 'package:rasadyar_chicken/data/models/response/out_province_carcasses_buyer/out_province_carcasses_buyer.dart';
import 'package:rasadyar_chicken/data/models/response/pagination_model/pagination_model.dart';
import 'package:rasadyar_chicken/data/models/response/roles_products/roles_products.dart';
import 'package:rasadyar_chicken/data/models/response/steward_free_bar/steward_free_bar.dart';
import 'package:rasadyar_chicken/data/models/response/steward_free_bar_dashboard/steward_free_bar_dashboard.dart';

View File

@@ -10,6 +10,7 @@ class BuyInProvinceAllLogic extends GetxController {
RxnString searchedValue = RxnString();
RootLogic rootLogic = Get.find<RootLogic>();
Rx<Resource<List<ImportedLoadsModel>>> importedLoads =
Resource<List<ImportedLoadsModel>>.loading().obs;

View File

@@ -10,26 +10,22 @@ import 'package:rasadyar_core/core.dart';
class BuyInProvinceWaitingLogic extends GetxController {
RxList<int> isExpandedList = <int>[].obs;
Rx<Jalali> fromDateFilter = Jalali
.now()
.obs;
Rx<Jalali> toDateFilter = Jalali
.now()
.obs;
Rx<Jalali> fromDateFilter = Jalali.now().obs;
Rx<Jalali> toDateFilter = Jalali.now().obs;
RxnString searchedValue = RxnString();
RxMap<String, bool> isLoadingConfirmMap = RxMap();
Rx<Color> bgConfirmAllColor = AppColor.blueNormal.obs;
RootLogic rootLogic = Get.find<RootLogic>();
Rx<Resource<List<WaitingArrivalModel>>> waitingProduct =
Resource<List<WaitingArrivalModel>>.loading().obs;
Rx<Resource<PaginationModel<WaitingArrivalModel>>> waitingProduct =
Resource<PaginationModel<WaitingArrivalModel>>.loading().obs;
@override
void onInit() {
super.onInit();
debounce(
searchedValue,
(callback) => getWaitingArrivals(),
(callback) => getWaitingArrivals(),
time: Duration(milliseconds: timeDebounce),
);
}
@@ -51,8 +47,7 @@ class BuyInProvinceWaitingLogic extends GetxController {
Future<void> getWaitingArrivals() async {
safeCall(
call: () async =>
await rootLogic.chickenRepository.getWaitingArrivals(
call: () async => await rootLogic.chickenRepository.getWaitingArrivals(
token: rootLogic.tokenService.accessToken.value!,
queryParameters: buildQueryParams(
queryParams: {'type': 'not_entered'},
@@ -68,9 +63,16 @@ class BuyInProvinceWaitingLogic extends GetxController {
onSuccess: (res) async {
await Future.delayed(Duration(milliseconds: 200));
if ((res?.count ?? 0) == 0) {
waitingProduct.value = Resource<List<WaitingArrivalModel>>.empty();
waitingProduct.value = Resource<PaginationModel<WaitingArrivalModel>>.empty();
} else {
waitingProduct.value = Resource<List<WaitingArrivalModel>>.success(res!.results!);
waitingProduct.value = Resource<PaginationModel<WaitingArrivalModel>>.success(
PaginationModel<WaitingArrivalModel>(
count: res?.count ?? 0,
next: res?.next,
previous: res?.previous,
results: [...(waitingProduct.value.data?.results ?? []), ...(res?.results ?? [])],
),
);
flashingFabBgColor();
}
},
@@ -90,8 +92,7 @@ class BuyInProvinceWaitingLogic extends GetxController {
request.removeWhere((key, value) => value == null);
safeCall(
call: () async =>
await rootLogic.chickenRepository.setSateForArrivals(
call: () async => await rootLogic.chickenRepository.setSateForArrivals(
token: rootLogic.tokenService.accessToken.value!,
request: request,
),
@@ -114,8 +115,7 @@ class BuyInProvinceWaitingLogic extends GetxController {
request.removeWhere((key, value) => value == null);
safeCall(
call: () async =>
await rootLogic.chickenRepository.setSateForArrivals(
call: () async => await rootLogic.chickenRepository.setSateForArrivals(
token: rootLogic.tokenService.accessToken.value!,
request: request,
),
@@ -133,11 +133,10 @@ class BuyInProvinceWaitingLogic extends GetxController {
void flashingFabBgColor() {
Timer.periodic(Duration(seconds: 2), (timer) {
if (bgConfirmAllColor.value == AppColor.blueNormal) {
bgConfirmAllColor.value = AppColor.blueDarkActive;
bgConfirmAllColor.value = AppColor.blueLightHover;
} else {
bgConfirmAllColor.value = AppColor.blueNormal;
}
});
}
}

View File

@@ -20,7 +20,7 @@ class BuyInProvinceWaitingPage extends GetView<BuyInProvinceWaitingLogic> {
resource: data.value,
padding: EdgeInsets.fromLTRB(8, 8, 8, 80),
itemBuilder: (context, index) {
var item = data.value.data![index];
var item = data.value.data!.results![index];
return ObxValue((val) {
return ListItem2(
selected: val.contains(index),
@@ -33,7 +33,7 @@ class BuyInProvinceWaitingPage extends GetView<BuyInProvinceWaitingLogic> {
);
}, controller.isExpandedList);
},
itemCount: data.value.data?.length ?? 0,
itemCount: data.value.data?.results?.length ?? 0,
separatorBuilder: (context, index) => SizedBox(height: 8.h),
onLoadMore: () async {},
);
@@ -41,7 +41,7 @@ class BuyInProvinceWaitingPage extends GetView<BuyInProvinceWaitingLogic> {
),
floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
floatingActionButton: ObxValue((data) {
if ((data.value.data?.length ?? 0) > 1) {
if ((data.value.data?.results?.length ?? 0) > 1) {
return AnimatedFab(
onPressed: () {},
message: 'تایید یکجا',

View File

@@ -19,8 +19,8 @@ class BuyOutOfProvinceLogic extends GetxController {
//TODO add this to Di
ImagePicker imagePicker = ImagePicker();
Rx<Resource<List<StewardFreeBar>>> purchaseOutOfProvinceList =
Resource<List<StewardFreeBar>>.loading().obs;
Rx<Resource<PaginationModel<StewardFreeBar>>> purchaseOutOfProvinceList =
Resource<PaginationModel<StewardFreeBar>>.loading().obs;
Rxn<ProductModel> selectedProduct = Rxn();
RxList<IranProvinceCityModel> cites = <IranProvinceCityModel>[].obs;
@@ -31,6 +31,7 @@ class BuyOutOfProvinceLogic extends GetxController {
RxnString editImageUrl = RxnString();
RootLogic get rootLogic => Get.find<RootLogic>();
BuyLogic get buyLogic => Get.find<BuyLogic>();
SaleLogic get outOfTheProvinceLogic => Get.find<SaleLogic>();
@@ -78,7 +79,7 @@ class BuyOutOfProvinceLogic extends GetxController {
}
Future<void> getStewardPurchaseOutOfProvince() async {
purchaseOutOfProvinceList.value = Resource<List<StewardFreeBar>>.loading();
purchaseOutOfProvinceList.value = Resource<PaginationModel<StewardFreeBar>>.loading();
await safeCall(
call: () => rootLogic.chickenRepository.getStewardPurchasesOutSideOfTheProvince(
token: rootLogic.tokenService.accessToken.value!,
@@ -95,9 +96,19 @@ class BuyOutOfProvinceLogic extends GetxController {
onSuccess: (res) async {
await Future.delayed(Duration(milliseconds: 500));
if ((res?.count ?? 0) == 0) {
purchaseOutOfProvinceList.value = Resource<List<StewardFreeBar>>.empty();
purchaseOutOfProvinceList.value = Resource<PaginationModel<StewardFreeBar>>.empty();
} else {
purchaseOutOfProvinceList.value = Resource<List<StewardFreeBar>>.success(res!.results!);
purchaseOutOfProvinceList.value = Resource<PaginationModel<StewardFreeBar>>.success(
PaginationModel<StewardFreeBar>(
count: res?.count ?? 0,
next: res?.next,
previous: res?.previous,
results: [
...(purchaseOutOfProvinceList.value.data?.results ?? []),
...(res?.results ?? []),
],
),
);
}
},
);

View File

@@ -31,7 +31,7 @@ class BuyOutOfProvincePage extends GetView<BuyOutOfProvinceLogic> {
resource: data.value,
padding: EdgeInsets.fromLTRB(8, 8, 8, 80),
itemBuilder: (context, index) {
var item = data.value.data![index];
var item = data.value.data!.results![index];
return ObxValue((val) {
return ListItem2(
selected: val.contains(index),
@@ -44,7 +44,7 @@ class BuyOutOfProvincePage extends GetView<BuyOutOfProvinceLogic> {
);
}, controller.isExpandedList);
},
itemCount: data.value.data?.length ?? 0,
itemCount: data.value.data?.results?.length ?? 0,
separatorBuilder: (context, index) => SizedBox(height: 8.h),
onLoadMore: () async {},
);

View File

@@ -1,7 +1,6 @@
import 'package:rasadyar_auth/data/utils/safe_call.dart';
import 'package:rasadyar_chicken/data/models/request/conform_allocation/conform_allocation.dart';
import 'package:rasadyar_chicken/data/models/response/allocated_made/allocated_made.dart';
import 'package:rasadyar_chicken/data/models/response/dashboard_kill_house_free_bar/dashboard_kill_house_free_bar.dart';
import 'package:rasadyar_chicken/data/models/response/guild/guild_model.dart';
import 'package:rasadyar_chicken/data/models/response/roles_products/roles_products.dart';
import 'package:rasadyar_chicken/data/models/response/steward_free_bar_dashboard/steward_free_bar_dashboard.dart';
@@ -9,19 +8,21 @@ import 'package:rasadyar_chicken/presentation/pages/root/logic.dart';
import 'package:rasadyar_core/core.dart';
class SaleLogic extends GetxController {
var rootLogic = Get.find<RootLogic>();
Rxn<List<AllocatedMadeModel>?> allocatedMadeModel =
Rxn<List<AllocatedMadeModel>?>();
Rxn<List<AllocatedMadeModel>?> allocatedMadeModel = Rxn<List<AllocatedMadeModel>?>();
RxList<ProductModel> rolesProductsModel = RxList<ProductModel>();
RxList<GuildModel> guildsModel = <GuildModel>[].obs;
Rxn<StewardFreeBarDashboard> stewardFreeDashboard =
Rxn<StewardFreeBarDashboard>();
Rxn<StewardFreeBarDashboard> stewardFreeDashboard = Rxn<StewardFreeBarDashboard>();
RootLogic rootLogic = Get.find<RootLogic>();
late List<String> routesName;
@override
void onInit() {
super.onInit();
routesName = [...rootLogic.routesName, 'فروش'].toList();
getStewardDashBord();
getRolesProducts();
}
@@ -30,12 +31,7 @@ class SaleLogic extends GetxController {
safeCall(
call: () async => await rootLogic.chickenRepository.getAllocatedMade(
token: rootLogic.tokenService.accessToken.value!,
queryParameters: buildQueryParams(
page: 1,
pageSize: 20,
search: 'filter',
role: 'Steward',
),
queryParameters: buildQueryParams(page: 1, pageSize: 20, search: 'filter', role: 'Steward'),
),
onSuccess: (result) {
if (result != null) {
@@ -78,8 +74,7 @@ class SaleLogic extends GetxController {
safeCall(
call: () async => await rootLogic.chickenRepository.confirmAllAllocation(
token: rootLogic.tokenService.accessToken.value!,
allocationTokens:
allocatedMadeModel.value?.map((e) => e.key!).toList() ?? [],
allocationTokens: allocatedMadeModel.value?.map((e) => e.key!).toList() ?? [],
),
onSuccess: (result) {
getAllocatedMade();

View File

@@ -1,6 +1,8 @@
import 'package:flutter/material.dart';
import 'package:rasadyar_chicken/chicken.dart';
import 'package:rasadyar_chicken/data/models/response/steward_free_bar_dashboard/steward_free_bar_dashboard.dart';
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
import 'package:rasadyar_chicken/presentation/widget/sale_buy_card_item.dart';
import 'package:rasadyar_core/core.dart';
import 'logic.dart';
@@ -10,64 +12,41 @@ class SalePage extends GetView<SaleLogic> {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColor.bgLight,
appBar: RAppBar(
title: 'رصدطیور',
iconTitle: Assets.vec.chickenSvg.path,
titleTextStyle: AppFonts.yekan16Bold.copyWith(color: Colors.white),
centerTitle: true,
hasBack: false,
leadingWidth: 130,
leading: Row(
mainAxisSize: MainAxisSize.min,
spacing: 6,
return BasePage(
routes: controller.routesName,
isBase: true,
widgets: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Assets.vec.cubeSearchSvg.svg(
width: 24,
height: 24,
colorFilter: const ColorFilter.mode(Colors.white, BlendMode.srcIn),
),
Text('خارج استان', style: AppFonts.yekan16Bold.copyWith(color: Colors.white)),
],
),
),
body: Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
spacing: 8,
Wrap(
alignment: WrapAlignment.center,
spacing: 14.w,
children: [
Expanded(
child: _typeOuterInfoCard(
title: 'خرید',
iconPath: Assets.vec.cubeBottomRotationSvg.path,
foregroundColor: AppColor.blueNormal,
onTap: () {
Get.toNamed(ChickenRoutes.buysOutOfProvince, id: 1);
},
),
saleOrBuyItemCard(
title: 'داخل استان',
iconPath: Assets.vec.cubeSvg.path,
onTap: () {
Get.toNamed(ChickenRoutes.salesInProvince, id: 1);
},
),
Expanded(
child: _typeOuterInfoCard(
title: 'فروش',
iconPath: Assets.vec.cubeTopRotationSvg.path,
foregroundColor: AppColor.greenDark,
onTap: () {
iLog('فروش');
Get.toNamed(ChickenRoutes.salesOutOfProvince, id: 1);
},
),
saleOrBuyItemCard(
title: 'خارج استان',
iconPath: Assets.vec.truckFastSvg.path,
onTap: () {
Get.toNamed(ChickenRoutes.salesOutOfProvince, id: 1);
},
),
],
),
),
],
),
],
),
],
);
}
Widget addSaleOutOfTheProvinceBottomSheet() {
return BaseBottomSheet(
child: Column(

View File

@@ -1,3 +1,5 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:rasadyar_auth/data/utils/safe_call.dart';
import 'package:rasadyar_chicken/data/models/request/conform_allocation/conform_allocation.dart';
@@ -7,16 +9,26 @@ import 'package:rasadyar_chicken/data/models/response/guild/guild_model.dart';
import 'package:rasadyar_chicken/data/models/response/guild_profile/guild_profile.dart';
import 'package:rasadyar_chicken/data/models/response/roles_products/roles_products.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/string_utils.dart';
import 'package:rasadyar_chicken/presentation/utils/utils.dart';
import 'package:rasadyar_core/core.dart';
class SalesInProvinceLogic extends GetxController {
var rootLogic = Get.find<RootLogic>();
Rxn<List<AllocatedMadeModel>?> allocatedMadeModel = Rxn<List<AllocatedMadeModel>?>();
RootLogic rootLogic = Get.find<RootLogic>();
SaleLogic saleLogic = Get.find<SaleLogic>();
RxnString searchedValue = RxnString();
RxList<int> isExpandedList = <int>[].obs;
RxList<String> routesName = RxList();
Rx<Color> bgConfirmAllColor = AppColor.blueNormal.obs;
final RxBool isLoadingMoreAllocationsMade = false.obs;
Timer? _flashingTimer;
Rx<Resource<PaginationModel<AllocatedMadeModel>>> allocatedList =
Resource<PaginationModel<AllocatedMadeModel>>.loading().obs;
RxList<ProductModel> rolesProductsModel = RxList<ProductModel>();
RxBool searchIsSelected = false.obs;
RxnString searchedValue = RxnString();
RxList<GuildModel> guildsModel = <GuildModel>[].obs;
GlobalKey<FormState> formKey = GlobalKey<FormState>();
@@ -36,8 +48,7 @@ class SalesInProvinceLogic extends GetxController {
final totalCostController = TextEditingController();
final ScrollController scrollControllerAllocationsMade = ScrollController();
final RxInt currentPageAllocationsMade = 1.obs;
final RxBool isLoadingMoreAllocationsMade = false.obs;
final RxInt currentPage = 1.obs;
final RxBool addPageAllocationsMade = false.obs;
final RxBool hasMoreDataAllocationsMade = true.obs;
@@ -47,7 +58,7 @@ class SalesInProvinceLogic extends GetxController {
@override
void onInit() {
super.onInit();
routesName.value = [...saleLogic.routesName, 'داخل استان'].toList();
getAllocatedMade();
getRolesProducts();
getGuilds();
@@ -82,47 +93,57 @@ class SalesInProvinceLogic extends GetxController {
}
});
debounce(searchedValue, (callback) => getAllocatedMade(), time: Duration(milliseconds: 2000));
ever(searchIsSelected, (data) {
if (data == false) {
searchedValue.value = null;
}
});
debounce(
searchedValue,
(callback) => getAllocatedMade(),
time: Duration(milliseconds: timeDebounce),
);
}
Future<void> getAllocatedMade() async {
if (isLoadingMoreAllocationsMade.value || !hasMoreDataAllocationsMade.value) {
return;
Future<void> getAllocatedMade([bool isLoadingMore = false]) async {
if (isLoadingMore) {
isLoadingMoreAllocationsMade.value = true;
} else {
allocatedList.value = Resource<PaginationModel<AllocatedMadeModel>>.loading();
}
if (searchIsSelected.value) {
currentPageAllocationsMade.value = 1;
} else if (addPageAllocationsMade.value) {
currentPageAllocationsMade.value++;
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.getAllocatedMade(
token: rootLogic.tokenService.accessToken.value!,
queryParameters: buildQueryParams(
page: currentPageAllocationsMade.value,
page: currentPage.value,
pageSize: 20,
search: 'filter',
role: 'Steward',
value: searchedValue.value,
),
),
onSuccess: (result) {
if (result != null) {
if (isLoadingMoreAllocationsMade.value &&
allocatedMadeModel.value != null &&
(allocatedMadeModel.value?.isNotEmpty ?? false)) {
allocatedMadeModel.value?.addAll(result.results!);
} else {
allocatedMadeModel.value = result.results;
onSuccess: (res) async {
await Future.delayed(Duration(milliseconds: 200));
if ((res?.count ?? 0) == 0) {
allocatedList.value = Resource<PaginationModel<AllocatedMadeModel>>.empty();
} else {
allocatedList.value = Resource<PaginationModel<AllocatedMadeModel>>.success(
PaginationModel<AllocatedMadeModel>(
count: res?.count ?? 0,
next: res?.next,
previous: res?.previous,
results: isLoadingMore
? [...(allocatedList.value.data?.results ?? []), ...(res?.results ?? [])]
: res?.results ?? [],
),
);
isLoadingMoreAllocationsMade.value = false;
if ((allocatedList.value.data?.results?.length ?? 0) > 1) {
flashingFabBgColor();
}
}
isLoadingMoreAllocationsMade.value = false;
},
onError: (error, stacktrace) {
isLoadingMoreAllocationsMade.value = false;
@@ -130,7 +151,7 @@ class SalesInProvinceLogic extends GetxController {
);
}
void checkVerfication() {
void checkVerification() {
isValid.value =
weight.value > 0 &&
pricePerKilo.value > 0 &&
@@ -169,7 +190,7 @@ class SalesInProvinceLogic extends GetxController {
safeCall(
call: () async => await rootLogic.chickenRepository.confirmAllAllocation(
token: rootLogic.tokenService.accessToken.value!,
allocationTokens: allocatedMadeModel.value?.map((e) => e.key!).toList() ?? [],
allocationTokens: allocatedList.value.data?.results?.map((e) => e.key!).toList() ?? [],
),
onSuccess: (result) {
getAllocatedMade();
@@ -180,8 +201,9 @@ class SalesInProvinceLogic extends GetxController {
Future<void> getRolesProducts() async {
safeCall(
call: () async =>
await rootLogic.chickenRepository.getRolesProducts(token: rootLogic.tokenService.accessToken.value!),
call: () async => await rootLogic.chickenRepository.getRolesProducts(
token: rootLogic.tokenService.accessToken.value!,
),
onSuccess: (result) {
if (result != null) {
rolesProductsModel.value = result;
@@ -196,7 +218,10 @@ class SalesInProvinceLogic extends GetxController {
safeCall(
call: () async => await rootLogic.chickenRepository.getGuilds(
token: rootLogic.tokenService.accessToken.value!,
queryParameters: buildQueryParams(queryParams: {'free': saleType.value == 2 ? true : false}, role: 'Steward'),
queryParameters: buildQueryParams(
queryParams: {'free': saleType.value == 2 ? true : false},
role: 'Steward',
),
),
onSuccess: (result) {
if (result != null) {
@@ -222,7 +247,9 @@ class SalesInProvinceLogic extends GetxController {
Future<void> getGuildProfile() async {
await safeCall(
call: () async => await rootLogic.chickenRepository.getProfile(token: rootLogic.tokenService.accessToken.value!),
call: () async => await rootLogic.chickenRepository.getProfile(
token: rootLogic.tokenService.accessToken.value!,
),
onError: (error, stackTrace) {},
onSuccess: (result) {
guildProfile.value = result;
@@ -280,6 +307,7 @@ class SalesInProvinceLogic extends GetxController {
@override
void dispose() {
rootLogic.inventoryExpandedList.clear();
stopFlashing();
super.dispose();
}
@@ -328,4 +356,34 @@ class SalesInProvinceLogic extends GetxController {
onError: (error, stackTrace) {},
);
}
void setSearchValue(String? data) {
searchedValue.value = data?.trim();
}
void flashingFabBgColor() {
_flashingTimer?.cancel();
_flashingTimer = Timer.periodic(Duration(seconds: 2), (timer) {
if (bgConfirmAllColor.value == AppColor.blueNormal) {
bgConfirmAllColor.value = AppColor.blueLightHover;
} else {
bgConfirmAllColor.value = AppColor.blueNormal;
}
});
}
void stopFlashing() {
_flashingTimer?.cancel();
_flashingTimer = null;
bgConfirmAllColor.value = AppColor.blueNormal; // بازگرداندن به رنگ پیش‌فرض
}
Steward? getBuyerInformation(AllocatedMadeModel model) {
if (model.allocationType?.buyerIsGuild) {
return model.toGuilds;
} else {
return model.steward;
}
}
}

View File

@@ -1,11 +1,13 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:rasadyar_chicken/data/models/request/conform_allocation/conform_allocation.dart';
import 'package:rasadyar_chicken/data/models/response/allocated_made/allocated_made.dart';
import 'package:rasadyar_chicken/data/models/response/guild/guild_model.dart';
import 'package:rasadyar_chicken/data/models/response/roles_products/roles_products.dart';
import 'package:rasadyar_chicken/presentation/routes/routes.dart';
import 'package:rasadyar_chicken/presentation/utils/string_utils.dart';
import 'package:rasadyar_chicken/presentation/widget/base_page/view.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';
@@ -16,63 +18,79 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: RAppBar(
titleTextStyle: AppFonts.yekan16Bold.copyWith(color: Colors.white),
hasBack: false,
leadingWidth: 155,
leading: Row(
mainAxisSize: MainAxisSize.min,
spacing: 6,
children: [
Assets.vec.chickenSvg.svg(
width: 24,
height: 24,
colorFilter: const ColorFilter.mode(Colors.white, BlendMode.srcIn),
),
Text('رصدطیور', style: AppFonts.yekan16Bold.copyWith(color: Colors.white)),
],
),
additionalActions: [
GestureDetector(
onTap: () {
controller.searchIsSelected.value = !controller.searchIsSelected.value;
},
child: Assets.vec.searchSvg.svg(
width: 24,
height: 24,
colorFilter: const ColorFilter.mode(Colors.white, BlendMode.srcIn),
),
body: BasePage(
routesWidget: ObxValue((route) => buildPageRoute(route), controller.routesName),
onBackPressed: () => Get.back(id: 1),
onSearchChanged: (data) => controller.setSearchValue(data),
filteringWidget: filterBottomSheet(),
widgets: [
inventoryWidget(),
Expanded(
child: ObxValue((data) {
return RPaginatedListView(
listType: ListType.separated,
resource: data.value,
hasMore: data.value.data?.next != null,
isPaginating: controller.isLoadingMoreAllocationsMade.value,
onRefresh: () async => await controller.getAllocatedMade(),
onLoadMore: () async {
controller.currentPage.value++;
iLog(controller.currentPage.value);
await controller.getAllocatedMade(true);
},
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.allocatedList),
),
SizedBox(width: 8),
GestureDetector(
onTap: () {
Get.bottomSheet(filterBottomSheet());
},
child: Assets.vec.filterOutlineSvg.svg(
width: 20,
height: 20,
colorFilter: const ColorFilter.mode(Colors.white, BlendMode.srcIn),
),
),
SizedBox(width: 8),
],
),
body: SingleChildScrollView(
child: Column(
floatingActionButton: SizedBox(
width: Get.width - 30,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
routePageWidget(),
buildSearchWidget(),
inventoryWidget(),
allocationsMade(),
SizedBox(height: 40),
RFab.add(
onPressed: () {
Get.bottomSheet(
addOrEditBottomSheet(),
isScrollControlled: true,
backgroundColor: Colors.transparent,
);
},
),
ObxValue((data) {
return Visibility(
visible: (data.value.data?.results?.length ?? 0) > 1,
child: AnimatedFab(
onPressed: () async {
await controller.confirmAllAllocations();
},
message: 'تایید یکجا',
icon: Assets.vec.clipboardTaskSvg.svg(width: 40.w, height: 40.h),
backgroundColor: controller.bgConfirmAllColor.value,
),
);
}, controller.allocatedList),
],
),
),
floatingActionButton: RFab.add(
onPressed: () {
Get.bottomSheet(showAddBottomSheet(), isScrollControlled: true, backgroundColor: Colors.transparent);
},
),
floatingActionButtonLocation: FloatingActionButtonLocation.startFloat,
);
}
@@ -81,7 +99,7 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
return Container(
width: Get.width,
height: 39,
margin: EdgeInsets.all(4),
margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(color: AppColor.greenLight, borderRadius: BorderRadius.circular(8)),
alignment: Alignment.center,
child: ObxValue((data) {
@@ -93,112 +111,220 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
);
}
Widget buildRow(String title, String value) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
itemListWidget(AllocatedMadeModel item) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
SizedBox(width: 20),
Expanded(
flex: 2,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
spacing: 4,
children: [
Text(
item.steward?.user?.fullname ?? 'N/A',
textAlign: TextAlign.center,
style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
),
SizedBox(height: 2),
Text(
item.createDate?.formattedJalaliDate ?? 'N/A',
textAlign: TextAlign.center,
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark),
),
],
),
),
Expanded(
flex: 3,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
spacing: 6,
children: [
Visibility(
visible: item.product?.name?.contains('مرغ گرم') ?? false,
child: Assets.vec.hotChickenSvg.svg(
width: 24,
height: 24,
colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
),
),
Text(
'${item.weightOfCarcasses?.separatedByComma}kg',
textAlign: TextAlign.left,
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
),
],
),
SizedBox(height: 2),
Text(
'${item.amount.separatedByComma} ریال',
textAlign: TextAlign.center,
style: AppFonts.yekan12.copyWith(color: AppColor.darkGreyDark),
),
],
),
),
SizedBox(width: 8),
Expanded(
flex: 1,
child: Assets.vec.scanSvg.svg(
width: 32.w,
height: 32.h,
colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
),
),
],
);
}
itemListExpandedWidget(AllocatedMadeModel item, int index) {
return Container(
padding: EdgeInsets.all(8),
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8)),
child: Column(
spacing: 8,
children: [
Flexible(
flex: 2,
child: Text(
title,
textAlign: TextAlign.right,
style: AppFonts.yekan14.copyWith(color: AppColor.darkGreyDarkHover),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
item.steward?.user?.fullname ?? 'N/A',
textAlign: TextAlign.center,
style: AppFonts.yekan16.copyWith(color: AppColor.greenDark),
),
Spacer(),
Text(
'در انتظار',
textAlign: TextAlign.center,
style: AppFonts.yekan10.copyWith(color: AppColor.darkGreyDark),
),
SizedBox(width: 7),
Assets.vec.clockSvg.svg(width: 16.w, height: 16.h),
],
),
Container(
height: 32,
padding: EdgeInsets.symmetric(horizontal: 4),
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),
),
],
),
),
Flexible(
flex: 2,
child: Text(
value,
textAlign: TextAlign.left,
style: AppFonts.yekan14.copyWith(color: AppColor.darkGreyDarkHover),
),
buildRow(
title: 'نام و نام خانوادگی فروشنده',
value: controller.getBuyerInformation(item)?.user?.fullname ?? 'N/A',
),
buildRow(
title: 'تلفن فروشنده',
value: controller.getBuyerInformation(item)?.user?.mobile ?? 'N/A',
valueStyle: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
),
buildRow(title: 'نوع فروش', value: item.sellType?.faItem ?? 'N/A'),
buildRow(title: 'محصول', value: item.product?.name ?? 'N/A'),
buildRow(
title: 'وزن خریداری شده',
value: '${item.weightOfCarcasses?.separatedByComma} کیلوگرم',
),
buildRow(
title: 'افت وزن(کیلوگرم)',
value: item.weightLossOfCarcasses?.toInt().toString() ?? 'N/A',
),
buildRow(title: 'قیمت کل', value: '${item.totalAmount?.separatedByComma} ریال'),
buildRow(title: 'کداحراز', value: item.registrationCode?.toString() ?? 'ندارد'),
buildRow(
title: 'وضعیت کد احراز',
value: item.systemRegistrationCode == true ? "ارسال شده" : "ارسال نشده",
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
spacing: 16.w,
children: [
RElevated(
text: 'ویرایش',
width: 150.w,
height: 40.h,
onPressed: () {
controller.setEditData(item);
Get.bottomSheet(
addOrEditBottomSheet(true),
isScrollControlled: true,
backgroundColor: Colors.transparent,
);
},
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.denyAllocation(item.key ?? '');
//await controller.deleteAllocation(item);
},
onRefresh: () => controller.getAllocatedMade(),
);
},
borderColor: AppColor.redNormal,
),
],
),
],
),
);
}
Widget allocationsMade() {
return Column(
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 6),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('تخصیصات صورت گرفته', style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal)),
RElevated(
text: 'تایید یکجا',
height: 30,
textStyle: AppFonts.yekan12.copyWith(color: Colors.white),
onPressed: () {
controller.confirmAllAllocations();
},
),
],
),
),
ObxValue((data) {
if (data.value == null) {
return Container(
height: 80,
margin: const EdgeInsets.all(4),
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
border: Border.all(color: AppColor.blueNormal, width: 1),
),
child: Center(child: CircularProgressIndicator()),
);
} else if (data.value?.isEmpty ?? true) {
return Container(
height: 80,
margin: const EdgeInsets.all(8),
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
border: Border.all(color: AppColor.blueNormal, width: 1),
),
child: Center(child: Text('هیچ تخصیصات صورت نگرفته است ')),
);
} else {
return Container(
margin: const EdgeInsets.symmetric(vertical: 2),
child: ListView.separated(
padding: const EdgeInsets.all(8.0),
shrinkWrap: true,
controller: controller.scrollControllerAllocationsMade,
itemCount: data.value?.length ?? 0,
itemBuilder: (BuildContext context, int index) {
if (index == data.value!.length) {
return Obx(
() => controller.isLoadingMoreAllocationsMade.value
? const Padding(
padding: EdgeInsets.symmetric(vertical: 8),
child: Center(child: CircularProgressIndicator()),
)
: const SizedBox(),
);
}
final result = data.value![index];
return ObxValue((data) {
return allocationsMadeListItem(expandList: controller.isExpandedList, index: index, item: result);
}, controller.isExpandedList);
},
separatorBuilder: (BuildContext context, int index) => SizedBox(height: 8),
),
);
}
}, controller.allocatedMadeModel),
],
);
}
Widget showAddBottomSheet([bool isEditMode = false]) {
Widget addOrEditBottomSheet([bool isEditMode = false]) {
return BaseBottomSheet(
height: Get.height * (isEditMode ? 0.45 : 0.75),
child: Padding(
@@ -271,10 +397,14 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
controller: controller.weightController,
keyboardType: TextInputType.number,
borderColor: AppColor.darkGreyLight,
inputFormatters: [FilteringTextInputFormatter.digitsOnly, SeparatorInputFormatter()],
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
SeparatorInputFormatter(),
],
validator: (value) {
if (int.parse(value!.clearComma) > (controller.rootLogic.inventoryModel.value?.totalRemainWeight?.toInt() ?? 100) ){
if (int.parse(value!.clearComma) >
(controller.rootLogic.inventoryModel.value?.totalRemainWeight?.toInt() ??
100)) {
return 'وزن تخصیصی بیشتر از موجودی انبار است';
}
return null;
@@ -288,7 +418,10 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
RTextField(
controller: controller.pricePerKiloController,
borderColor: AppColor.darkGreyLight,
inputFormatters: [FilteringTextInputFormatter.digitsOnly, SeparatorInputFormatter()],
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
SeparatorInputFormatter(),
],
onChanged: (p0) {
controller.pricePerKilo.value = int.tryParse(p0.clearComma) ?? 0;
@@ -300,7 +433,10 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
RTextField(
enabled: false,
keyboardType: TextInputType.number,
inputFormatters: [FilteringTextInputFormatter.digitsOnly, SeparatorInputFormatter()],
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
SeparatorInputFormatter(),
],
borderColor: AppColor.darkGreyLight,
controller: controller.totalCostController,
label: 'هزینه کل',
@@ -309,17 +445,18 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
ObxValue((data) {
return RElevated(
text: isEditMode ? 'ویرایش' : 'ثبت',
isFullWidth: true,
textStyle: AppFonts.yekan16.copyWith(color: Colors.white),
height: 40,
onPressed: data.value
? () async {
if (controller.formKey.currentState?.validate() ?? false) {
iLog("s2");
controller.setSubmitData();
iLog("s3");
Get.bottomSheet(show2StepAddBottomSheet());
}
/* isEditMode
if (controller.formKey.currentState?.validate() ?? false) {
iLog("s2");
controller.setSubmitData();
iLog("s3");
// Get.bottomSheet(show2StepAddBottomSheet());
}
/* isEditMode
? await controller.updateAllocation()
: () {
iLog("s1");
@@ -384,379 +521,6 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
});
}
Padding routePageWidget() {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0),
child: Row(
children: [
SizedBox(width: 8),
RichText(
text: TextSpan(
style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
children: [
WidgetSpan(
child: Row(
children: [
Assets.vec.cubeSearchSvg.svg(
width: 24,
height: 24,
colorFilter: const ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
),
SizedBox(width: 6),
],
),
),
TextSpan(text: 'داخل استان'),
TextSpan(text: '/'),
TextSpan(text: 'فروش'),
],
),
),
],
),
);
}
Widget allocationsMadeListItem({
required RxList<int> expandList,
required int index,
required AllocatedMadeModel item,
}) {
return GestureDetector(
onTap: () {
if (expandList.contains(index)) {
controller.isExpandedList.remove(index);
} else {
controller.isExpandedList.add(index);
}
},
child: Container(
width: Get.width,
margin: const EdgeInsets.fromLTRB(0, 0, 10, 0),
decoration: BoxDecoration(color: getTintColor(item), borderRadius: BorderRadius.circular(8)),
child: AnimatedSize(
duration: Duration(milliseconds: 400),
alignment: Alignment.center,
child: Stack(
clipBehavior: Clip.none,
alignment: Alignment.centerRight,
children: [
AnimatedSize(
duration: Duration(milliseconds: 300),
child: Container(
width: Get.width - 30,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.transparent,
borderRadius: BorderRadius.circular(8),
border: Border.all(width: 2, color: getTintColor(item)),
),
child: Row(
children: [
Expanded(
child: AnimatedCrossFade(
alignment: Alignment.center,
firstChild: Container(
height: 75,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
bottomLeft: Radius.zero,
bottomRight: Radius.circular(8),
topLeft: Radius.zero,
topRight: Radius.circular(8),
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
SizedBox(width: 12),
Expanded(
flex: 2,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
spacing: 4,
children: [
Text(
item.steward?.user?.fullname ?? 'N/A',
textAlign: TextAlign.center,
style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
),
SizedBox(height: 2),
Text(
item.createDate?.formattedJalaliDate ?? 'N/A',
textAlign: TextAlign.center,
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark),
),
],
),
),
SizedBox(width: 8),
Expanded(
flex: 2,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
spacing: 4,
children: [
Text(
'${item.weightOfCarcasses.separatedByComma} Kg',
textAlign: TextAlign.center,
style: AppFonts.yekan12.copyWith(color: AppColor.bgDark),
),
Text(
'${item.amount.separatedByComma} ریال',
textAlign: TextAlign.center,
style: AppFonts.yekan12.copyWith(color: AppColor.darkGreyDark),
),
],
),
),
Expanded(
flex: 1,
child: Text(
'${item.allocationType?.faAllocationType}',
textAlign: TextAlign.center,
style: AppFonts.yekan10.copyWith(color: AppColor.darkGreyDark),
),
),
SizedBox(width: 8),
],
),
),
secondChild: Container(
padding: EdgeInsets.fromLTRB(8, 12, 14, 12),
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8)),
child: Column(
spacing: 8,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
GestureDetector(
onTap: () {
controller.setEditData(item);
Get.bottomSheet(
showAddBottomSheet(true),
isScrollControlled: true,
).whenComplete(() {
controller.clearForm();
});
},
child: Assets.vec.editSvg.svg(
width: 20,
height: 20,
colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
),
),
Text(
item.allocationType?.faAllocationType,
textAlign: TextAlign.center,
style: AppFonts.yekan16.copyWith(color: AppColor.greenDark),
),
GestureDetector(
onTap: () {
buildDeleteDialog(
onConfirm: () {
expandList.remove(index);
return controller.deleteAllocation(item);
},
);
},
child: Assets.vec.trashSvg.svg(
width: 16,
height: 16,
colorFilter: ColorFilter.mode(AppColor.error, BlendMode.srcIn),
),
),
],
),
buildRow('تاریخ ثبت', item.date!.formattedJalaliDate ?? 'N/A'),
buildRow(
'نام و نام خانوادگی خریدار',
getBuyerInformation(item)?.user?.fullname ?? 'N/A',
),
buildRow('شماره خریدار', getBuyerInformation(item)?.user?.mobile ?? 'N/A'),
buildRow('نوع فروش', item.sellType?.faItem ?? 'N/A'),
buildRow('قیمت هر کیلو', '${item.amount.separatedByComma ?? 0} ریال '),
buildRow('قیمت کل', '${item.totalAmount.separatedByComma ?? 0} ریال'),
buildRow(
'وزن تخصیصی',
'${item.weightOfCarcasses?.toInt().separatedByComma ?? 0} کیلوگرم',
),
buildRow('کداحراز', item.registrationCode?.toString() ?? 'N/A'),
buildRow(
'وضعیت کد احراز',
item.systemRegistrationCode == true ? "ارسال شده" : "ارسال نشده" ?? 'N/A',
),
buildRow('افت وزن(کیلوگرم)', item.weightLossOfCarcasses?.toInt().toString() ?? 'N/A'),
Row(
spacing: 10,
children: [
Expanded(
child: RElevated(
backgroundColor: AppColor.greenNormal,
height: 40,
text: 'تایید',
textStyle: AppFonts.yekan18.copyWith(color: Colors.white),
onPressed: () {
ConformAllocation confromation = ConformAllocation(
allocation_key: item.key,
number_of_carcasses: item.numberOfCarcasses,
weight_of_carcasses: item.weightOfCarcasses?.toInt(),
amount: item.amount,
total_amount: item.totalAmount,
);
controller.confirmAllocation(confromation);
},
),
),
Expanded(
child: ROutlinedElevated(
height: 40,
borderColor: AppColor.error,
text: 'رد',
textStyle: AppFonts.yekan18.copyWith(color: AppColor.error),
onPressed: () {
controller.denyAllocation(item.key ?? '');
},
),
),
],
),
],
),
),
crossFadeState: expandList.contains(index)
? CrossFadeState.showSecond
: CrossFadeState.showFirst,
duration: Duration(milliseconds: 300),
),
),
Container(
width: 20,
child: Center(
child: RotatedBox(
quarterTurns: 3,
child: Text(item.state?.faItem, style: AppFonts.yekan8, textAlign: TextAlign.center),
),
),
),
],
),
),
),
Positioned(
right: -12,
child: Container(
width: index < 999 ? 24 : null,
height: index < 999 ? 24 : null,
padding: EdgeInsets.all(2),
decoration: BoxDecoration(
color: AppColor.greenLightHover,
borderRadius: BorderRadius.circular(4),
border: Border.all(width: 0.50, color: AppColor.greenDarkActive),
),
alignment: Alignment.center,
child: Text((index + 1).toString(), style: AppFonts.yekan12.copyWith(color: Colors.black)),
),
),
],
),
),
),
);
}
Color getTintColor(AllocatedMadeModel model) {
Color res;
if (model.receiverState == 'pending') {
res = AppColor.yellowNormal;
} else if (model.receiverState == 'approved') {
res = AppColor.greenLightActive;
} else if (model.receiverState == 'rejected') {
res = AppColor.redLight;
} else {
res = AppColor.blueLight;
}
return res;
}
Steward? getBuyerInformation(AllocatedMadeModel model) {
if (model.allocationType?.buyerIsGuild) {
return model.toGuilds;
} else {
return model.steward;
}
}
Future<void> buildDeleteDialog({required Future<void> Function() onConfirm}) async {
await Get.defaultDialog(
title: 'حذف ',
middleText: 'آیا از حذف این مورد مطمئن هستید؟',
confirm: ElevatedButton(
style: ElevatedButton.styleFrom(backgroundColor: AppColor.error, foregroundColor: Colors.white),
onPressed: () async {
await onConfirm();
Get.back();
},
child: Text('بله'),
),
cancel: ElevatedButton(
onPressed: () {
Get.back();
},
child: Text('خیر'),
),
).whenComplete(() => controller.getAllocatedMade());
}
ObxValue<RxBool> buildSearchWidget() {
return ObxValue((data) {
return AnimatedContainer(
duration: Duration(milliseconds: 300),
padding: EdgeInsets.only(top: 5),
curve: Curves.easeInOut,
height: data.value ? 50 : 0,
child: Visibility(
visible: data.value,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: RTextField(
suffixIcon: Padding(
padding: const EdgeInsets.all(12.0),
child: Assets.vec.searchSvg.svg(
width: 10,
height: 10,
colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
),
),
hintText: 'جستجو',
onChanged: (value) {
controller.searchedValue.value = value;
},
controller: TextEditingController(),
),
),
),
);
}, controller.searchIsSelected);
}
Widget filterBottomSheet() {
return BaseBottomSheet(
height: 250,
@@ -821,7 +585,10 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
height: 24,
colorFilter: const ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
),
Text(isFrom ? 'از' : 'تا', style: AppFonts.yekan16.copyWith(color: AppColor.blueNormal)),
Text(
isFrom ? 'از' : 'تا',
style: AppFonts.yekan16.copyWith(color: AppColor.blueNormal),
),
Expanded(
child: ObxValue((data) {
return Text(
@@ -892,7 +659,7 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
);
}
Widget show2StepAddBottomSheet() {
/* Widget show2StepAddBottomSheet() {
return BaseBottomSheet(
height: Get.height*.35,
child: Column(
@@ -951,5 +718,5 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
],
),
);
}
}*/
}

View File

@@ -16,8 +16,6 @@ class BuyersPage extends GetView<SalesOutOfProvinceLogic> {
return Scaffold(
body: Column(
children: [
buyerListWidget(),
],
),

View File

@@ -45,6 +45,7 @@ class SalesPage extends GetView<SalesOutOfProvinceLogic> {
case Status.loading:
return Center(child: CupertinoActivityIndicator());
case Status.success:
return ListView.separated(
shrinkWrap: true,
physics: BouncingScrollPhysics(),

View File

@@ -83,6 +83,7 @@ sealed class ChickenPages {
Get.lazyPut(() => SalesOutOfProvinceLogic());
Get.lazyPut(() => RootLogic());
Get.lazyPut(() => BaseLogic());
Get.lazyPut(() => SearchLogic());
}),
),
GetPage(
@@ -93,6 +94,7 @@ sealed class ChickenPages {
Get.lazyPut(() => BaseLogic());
Get.lazyPut(() => SalesInProvinceLogic());
Get.lazyPut(() => RootLogic());
Get.lazyPut(() => SearchLogic());
}),
),

View File

@@ -1,5 +1,8 @@
library;
//models
export 'data/model/pagination_model/pagination_model.dart';
//other packages
export 'package:flutter_localizations/flutter_localizations.dart';
export 'package:flutter_map/flutter_map.dart';
@@ -9,7 +12,7 @@ export 'package:flutter_secure_storage/flutter_secure_storage.dart';
export 'package:flutter_slidable/flutter_slidable.dart';
export 'package:font_awesome_flutter/font_awesome_flutter.dart';
export 'package:device_info_plus/device_info_plus.dart';
export 'package:dio/dio.dart' ;
export 'package:dio/dio.dart';
export 'package:pretty_dio_logger/pretty_dio_logger.dart';
export 'package:flutter_screenutil/flutter_screenutil.dart';
@@ -17,6 +20,7 @@ export 'package:flutter_screenutil/flutter_screenutil.dart';
export 'package:freezed_annotation/freezed_annotation.dart';
export 'package:geolocator/geolocator.dart';
export 'package:get/get.dart' hide FormData, MultipartFile, Response;
//di
export 'package:get_it/get_it.dart';
export 'injection/di.dart';
@@ -29,7 +33,7 @@ export 'infrastructure/local/hive_local_storage.dart';
//export 'package:encrypt/encrypt.dart' show Encrypted;
//Map and location
export 'package:latlong2/latlong.dart' ;
export 'package:latlong2/latlong.dart';
export 'package:persian_datetime_picker/persian_datetime_picker.dart';
export 'package:rasadyar_core/presentation/common/common.dart';
export 'package:rasadyar_core/presentation/utils/utils.dart';

View File

@@ -1,6 +1,7 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:rasadyar_core/core.dart';
import 'package:rasadyar_core/data/model/pagination_model/pagination_model.dart';
enum ListType { builder, separated }
@@ -24,7 +25,7 @@ class RPaginatedListView<T> extends StatelessWidget {
this.physics = const BouncingScrollPhysics(),
});
final Resource<List<T>> resource;
final Resource<PaginationModel<T>> resource;
final NullableIndexedWidgetBuilder itemBuilder;
final IndexedWidgetBuilder? separatorBuilder;
final Future<void> Function()? onRefresh;
@@ -54,7 +55,7 @@ class RPaginatedListView<T> extends StatelessWidget {
return errorWidget ?? Center(child: Text(resource.message ?? 'خطا'));
}
if (resource.isEmpty || resource.data?.isEmpty == true) {
if (resource.isEmpty || resource.data?.results?.isEmpty == true) {
return emptyWidget ?? const EmptyWidget();
}
@@ -80,9 +81,12 @@ class RPaginatedListView<T> extends StatelessWidget {
itemCount: itemCount + (isPaginating ? 1 : 0),
itemBuilder: (context, index) {
if (isPaginating && index == itemCount) {
return const Padding(
padding: EdgeInsets.all(16),
child: Center(child: CupertinoActivityIndicator()),
return SizedBox(
height: 50,
child: const Padding(
padding: EdgeInsets.all(16),
child: Center(child: CupertinoActivityIndicator()),
),
);
}
return itemBuilder(context, index);
@@ -96,9 +100,12 @@ class RPaginatedListView<T> extends StatelessWidget {
itemCount: itemCount + (isPaginating ? 1 : 0),
itemBuilder: (context, index) {
if (isPaginating && index == itemCount) {
return const Padding(
padding: EdgeInsets.all(16),
child: Center(child: CupertinoActivityIndicator()),
return SizedBox(
height: 50,
child: const Padding(
padding: EdgeInsets.all(16),
child: Center(child: CupertinoActivityIndicator()),
),
);
}
return itemBuilder(context, index);

View File

@@ -1,22 +1,11 @@
enum Status {
initial,
loading,
success,
error,
empty,
}
enum Status { initial, loading, success, error, empty }
class Resource<T> {
final Status status;
final T? data;
final String? message;
const Resource._({
required this.status,
this.data,
this.message,
});
const Resource._({required this.status, this.data, this.message});
const Resource.initial() : this._(status: Status.initial);
@@ -28,7 +17,6 @@ class Resource<T> {
const Resource.empty() : this._(status: Status.empty);
bool get isInitial => status == Status.initial;
bool get isLoading => status == Status.loading;
@@ -43,4 +31,4 @@ class Resource<T> {
String toString() {
return 'Resource{status: $status, data: $data, message: $message}';
}
}
}