refactor: update data source and repository structure by removing unused files, enhancing model integration, and adjusting import paths for better organization
This commit is contained in:
@@ -0,0 +1,542 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/data/models/request/conform_allocation/conform_allocation.dart';
|
||||
import 'package:rasadyar_chicken/data/models/request/submit_steward_allocation/submit_steward_allocation.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/allocated_made/allocated_made.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/broadcast_price/broadcast_price.dart';
|
||||
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/data/models/response/steward_remain_weight/steward_remain_weight.dart';
|
||||
import 'package:rasadyar_chicken/features/steward/root/logic.dart';
|
||||
import 'package:rasadyar_chicken/features/steward/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 {
|
||||
StewardRootLogic rootLogic = Get.find<StewardRootLogic>();
|
||||
SaleLogic saleLogic = Get.find<SaleLogic>();
|
||||
RxnString searchedValue = RxnString();
|
||||
RxInt expandedListIndex = (-1).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>();
|
||||
|
||||
RxList<GuildModel> guildsModel = <GuildModel>[].obs;
|
||||
|
||||
GlobalKey<FormState> formKey = GlobalKey<FormState>();
|
||||
|
||||
Rx<Jalali> fromDateFilter = Jalali.now().obs;
|
||||
Rx<Jalali> toDateFilter = Jalali.now().obs;
|
||||
Rxn<ProductModel> selectedProductModel = Rxn<ProductModel>();
|
||||
Rxn<GuildModel> selectedGuildModel = Rxn<GuildModel>();
|
||||
Rxn<GuildProfile> guildProfile = Rxn<GuildProfile>();
|
||||
RxInt saleType = 1.obs;
|
||||
RxInt priceType = 2.obs;
|
||||
RxInt quotaType = 1.obs;
|
||||
RxInt weight = 0.obs;
|
||||
RxInt pricePerKilo = 0.obs;
|
||||
RxInt totalCost = 0.obs;
|
||||
RxBool isValid = false.obs;
|
||||
final weightController = TextEditingController();
|
||||
final pricePerKiloController = TextEditingController();
|
||||
final totalCostController = TextEditingController();
|
||||
|
||||
final ScrollController scrollControllerAllocationsMade = ScrollController();
|
||||
final RxInt currentPage = 1.obs;
|
||||
final RxBool addPageAllocationsMade = false.obs;
|
||||
final RxBool hasMoreDataAllocationsMade = true.obs;
|
||||
|
||||
Rxn<BroadcastPrice> broadcastPrice = Rxn<BroadcastPrice>();
|
||||
Rxn<AllocatedMadeModel> selectedAllocationModelForUpdate =
|
||||
Rxn<AllocatedMadeModel>();
|
||||
SubmitStewardAllocation? tmpStewardAllocation;
|
||||
|
||||
Rxn<Jalali> productionDate = Rxn(null);
|
||||
Rxn<int> remainingStock = Rxn(null);
|
||||
Map<String, DayData> freeProductionDateData = {};
|
||||
Map<String, DayData> governmentalProductionDateData = {};
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
routesName.value = [...saleLogic.routesName, 'داخل استان'].toList();
|
||||
getAllocatedMade();
|
||||
getRolesProducts();
|
||||
getGuilds();
|
||||
getGuildProfile();
|
||||
getBroadcastPrice();
|
||||
ever(saleType, (callback) {
|
||||
getGuilds();
|
||||
});
|
||||
|
||||
ever(quotaType, (_) {
|
||||
remainingStock.value = null;
|
||||
productionDate.value = null;
|
||||
});
|
||||
|
||||
debounce(weight, time: Duration(milliseconds: 110), (callback) {
|
||||
totalCost.value = callback * pricePerKilo.value;
|
||||
});
|
||||
|
||||
debounce(pricePerKilo, time: Duration(milliseconds: 100), (callback) {
|
||||
totalCost.value = callback * weight.value;
|
||||
});
|
||||
|
||||
totalCost.listen((data) {
|
||||
totalCostController.text = data.toString().separatedByComma;
|
||||
|
||||
isValid.value =
|
||||
weight.value > 0 &&
|
||||
pricePerKilo.value > 0 &&
|
||||
totalCost.value > 0 &&
|
||||
selectedProductModel.value != null &&
|
||||
selectedGuildModel.value != null;
|
||||
});
|
||||
everAll([
|
||||
totalCost,
|
||||
weight,
|
||||
pricePerKilo,
|
||||
totalCost,
|
||||
selectedProductModel,
|
||||
selectedGuildModel,
|
||||
productionDate,
|
||||
], (callback) => checkVerification());
|
||||
|
||||
scrollControllerAllocationsMade.addListener(() {
|
||||
if (scrollControllerAllocationsMade.position.pixels >=
|
||||
scrollControllerAllocationsMade.position.maxScrollExtent - 100) {
|
||||
addPageAllocationsMade.value = true;
|
||||
getAllocatedMade();
|
||||
}
|
||||
});
|
||||
|
||||
debounce(
|
||||
searchedValue,
|
||||
(callback) => getAllocatedMade(),
|
||||
time: Duration(milliseconds: timeDebounce),
|
||||
);
|
||||
|
||||
_updateGovernmentalProductionDateData();
|
||||
_updateFreeProductionDateData();
|
||||
ever(rootLogic.stewardRemainWeight, (callback) {
|
||||
_updateGovernmentalProductionDateData();
|
||||
_updateFreeProductionDateData();
|
||||
});
|
||||
}
|
||||
|
||||
void _updateGovernmentalProductionDateData() {
|
||||
List<RemainWeightDay> dates =
|
||||
rootLogic.stewardRemainWeight.value?.governmental ?? [];
|
||||
governmentalProductionDateData = {
|
||||
for (var element in dates)
|
||||
element.day.toString().toJalali.formatCompactDate(): DayData(
|
||||
value: element.amount?.toInt(),
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
void _updateFreeProductionDateData() {
|
||||
var dates = rootLogic.stewardRemainWeight.value?.free ?? [];
|
||||
freeProductionDateData = {
|
||||
for (var element in dates)
|
||||
element.day.toString().toJalali.formatCompactDate(): DayData(
|
||||
value: element.amount?.toInt(),
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
Future<void> getAllocatedMade([bool isLoadingMore = false]) async {
|
||||
if (isLoadingMore) {
|
||||
isLoadingMoreAllocationsMade.value = true;
|
||||
} else {
|
||||
allocatedList.value =
|
||||
Resource<PaginationModel<AllocatedMadeModel>>.loading();
|
||||
}
|
||||
|
||||
if (searchedValue.value != null &&
|
||||
searchedValue.value!.trim().isNotEmpty &&
|
||||
currentPage.value > 1) {
|
||||
currentPage.value = 1; // Reset to first page if search value is set
|
||||
}
|
||||
|
||||
safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.getAllocatedMade(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
queryParameters: buildQueryParams(
|
||||
page: currentPage.value,
|
||||
pageSize: 20,
|
||||
search: 'filter',
|
||||
role: 'Steward',
|
||||
value: searchedValue.value,
|
||||
fromDate: fromDateFilter.value.toDateTime(),
|
||||
toDate: toDateFilter.value.toDateTime(),
|
||||
),
|
||||
),
|
||||
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();
|
||||
}
|
||||
}
|
||||
},
|
||||
onError: (error, stacktrace) {
|
||||
isLoadingMoreAllocationsMade.value = false;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void checkVerification() {
|
||||
var hasWeight = quotaType.value == 1
|
||||
? weight.value <=
|
||||
(governmentalProductionDateData[productionDate.value
|
||||
?.formatCompactDate()]
|
||||
?.value ??
|
||||
0)
|
||||
: weight.value <=
|
||||
(freeProductionDateData[productionDate.value?.formatCompactDate()]
|
||||
?.value ??
|
||||
0);
|
||||
|
||||
isValid.value =
|
||||
weight.value > 0 &&
|
||||
pricePerKilo.value > 0 &&
|
||||
totalCost.value > 0 &&
|
||||
hasWeight &&
|
||||
selectedProductModel.value != null &&
|
||||
selectedGuildModel.value != null;
|
||||
}
|
||||
|
||||
void confirmAllocation(ConformAllocation allocation) {
|
||||
safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.confirmAllocation(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
allocation: allocation.toJson(),
|
||||
),
|
||||
onSuccess: (result) {
|
||||
getAllocatedMade();
|
||||
},
|
||||
onError: (error, stacktrace) {},
|
||||
);
|
||||
}
|
||||
|
||||
void denyAllocation(String token) {
|
||||
safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.denyAllocation(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
allocationToken: token,
|
||||
),
|
||||
onSuccess: (result) {
|
||||
getAllocatedMade();
|
||||
},
|
||||
onError: (error, stacktrace) {},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> confirmAllAllocations() async {
|
||||
safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.confirmAllAllocation(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
allocationTokens:
|
||||
allocatedList.value.data?.results?.map((e) => e.key!).toList() ??
|
||||
[],
|
||||
),
|
||||
onSuccess: (result) {
|
||||
getAllocatedMade();
|
||||
},
|
||||
onError: (error, stacktrace) {},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> getRolesProducts() async {
|
||||
safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.getRolesProducts(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
queryParameters: buildQueryParams(role: 'Steward'),
|
||||
),
|
||||
onSuccess: (result) {
|
||||
if (result != null) {
|
||||
rolesProductsModel.value = result;
|
||||
selectedProductModel.value = result.first;
|
||||
}
|
||||
},
|
||||
onError: (error, stacktrace) {},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> getGuilds() async {
|
||||
safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.getGuilds(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
queryParameters: buildQueryParams(
|
||||
//queryParams: {'free': saleType.value == 2 ? true : false},
|
||||
queryParams: {'all': true},
|
||||
role: 'Steward',
|
||||
),
|
||||
),
|
||||
onSuccess: (result) {
|
||||
if (result != null) {
|
||||
guildsModel.clear();
|
||||
guildsModel.addAll(result);
|
||||
}
|
||||
},
|
||||
onError: (error, stacktrace) {},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> addSale() async {}
|
||||
|
||||
void setSelectedGuild(GuildModel value) {
|
||||
selectedGuildModel.value = value;
|
||||
update();
|
||||
}
|
||||
|
||||
void setSelectedProduct(ProductModel value) {
|
||||
selectedProductModel.value = value;
|
||||
update();
|
||||
}
|
||||
|
||||
Future<void> getGuildProfile() async {
|
||||
await safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.getProfile(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
),
|
||||
onError: (error, stackTrace) {},
|
||||
onSuccess: (result) {
|
||||
guildProfile.value = result;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void setSubmitData() {
|
||||
tmpStewardAllocation = SubmitStewardAllocation(
|
||||
approvedPriceStatus: priceType.value == 1,
|
||||
allocationType:
|
||||
'${guildProfile.value?.steward == true ? "steward" : "guild"}_${selectedGuildModel.value?.steward == true ? "steward" : "guild"}',
|
||||
sellerType: guildProfile.value?.steward == true ? "Steward" : "Guild",
|
||||
buyerType: selectedGuildModel.value?.steward == true
|
||||
? "Steward"
|
||||
: "Guild",
|
||||
amount: pricePerKilo.value,
|
||||
totalAmount: totalCost.value,
|
||||
weightOfCarcasses: weight.value,
|
||||
sellType: saleType.value == 2 ? "free" : 'exclusive',
|
||||
numberOfCarcasses: 0,
|
||||
productionDate: productionDate.value
|
||||
?.toDateTime()
|
||||
.formattedDashedGregorian,
|
||||
quota: quotaType.value == 1 ? 'governmental' : 'free',
|
||||
guildKey: selectedGuildModel.value?.key,
|
||||
productKey: selectedProductModel.value?.key,
|
||||
date: DateTime.now().formattedDashedGregorian,
|
||||
type: "manual",
|
||||
distributionType: 'App',
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> submitAllocation() async {
|
||||
setSubmitData();
|
||||
|
||||
safeCall(
|
||||
showError: true,
|
||||
call: () async =>
|
||||
await rootLogic.chickenRepository.postSubmitStewardAllocation(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
request: tmpStewardAllocation!,
|
||||
),
|
||||
|
||||
onSuccess: (result) {
|
||||
clearForm();
|
||||
onRefresh();
|
||||
rootLogic.onRefresh();
|
||||
Future.delayed(
|
||||
Duration(seconds: 1),
|
||||
() => defaultShowSuccessMessage("ثبت موفق بود"),
|
||||
);
|
||||
Get.back();
|
||||
},
|
||||
onError: (error, stackTrace) {},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> deleteAllocation(AllocatedMadeModel model) async {
|
||||
safeCall(
|
||||
call: () async =>
|
||||
await rootLogic.chickenRepository.deleteStewardAllocation(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
queryParameters: {'steward_allocation_key': model.key},
|
||||
),
|
||||
|
||||
onSuccess: (result) {
|
||||
getAllocatedMade();
|
||||
},
|
||||
onError: (error, stackTrace) {},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
rootLogic.inventoryExpandedList.clear();
|
||||
stopFlashing();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void setEditData(AllocatedMadeModel item) {
|
||||
selectedAllocationModelForUpdate.value = item;
|
||||
selectedProductModel.value = rolesProductsModel.first;
|
||||
selectedGuildModel.value = GuildModel(guildsName: 'tst');
|
||||
weight.value = item.weightOfCarcasses ?? 0;
|
||||
pricePerKilo.value = item.amount ?? 0;
|
||||
totalCost.value = item.totalAmount ?? 0;
|
||||
weightController.text = weight.value.toString().separatedByComma;
|
||||
pricePerKiloController.text = pricePerKilo.value
|
||||
.toString()
|
||||
.separatedByComma;
|
||||
totalCostController.text = totalCost.value.toString().separatedByComma;
|
||||
isValid.value = true;
|
||||
productionDate.value = item.productionDate.toJalali;
|
||||
}
|
||||
|
||||
void clearForm() {
|
||||
selectedGuildModel.value = null;
|
||||
weight.value = 0;
|
||||
totalCost.value = 0;
|
||||
weightController.clear();
|
||||
if (broadcastPrice.value?.active == false) {
|
||||
pricePerKilo.value = 0;
|
||||
pricePerKiloController.clear();
|
||||
}
|
||||
totalCostController.clear();
|
||||
isValid.value = false;
|
||||
productionDate.value = null;
|
||||
quotaType.value = 1;
|
||||
priceType.value = 2;
|
||||
saleType.value = 2;
|
||||
}
|
||||
|
||||
Future<void> updateAllocation() async {
|
||||
ConformAllocation updatedAllocationModel = ConformAllocation(
|
||||
allocation_key: selectedAllocationModelForUpdate.value?.key,
|
||||
amount: pricePerKilo.value,
|
||||
total_amount: totalCost.value,
|
||||
number_of_carcasses: 0,
|
||||
weight_of_carcasses: weight.value,
|
||||
);
|
||||
|
||||
safeCall(
|
||||
showError: true,
|
||||
call: () async =>
|
||||
await rootLogic.chickenRepository.updateStewardAllocation(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
request: updatedAllocationModel,
|
||||
),
|
||||
|
||||
onSuccess: (result) {
|
||||
clearForm();
|
||||
onRefresh();
|
||||
rootLogic.onRefresh();
|
||||
Future.delayed(
|
||||
Duration(seconds: 1),
|
||||
() => defaultShowSuccessMessage("ویرایش موفق بود"),
|
||||
);
|
||||
Get.back();
|
||||
},
|
||||
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 ?? false) {
|
||||
return model.toGuilds;
|
||||
} else {
|
||||
return model.steward;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> getBroadcastPrice() async {
|
||||
safeCall(
|
||||
call: () async => await rootLogic.chickenRepository.getBroadcastPrice(
|
||||
token: rootLogic.tokenService.accessToken.value!,
|
||||
),
|
||||
onSuccess: (result) {
|
||||
broadcastPrice.value = result;
|
||||
if (broadcastPrice.value?.active == true) {
|
||||
pricePerKilo.value = broadcastPrice.value?.stewardPrice ?? 0;
|
||||
pricePerKiloController.text = pricePerKilo.value
|
||||
.toString()
|
||||
.separatedByComma;
|
||||
priceType.value = 2;
|
||||
}
|
||||
},
|
||||
onError: (error, stacktrace) {},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> onRefresh() async {
|
||||
toggleExpansion();
|
||||
currentPage.value = 1;
|
||||
hasMoreDataAllocationsMade.value = true;
|
||||
await Future.wait([
|
||||
getAllocatedMade(),
|
||||
getRolesProducts(),
|
||||
rootLogic.onRefresh(),
|
||||
]);
|
||||
}
|
||||
|
||||
void toggleExpansion({int? index}) {
|
||||
if (expandedListIndex.value == index || index == null) {
|
||||
expandedListIndex.value = -1;
|
||||
} else {
|
||||
expandedListIndex.value = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,527 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/allocated_made/allocated_made.dart';
|
||||
import 'package:rasadyar_chicken/features/steward/sales_in_province/widgets/cu_sale_in_provience.dart';
|
||||
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.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/inventory/inventory_widget.dart';
|
||||
|
||||
import 'package:rasadyar_core/core.dart' hide modalDatePicker;
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
|
||||
SalesInProvincePage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChickenBasePage(
|
||||
routes: controller.routesName,
|
||||
backId: stewardSecondKey,
|
||||
onSearchChanged: (data) => controller.setSearchValue(data),
|
||||
onRefresh: controller.onRefresh,
|
||||
onFilterTap: () {
|
||||
Get.bottomSheet(filterBottomSheet());
|
||||
},
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: Column(
|
||||
children: [
|
||||
Obx(() {
|
||||
var list = [
|
||||
InventoryItemData(
|
||||
title: 'موجودی انبار',
|
||||
value: controller
|
||||
.rootLogic
|
||||
.inventoryModel
|
||||
.value
|
||||
?.totalRemainWeight
|
||||
?.separatedByCommaFa,
|
||||
color: const Color(0xFFEAFBFC),
|
||||
),
|
||||
InventoryItemData(
|
||||
title: 'مانده دولتی',
|
||||
value: controller
|
||||
.rootLogic
|
||||
.inventoryModel
|
||||
.value
|
||||
?.totalGovernmentalRemainWeight
|
||||
?.separatedByCommaFa,
|
||||
|
||||
color: const Color(0xFFF5ECEE),
|
||||
),
|
||||
InventoryItemData(
|
||||
title: 'مانده آزاد',
|
||||
value: controller
|
||||
.rootLogic
|
||||
.inventoryModel
|
||||
.value
|
||||
?.totalFreeRemainWeight
|
||||
?.separatedByCommaFa,
|
||||
|
||||
color: const Color(0xFFF1E7FF),
|
||||
),
|
||||
];
|
||||
|
||||
return InventoryWidget(inventoryModel: list);
|
||||
}),
|
||||
|
||||
Expanded(
|
||||
child: ObxValue((data) {
|
||||
return RPaginatedListView(
|
||||
listType: ListType.separated,
|
||||
resource: data.value,
|
||||
hasMore: data.value.data?.next != null,
|
||||
isPaginating: controller.isLoadingMoreAllocationsMade.value,
|
||||
onLoadMore: () async {
|
||||
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 ExpandableListItem2(
|
||||
selected: val.value == index,
|
||||
onTap: () => controller.toggleExpansion(index: index),
|
||||
index: index,
|
||||
child: itemListWidget(item),
|
||||
secondChild: itemListExpandedWidget(item, index),
|
||||
labelColor: AppColor.blueLight,
|
||||
labelIcon: Assets.vec.timerSvg.path,
|
||||
labelIconColor: item.registrationCode == null
|
||||
? AppColor.darkGreyDark
|
||||
: AppColor.error,
|
||||
);
|
||||
}, controller.expandedListIndex);
|
||||
},
|
||||
itemCount: data.value.data?.results?.length ?? 0,
|
||||
separatorBuilder: (context, index) => SizedBox(height: 8.h),
|
||||
);
|
||||
}, controller.allocatedList),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
right: 5,
|
||||
bottom: 95,
|
||||
child: SizedBox(
|
||||
width: Get.width - 30,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
RFab.add(
|
||||
onPressed: () {
|
||||
Get.bottomSheet(
|
||||
addOrEditBottomSheet(controller),
|
||||
isScrollControlled: true,
|
||||
backgroundColor: Colors.transparent,
|
||||
).whenComplete(() {
|
||||
controller.clearForm();
|
||||
});
|
||||
},
|
||||
),
|
||||
|
||||
ObxValue((data) {
|
||||
return Visibility(
|
||||
visible: (data.value.data?.results?.length ?? 0) > 1,
|
||||
child: AnimatedFab(
|
||||
onPressed: () async {
|
||||
Get.defaultDialog(
|
||||
title: 'تایید یکجا',
|
||||
middleText: 'آیا از تایید تمامی تخصیص ها اطمینان دارید؟',
|
||||
confirm: ElevatedButton(
|
||||
onPressed: () async {
|
||||
await controller.confirmAllAllocations();
|
||||
controller.getAllocatedMade();
|
||||
controller.rootLogic.getRolesProduct();
|
||||
Get.back();
|
||||
},
|
||||
child: Text('تایید'),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: AppColor.blueNormal,
|
||||
foregroundColor: Colors.white,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
),
|
||||
cancel: OutlinedButton(
|
||||
style: OutlinedButton.styleFrom(
|
||||
foregroundColor: AppColor.error,
|
||||
enableFeedback: true,
|
||||
side: BorderSide(color: AppColor.error, width: 1),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
onPressed: () {
|
||||
Get.back();
|
||||
},
|
||||
child: Text('لغو'),
|
||||
),
|
||||
);
|
||||
},
|
||||
message: 'تایید یکجا',
|
||||
icon: Assets.vec.clipboardTaskSvg.svg(width: 40.w, height: 40.h),
|
||||
backgroundColor: controller.bgConfirmAllColor.value,
|
||||
),
|
||||
);
|
||||
}, controller.allocatedList),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Row itemListWidget(AllocatedMadeModel item) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
SizedBox(width: 20),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 4,
|
||||
children: [
|
||||
Text(
|
||||
controller.getBuyerInformation(item)?.user?.fullname ?? 'ندارد',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
|
||||
SizedBox(height: 2),
|
||||
Text(
|
||||
item.createDate?.formattedJalaliDate ?? 'ندارد',
|
||||
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!.separatedByCommaFa.addKg,
|
||||
textAlign: TextAlign.left,
|
||||
textDirection: TextDirection.ltr,
|
||||
style: AppFonts.yekan12Bold.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 2),
|
||||
Text(
|
||||
item.amount.separatedByCommaFa.addReal,
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan12.copyWith(color: AppColor.darkGreyDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(width: 8),
|
||||
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Column(
|
||||
spacing: 3,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
item.approvedPriceStatus == true
|
||||
? 'دولتی'
|
||||
: item.approvedPriceStatus == false
|
||||
? 'آزاد'
|
||||
: '-',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan12.copyWith(
|
||||
color: item.approvedPriceStatus == true
|
||||
? AppColor.blueNormal
|
||||
: AppColor.greenNormal,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(width: 8),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Container itemListExpandedWidget(AllocatedMadeModel 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(
|
||||
controller.getBuyerInformation(item)?.user?.fullname ?? 'ندارد',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.greenDark),
|
||||
),
|
||||
Spacer(),
|
||||
Text(
|
||||
item.registrationCode == null ? 'در انتظار' : 'در انتظار تایید خریدار',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan10.copyWith(
|
||||
color: item.registrationCode == null ? AppColor.darkGreyDark : AppColor.error,
|
||||
),
|
||||
),
|
||||
SizedBox(width: 7),
|
||||
Assets.vec.clockSvg.svg(
|
||||
width: 16.w,
|
||||
height: 16.h,
|
||||
colorFilter: ColorFilter.mode(
|
||||
item.registrationCode == null ? AppColor.darkGreyDark : AppColor.error,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
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 ?? 'ندارد',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
|
||||
Text(
|
||||
'${item.date?.toJalali.formatter.d} ${item.date?.toJalali.formatter.mN ?? 'ندارد'}',
|
||||
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 ?? 'ندارد'}',
|
||||
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
buildRow(
|
||||
title: 'تلفن خریدار',
|
||||
value: controller.getBuyerInformation(item)?.user?.mobile ?? 'ندارد',
|
||||
valueStyle: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
buildRow(title: 'محصول', value: item.product?.name ?? 'ندارد'),
|
||||
|
||||
buildRow(
|
||||
title: 'تاریخ تولید گوشت',
|
||||
value: item.productionDate?.toJalali.formatCompactDate() ?? 'ندارد',
|
||||
),
|
||||
|
||||
buildRow(title: 'نوع تخصیص', value: item.allocationType?.faAllocationType ?? 'ندارد'),
|
||||
buildRow(
|
||||
title: 'نوع فروش',
|
||||
value: (item.approvedPriceStatus ?? false) ? 'دولتی' : 'آزاد',
|
||||
),
|
||||
buildRow(title: 'نوع انبار', value: (item.quota == 'governmental') ? 'دولتی' : 'آزاد'),
|
||||
|
||||
buildRow(
|
||||
title: 'وزن خریداری شده',
|
||||
value: '${item.weightOfCarcasses?.separatedByCommaFa} کیلوگرم',
|
||||
),
|
||||
buildRow(
|
||||
title: 'افت وزن(کیلوگرم)',
|
||||
value: item.weightLossOfCarcasses?.toInt().toString() ?? 'ندارد',
|
||||
),
|
||||
buildRow(
|
||||
title: 'قیمت هر کیلوگرم',
|
||||
titleLabel: (item.approvedPriceStatus ?? false) ? 'دولتی' : 'آزاد',
|
||||
titleLabelStyle: AppFonts.yekan14Bold.copyWith(
|
||||
color: (item.approvedPriceStatus ?? false)
|
||||
? AppColor.blueNormal
|
||||
: AppColor.greenNormal,
|
||||
),
|
||||
value: '${item.amount?.separatedByCommaFa} ریال',
|
||||
),
|
||||
buildRow(title: 'قیمت کل', value: '${item.totalAmount?.separatedByCommaFa} ریال'),
|
||||
|
||||
buildRow(title: 'کداحراز', value: item.registrationCode?.toString() ?? 'ندارد'),
|
||||
buildRow(
|
||||
title: 'وضعیت کد احراز',
|
||||
value: item.systemRegistrationCode == true ? "ارسال شده" : "ارسال نشده",
|
||||
),
|
||||
|
||||
Visibility(
|
||||
visible: item.registrationCode == null,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 16.w,
|
||||
children: [
|
||||
RElevated(
|
||||
text: 'ویرایش',
|
||||
width: 150.w,
|
||||
height: 40.h,
|
||||
onPressed: () {
|
||||
controller.setEditData(item);
|
||||
Get.bottomSheet(
|
||||
addOrEditBottomSheet(controller, isEditMode: true),
|
||||
isScrollControlled: true,
|
||||
backgroundColor: Colors.transparent,
|
||||
).whenComplete(() {
|
||||
controller.clearForm();
|
||||
});
|
||||
},
|
||||
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.toggleExpansion(index: index);
|
||||
|
||||
await controller.deleteAllocation(item);
|
||||
},
|
||||
onRefresh: controller.onRefresh,
|
||||
);
|
||||
},
|
||||
borderColor: AppColor.redNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget filterBottomSheet() {
|
||||
return BaseBottomSheet(
|
||||
height: 200,
|
||||
child: Column(
|
||||
spacing: 16,
|
||||
children: [
|
||||
Text('فیلترها', style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal)),
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Expanded(
|
||||
child: timeFilterWidget(
|
||||
controller: controller,
|
||||
date: controller.fromDateFilter,
|
||||
onChanged: (jalali) => controller.fromDateFilter.value = jalali,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: timeFilterWidget(
|
||||
controller: controller,
|
||||
isFrom: false,
|
||||
date: controller.toDateFilter,
|
||||
onChanged: (jalali) => controller.toDateFilter.value = jalali,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
RElevated(
|
||||
text: 'اعمال فیلتر',
|
||||
isFullWidth: true,
|
||||
backgroundColor: AppColor.greenNormal,
|
||||
onPressed: () {
|
||||
controller.getAllocatedMade();
|
||||
Get.back();
|
||||
},
|
||||
height: 40,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
GestureDetector timeFilterWidget({
|
||||
required SalesInProvinceLogic controller,
|
||||
isFrom = true,
|
||||
required Rx<Jalali> date,
|
||||
required Function(Jalali jalali) onChanged,
|
||||
}) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
Get.bottomSheet(modalDatePicker((value) => onChanged(value)));
|
||||
},
|
||||
child: Container(
|
||||
height: 35,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(width: 1, color: AppColor.blueNormal),
|
||||
),
|
||||
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.blueNormal, BlendMode.srcIn),
|
||||
),
|
||||
Text(
|
||||
isFrom ? 'از' : 'تا',
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
Expanded(
|
||||
child: ObxValue((data) {
|
||||
return Text(
|
||||
date.value.formatCompactDate(),
|
||||
textAlign: TextAlign.center,
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.lightGreyNormalActive),
|
||||
);
|
||||
}, date),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,515 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:rasadyar_chicken/data/models/response/roles_products/roles_products.dart';
|
||||
import 'package:rasadyar_chicken/features/steward/sales_in_province/logic.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
Widget addOrEditBottomSheet(SalesInProvinceLogic controller, {bool isEditMode = false}) {
|
||||
return BaseBottomSheet(
|
||||
height: Get.height * (isEditMode ? 0.60 : 0.75),
|
||||
child: Form(
|
||||
key: controller.formKey,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
'${isEditMode ? 'ویرایش' : 'ثبت'} توزیع/ فروش',
|
||||
style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
productDropDown(controller),
|
||||
const SizedBox(height: 12),
|
||||
|
||||
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: [
|
||||
const SizedBox(height: 8),
|
||||
ObxValue((data) {
|
||||
return RTextField(
|
||||
controller: TextEditingController(),
|
||||
filledColor: AppColor.bgLight,
|
||||
filled: true,
|
||||
label: 'تاریخ',
|
||||
onTap: () {
|
||||
Get.bottomSheet(
|
||||
modalDatePicker((value) {
|
||||
controller.fromDateFilter.value = value;
|
||||
controller.fromDateFilter.refresh();
|
||||
}),
|
||||
);
|
||||
},
|
||||
borderColor: AppColor.darkGreyLight,
|
||||
initText: (data.value).formatCompactDate(),
|
||||
);
|
||||
}, controller.fromDateFilter),
|
||||
Visibility(
|
||||
visible: isEditMode == false,
|
||||
child: Container(
|
||||
height: 50.h,
|
||||
clipBehavior: Clip.none,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(color: AppColor.darkGreyLight, width: 1),
|
||||
),
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
alignment: Alignment.center,
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
Positioned(
|
||||
child: Container(color: Colors.white, child: Text("انبار")),
|
||||
top: -10,
|
||||
right: 8,
|
||||
),
|
||||
Obx(() {
|
||||
return RadioGroup(
|
||||
groupValue: controller.quotaType.value,
|
||||
onChanged: (value) {
|
||||
controller.quotaType.value = value ?? 0;
|
||||
},
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
controller.quotaType.value = 1;
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
Radio(value: 1),
|
||||
Text('دولتی', style: AppFonts.yekan14),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Expanded(
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
controller.quotaType.value = 2;
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
Radio(value: 2),
|
||||
Text('آزاد', style: AppFonts.yekan14),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Obx(() {
|
||||
return MonthlyDataCalendar(
|
||||
label: 'تاریخ تولید گوشت',
|
||||
selectedDate: controller.productionDate.value?.formatCompactDate(),
|
||||
onDateSelect: (value) {
|
||||
controller.productionDate.value = value.date;
|
||||
controller.remainingStock.value = value.remainingStock;
|
||||
},
|
||||
dayData: controller.quotaType.value == 1
|
||||
? controller.governmentalProductionDateData
|
||||
: controller.freeProductionDateData,
|
||||
);
|
||||
}),
|
||||
|
||||
Visibility(visible: isEditMode == false, child: guildsDropDown(controller)),
|
||||
|
||||
RTextField(
|
||||
controller: controller.weightController,
|
||||
keyboardType: TextInputType.number,
|
||||
autoValidateMode: AutovalidateMode.onUserInteraction,
|
||||
borderColor: AppColor.darkGreyLight,
|
||||
filledColor: AppColor.bgLight,
|
||||
filled: true,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.digitsOnly,
|
||||
SeparatorInputFormatter(),
|
||||
],
|
||||
validator: (value) {
|
||||
if ((int.tryParse(value?.clearComma ?? '0') ?? 0) >
|
||||
(controller.remainingStock.value ?? 0)) {
|
||||
return 'وزن تخصیصی بیشتر از موجودی انبار است';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
onChanged: (p0) {
|
||||
controller.weight.value = int.tryParse(p0.clearComma) ?? 0;
|
||||
},
|
||||
label: 'وزن لاشه (کیلوگرم)',
|
||||
),
|
||||
|
||||
Visibility(
|
||||
visible: isEditMode == false,
|
||||
child: Container(
|
||||
height: 58.h,
|
||||
clipBehavior: Clip.none,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(color: AppColor.darkGreyLight, width: 1),
|
||||
),
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
alignment: Alignment.center,
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
Positioned(
|
||||
child: Container(color: Colors.white, child: Text("فروش")),
|
||||
top: -10,
|
||||
right: 8,
|
||||
),
|
||||
Obx(() {
|
||||
return RadioGroup(
|
||||
groupValue: controller.priceType.value,
|
||||
onChanged: (value) {
|
||||
controller.priceType.value = value!;
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: GestureDetector(
|
||||
onTap: (controller.broadcastPrice.value?.active ?? false)
|
||||
? () {
|
||||
controller.priceType.value = 1;
|
||||
}
|
||||
: null,
|
||||
child: Row(
|
||||
children: [
|
||||
Radio(
|
||||
value: 1,
|
||||
enabled: controller.broadcastPrice.value?.active ?? false,
|
||||
),
|
||||
Text(
|
||||
'قیمت مصوب',
|
||||
style: AppFonts.yekan14.copyWith(
|
||||
color:
|
||||
(controller.broadcastPrice.value?.active ?? false)
|
||||
? AppColor.textColor
|
||||
: AppColor.labelTextColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Expanded(
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
controller.priceType.value = 2;
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
Radio(value: 2),
|
||||
Text('قیمت آزاد', style: AppFonts.yekan14),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
ObxValue((data) {
|
||||
return RTextField(
|
||||
variant: RTextFieldVariant.noBorder,
|
||||
controller: controller.pricePerKiloController,
|
||||
borderColor: AppColor.darkGreyLight,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.digitsOnly,
|
||||
SeparatorInputFormatter(),
|
||||
],
|
||||
filledColor: AppColor.bgLight,
|
||||
filled: true,
|
||||
readonly: data.value == 1,
|
||||
onChanged: (p0) {
|
||||
controller.pricePerKilo.value = int.tryParse(p0.clearComma) ?? 0;
|
||||
},
|
||||
keyboardType: TextInputType.number,
|
||||
label: 'قیمت هر کیلو (ريال)',
|
||||
);
|
||||
}, controller.priceType),
|
||||
|
||||
RTextField(
|
||||
variant: RTextFieldVariant.noBorder,
|
||||
enabled: false,
|
||||
keyboardType: TextInputType.number,
|
||||
filledColor: AppColor.bgLight,
|
||||
filled: true,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.digitsOnly,
|
||||
SeparatorInputFormatter(),
|
||||
],
|
||||
controller: controller.totalCostController,
|
||||
label: 'هزینه کل (ريال)',
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(height: 12.h),
|
||||
ObxValue((data) {
|
||||
return RElevated(
|
||||
text: isEditMode ? 'ویرایش' : 'ثبت',
|
||||
isFullWidth: true,
|
||||
textStyle: AppFonts.yekan16.copyWith(color: Colors.white),
|
||||
backgroundColor: AppColor.greenNormal,
|
||||
height: 40,
|
||||
enabled: data.value,
|
||||
onPressed: isEditMode
|
||||
? () async {
|
||||
await controller.updateAllocation();
|
||||
Get.back();
|
||||
}
|
||||
: () async {
|
||||
await controller.submitAllocation();
|
||||
Get.back();
|
||||
},
|
||||
);
|
||||
}, controller.isValid),
|
||||
const SizedBox(height: 20),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget guildsDropDown(SalesInProvinceLogic controller) {
|
||||
return Obx(() {
|
||||
final item = controller.selectedGuildModel.value;
|
||||
|
||||
return SearchableDropdown(
|
||||
onChanged: (value) {
|
||||
controller.selectedGuildModel.value = value;
|
||||
},
|
||||
selectedItem: [?item],
|
||||
singleSelect: false,
|
||||
items: controller.guildsModel,
|
||||
hintText: 'انتخاب مباشر/صنف',
|
||||
itemBuilder: (item) => Text(
|
||||
item.user != null
|
||||
? '${item.steward == true ? 'مباشر' : 'صنف'} ${item.user!.fullname} (${item.user!.mobile})'
|
||||
: 'بدون نام',
|
||||
),
|
||||
multiLabelBuilder: (item) => Container(
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.bgLight,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(color: AppColor.darkGreyLight),
|
||||
),
|
||||
padding: EdgeInsets.all(4),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
item?.user != null
|
||||
? '${item?.steward == true ? 'مباشر' : 'صنف'} ${item?.user!.fullname}'
|
||||
: 'بدون نام',
|
||||
style: AppFonts.yekan14,
|
||||
),
|
||||
SizedBox(width: 4.w),
|
||||
Icon(Icons.close, size: 16, color: AppColor.labelTextColor),
|
||||
],
|
||||
),
|
||||
),
|
||||
onSearch: (query) async {
|
||||
return Future.microtask(() {
|
||||
return RxList(
|
||||
controller.guildsModel
|
||||
.where((element) => element.user?.fullname?.contains(query) ?? false)
|
||||
.toList(),
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Widget productDropDown(SalesInProvinceLogic controller) {
|
||||
return Obx(() {
|
||||
return OverlayDropdownWidget<ProductModel>(
|
||||
items: controller.rolesProductsModel,
|
||||
height: 56,
|
||||
hasDropIcon: false,
|
||||
background: Colors.white,
|
||||
onChanged: (value) {
|
||||
controller.selectedProductModel.value = value;
|
||||
},
|
||||
selectedItem: controller.selectedProductModel.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(),
|
||||
|
||||
ObxValue((data) {
|
||||
return Visibility(visible: data.value != null, child: Text('موجودی: $data'));
|
||||
}, controller.remainingStock),
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Container modalDatePicker(ValueChanged<Jalali> onDateSelected) {
|
||||
Jalali? tempPickedDate;
|
||||
return Container(
|
||||
height: 250,
|
||||
color: Colors.white,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
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: Jalali.now(),
|
||||
minimumDate: Jalali.now().add(days: -1),
|
||||
maximumDate: Jalali.now(),
|
||||
mode: PersianCupertinoDatePickerMode.date,
|
||||
onDateTimeChanged: (dateTime) {
|
||||
tempPickedDate = dateTime;
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget show2StepAddBottomSheet(SalesInProvinceLogic controller) {
|
||||
return BaseBottomSheet(
|
||||
height: Get.height * .39,
|
||||
child: Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
buildRow(
|
||||
title: 'تاریخ ثبت',
|
||||
value: controller.tmpStewardAllocation?.date?.formattedJalaliDate ?? 'ندارد',
|
||||
),
|
||||
buildRow(
|
||||
title: 'نام و نام خانوادگی خریدار',
|
||||
value:
|
||||
controller.guildsModel
|
||||
.firstWhere((p0) => p0.key == controller.tmpStewardAllocation?.guildKey)
|
||||
.user
|
||||
?.fullname ??
|
||||
'ندارد',
|
||||
),
|
||||
buildRow(
|
||||
title: 'شماره خریدار',
|
||||
value:
|
||||
controller.guildsModel
|
||||
.firstWhere((p0) => p0.key == controller.tmpStewardAllocation?.guildKey)
|
||||
.user
|
||||
?.mobile ??
|
||||
'ندارد',
|
||||
),
|
||||
|
||||
buildRow(
|
||||
title: 'قیمت هر کیلو',
|
||||
value: '${controller.tmpStewardAllocation?.amount.separatedByCommaFa ?? 0} ریال ',
|
||||
),
|
||||
buildRow(
|
||||
title: 'وزن تخصیصی',
|
||||
value:
|
||||
'${controller.tmpStewardAllocation?.weightOfCarcasses?.toInt().separatedByCommaFa ?? 0} کیلوگرم',
|
||||
),
|
||||
buildRow(
|
||||
title: 'قیمت کل',
|
||||
value: '${controller.tmpStewardAllocation?.totalAmount.separatedByCommaFa ?? 0} ریال',
|
||||
),
|
||||
|
||||
Row(
|
||||
spacing: 10,
|
||||
children: [
|
||||
Expanded(
|
||||
child: RElevated(
|
||||
backgroundColor: AppColor.greenNormal,
|
||||
height: 40,
|
||||
text: 'ثبت',
|
||||
textStyle: AppFonts.yekan18.copyWith(color: Colors.white),
|
||||
onPressed: () async {
|
||||
await controller.submitAllocation();
|
||||
Get
|
||||
..back()
|
||||
..back();
|
||||
},
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: ROutlinedElevated(
|
||||
height: 40,
|
||||
borderColor: AppColor.error,
|
||||
text: ' بازگشت',
|
||||
textStyle: AppFonts.yekan18.copyWith(color: AppColor.error),
|
||||
onPressed: () {
|
||||
Get
|
||||
..back()
|
||||
..back();
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user