feat : search and filter in buyer out of the province

This commit is contained in:
MrM
2025-06-24 16:59:23 +03:30
parent d4f1e86295
commit 701e8e0fbe
16 changed files with 2217 additions and 100 deletions

View File

@@ -468,8 +468,6 @@ class BuysOutOfProvincePage extends GetView<BuysOutOfProvinceLogic> {
}
Widget _productTypeWidget() {
tLog(controller.outOfTheProvinceLogic.rolesProductsModel);
iLog(controller.selectedProduct.value);
return Obx(() {
return OverlayDropdownWidget<ProductModel>(
items: controller.outOfTheProvinceLogic.rolesProductsModel,

View File

@@ -1,9 +1,11 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:rasadyar_auth/data/utils/safe_call.dart';
import 'package:rasadyar_chicken/data/models/request/steward_free_sale_bar/steward_free_sale_bar_request.dart';
import 'package:rasadyar_chicken/data/models/response/iran_province_city/iran_province_city_model.dart';
import 'package:rasadyar_chicken/data/models/response/out_province_carcasses_buyer/out_province_carcasses_buyer.dart';
import 'package:rasadyar_chicken/data/models/response/roles_products/roles_products.dart';
import 'package:rasadyar_chicken/data/models/response/steward_free_sale_bar/steward_free_sale_bar.dart';
import 'package:rasadyar_chicken/presentation/pages/out_of_province/logic.dart';
import 'package:rasadyar_chicken/presentation/pages/root/logic.dart';
import 'package:rasadyar_core/core.dart';
@@ -12,16 +14,21 @@ class SalesOutOfProvinceLogic extends GetxController {
RxInt currentIndex = 0.obs;
RxBool isExpanded = false.obs;
RxBool isSubmitButtonEnabled = false.obs;
RxBool isBuyerSubmitButtonEnabled = false.obs;
RxBool isSaleSubmitButtonEnabled = false.obs;
RxList<int> isExpandedList = <int>[].obs;
RxBool searchIsSelected = false.obs;
//TODO add this to Di
ImagePicker imagePicker = ImagePicker();
Rx<Resource<List<OutProvinceCarcassesBuyer>>> buyerList = Resource<List<OutProvinceCarcassesBuyer>>.loading().obs;
Rx<Resource<List<OutProvinceCarcassesBuyer>>> buyerList =
Resource<List<OutProvinceCarcassesBuyer>>.loading().obs;
Rx<Resource<List<StewardFreeSaleBar>>> salesList =
Resource<List<StewardFreeSaleBar>>.loading().obs;
Rxn<ProductModel> selectedProduct = Rxn();
Rxn<OutProvinceCarcassesBuyer> selectedBuyer = Rxn();
RxList<IranProvinceCityModel> cites = <IranProvinceCityModel>[].obs;
Rxn<IranProvinceCityModel> selectedProvince = Rxn();
@@ -29,7 +36,8 @@ class SalesOutOfProvinceLogic extends GetxController {
RootLogic get rootLogic => Get.find<RootLogic>();
OutOfProvinceLogic get outOfTheProvinceLogic => Get.find<OutOfProvinceLogic>();
OutOfProvinceLogic get outOfTheProvinceLogic =>
Get.find<OutOfProvinceLogic>();
GlobalKey<FormState> formKey = GlobalKey<FormState>();
TextEditingController buyerNameController = TextEditingController();
@@ -37,21 +45,39 @@ class SalesOutOfProvinceLogic extends GetxController {
TextEditingController buyerPhoneController = TextEditingController();
TextEditingController buyerUnitNameController = TextEditingController();
Rx<Jalali> fromDateFilter = Jalali.now().obs;
Rx<Jalali> toDateFilter = Jalali.now().obs;
//Sale
TextEditingController quarantineCodeController = TextEditingController();
TextEditingController saleWeightController = TextEditingController();
Rx<Jalali> saleDate = Jalali
.now()
.obs;
String? key;
Rx<Jalali> fromDateFilter = Jalali
.now()
.obs;
Rx<Jalali> toDateFilter = Jalali
.now()
.obs;
RxnString searchedValue = RxnString();
@override
void onReady() {
super.onReady();
getOutProvinceCarcassesBuyer();
getOutProvinceSales();
selectedProvince.listen((p0) => getCites());
tLog(selectedProduct.value);
outOfTheProvinceLogic.rolesProductsModel.listen((lists) {
selectedProduct.value = lists.first;
});
setupListeners();
debounce(searchedValue, (callback) => getOutProvinceCarcassesBuyer(), time: Duration(milliseconds: 2000));
debounce(
searchedValue,
(callback) => getOutProvinceCarcassesBuyer(),
time: Duration(milliseconds: 2000),
);
ever(searchIsSelected, (data) {
if (data == false) {
searchedValue.value = null;
@@ -74,22 +100,53 @@ class SalesOutOfProvinceLogic extends GetxController {
Future<void> getOutProvinceCarcassesBuyer() async {
await safeCall(
call: () => rootLogic.chickenRepository.getOutProvinceCarcassesBuyer(
token: rootLogic.tokenService.accessToken.value!,
queryParameters: buildQueryParams(
pageSize: 10,
page: 1,
state: 'buyer-list',
search: 'filter',
role: 'Steward',
value: searchedValue.value ?? '',
),
),
call: () =>
rootLogic.chickenRepository.getOutProvinceCarcassesBuyer(
token: rootLogic.tokenService.accessToken.value!,
queryParameters: buildQueryParams(
pageSize: 10,
page: 1,
state: 'buyer-list',
search: 'filter',
role: 'Steward',
value: searchedValue.value ?? '',
),
),
onSuccess: (res) {
if ((res?.count ?? 0) == 0) {
buyerList.value = Resource<List<OutProvinceCarcassesBuyer>>.empty();
} else {
buyerList.value = Resource<List<OutProvinceCarcassesBuyer>>.success(res!.results!);
buyerList.value = Resource<List<OutProvinceCarcassesBuyer>>.success(
res!.results!,
);
}
},
);
}
Future<void> getOutProvinceSales() async {
await safeCall(
call: () =>
rootLogic.chickenRepository.getStewardFreeSaleBar(
token: rootLogic.tokenService.accessToken.value!,
queryParameters: buildQueryParams(
pageSize: 10,
page: 1,
state: 'buyer-list',
search: 'filter',
role: 'Steward',
value: searchedValue.value ?? '',
fromDate: fromDateFilter.value.toDateTime(),
toDate: toDateFilter.value.toDateTime(),
),
),
onSuccess: (res) {
if ((res?.count ?? 0) == 0) {
salesList.value = Resource<List<StewardFreeSaleBar>>.empty();
} else {
salesList.value = Resource<List<StewardFreeSaleBar>>.success(
res!.results!,
);
}
},
);
@@ -97,7 +154,10 @@ class SalesOutOfProvinceLogic extends GetxController {
Future<void> getCites() async {
await safeCall(
call: () => rootLogic.chickenRepository.getCity(provinceName: selectedProvince.value?.name ?? ''),
call: () =>
rootLogic.chickenRepository.getCity(
provinceName: selectedProvince.value?.name ?? '',
),
onSuccess: (result) {
if (result != null && result.isNotEmpty) {
cites.value = result;
@@ -107,25 +167,44 @@ class SalesOutOfProvinceLogic extends GetxController {
}
void setupListeners() {
buyerNameController.addListener(checkFormValid);
buyerLastNameController.addListener(checkFormValid);
buyerPhoneController.addListener(checkFormValid);
buyerUnitNameController.addListener(checkFormValid);
//buyer form listeners
buyerNameController.addListener(checkBuyerFormValid);
buyerLastNameController.addListener(checkBuyerFormValid);
buyerPhoneController.addListener(checkBuyerFormValid);
buyerUnitNameController.addListener(checkBuyerFormValid);
ever(selectedProvince, (_) => checkFormValid());
ever(selectedCity, (_) => checkFormValid());
ever(selectedProduct, (_) => checkFormValid());
ever(selectedProvince, (_) => checkBuyerFormValid());
ever(selectedCity, (_) => checkBuyerFormValid());
ever(selectedProduct, (_) => checkBuyerFormValid());
//sales form listeners
saleWeightController.addListener(checkSalesFormValid);
quarantineCodeController.addListener(checkSalesFormValid);
ever(selectedBuyer, (_) => checkSalesFormValid);
ever(selectedProduct, (_) => checkSalesFormValid);
ever(saleDate, (_) => checkSalesFormValid());
}
void checkFormValid() {
isSubmitButtonEnabled.value =
void checkBuyerFormValid() {
isBuyerSubmitButtonEnabled.value =
buyerNameController.text.isNotEmpty &&
buyerLastNameController.text.isNotEmpty &&
buyerPhoneController.text.isNotEmpty &&
buyerUnitNameController.text.isNotEmpty &&
selectedProvince.value != null &&
selectedCity.value != null &&
selectedProduct.value != null;
buyerLastNameController.text.isNotEmpty &&
buyerPhoneController.text.isNotEmpty &&
buyerUnitNameController.text.isNotEmpty &&
selectedProvince.value != null &&
selectedCity.value != null &&
selectedProduct.value != null;
}
void checkSalesFormValid() {
isSaleSubmitButtonEnabled.value =
saleDate.value
.toString()
.isNotEmpty &&
selectedProduct.value != null &&
selectedBuyer.value != null &&
saleWeightController.text.isNotEmpty &&
quarantineCodeController.text.isNotEmpty;
}
Future<bool> createBuyer() async {
@@ -144,7 +223,8 @@ class SalesOutOfProvinceLogic extends GetxController {
mobile: buyerPhoneController.text,
role: 'Steward',
);
final res = await rootLogic.chickenRepository.createOutProvinceCarcassesBuyer(
final res = await rootLogic.chickenRepository
.createOutProvinceCarcassesBuyer(
token: rootLogic.tokenService.accessToken.value!,
body: buyer,
);
@@ -166,26 +246,101 @@ class SalesOutOfProvinceLogic extends GetxController {
selectedProvince.value = null;
selectedCity.value = null;
selectedProduct.value = null;
isSubmitButtonEnabled.value = false;
key = null;
isBuyerSubmitButtonEnabled.value = false;
}
void setEditData(OutProvinceCarcassesBuyer item) {
void setEditDataBuyer(OutProvinceCarcassesBuyer item) {
buyerNameController.text = item.firstName ?? '';
buyerLastNameController.text = item.lastName ?? '';
buyerUnitNameController.text = item.unitName ?? '';
buyerPhoneController.text = item.mobile ?? '';
selectedProvince.value = IranProvinceCityModel(name: item.province);
selectedCity.value = IranProvinceCityModel(name: item.city);
isSubmitButtonEnabled.value = true;
isBuyerSubmitButtonEnabled.value = true;
}
void setEditDataSales(StewardFreeSaleBar item) {
quarantineCodeController.text = item.clearanceCode ?? '';
saleWeightController.text =
item.weightOfCarcasses?.toInt().toString() ?? '';
saleDate.value = Jalali.fromDateTime(DateTime.parse(item.date!));
selectedCity.value = IranProvinceCityModel(name: item.city);
selectedBuyer.value = buyerList.value.data?.firstWhere(
(element) => element.key == item.buyer?.key,
);
selectedProduct.value =
outOfTheProvinceLogic.rolesProductsModel.value.first;
key = item.key;
isSaleSubmitButtonEnabled.value = true;
}
Future<void> deleteStewardPurchaseOutOfProvince(String key) async {
await safeCall(
call: () => rootLogic.chickenRepository.deleteStewardPurchasesOutSideOfTheProvince(
token: rootLogic.tokenService.accessToken.value!,
stewardFreeBarKey: key,
),
call: () =>
rootLogic.chickenRepository
.deleteStewardPurchasesOutSideOfTheProvince(
token: rootLogic.tokenService.accessToken.value!,
stewardFreeBarKey: key,
),
);
}
Future<bool> createSale() async {
bool res = false;
StewardFreeSaleBarRequest requestBody = StewardFreeSaleBarRequest(
buyerKey: selectedBuyer.value?.key,
numberOfCarcasses: 0,
weightOfCarcasses: int.tryParse(saleWeightController.text.clearComma),
date: saleDate.value
.toDateTime()
.formattedDashedGregorian,
clearanceCode: quarantineCodeController.text,
productKey: selectedProduct.value?.key,
);
await safeCall(
call: () =>
rootLogic.chickenRepository.createOutProvinceStewardFreeBar(
token: rootLogic.tokenService.accessToken.value!,
body: requestBody,
),
onSuccess: (_) {
res = true;
},
);
return res;
}
void clearSaleForm() {
quarantineCodeController.clear();
saleWeightController.clear();
saleDate.value = Jalali.now();
selectedBuyer.value = null;
selectedProduct.value = null;
isBuyerSubmitButtonEnabled.value = false;
}
Future<bool> editSale() async {
bool res = false;
StewardFreeSaleBarRequest requestBody = StewardFreeSaleBarRequest(
numberOfCarcasses: 0,
weightOfCarcasses: int.tryParse(saleWeightController.text.clearComma),
date: saleDate.value
.toDateTime()
.formattedDashedGregorian,
clearanceCode: quarantineCodeController.text,
key:key
);
await safeCall(
call: () =>
rootLogic.chickenRepository.updateOutProvinceStewardFreeBar(
token: rootLogic.tokenService.accessToken.value!,
body: requestBody,
),
onSuccess: (_) {
res = true;
},
);
return res;
}
}

View File

@@ -6,7 +6,7 @@ import 'package:rasadyar_chicken/presentation/pages/sales_out_of_province/logic.
import 'package:rasadyar_chicken/presentation/pages/sales_out_of_province/widgets/search_widget.dart';
import 'package:rasadyar_core/core.dart';
import 'empty_widget.dart';
import '../widgets/empty_widget.dart';
class BuyersPage extends GetView<SalesOutOfProvinceLogic> {
const BuyersPage({super.key});
@@ -181,7 +181,7 @@ class BuyersPage extends GetView<SalesOutOfProvinceLogic> {
children: [
GestureDetector(
onTap: () {
controller.setEditData(item);
controller.setEditDataBuyer(item);
Get.bottomSheet(
addOrEditBuyerBottomSheet(true),
isScrollControlled: true,
@@ -368,7 +368,7 @@ class BuyersPage extends GetView<SalesOutOfProvinceLogic> {
: null,
height: 40,
);
}, controller.isSubmitButtonEnabled);
}, controller.isBuyerSubmitButtonEnabled);
}
Widget _provinceWidget() {

View File

@@ -0,0 +1,596 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:rasadyar_chicken/data/models/response/iran_province_city/iran_province_city_model.dart';
import 'package:rasadyar_chicken/data/models/response/out_province_carcasses_buyer/out_province_carcasses_buyer.dart';
import 'package:rasadyar_chicken/data/models/response/roles_products/roles_products.dart';
import 'package:rasadyar_chicken/data/models/response/steward_free_sale_bar/steward_free_sale_bar.dart';
import 'package:rasadyar_chicken/presentation/pages/sales_out_of_province/logic.dart';
import 'package:rasadyar_chicken/presentation/pages/sales_out_of_province/widgets/empty_widget.dart';
import 'package:rasadyar_core/core.dart';
import '../widgets/search_widget.dart';
class SalesPage extends GetView<SalesOutOfProvinceLogic> {
const SalesPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
searchWidget(controller.searchIsSelected, (data) {
controller.searchedValue.value = data;
//TODO: Implement search functionality
controller.getOutProvinceSales();
}),
salesListWidget(),
],
),
floatingActionButton: RFab.add(
onPressed: () {
Get.bottomSheet(addOrEditSaleBottomSheet(), isScrollControlled: true);
},
),
floatingActionButtonLocation: FloatingActionButtonLocation.startFloat,
);
}
Widget salesListWidget() {
return ObxValue((data) {
switch (data.value.status) {
case Status.initial:
case Status.loading:
return Center(child: CupertinoActivityIndicator());
case Status.success:
return ListView.separated(
shrinkWrap: true,
physics: BouncingScrollPhysics(),
padding: EdgeInsets.fromLTRB(8, 8, 18, 80),
itemBuilder: (context, index) {
return ObxValue(
(expandList) => salesListItem(
expandList: expandList,
index: index,
item: data.value.data![index],
),
controller.isExpandedList,
);
},
separatorBuilder: (context, index) => SizedBox(height: 8),
itemCount: data.value.data?.length ?? 0,
);
case Status.error:
return Center(
child: Text(
data.value.message ?? 'خطا در دریافت اطلاعات',
style: AppFonts.yekan16.copyWith(color: AppColor.error),
),
);
case Status.empty:
return emptyWidget();
}
}, controller.salesList);
}
GestureDetector salesListItem({
required RxList<int> expandList,
required int index,
required StewardFreeSaleBar item,
}) {
return GestureDetector(
onTap: () {
if (expandList.contains(index)) {
controller.isExpandedList.remove(index);
} else {
controller.isExpandedList.add(index);
}
},
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: 0.5,
color: AppColor.darkGreyNormal,
),
),
child: AnimatedCrossFade(
alignment: Alignment.center,
firstChild: Padding(
padding: const EdgeInsets.symmetric(vertical: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
SizedBox(width: 12),
Expanded(
flex: 3,
child: Text(
item.date?.formattedJalaliDate ?? 'N/A',
textAlign: TextAlign.center,
style: AppFonts.yekan12.copyWith(
color: AppColor.bgDark,
),
),
),
SizedBox(width: 4),
Expanded(
flex: 5,
child: Column(
children: [
Text(
item.buyer?.fullname ?? 'N/A',
textAlign: TextAlign.center,
style: AppFonts.yekan14.copyWith(
color: AppColor.blueNormal,
),
),
SizedBox(height: 2),
Text(
item.buyer?.mobile ?? 'N/A',
textAlign: TextAlign.center,
style: AppFonts.yekan14.copyWith(
color: AppColor.bgDark,
),
),
],
),
),
SizedBox(width: 4),
Expanded(
flex: 4,
child: Column(
spacing: 8,
children: [
Text(
item.buyer?.unitName ?? 'N/A',
textAlign: TextAlign.center,
style: AppFonts.yekan12.copyWith(
color: AppColor.bgDark,
),
),
Text(
'${item.weightOfCarcasses?.separatedByComma ?? 0}KG',
textAlign: TextAlign.center,
style: AppFonts.yekan12.copyWith(
color: AppColor.bgDark,
),
),
],
),
),
Expanded(
flex: 2,
child: Text(
'${item.buyer?.province}\n${item.buyer?.city}',
textAlign: TextAlign.center,
style: AppFonts.yekan12.copyWith(
color: AppColor.bgDark,
),
),
),
SizedBox(width: 8),
Icon(CupertinoIcons.chevron_down, size: 12),
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.setEditDataSales(item);
Get.bottomSheet(
addOrEditSaleBottomSheet(true),
isScrollControlled: true,
).whenComplete(() {
controller.resetSubmitForm();
});
},
child: Assets.vec.editSvg.svg(
width: 20,
height: 20,
colorFilter: ColorFilter.mode(
AppColor.blueNormal,
BlendMode.srcIn,
),
),
),
Text(
'${item.province}-${item.city}',
textAlign: TextAlign.center,
style: AppFonts.yekan16.copyWith(
color: AppColor.greenDark,
),
),
GestureDetector(
onTap: () {
buildDeleteDialog(
onConfirm: () => controller
.deleteStewardPurchaseOutOfProvince(
item.key!,
),
);
},
child: Assets.vec.trashSvg.svg(
width: 20,
height: 20,
colorFilter: ColorFilter.mode(
AppColor.error,
BlendMode.srcIn,
),
),
),
],
),
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: buildRow(
'تاریخ',
item.date?.formattedJalaliDateYHMS ?? 'N/A',
),
),
buildRow(
'مشخصات خریدار',
item.buyer?.fullname ?? 'N/A',
),
buildRow('تلفن خریدار', item.buyer?.mobile ?? 'N/A'),
buildRow('نام واحد', item.buyer?.unitName ?? 'N/A'),
buildRow(
'وزن لاشه',
'${item.weightOfCarcasses?.separatedByComma}',
),
],
),
),
crossFadeState: expandList.contains(index)
? CrossFadeState.showSecond
: CrossFadeState.showFirst,
duration: Duration(milliseconds: 300),
),
),
),
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),
),
),
),
],
),
),
);
}
Widget buildRow(String title, String value) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Flexible(
flex: 2,
child: Text(
title,
textAlign: TextAlign.right,
style: AppFonts.yekan14.copyWith(
color: AppColor.darkGreyDarkHover,
),
),
),
Flexible(
flex: 2,
child: Text(
value,
textAlign: TextAlign.left,
style: AppFonts.yekan14.copyWith(
color: AppColor.darkGreyDarkHover,
),
),
),
],
),
);
}
Widget addOrEditSaleBottomSheet([bool isOnEdit = false]) {
return BaseBottomSheet(
height: 600,
child: SingleChildScrollView(
child: Form(
key: controller.formKey,
child: Column(
spacing: 16,
children: [
Text(
isOnEdit ? 'ویرایش فروش' : 'افزودن فروش',
style: AppFonts.yekan16Bold.copyWith(
color: AppColor.darkGreyDarkHover,
),
),
_productWidget(),
_buyerWidget(),
RTextField(
controller: controller.saleWeightController,
label: 'وزن لاشه',
keyboardType: TextInputType.number,
borderColor: AppColor.darkGreyLight,
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
SeparatorInputFormatter(),
],
validator: (value) {
if (value == null) {
return 'لطفاً وزن لاشه را وارد کنید';
}
return null;
},
),
RTextField(
controller: controller.quarantineCodeController,
label: 'کد قرنطینه',
borderColor: AppColor.darkGreyLight,
validator: (value) {
if (value == null) {
return 'لطفاً کد قرنطینه را وارد کنید';
}
return null;
},
),
Row(
spacing: 8,
children: [
Expanded(
child: timeFilterWidget(
date: controller.saleDate,
onChanged: (jalali) => controller.saleDate.value = jalali,
),
),
],
),
submitButtonWidget(isOnEdit),
SizedBox(),
],
),
),
),
);
}
Widget submitButtonWidget(bool isOnEdit) {
return ObxValue((data) {
return RElevated(
text: isOnEdit ? 'ویرایش' : 'ثبت',
onPressed: data.value
? () async {
var res = isOnEdit
? await controller.editSale()
: await controller.createSale();
if (res) {
controller.getOutProvinceSales();
controller.clearSaleForm();
Get.back();
}
}
: null,
height: 40,
);
}, controller.isSaleSubmitButtonEnabled);
}
Widget _buyerWidget() {
return Obx(() {
return OverlayDropdownWidget<OutProvinceCarcassesBuyer>(
items: controller.buyerList.value.data ?? [],
onChanged: (value) {
controller.selectedBuyer.value = value;
},
selectedItem: controller.selectedBuyer.value,
itemBuilder: (item) => Text(item.buyer?.fullname ?? 'بدون نام'),
labelBuilder: (item) => Text(item?.buyer?.fullname ?? 'انتخاب خریدار'),
);
});
}
Widget _productWidget() {
return ObxValue((data) {
return OverlayDropdownWidget<ProductModel>(
items: controller.outOfTheProvinceLogic.rolesProductsModel,
onChanged: (value) {
controller.selectedProduct.value = value;
},
selectedItem: controller.selectedProduct.value,
initialValue: controller.selectedProduct.value,
itemBuilder: (item) => Text(item.name ?? 'بدون نام'),
labelBuilder: (item) => Text(item?.name ?? 'انتخاب محصول'),
);
}, controller.selectedProduct);
}
GestureDetector timeFilterWidget({
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.bgDark),
),
padding: EdgeInsets.symmetric(horizontal: 11, vertical: 4),
child: Row(
spacing: 8,
children: [
Assets.vec.calendarSvg.svg(
width: 24,
height: 24,
colorFilter: const ColorFilter.mode(
AppColor.bgDark,
BlendMode.srcIn,
),
),
Text(
'تاریخ',
style: AppFonts.yekan16.copyWith(color: AppColor.bgDark),
),
Expanded(
child: ObxValue((data) {
return Text(
date.value.formatCompactDate(),
textAlign: TextAlign.center,
style: AppFonts.yekan16.copyWith(
color: AppColor.darkGreyDark,
),
);
}, date),
),
],
),
),
);
}
Container modalDatePicker(ValueChanged<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: controller.saleDate.value,
mode: PersianCupertinoDatePickerMode.date,
onDateTimeChanged: (dateTime) {
tempPickedDate = dateTime;
},
),
),
),
],
),
);
}
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.getOutProvinceSales());
}
}

