feat : new bottom sheet

This commit is contained in:
2025-07-08 11:10:31 +03:30
parent 639a8dd585
commit bbaeb6c2a5
9 changed files with 429 additions and 299 deletions

View File

@@ -18,6 +18,7 @@ class BuyInProvincePage extends GetView<BuyInProvinceLogic> {
onSearchChanged: (data) => controller.setSearchValue(data), onSearchChanged: (data) => controller.setSearchValue(data),
filteringWidget: filterBottomSheet(), filteringWidget: filterBottomSheet(),
widgets: [ widgets: [
inventoryWidget(),
segmentWidget(), segmentWidget(),
ObxValue((index) { ObxValue((index) {
return Expanded( return Expanded(
@@ -88,4 +89,23 @@ class BuyInProvincePage extends GetView<BuyInProvinceLogic> {
), ),
); );
} }
Widget inventoryWidget() {
return Container(
width: Get.width,
height: 39,
margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: AppColor.greenLight,
borderRadius: BorderRadius.circular(8),
),
alignment: Alignment.center,
child: ObxValue((data) {
return Text(
' موجودی انبار: ${data.value?.totalRemainWeight?.toInt().separatedByComma ?? '0'} کیلوگرم',
style: AppFonts.yekan16.copyWith(color: AppColor.mediumGreyDarkHover),
);
}, controller.rootLogic.inventoryModel),
);
}
} }

View File

@@ -24,6 +24,7 @@ class BuyOutOfProvincePage extends GetView<BuyOutOfProvinceLogic> {
onSearchChanged: (data) => controller.setSearchValue(data), onSearchChanged: (data) => controller.setSearchValue(data),
filteringWidget: filterBottomSheet(), filteringWidget: filterBottomSheet(),
widgets: [ widgets: [
inventoryWidget(),
Expanded( Expanded(
child: ObxValue((data) { child: ObxValue((data) {
return RPaginatedListView( return RPaginatedListView(
@@ -554,4 +555,23 @@ class BuyOutOfProvincePage extends GetView<BuyOutOfProvinceLogic> {
), ),
); );
} }
Widget inventoryWidget() {
return Container(
width: Get.width,
height: 39,
margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: AppColor.greenLight,
borderRadius: BorderRadius.circular(8),
),
alignment: Alignment.center,
child: ObxValue((data) {
return Text(
' موجودی انبار: ${data.value?.totalRemainWeight?.toInt().separatedByComma ?? '0'} کیلوگرم',
style: AppFonts.yekan16.copyWith(color: AppColor.mediumGreyDarkHover),
);
}, controller.rootLogic.inventoryModel),
);
}
} }

View File

@@ -74,16 +74,27 @@ class SalesInProvinceLogic extends GetxController {
totalCost.value = callback * weight.value; totalCost.value = callback * weight.value;
}); });
totalCost.listen((data) { totalCost.listen((data) {
totalCostController.text = data.toString().separatedByComma; totalCostController.text = data
.toString()
.separatedByComma;
isValid.value = isValid.value =
weight.value > 0 && weight.value > 0 &&
pricePerKilo.value > 0 && pricePerKilo.value > 0 &&
totalCost.value > 0 && totalCost.value > 0 &&
selectedProductModel.value != null && selectedProductModel.value != null &&
selectedGuildModel.value != null; selectedGuildModel.value != null;
}); });
everAll([
totalCost,
weight,
pricePerKilo,
totalCost,
selectedProductModel,
selectedGuildModel
], (callback) => checkVerification(),);
scrollControllerAllocationsMade.addListener(() { scrollControllerAllocationsMade.addListener(() {
if (scrollControllerAllocationsMade.position.pixels >= if (scrollControllerAllocationsMade.position.pixels >=
@@ -95,7 +106,7 @@ class SalesInProvinceLogic extends GetxController {
debounce( debounce(
searchedValue, searchedValue,
(callback) => getAllocatedMade(), (callback) => getAllocatedMade(),
time: Duration(milliseconds: timeDebounce), time: Duration(milliseconds: timeDebounce),
); );
} }
@@ -114,7 +125,8 @@ class SalesInProvinceLogic extends GetxController {
} }
safeCall( safeCall(
call: () async => await rootLogic.chickenRepository.getAllocatedMade( call: () async =>
await rootLogic.chickenRepository.getAllocatedMade(
token: rootLogic.tokenService.accessToken.value!, token: rootLogic.tokenService.accessToken.value!,
queryParameters: buildQueryParams( queryParameters: buildQueryParams(
page: currentPage.value, page: currentPage.value,
@@ -154,15 +166,16 @@ class SalesInProvinceLogic extends GetxController {
void checkVerification() { void checkVerification() {
isValid.value = isValid.value =
weight.value > 0 && weight.value > 0 &&
pricePerKilo.value > 0 && pricePerKilo.value > 0 &&
totalCost.value > 0 && totalCost.value > 0 &&
selectedProductModel.value != null && selectedProductModel.value != null &&
selectedGuildModel.value != null; selectedGuildModel.value != null;
} }
void confirmAllocation(ConformAllocation allocation) { void confirmAllocation(ConformAllocation allocation) {
safeCall( safeCall(
call: () async => await rootLogic.chickenRepository.confirmAllocation( call: () async =>
await rootLogic.chickenRepository.confirmAllocation(
token: rootLogic.tokenService.accessToken.value!, token: rootLogic.tokenService.accessToken.value!,
allocation: allocation.toJson(), allocation: allocation.toJson(),
), ),
@@ -175,7 +188,8 @@ class SalesInProvinceLogic extends GetxController {
void denyAllocation(String token) { void denyAllocation(String token) {
safeCall( safeCall(
call: () async => await rootLogic.chickenRepository.denyAllocation( call: () async =>
await rootLogic.chickenRepository.denyAllocation(
token: rootLogic.tokenService.accessToken.value!, token: rootLogic.tokenService.accessToken.value!,
allocationToken: token, allocationToken: token,
), ),
@@ -188,7 +202,8 @@ class SalesInProvinceLogic extends GetxController {
Future<void> confirmAllAllocations() async { Future<void> confirmAllAllocations() async {
safeCall( safeCall(
call: () async => await rootLogic.chickenRepository.confirmAllAllocation( call: () async =>
await rootLogic.chickenRepository.confirmAllAllocation(
token: rootLogic.tokenService.accessToken.value!, token: rootLogic.tokenService.accessToken.value!,
allocationTokens: allocatedList.value.data?.results?.map((e) => e.key!).toList() ?? [], allocationTokens: allocatedList.value.data?.results?.map((e) => e.key!).toList() ?? [],
), ),
@@ -201,7 +216,8 @@ class SalesInProvinceLogic extends GetxController {
Future<void> getRolesProducts() async { Future<void> getRolesProducts() async {
safeCall( safeCall(
call: () async => await rootLogic.chickenRepository.getRolesProducts( call: () async =>
await rootLogic.chickenRepository.getRolesProducts(
token: rootLogic.tokenService.accessToken.value!, token: rootLogic.tokenService.accessToken.value!,
), ),
onSuccess: (result) { onSuccess: (result) {
@@ -216,7 +232,8 @@ class SalesInProvinceLogic extends GetxController {
Future<void> getGuilds() async { Future<void> getGuilds() async {
safeCall( safeCall(
call: () async => await rootLogic.chickenRepository.getGuilds( call: () async =>
await rootLogic.chickenRepository.getGuilds(
token: rootLogic.tokenService.accessToken.value!, token: rootLogic.tokenService.accessToken.value!,
queryParameters: buildQueryParams( queryParameters: buildQueryParams(
queryParams: {'free': saleType.value == 2 ? true : false}, queryParams: {'free': saleType.value == 2 ? true : false},
@@ -247,7 +264,8 @@ class SalesInProvinceLogic extends GetxController {
Future<void> getGuildProfile() async { Future<void> getGuildProfile() async {
await safeCall( await safeCall(
call: () async => await rootLogic.chickenRepository.getProfile( call: () async =>
await rootLogic.chickenRepository.getProfile(
token: rootLogic.tokenService.accessToken.value!, token: rootLogic.tokenService.accessToken.value!,
), ),
onError: (error, stackTrace) {}, onError: (error, stackTrace) {},
@@ -261,7 +279,8 @@ class SalesInProvinceLogic extends GetxController {
tmpStewardAllocation = SubmitStewardAllocation( tmpStewardAllocation = SubmitStewardAllocation(
approvedPriceStatus: false, approvedPriceStatus: false,
allocationType: allocationType:
'${guildProfile.value?.steward == true ? "steward" : "guild"}_${selectedGuildModel.value?.steward == true ? "steward" : "guild"}', '${guildProfile.value?.steward == true ? "steward" : "guild"}_${selectedGuildModel.value
?.steward == true ? "steward" : "guild"}',
sellerType: guildProfile.value?.steward == true ? "Steward" : "Guild", sellerType: guildProfile.value?.steward == true ? "Steward" : "Guild",
buyerType: selectedGuildModel.value?.steward == true ? "Steward" : "Guild", buyerType: selectedGuildModel.value?.steward == true ? "Steward" : "Guild",
amount: pricePerKilo.value, amount: pricePerKilo.value,
@@ -271,14 +290,17 @@ class SalesInProvinceLogic extends GetxController {
numberOfCarcasses: 0, numberOfCarcasses: 0,
guildKey: selectedGuildModel.value?.key, guildKey: selectedGuildModel.value?.key,
productKey: selectedProductModel.value?.key, productKey: selectedProductModel.value?.key,
date: DateTime.now().formattedDashedGregorian, date: DateTime
.now()
.formattedDashedGregorian,
type: "manual", type: "manual",
); );
} }
Future<void> submitAllocation() async { Future<void> submitAllocation() async {
safeCall( safeCall(
call: () async => await rootLogic.chickenRepository.postSubmitStewardAllocation( call: () async =>
await rootLogic.chickenRepository.postSubmitStewardAllocation(
token: rootLogic.tokenService.accessToken.value!, token: rootLogic.tokenService.accessToken.value!,
request: tmpStewardAllocation!, request: tmpStewardAllocation!,
), ),
@@ -292,7 +314,8 @@ class SalesInProvinceLogic extends GetxController {
Future<void> deleteAllocation(AllocatedMadeModel model) async { Future<void> deleteAllocation(AllocatedMadeModel model) async {
safeCall( safeCall(
call: () async => await rootLogic.chickenRepository.deleteStewardAllocation( call: () async =>
await rootLogic.chickenRepository.deleteStewardAllocation(
token: rootLogic.tokenService.accessToken.value!, token: rootLogic.tokenService.accessToken.value!,
queryParameters: {'steward_allocation_key': model.key}, queryParameters: {'steward_allocation_key': model.key},
), ),
@@ -318,9 +341,15 @@ class SalesInProvinceLogic extends GetxController {
weight.value = item.weightOfCarcasses ?? 0; weight.value = item.weightOfCarcasses ?? 0;
pricePerKilo.value = item.amount ?? 0; pricePerKilo.value = item.amount ?? 0;
totalCost.value = item.totalAmount ?? 0; totalCost.value = item.totalAmount ?? 0;
weightController.text = weight.value.toString().separatedByComma; weightController.text = weight.value
pricePerKiloController.text = pricePerKilo.value.toString().separatedByComma; .toString()
totalCostController.text = totalCost.value.toString().separatedByComma; .separatedByComma;
pricePerKiloController.text = pricePerKilo.value
.toString()
.separatedByComma;
totalCostController.text = totalCost.value
.toString()
.separatedByComma;
isValid.value = true; isValid.value = true;
} }
@@ -345,7 +374,8 @@ class SalesInProvinceLogic extends GetxController {
); );
safeCall( safeCall(
call: () async => await rootLogic.chickenRepository.updateStewardAllocation( call: () async =>
await rootLogic.chickenRepository.updateStewardAllocation(
token: rootLogic.tokenService.accessToken.value!, token: rootLogic.tokenService.accessToken.value!,
request: updatedAllocationModel, request: updatedAllocationModel,
), ),

View File

@@ -3,6 +3,7 @@ import 'package:flutter/services.dart';
import 'package:rasadyar_chicken/data/models/response/allocated_made/allocated_made.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/guild/guild_model.dart';
import 'package:rasadyar_chicken/data/models/response/roles_products/roles_products.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/utils/string_utils.dart';
import 'package:rasadyar_chicken/presentation/widget/base_page/view.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_item/list_item.dart';
@@ -19,10 +20,7 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
body: BasePage( body: BasePage(
routesWidget: ObxValue( routesWidget: ObxValue((route) => buildPageRoute(route), controller.routesName),
(route) => buildPageRoute(route),
controller.routesName,
),
onBackPressed: () => Get.back(id: 1), onBackPressed: () => Get.back(id: 1),
onSearchChanged: (data) => controller.setSearchValue(data), onSearchChanged: (data) => controller.setSearchValue(data),
filteringWidget: filterBottomSheet(), filteringWidget: filterBottomSheet(),
@@ -89,10 +87,7 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
await controller.confirmAllAllocations(); await controller.confirmAllAllocations();
}, },
message: 'تایید یکجا', message: 'تایید یکجا',
icon: Assets.vec.clipboardTaskSvg.svg( icon: Assets.vec.clipboardTaskSvg.svg(width: 40.w, height: 40.h),
width: 40.w,
height: 40.h,
),
backgroundColor: controller.bgConfirmAllColor.value, backgroundColor: controller.bgConfirmAllColor.value,
), ),
); );
@@ -109,10 +104,7 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
width: Get.width, width: Get.width,
height: 39, height: 39,
margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4), margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration( decoration: BoxDecoration(color: AppColor.greenLight, borderRadius: BorderRadius.circular(8)),
color: AppColor.greenLight,
borderRadius: BorderRadius.circular(8),
),
alignment: Alignment.center, alignment: Alignment.center,
child: ObxValue((data) { child: ObxValue((data) {
return Text( return Text(
@@ -165,18 +157,13 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
child: Assets.vec.hotChickenSvg.svg( child: Assets.vec.hotChickenSvg.svg(
width: 24, width: 24,
height: 24, height: 24,
colorFilter: ColorFilter.mode( colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
AppColor.blueNormal,
BlendMode.srcIn,
),
), ),
), ),
Text( Text(
'${item.weightOfCarcasses?.separatedByComma}kg', '${item.weightOfCarcasses?.separatedByComma}kg',
textAlign: TextAlign.left, textAlign: TextAlign.left,
style: AppFonts.yekan12.copyWith( style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
color: AppColor.blueNormal,
),
), ),
], ],
), ),
@@ -207,10 +194,7 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
itemListExpandedWidget(AllocatedMadeModel item, int index) { itemListExpandedWidget(AllocatedMadeModel item, int index) {
return Container( return Container(
padding: EdgeInsets.all(8), padding: EdgeInsets.all(8),
decoration: BoxDecoration( decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8)),
color: Colors.white,
borderRadius: BorderRadius.circular(8),
),
child: Column( child: Column(
spacing: 8, spacing: 8,
children: [ children: [
@@ -250,16 +234,12 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
children: [ children: [
Text( Text(
item.date?.toJalali.formatter.wN ?? 'N/A', item.date?.toJalali.formatter.wN ?? 'N/A',
style: AppFonts.yekan14.copyWith( style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
color: AppColor.textColor,
),
), ),
Text( Text(
'${item.date?.toJalali.formatter.d} ${item.date?.toJalali.formatter.mN ?? 'N/A'}', '${item.date?.toJalali.formatter.d} ${item.date?.toJalali.formatter.mN ?? 'N/A'}',
style: AppFonts.yekan14.copyWith( style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
color: AppColor.blueNormal,
),
), ),
], ],
), ),
@@ -279,8 +259,7 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
buildRow( buildRow(
title: 'نام و نام خانوادگی فروشنده', title: 'نام و نام خانوادگی فروشنده',
value: value: controller.getBuyerInformation(item)?.user?.fullname ?? 'N/A',
controller.getBuyerInformation(item)?.user?.fullname ?? 'N/A',
), ),
buildRow( buildRow(
@@ -298,20 +277,12 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
title: 'افت وزن(کیلوگرم)', title: 'افت وزن(کیلوگرم)',
value: item.weightLossOfCarcasses?.toInt().toString() ?? 'N/A', value: item.weightLossOfCarcasses?.toInt().toString() ?? 'N/A',
), ),
buildRow( buildRow(title: 'قیمت کل', value: '${item.totalAmount?.separatedByComma} ریال'),
title: 'قیمت کل',
value: '${item.totalAmount?.separatedByComma} ریال',
),
buildRow( buildRow(title: 'کداحراز', value: item.registrationCode?.toString() ?? 'ندارد'),
title: 'کداحراز',
value: item.registrationCode?.toString() ?? 'ندارد',
),
buildRow( buildRow(
title: 'وضعیت کد احراز', title: 'وضعیت کد احراز',
value: item.systemRegistrationCode == true value: item.systemRegistrationCode == true ? "ارسال شده" : "ارسال نشده",
? "ارسال شده"
: "ارسال نشده",
), ),
Row( Row(
@@ -360,45 +331,36 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
Widget addOrEditBottomSheet([bool isEditMode = false]) { Widget addOrEditBottomSheet([bool isEditMode = false]) {
return BaseBottomSheet( return BaseBottomSheet(
height: Get.height * (isEditMode ? 0.45 : 0.75), height: Get.height * (isEditMode ? 0.45 : 0.75),
child: Padding( child: Form(
padding: EdgeInsets.only( key: controller.formKey,
left: 16, child: Column(
right: 16, mainAxisSize: MainAxisSize.min,
top: 16, children: [
bottom: MediaQuery.of(Get.context!).viewInsets.bottom + 16, Text(
), '${isEditMode ? 'ویرایش' : 'ثبت'} توزیع/ فروش',
child: Form( style: AppFonts.yekan16Bold.copyWith(color: AppColor.textColor),
key: controller.formKey, ),
child: Column( const SizedBox(height: 12),
mainAxisSize: MainAxisSize.min, productDropDown(),
children: [ const SizedBox(height: 12),
Text( Visibility(
'${isEditMode ? 'ویرایش' : 'ثبت'} توزیع/ فروش', visible: isEditMode == false,
style: AppFonts.yekan16Bold.copyWith( child: Container(
color: AppColor.blueNormal, padding: EdgeInsets.all(8),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
border: Border.all(color: AppColor.darkGreyLight, width: 1),
), ),
),
Visibility(
visible: isEditMode == false,
child: Column( child: Column(
children: [ children: [
const SizedBox(height: 12), const SizedBox(height: 8),
RTextField(
controller: TextEditingController(),
label: 'تاریخ',
enabled: false,
initText: Jalali.now().formatCompactDate(),
),
const SizedBox(height: 12),
Material(
type: MaterialType.transparency,
child: productDropDown(),
),
const SizedBox(height: 12),
SizedBox( SizedBox(
height: 40, height: 40,
child: ObxValue((data) { child: ObxValue((data) {
return Row( return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Radio( Radio(
value: 1, value: 1,
@@ -430,99 +392,129 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
], ],
), ),
), ),
const SizedBox(height: 12), ),
RTextField( const SizedBox(height: 12),
controller: controller.weightController, Container(
keyboardType: TextInputType.number, padding: EdgeInsets.all(8),
borderColor: AppColor.darkGreyLight, decoration: BoxDecoration(
inputFormatters: [ color: Colors.white,
FilteringTextInputFormatter.digitsOnly, borderRadius: BorderRadius.circular(8),
SeparatorInputFormatter(), border: Border.all(color: AppColor.darkGreyLight, width: 1),
],
validator: (value) {
if (int.parse(value!.clearComma) >
(controller
.rootLogic
.inventoryModel
.value
?.totalRemainWeight
?.toInt() ??
100)) {
return 'وزن تخصیصی بیشتر از موجودی انبار است';
}
return null;
},
onChanged: (p0) {
controller.weight.value = int.tryParse(p0.clearComma) ?? 0;
},
label: 'وزن لاشه',
), ),
const SizedBox(height: 12), child: Column(
RTextField( spacing: 12,
controller: controller.pricePerKiloController, children: [
borderColor: AppColor.darkGreyLight, Visibility(
inputFormatters: [ visible: isEditMode == false,
FilteringTextInputFormatter.digitsOnly, child: Column(
SeparatorInputFormatter(), 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 ?? Jalali.now()).formatCompactDate(),
);
}, controller.fromDateFilter),
],
),
),
onChanged: (p0) { RTextField(
controller.pricePerKilo.value = controller: controller.weightController,
int.tryParse(p0.clearComma) ?? 0; keyboardType: TextInputType.number,
}, borderColor: AppColor.darkGreyLight,
keyboardType: TextInputType.number, filledColor: AppColor.bgLight,
label: 'قیمت هر کیلو', filled: true,
), inputFormatters: [
const SizedBox(height: 12), FilteringTextInputFormatter.digitsOnly,
RTextField( SeparatorInputFormatter(),
enabled: false, ],
keyboardType: TextInputType.number, validator: (value) {
inputFormatters: [ if (int.parse(value!.clearComma) >
FilteringTextInputFormatter.digitsOnly, (controller.rootLogic.inventoryModel.value?.totalRemainWeight?.toInt() ??
SeparatorInputFormatter(), 100)) {
], return 'وزن تخصیصی بیشتر از موجودی انبار است';
borderColor: AppColor.darkGreyLight, }
controller: controller.totalCostController, return null;
label: 'هزینه کل', },
), onChanged: (p0) {
const SizedBox(height: 20), controller.weight.value = int.tryParse(p0.clearComma) ?? 0;
ObxValue((data) { },
return RElevated( label: 'وزن لاشه',
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
? await controller.updateAllocation()
: () {
iLog("s1");
if (controller.formKey.currentState?.validate() ?? false) {
iLog("s2");
controller.setSubmitData();
iLog("s3");
Get.bottomSheet(show2StepAddBottomSheet());
}
};
controller.clearForm(); RTextField(
controller.getAllocatedMade(); controller: controller.pricePerKiloController,
Get.back();*/ borderColor: AppColor.darkGreyLight,
} inputFormatters: [
: null, FilteringTextInputFormatter.digitsOnly,
); SeparatorInputFormatter(),
}, controller.isValid), ],
const SizedBox(height: 20), filledColor: AppColor.bgLight,
], filled: true,
), onChanged: (p0) {
controller.pricePerKilo.value = int.tryParse(p0.clearComma) ?? 0;
},
keyboardType: TextInputType.number,
label: 'قیمت هر کیلو',
),
RTextField(
variant: RTextFieldVariant.noBorder,
enabled: false,
keyboardType: TextInputType.number,
filledColor: AppColor.bgLight,
filled: true,
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
SeparatorInputFormatter(),
],
controller: controller.totalCostController,
label: 'هزینه کل',
),
ObxValue((data) {
return RElevated(
text: isEditMode ? 'ویرایش' : 'ثبت',
isFullWidth: true,
textStyle: AppFonts.yekan16.copyWith(color: Colors.white),
backgroundColor: AppColor.greenNormal,
height: 40,
onPressed: data.value
? () async {
if (isEditMode) {
await controller.updateAllocation();
controller.clearForm();
controller.getAllocatedMade();
controller.rootLogic.getInventory();
Get.back();
} else {
if (controller.formKey.currentState?.validate() ?? false) {
controller.setSubmitData();
await Get.bottomSheet(show2StepAddBottomSheet());
}
}
}
: null,
);
}, controller.isValid),
],
),
),
const SizedBox(height: 20),
],
), ),
), ),
); );
@@ -556,12 +548,28 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
return Obx(() { return Obx(() {
return OverlayDropdownWidget<ProductModel>( return OverlayDropdownWidget<ProductModel>(
items: controller.rolesProductsModel, items: controller.rolesProductsModel,
height: 56,
hasDropIcon: false,
background: Colors.white,
onChanged: (value) { onChanged: (value) {
controller.selectedProductModel.value = value; controller.selectedProductModel.value = value;
}, },
selectedItem: controller.selectedProductModel.value, selectedItem: controller.selectedProductModel.value,
itemBuilder: (item) => Text(item.name ?? 'بدون نام'), itemBuilder: (item) => Text(item.name ?? 'بدون نام'),
labelBuilder: (item) => Text(item?.name ?? 'انتخاب محصول'), labelBuilder: (item) => Row(
spacing: 8,
children: [
(item?.name?.contains('مرغ گرم') ?? false)
? Assets.images.chicken.image(width: 40, height: 40)
: Assets.vec.placeHolderSvg.svg(width: 40, height: 40),
Text(item?.name ?? 'انتخاب محصول'),
Spacer(),
Text(
'موجودی:${controller.rootLogic.inventoryModel.value?.totalRemainWeight.separatedByComma ?? 0}',
),
],
),
); );
}); });
} }
@@ -572,20 +580,14 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
child: Column( child: Column(
spacing: 16, spacing: 16,
children: [ children: [
Text( Text('فیلترها', style: AppFonts.yekan16Bold.copyWith(color: AppColor.darkGreyDarkHover)),
'فیلترها',
style: AppFonts.yekan16Bold.copyWith(
color: AppColor.darkGreyDarkHover,
),
),
Row( Row(
spacing: 8, spacing: 8,
children: [ children: [
Expanded( Expanded(
child: timeFilterWidget( child: timeFilterWidget(
date: controller.fromDateFilter, date: controller.fromDateFilter,
onChanged: (jalali) => onChanged: (jalali) => controller.fromDateFilter.value = jalali,
controller.fromDateFilter.value = jalali,
), ),
), ),
Expanded( Expanded(
@@ -634,10 +636,7 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
Assets.vec.calendarSvg.svg( Assets.vec.calendarSvg.svg(
width: 24, width: 24,
height: 24, height: 24,
colorFilter: const ColorFilter.mode( colorFilter: const ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
AppColor.blueNormal,
BlendMode.srcIn,
),
), ),
Text( Text(
isFrom ? 'از' : 'تا', isFrom ? 'از' : 'تا',
@@ -646,12 +645,9 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
Expanded( Expanded(
child: ObxValue((data) { child: ObxValue((data) {
return Text( return Text(
date.value?.formatCompactDate() ?? date.value?.formatCompactDate() ?? Jalali.now().formatCompactDate(),
Jalali.now().formatCompactDate(),
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: AppFonts.yekan16.copyWith( style: AppFonts.yekan16.copyWith(color: AppColor.lightGreyNormalActive),
color: AppColor.lightGreyNormalActive,
),
); );
}, date), }, date),
), ),
@@ -716,33 +712,48 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
); );
} }
/* Widget show2StepAddBottomSheet() { Widget show2StepAddBottomSheet() {
return BaseBottomSheet( return BaseBottomSheet(
height: Get.height*.35, height: Get.height * .35,
child: Column( child: Column(
spacing: 8, spacing: 8,
children: [ children: [
buildRow('تاریخ ثبت', controller.tmpStewardAllocation?.date?.formattedJalaliDate ?? 'N/A'),
buildRow( buildRow(
'نام و نام خانوادگی خریدار', title: 'تاریخ ثبت',
controller.guildsModel value: controller.tmpStewardAllocation?.date?.formattedJalaliDate ?? 'N/A',
),
buildRow(
title: 'نام و نام خانوادگی خریدار',
value:
controller.guildsModel
.firstWhere((p0) => p0.key == controller.tmpStewardAllocation?.guildKey) .firstWhere((p0) => p0.key == controller.tmpStewardAllocation?.guildKey)
.user .user
?.fullname ?? ?.fullname ??
'N/A', 'N/A',
), ),
buildRow( buildRow(
'شماره خریدار', title: 'شماره خریدار',
controller.guildsModel.firstWhere((p0) => p0.key == controller.tmpStewardAllocation?.guildKey).user?.mobile ?? value:
controller.guildsModel
.firstWhere((p0) => p0.key == controller.tmpStewardAllocation?.guildKey)
.user
?.mobile ??
'N/A', 'N/A',
), ),
buildRow('قیمت هر کیلو', '${controller.tmpStewardAllocation?.amount.separatedByComma ?? 0} ریال '),
buildRow( buildRow(
'وزن تخصیصی', title: 'قیمت هر کیلو',
'${controller.tmpStewardAllocation?.weightOfCarcasses?.toInt().separatedByComma ?? 0} کیلوگرم', value: '${controller.tmpStewardAllocation?.amount.separatedByComma ?? 0} ریال ',
),
buildRow(
title: 'وزن تخصیصی',
value:
'${controller.tmpStewardAllocation?.weightOfCarcasses?.toInt().separatedByComma ?? 0} کیلوگرم',
),
buildRow(
title: 'قیمت کل',
value: '${controller.tmpStewardAllocation?.totalAmount.separatedByComma ?? 0} ریال',
), ),
buildRow('قیمت کل', '${controller.tmpStewardAllocation?.totalAmount.separatedByComma ?? 0} ریال'),
Row( Row(
spacing: 10, spacing: 10,
@@ -754,8 +765,10 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
text: 'ثبت', text: 'ثبت',
textStyle: AppFonts.yekan18.copyWith(color: Colors.white), textStyle: AppFonts.yekan18.copyWith(color: Colors.white),
onPressed: () async { onPressed: () async {
await controller.submitAllocation(); await controller.submitAllocation();
Get..back()..back(); Get
..back()
..back();
}, },
), ),
), ),
@@ -775,5 +788,5 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
], ],
), ),
); );
}*/ }
} }

View File

@@ -21,6 +21,7 @@ class SalesOutOfProvincePage extends GetView<SalesOutOfProvinceLogic> {
onSearchChanged: (data) => controller.setSearchValue(data), onSearchChanged: (data) => controller.setSearchValue(data),
filteringWidget: filterBottomSheet(), filteringWidget: filterBottomSheet(),
widgets: [ widgets: [
inventoryWidget(),
segmentWidget(), segmentWidget(),
Expanded( Expanded(
child: ObxValue((index) { child: ObxValue((index) {
@@ -100,4 +101,23 @@ class SalesOutOfProvincePage extends GetView<SalesOutOfProvinceLogic> {
), ),
); );
} }
Widget inventoryWidget() {
return Container(
width: Get.width,
height: 39,
margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: AppColor.greenLight,
borderRadius: BorderRadius.circular(8),
),
alignment: Alignment.center,
child: ObxValue((data) {
return Text(
' موجودی انبار: ${data.value?.totalRemainWeight?.toInt().separatedByComma ?? '0'} کیلوگرم',
style: AppFonts.yekan16.copyWith(color: AppColor.mediumGreyDarkHover),
);
}, controller.rootLogic.inventoryModel),
);
}
} }

View File

@@ -1,5 +1,4 @@
import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:rasadyar_chicken/data/models/response/out_province_carcasses_buyer/out_province_carcasses_buyer.dart';
part 'pagination_model.freezed.dart'; part 'pagination_model.freezed.dart';
part 'pagination_model.g.dart'; part 'pagination_model.g.dart';

View File

@@ -13,7 +13,7 @@ class BaseBottomSheet extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Container(
height: height ?? MediaQuery.of(context).size.height * 0.85, height: height ?? MediaQuery.of(context).size.height * 0.85,
padding: EdgeInsets.symmetric(vertical: 15, horizontal: 20), padding: EdgeInsets.symmetric(vertical: 15, horizontal: 10),
decoration: BoxDecoration( decoration: BoxDecoration(
color: bgColor ?? Colors.white, color: bgColor ?? Colors.white,
borderRadius: BorderRadius.only( borderRadius: BorderRadius.only(

View File

@@ -34,6 +34,7 @@ class RTextField extends StatefulWidget {
final FormFieldValidator<String>? validator; final FormFieldValidator<String>? validator;
final void Function(String)? onChanged; final void Function(String)? onChanged;
final void Function(String)? onSubmitted; final void Function(String)? onSubmitted;
final VoidCallback? onTap;
final List<TextInputFormatter>? inputFormatters; final List<TextInputFormatter>? inputFormatters;
final Widget? suffix; final Widget? suffix;
@@ -68,6 +69,7 @@ class RTextField extends StatefulWidget {
this.onSubmitted, this.onSubmitted,
this.borderColor, this.borderColor,
this.inputFormatters, this.inputFormatters,
this.onTap,
this.suffix, this.suffix,
}); });
@@ -80,12 +82,12 @@ class RTextField extends StatefulWidget {
bool get _passwordNoBorder => variant == RTextFieldVariant.passwordNoBorder; bool get _passwordNoBorder => variant == RTextFieldVariant.passwordNoBorder;
InputBorder get _inputBorder => _noBorder || _passwordNoBorder InputBorder get _inputBorder => OutlineInputBorder(
? InputBorder.none borderRadius: BorderRadius.circular(8),
: OutlineInputBorder( borderSide: _noBorder || _passwordNoBorder
borderRadius: BorderRadius.circular(8), ? BorderSide.none
borderSide: BorderSide(color: borderColor ?? AppColor.lightGreyDarkActive, width: 1), : BorderSide(color: borderColor ?? AppColor.darkGreyLight, width: 1),
); );
} }
class _RTextFieldState extends State<RTextField> { class _RTextFieldState extends State<RTextField> {
@@ -142,6 +144,7 @@ class _RTextFieldState extends State<RTextField> {
inputFormatters: widget.inputFormatters, inputFormatters: widget.inputFormatters,
enabled: widget.enabled, enabled: widget.enabled,
obscureText: obscure, obscureText: obscure,
onTap: widget.onTap,
onTapOutside: (_) => FocusScope.of(context).unfocus(), onTapOutside: (_) => FocusScope.of(context).unfocus(),
onFieldSubmitted: widget.onSubmitted, onFieldSubmitted: widget.onSubmitted,
maxLength: widget.maxLength, maxLength: widget.maxLength,

View File

@@ -7,6 +7,9 @@ class OverlayDropdownWidget<T> extends StatefulWidget {
final List<T> items; final List<T> items;
final T? selectedItem; final T? selectedItem;
final T? initialValue; final T? initialValue;
final int? height;
final Color? background;
final bool? hasDropIcon;
final Widget Function(T item) itemBuilder; final Widget Function(T item) itemBuilder;
final Widget Function(T? selected) labelBuilder; final Widget Function(T? selected) labelBuilder;
final void Function(T selected)? onChanged; final void Function(T selected)? onChanged;
@@ -21,6 +24,9 @@ class OverlayDropdownWidget<T> extends StatefulWidget {
this.onChanged, this.onChanged,
this.selectedItem, this.selectedItem,
this.contentPadding, this.contentPadding,
this.height,
this.background,
this.hasDropIcon = true,
}); });
@override @override
@@ -58,7 +64,6 @@ class _OverlayDropdownState<T> extends State<OverlayDropdownWidget<T>> {
elevation: 4, elevation: 4,
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
child: Container( child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: AppColor.bgLight, color: AppColor.bgLight,
border: Border.all(color: AppColor.darkGreyLight), border: Border.all(color: AppColor.darkGreyLight),
@@ -81,7 +86,9 @@ class _OverlayDropdownState<T> extends State<OverlayDropdownWidget<T>> {
_removeOverlay(); _removeOverlay();
}, },
child: Padding( child: Padding(
padding: widget.contentPadding ?? const EdgeInsets.symmetric(horizontal: 8, vertical: 4), padding:
widget.contentPadding ??
const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
child: widget.itemBuilder(item), child: widget.itemBuilder(item),
), ),
); );
@@ -120,19 +127,25 @@ class _OverlayDropdownState<T> extends State<OverlayDropdownWidget<T>> {
_isOpen.value ? _removeOverlay() : _showOverlay(); _isOpen.value ? _removeOverlay() : _showOverlay();
}, },
child: Container( child: Container(
height: 40, height: widget.height?.toDouble() ?? 40,
width: Get.width, width: Get.width,
padding: const EdgeInsets.symmetric(horizontal: 12), padding: const EdgeInsets.symmetric(horizontal: 12),
decoration: BoxDecoration( decoration: BoxDecoration(
color: AppColor.bgLight, color: widget.background ?? AppColor.bgLight,
border: Border.all(color: AppColor.darkGreyLight), border: Border.all(color: AppColor.darkGreyLight),
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
), ),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
widget.labelBuilder(selectedItem), Expanded(child: widget.labelBuilder(selectedItem)),
Icon(_isOpen.value ? CupertinoIcons.chevron_up : CupertinoIcons.chevron_down, size: 14), Visibility(
visible: widget.hasDropIcon!,
child: Icon(
_isOpen.value ? CupertinoIcons.chevron_up : CupertinoIcons.chevron_down,
size: 14,
),
),
], ],
), ),
), ),
@@ -140,7 +153,6 @@ class _OverlayDropdownState<T> extends State<OverlayDropdownWidget<T>> {
} }
} }
class OverlayDropdownWidget2<T> extends StatefulWidget { class OverlayDropdownWidget2<T> extends StatefulWidget {
final List<T> items; final List<T> items;
final T? selectedItem; final T? selectedItem;
@@ -208,65 +220,73 @@ class _OverlayDropdownState2<T> extends State<OverlayDropdownWidget2<T>> {
child: Material( child: Material(
elevation: 4, elevation: 4,
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
child: Obx(() => Container( child: Obx(
decoration: BoxDecoration( () => Container(
color: AppColor.bgLight, decoration: BoxDecoration(
border: Border.all(color: AppColor.darkGreyLight), color: AppColor.bgLight,
borderRadius: BorderRadius.circular(8), border: Border.all(color: AppColor.darkGreyLight),
), borderRadius: BorderRadius.circular(8),
constraints: BoxConstraints(maxHeight: 300), ),
child: Column( constraints: BoxConstraints(maxHeight: 300),
children: [ child: Column(
Padding( children: [
padding: const EdgeInsets.all(8), Padding(
child: TextField( padding: const EdgeInsets.all(8),
controller: _searchController, child: TextField(
decoration: const InputDecoration( controller: _searchController,
hintText: 'جستجو...', decoration: const InputDecoration(
isDense: true, hintText: 'جستجو...',
contentPadding: EdgeInsets.symmetric(horizontal: 12, vertical: 8), isDense: true,
border: OutlineInputBorder(), contentPadding: EdgeInsets.symmetric(horizontal: 12, vertical: 8),
), border: OutlineInputBorder(),
onChanged: (query) { ),
_filteredItems.value = widget.items onChanged: (query) {
.where((item) => _filteredItems.value = widget.items
widget.itemToString?.call(item).toLowerCase().contains(query.toLowerCase()) ?? .where(
false) (item) =>
.toList(); widget.itemToString
}, ?.call(item)
), .toLowerCase()
), .contains(query.toLowerCase()) ??
if (_filteredItems.isEmpty) false,
const Padding( )
padding: EdgeInsets.all(16.0), .toList();
child: Text("نتیجه‌ای یافت نشد."), },
),
if (_filteredItems.isNotEmpty)
Expanded(
child: ListView(
shrinkWrap: true,
physics: const BouncingScrollPhysics(),
children: _filteredItems.map((item) {
return InkWell(
onTap: () {
widget.onChanged?.call(item);
setState(() {
selectedItem = item;
});
_removeOverlay();
},
child: Padding(
padding: widget.contentPadding ??
const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
child: widget.itemBuilder(item),
),
);
}).toList(),
), ),
), ),
], if (_filteredItems.isEmpty)
const Padding(
padding: EdgeInsets.all(16.0),
child: Text("نتیجه‌ای یافت نشد."),
),
if (_filteredItems.isNotEmpty)
Expanded(
child: ListView(
shrinkWrap: true,
physics: const BouncingScrollPhysics(),
children: _filteredItems.map((item) {
return InkWell(
onTap: () {
widget.onChanged?.call(item);
setState(() {
selectedItem = item;
});
_removeOverlay();
},
child: Padding(
padding:
widget.contentPadding ??
const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
child: widget.itemBuilder(item),
),
);
}).toList(),
),
),
],
),
), ),
)), ),
), ),
), ),
], ],
@@ -309,13 +329,18 @@ class _OverlayDropdownState2<T> extends State<OverlayDropdownWidget2<T>> {
border: Border.all(color: AppColor.darkGreyLight), border: Border.all(color: AppColor.darkGreyLight),
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
), ),
child: Obx(() => Row( child: Obx(
mainAxisAlignment: MainAxisAlignment.spaceBetween, () => Row(
children: [ mainAxisAlignment: MainAxisAlignment.spaceBetween,
widget.labelBuilder(selectedItem), children: [
Icon(_isOpen.value ? CupertinoIcons.chevron_up : CupertinoIcons.chevron_down, size: 14), Expanded(child: widget.labelBuilder(selectedItem)),
], Icon(
)), _isOpen.value ? CupertinoIcons.chevron_up : CupertinoIcons.chevron_down,
size: 14,
),
],
),
),
), ),
), ),
); );