View File

@@ -5,7 +5,8 @@ import 'package:flutter/material.dart';
import 'package:rasadyar_chicken/data/models/response/iran_province_city/iran_province_city_model.dart';
import 'package:rasadyar_chicken/data/models/response/roles_products/roles_products.dart';
import 'package:rasadyar_chicken/data/models/response/steward_free_bar/steward_free_bar.dart';
import 'package:rasadyar_chicken/presentation/pages/sales_out_of_province/widgets/buyers_page.dart';
import 'package:rasadyar_chicken/presentation/pages/sales_out_of_province/pages/buyers_page.dart';
import 'package:rasadyar_chicken/presentation/pages/sales_out_of_province/pages/sales_page.dart';
import 'package:rasadyar_core/core.dart';
import 'logic.dart';
@@ -56,7 +57,7 @@ class SalesOutOfProvincePage extends GetView<SalesOutOfProvinceLogic> {
visible: controller.currentIndex.value==0,
child: GestureDetector(
onTap: () {
// Get.bottomSheet(filterBottomSheet());
Get.bottomSheet(filterBottomSheet());
},
child: Assets.vec.filterOutlineSvg.svg(
width: 20,
@@ -98,7 +99,7 @@ class SalesOutOfProvincePage extends GetView<SalesOutOfProvinceLogic> {
Expanded(
child: TabBarView(
children: [
salePage(),
SalesPage(),
BuyersPage()
],
),
@@ -668,6 +669,8 @@ class SalesOutOfProvincePage extends GetView<SalesOutOfProvinceLogic> {
).whenComplete(() => controller.getStewardPurchaseOutOfProvince());
}
*/
Widget filterBottomSheet() {
return BaseBottomSheet(
height: 250,
@@ -697,7 +700,7 @@ class SalesOutOfProvincePage extends GetView<SalesOutOfProvinceLogic> {
RElevated(
text: 'اعمال فیلتر',
onPressed: () {
controller.getStewardPurchaseOutOfProvince();
controller.getOutProvinceSales();
Get.back();
},
height: 40,
@@ -706,7 +709,7 @@ class SalesOutOfProvincePage extends GetView<SalesOutOfProvinceLogic> {
],
),
);
}*/
}
GestureDetector timeFilterWidget({
isFrom = true,

View File

@@ -2,7 +2,9 @@ import 'package:flutter/material.dart';
import 'package:rasadyar_core/core.dart';
Widget emptyWidget() {
return Center(
child: Text('داده ای دریافت نشد!', style: AppFonts.yekan16.copyWith(color: AppColor.darkGreyDarkHover)),
return Expanded(
child: Center(
child: Text('داده ای دریافت نشد!', style: AppFonts.yekan16.copyWith(color: AppColor.darkGreyDarkHover)),
),
);
}