feat : sale out of province
This commit is contained in:
@@ -8,12 +8,14 @@ import 'package:rasadyar_chicken/presentation/pages/root/logic.dart';
|
|||||||
import 'package:rasadyar_core/core.dart';
|
import 'package:rasadyar_core/core.dart';
|
||||||
|
|
||||||
class SaleLogic extends GetxController {
|
class SaleLogic extends GetxController {
|
||||||
Rxn<List<AllocatedMadeModel>?> allocatedMadeModel = Rxn<List<AllocatedMadeModel>?>();
|
Rxn<List<AllocatedMadeModel>?> allocatedMadeModel =
|
||||||
|
Rxn<List<AllocatedMadeModel>?>();
|
||||||
RxList<ProductModel> rolesProductsModel = RxList<ProductModel>();
|
RxList<ProductModel> rolesProductsModel = RxList<ProductModel>();
|
||||||
|
|
||||||
RxList<GuildModel> guildsModel = <GuildModel>[].obs;
|
RxList<GuildModel> guildsModel = <GuildModel>[].obs;
|
||||||
|
|
||||||
Rxn<StewardFreeBarDashboard> stewardFreeDashboard = Rxn<StewardFreeBarDashboard>();
|
Rxn<StewardFreeBarDashboard> stewardFreeDashboard =
|
||||||
|
Rxn<StewardFreeBarDashboard>();
|
||||||
|
|
||||||
RootLogic rootLogic = Get.find<RootLogic>();
|
RootLogic rootLogic = Get.find<RootLogic>();
|
||||||
|
|
||||||
@@ -31,7 +33,12 @@ class SaleLogic 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(page: 1, pageSize: 20, search: 'filter', role: 'Steward'),
|
queryParameters: buildQueryParams(
|
||||||
|
page: 1,
|
||||||
|
pageSize: 20,
|
||||||
|
search: 'filter',
|
||||||
|
role: 'Steward',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
onSuccess: (result) {
|
onSuccess: (result) {
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
@@ -74,7 +81,8 @@ class SaleLogic extends GetxController {
|
|||||||
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: allocatedMadeModel.value?.map((e) => e.key!).toList() ?? [],
|
allocationTokens:
|
||||||
|
allocatedMadeModel.value?.map((e) => e.key!).toList() ?? [],
|
||||||
),
|
),
|
||||||
onSuccess: (result) {
|
onSuccess: (result) {
|
||||||
getAllocatedMade();
|
getAllocatedMade();
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
import 'package:get/get.dart';
|
|
||||||
|
|
||||||
class SalesOutOfProvinceSalesListLogic extends GetxController {
|
|
||||||
@override
|
|
||||||
void onReady() {
|
|
||||||
// TODO: implement onReady
|
|
||||||
super.onReady();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void onClose() {
|
|
||||||
// TODO: implement onClose
|
|
||||||
super.onClose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:get/get.dart';
|
|
||||||
|
|
||||||
import 'logic.dart';
|
|
||||||
|
|
||||||
class SalesOutOfProvinceSalesListPage extends StatelessWidget {
|
|
||||||
const SalesOutOfProvinceSalesListPage({Key? key}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final SalesOutOfProvinceSalesListLogic logic = Get.put(SalesOutOfProvinceSalesListLogic());
|
|
||||||
|
|
||||||
return Container();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -19,7 +19,10 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: BasePage(
|
body: BasePage(
|
||||||
routesWidget: ObxValue((route) => buildPageRoute(route), controller.routesName),
|
routesWidget: ObxValue(
|
||||||
|
(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(),
|
||||||
@@ -32,7 +35,10 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
|
|||||||
resource: data.value,
|
resource: data.value,
|
||||||
hasMore: data.value.data?.next != null,
|
hasMore: data.value.data?.next != null,
|
||||||
isPaginating: controller.isLoadingMoreAllocationsMade.value,
|
isPaginating: controller.isLoadingMoreAllocationsMade.value,
|
||||||
onRefresh: () async => await controller.getAllocatedMade(),
|
onRefresh: () async {
|
||||||
|
controller.currentPage.value = 1;
|
||||||
|
await controller.getAllocatedMade();
|
||||||
|
},
|
||||||
onLoadMore: () async {
|
onLoadMore: () async {
|
||||||
controller.currentPage.value++;
|
controller.currentPage.value++;
|
||||||
iLog(controller.currentPage.value);
|
iLog(controller.currentPage.value);
|
||||||
@@ -83,7 +89,10 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
|
|||||||
await controller.confirmAllAllocations();
|
await controller.confirmAllAllocations();
|
||||||
},
|
},
|
||||||
message: 'تایید یکجا',
|
message: 'تایید یکجا',
|
||||||
icon: Assets.vec.clipboardTaskSvg.svg(width: 40.w, height: 40.h),
|
icon: Assets.vec.clipboardTaskSvg.svg(
|
||||||
|
width: 40.w,
|
||||||
|
height: 40.h,
|
||||||
|
),
|
||||||
backgroundColor: controller.bgConfirmAllColor.value,
|
backgroundColor: controller.bgConfirmAllColor.value,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -100,7 +109,10 @@ 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(color: AppColor.greenLight, borderRadius: BorderRadius.circular(8)),
|
decoration: BoxDecoration(
|
||||||
|
color: AppColor.greenLight,
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
),
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
child: ObxValue((data) {
|
child: ObxValue((data) {
|
||||||
return Text(
|
return Text(
|
||||||
@@ -153,13 +165,18 @@ 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(AppColor.blueNormal, BlendMode.srcIn),
|
colorFilter: ColorFilter.mode(
|
||||||
|
AppColor.blueNormal,
|
||||||
|
BlendMode.srcIn,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
'${item.weightOfCarcasses?.separatedByComma}kg',
|
'${item.weightOfCarcasses?.separatedByComma}kg',
|
||||||
textAlign: TextAlign.left,
|
textAlign: TextAlign.left,
|
||||||
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
|
style: AppFonts.yekan12.copyWith(
|
||||||
|
color: AppColor.blueNormal,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -190,7 +207,10 @@ 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(color: Colors.white, borderRadius: BorderRadius.circular(8)),
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
spacing: 8,
|
spacing: 8,
|
||||||
children: [
|
children: [
|
||||||
@@ -230,12 +250,16 @@ 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(color: AppColor.textColor),
|
style: AppFonts.yekan14.copyWith(
|
||||||
|
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(color: AppColor.blueNormal),
|
style: AppFonts.yekan14.copyWith(
|
||||||
|
color: AppColor.blueNormal,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -255,7 +279,8 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
|
|||||||
|
|
||||||
buildRow(
|
buildRow(
|
||||||
title: 'نام و نام خانوادگی فروشنده',
|
title: 'نام و نام خانوادگی فروشنده',
|
||||||
value: controller.getBuyerInformation(item)?.user?.fullname ?? 'N/A',
|
value:
|
||||||
|
controller.getBuyerInformation(item)?.user?.fullname ?? 'N/A',
|
||||||
),
|
),
|
||||||
|
|
||||||
buildRow(
|
buildRow(
|
||||||
@@ -273,12 +298,20 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
|
|||||||
title: 'افت وزن(کیلوگرم)',
|
title: 'افت وزن(کیلوگرم)',
|
||||||
value: item.weightLossOfCarcasses?.toInt().toString() ?? 'N/A',
|
value: item.weightLossOfCarcasses?.toInt().toString() ?? 'N/A',
|
||||||
),
|
),
|
||||||
buildRow(title: 'قیمت کل', value: '${item.totalAmount?.separatedByComma} ریال'),
|
buildRow(
|
||||||
|
title: 'قیمت کل',
|
||||||
|
value: '${item.totalAmount?.separatedByComma} ریال',
|
||||||
|
),
|
||||||
|
|
||||||
buildRow(title: 'کداحراز', value: item.registrationCode?.toString() ?? 'ندارد'),
|
buildRow(
|
||||||
|
title: 'کداحراز',
|
||||||
|
value: item.registrationCode?.toString() ?? 'ندارد',
|
||||||
|
),
|
||||||
buildRow(
|
buildRow(
|
||||||
title: 'وضعیت کد احراز',
|
title: 'وضعیت کد احراز',
|
||||||
value: item.systemRegistrationCode == true ? "ارسال شده" : "ارسال نشده",
|
value: item.systemRegistrationCode == true
|
||||||
|
? "ارسال شده"
|
||||||
|
: "ارسال نشده",
|
||||||
),
|
),
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
@@ -341,7 +374,9 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
|
|||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'${isEditMode ? 'ویرایش' : 'ثبت'} توزیع/ فروش',
|
'${isEditMode ? 'ویرایش' : 'ثبت'} توزیع/ فروش',
|
||||||
style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal),
|
style: AppFonts.yekan16Bold.copyWith(
|
||||||
|
color: AppColor.blueNormal,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
Visibility(
|
Visibility(
|
||||||
visible: isEditMode == false,
|
visible: isEditMode == false,
|
||||||
@@ -355,7 +390,10 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
|
|||||||
initText: Jalali.now().formatCompactDate(),
|
initText: Jalali.now().formatCompactDate(),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
Material(type: MaterialType.transparency, child: productDropDown()),
|
Material(
|
||||||
|
type: MaterialType.transparency,
|
||||||
|
child: productDropDown(),
|
||||||
|
),
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
@@ -403,7 +441,12 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
|
|||||||
],
|
],
|
||||||
validator: (value) {
|
validator: (value) {
|
||||||
if (int.parse(value!.clearComma) >
|
if (int.parse(value!.clearComma) >
|
||||||
(controller.rootLogic.inventoryModel.value?.totalRemainWeight?.toInt() ??
|
(controller
|
||||||
|
.rootLogic
|
||||||
|
.inventoryModel
|
||||||
|
.value
|
||||||
|
?.totalRemainWeight
|
||||||
|
?.toInt() ??
|
||||||
100)) {
|
100)) {
|
||||||
return 'وزن تخصیصی بیشتر از موجودی انبار است';
|
return 'وزن تخصیصی بیشتر از موجودی انبار است';
|
||||||
}
|
}
|
||||||
@@ -424,7 +467,8 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
|
|||||||
],
|
],
|
||||||
|
|
||||||
onChanged: (p0) {
|
onChanged: (p0) {
|
||||||
controller.pricePerKilo.value = int.tryParse(p0.clearComma) ?? 0;
|
controller.pricePerKilo.value =
|
||||||
|
int.tryParse(p0.clearComma) ?? 0;
|
||||||
},
|
},
|
||||||
keyboardType: TextInputType.number,
|
keyboardType: TextInputType.number,
|
||||||
label: 'قیمت هر کیلو',
|
label: 'قیمت هر کیلو',
|
||||||
@@ -450,7 +494,8 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
|
|||||||
height: 40,
|
height: 40,
|
||||||
onPressed: data.value
|
onPressed: data.value
|
||||||
? () async {
|
? () async {
|
||||||
if (controller.formKey.currentState?.validate() ?? false) {
|
if (controller.formKey.currentState?.validate() ??
|
||||||
|
false) {
|
||||||
iLog("s2");
|
iLog("s2");
|
||||||
controller.setSubmitData();
|
controller.setSubmitData();
|
||||||
iLog("s3");
|
iLog("s3");
|
||||||
@@ -527,14 +572,20 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
spacing: 16,
|
spacing: 16,
|
||||||
children: [
|
children: [
|
||||||
Text('فیلترها', style: AppFonts.yekan16Bold.copyWith(color: AppColor.darkGreyDarkHover)),
|
Text(
|
||||||
|
'فیلترها',
|
||||||
|
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) => controller.fromDateFilter.value = jalali,
|
onChanged: (jalali) =>
|
||||||
|
controller.fromDateFilter.value = jalali,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
@@ -583,7 +634,10 @@ 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(AppColor.blueNormal, BlendMode.srcIn),
|
colorFilter: const ColorFilter.mode(
|
||||||
|
AppColor.blueNormal,
|
||||||
|
BlendMode.srcIn,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
isFrom ? 'از' : 'تا',
|
isFrom ? 'از' : 'تا',
|
||||||
@@ -592,9 +646,12 @@ class SalesInProvincePage extends GetView<SalesInProvinceLogic> {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: ObxValue((data) {
|
child: ObxValue((data) {
|
||||||
return Text(
|
return Text(
|
||||||
date.value?.formatCompactDate() ?? Jalali.now().formatCompactDate(),
|
date.value?.formatCompactDate() ??
|
||||||
|
Jalali.now().formatCompactDate(),
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: AppFonts.yekan16.copyWith(color: AppColor.lightGreyNormalActive),
|
style: AppFonts.yekan16.copyWith(
|
||||||
|
color: AppColor.lightGreyNormalActive,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}, date),
|
}, date),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,318 +1,66 @@
|
|||||||
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/root/logic.dart';
|
import 'package:rasadyar_chicken/presentation/pages/root/logic.dart';
|
||||||
import 'package:rasadyar_chicken/presentation/pages/sale/logic.dart';
|
import 'package:rasadyar_chicken/presentation/pages/sale/logic.dart';
|
||||||
|
import 'package:rasadyar_chicken/presentation/pages/sales_out_of_province_buyers/logic.dart';
|
||||||
|
import 'package:rasadyar_chicken/presentation/pages/sales_out_of_province_sales_list/logic.dart';
|
||||||
import 'package:rasadyar_core/core.dart';
|
import 'package:rasadyar_core/core.dart';
|
||||||
|
|
||||||
class SalesOutOfProvinceLogic extends GetxController {
|
class SalesOutOfProvinceLogic extends GetxController {
|
||||||
RootLogic get rootLogic => Get.find<RootLogic>();
|
RootLogic get rootLogic => Get.find<RootLogic>();
|
||||||
|
|
||||||
SaleLogic get saleLogic => Get.find<SaleLogic>();
|
SaleLogic get saleLogic => Get.find<SaleLogic>();
|
||||||
|
|
||||||
|
SalesOutOfProvinceBuyersLogic get buyersLogic =>
|
||||||
|
Get.find<SalesOutOfProvinceBuyersLogic>();
|
||||||
|
|
||||||
|
SalesOutOfProvinceSalesListLogic get saleListLogic =>
|
||||||
|
Get.find<SalesOutOfProvinceSalesListLogic>();
|
||||||
|
|
||||||
RxInt selectedSegmentIndex = 0.obs;
|
RxInt selectedSegmentIndex = 0.obs;
|
||||||
RxBool isExpanded = false.obs;
|
RxBool isExpanded = false.obs;
|
||||||
RxBool isBuyerSubmitButtonEnabled = false.obs;
|
|
||||||
RxBool isSaleSubmitButtonEnabled = false.obs;
|
|
||||||
RxList<int> isExpandedList = <int>[].obs;
|
RxList<int> isExpandedList = <int>[].obs;
|
||||||
Rx<Jalali> fromDateFilter = Jalali.now().obs;
|
Rx<Jalali> fromDateFilter = Jalali.now().obs;
|
||||||
Rx<Jalali> toDateFilter = Jalali.now().obs;
|
Rx<Jalali> toDateFilter = Jalali.now().obs;
|
||||||
RxnString searchedValue = RxnString();
|
RxnString searchedValue = RxnString();
|
||||||
RxList<String> routesName = RxList();
|
RxList<String> routesName = RxList();
|
||||||
|
|
||||||
//TODO add this to Di
|
@override
|
||||||
ImagePicker imagePicker = ImagePicker();
|
void onInit() {
|
||||||
|
super.onInit();
|
||||||
|
routesName.value = [...saleLogic.routesName, 'خارج استان'].toList();
|
||||||
|
|
||||||
Rx<Resource<List<OutProvinceCarcassesBuyer>>> buyerList =
|
routesName.add(selectedSegmentIndex.value == 0 ? 'فروش' : 'خریداران');
|
||||||
Resource<List<OutProvinceCarcassesBuyer>>.loading().obs;
|
ever(selectedSegmentIndex, (callback) {
|
||||||
Rx<Resource<List<StewardFreeSaleBar>>> salesList =
|
routesName.removeLast();
|
||||||
Resource<List<StewardFreeSaleBar>>.loading().obs;
|
routesName.add(callback == 0 ? 'فروش' : 'خریداران');
|
||||||
|
});
|
||||||
Rxn<ProductModel> selectedProduct = Rxn();
|
}
|
||||||
Rxn<OutProvinceCarcassesBuyer> selectedBuyer = Rxn();
|
|
||||||
|
|
||||||
RxList<IranProvinceCityModel> cites = <IranProvinceCityModel>[].obs;
|
|
||||||
Rxn<IranProvinceCityModel> selectedProvince = Rxn();
|
|
||||||
Rxn<IranProvinceCityModel> selectedCity = Rxn();
|
|
||||||
|
|
||||||
GlobalKey<FormState> formKey = GlobalKey<FormState>();
|
|
||||||
TextEditingController buyerNameController = TextEditingController();
|
|
||||||
TextEditingController buyerLastNameController = TextEditingController();
|
|
||||||
TextEditingController buyerPhoneController = TextEditingController();
|
|
||||||
TextEditingController buyerUnitNameController = TextEditingController();
|
|
||||||
|
|
||||||
//Sale
|
|
||||||
TextEditingController quarantineCodeController = TextEditingController();
|
|
||||||
TextEditingController saleWeightController = TextEditingController();
|
|
||||||
Rx<Jalali> saleDate = Jalali.now().obs;
|
|
||||||
String? key;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onReady() {
|
void onReady() {
|
||||||
super.onReady();
|
super.onReady();
|
||||||
getOutProvinceCarcassesBuyer();
|
|
||||||
getOutProvinceSales();
|
|
||||||
routesName.value = [...saleLogic.routesName, 'داخل استان'].toList();
|
|
||||||
selectedProvince.listen((p0) => getCites());
|
|
||||||
tLog(selectedProduct.value);
|
|
||||||
saleLogic.rolesProductsModel.listen((lists) {
|
|
||||||
selectedProduct.value = lists.first;
|
|
||||||
});
|
|
||||||
setupListeners();
|
|
||||||
debounce(
|
|
||||||
searchedValue,
|
|
||||||
(callback) => getOutProvinceCarcassesBuyer(),
|
|
||||||
time: Duration(milliseconds: 2000),
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void onClose() {
|
|
||||||
buyerNameController.dispose();
|
|
||||||
buyerLastNameController.dispose();
|
|
||||||
buyerPhoneController.dispose();
|
|
||||||
buyerUnitNameController.dispose();
|
|
||||||
selectedCity.value = null;
|
|
||||||
selectedProvince.value = null;
|
|
||||||
isExpandedList.clear();
|
|
||||||
|
|
||||||
super.onClose();
|
|
||||||
}
|
|
||||||
|
|
||||||
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 ?? '',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onSuccess: (res) {
|
|
||||||
if ((res?.count ?? 0) == 0) {
|
|
||||||
buyerList.value = Resource<List<OutProvinceCarcassesBuyer>>.empty();
|
|
||||||
} else {
|
|
||||||
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!);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> getCites() async {
|
|
||||||
await safeCall(
|
|
||||||
call: () =>
|
|
||||||
rootLogic.chickenRepository.getCity(provinceName: selectedProvince.value?.name ?? ''),
|
|
||||||
onSuccess: (result) {
|
|
||||||
if (result != null && result.isNotEmpty) {
|
|
||||||
cites.value = result;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setupListeners() {
|
|
||||||
//buyer form listeners
|
|
||||||
buyerNameController.addListener(checkBuyerFormValid);
|
|
||||||
buyerLastNameController.addListener(checkBuyerFormValid);
|
|
||||||
buyerPhoneController.addListener(checkBuyerFormValid);
|
|
||||||
buyerUnitNameController.addListener(checkBuyerFormValid);
|
|
||||||
|
|
||||||
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 checkBuyerFormValid() {
|
|
||||||
isBuyerSubmitButtonEnabled.value =
|
|
||||||
buyerNameController.text.isNotEmpty &&
|
|
||||||
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 {
|
|
||||||
bool res = false;
|
|
||||||
if (!(formKey.currentState?.validate() ?? false)) {
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
await safeCall(
|
|
||||||
call: () async {
|
|
||||||
OutProvinceCarcassesBuyer buyer = OutProvinceCarcassesBuyer(
|
|
||||||
province: selectedProvince.value!.name,
|
|
||||||
city: selectedCity.value!.name,
|
|
||||||
firstName: buyerNameController.text,
|
|
||||||
lastName: buyerLastNameController.text,
|
|
||||||
unitName: buyerUnitNameController.text,
|
|
||||||
mobile: buyerPhoneController.text,
|
|
||||||
role: 'Steward',
|
|
||||||
);
|
|
||||||
final res = await rootLogic.chickenRepository.createOutProvinceCarcassesBuyer(
|
|
||||||
token: rootLogic.tokenService.accessToken.value!,
|
|
||||||
body: buyer,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
onSuccess: (result) {
|
|
||||||
getOutProvinceCarcassesBuyer();
|
|
||||||
resetSubmitForm();
|
|
||||||
res = true;
|
|
||||||
},
|
|
||||||
);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
void resetSubmitForm() {
|
|
||||||
buyerNameController.clear();
|
|
||||||
buyerLastNameController.clear();
|
|
||||||
buyerPhoneController.clear();
|
|
||||||
buyerUnitNameController.clear();
|
|
||||||
selectedProvince.value = null;
|
|
||||||
selectedCity.value = null;
|
|
||||||
selectedProduct.value = null;
|
|
||||||
key = null;
|
|
||||||
isBuyerSubmitButtonEnabled.value = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
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 = saleLogic.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,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setSearchValue(String value) {
|
void setSearchValue(String value) {
|
||||||
searchedValue.value = value.trim();
|
searchedValue.value = value.trim();
|
||||||
|
if (selectedSegmentIndex.value == 0) {
|
||||||
|
saleListLogic.searchedValue.value = value.trim();
|
||||||
|
} else {
|
||||||
|
buyersLogic.searchedValue.value = value.trim();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void submitFilter() {
|
void submitFilter() {
|
||||||
//TODO: Implement filter logic
|
if (selectedSegmentIndex.value == 0) {
|
||||||
|
saleListLogic.fromDateFilter.value = fromDateFilter.value;
|
||||||
|
saleListLogic.toDateFilter.value = toDateFilter.value;
|
||||||
|
saleListLogic.getOutProvinceSales();
|
||||||
|
} else {
|
||||||
|
buyersLogic.fromDateFilter.value = fromDateFilter.value;
|
||||||
|
buyersLogic.toDateFilter.value = toDateFilter.value;
|
||||||
|
buyersLogic.getOutProvinceCarcassesBuyer();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,398 +0,0 @@
|
|||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:rasadyar_chicken/data/models/response/iran_province_city/iran_province_city_model.dart';
|
|
||||||
import 'package:rasadyar_chicken/data/models/response/out_province_carcasses_buyer/out_province_carcasses_buyer.dart';
|
|
||||||
import 'package:rasadyar_chicken/presentation/pages/sales_out_of_province/logic.dart';
|
|
||||||
import 'package:rasadyar_chicken/presentation/pages/sales_out_of_province/widgets/search_widget.dart';
|
|
||||||
import 'package:rasadyar_core/core.dart';
|
|
||||||
|
|
||||||
import '../widgets/empty_widget.dart';
|
|
||||||
|
|
||||||
class BuyersPage extends GetView<SalesOutOfProvinceLogic> {
|
|
||||||
const BuyersPage({super.key});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Scaffold(
|
|
||||||
body: Column(
|
|
||||||
children: [
|
|
||||||
buyerListWidget(),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
floatingActionButton: RFab.add(
|
|
||||||
onPressed: () {
|
|
||||||
Get.bottomSheet(
|
|
||||||
addOrEditBuyerBottomSheet(),
|
|
||||||
isScrollControlled: true,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
floatingActionButtonLocation: FloatingActionButtonLocation.startFloat,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget buyerListWidget() {
|
|
||||||
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) => buyerListItem(
|
|
||||||
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.buyerList);
|
|
||||||
}
|
|
||||||
|
|
||||||
GestureDetector buyerListItem({
|
|
||||||
required RxList<int> expandList,
|
|
||||||
required int index,
|
|
||||||
required OutProvinceCarcassesBuyer 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: 2,
|
|
||||||
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: 8),
|
|
||||||
Expanded(
|
|
||||||
flex: 2,
|
|
||||||
child: Text(
|
|
||||||
'${item.unitName}',
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: AppFonts.yekan12.copyWith(
|
|
||||||
color: AppColor.bgDark,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
flex: 1,
|
|
||||||
child: Text(
|
|
||||||
'${item.buyer?.province}\n${item.buyer?.city}',
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: AppFonts.yekan12.copyWith(
|
|
||||||
color: AppColor.darkGreyDark,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
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.setEditDataBuyer(item);
|
|
||||||
Get.bottomSheet(
|
|
||||||
addOrEditBuyerBottomSheet(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,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
SizedBox(),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
|
|
||||||
buildRow('مشخصات خریدار', item.fullname ?? 'N/A'),
|
|
||||||
buildRow('نام واحد', item.unitName ?? 'N/A'),
|
|
||||||
buildRow(
|
|
||||||
'تعداد درخواست ها',
|
|
||||||
'${item.requestsInfo?.numberOfRequests.separatedByComma}',
|
|
||||||
),
|
|
||||||
buildRow(
|
|
||||||
'وزن',
|
|
||||||
'${item.requestsInfo?.totalWeight.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 addOrEditBuyerBottomSheet([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,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
RTextField(
|
|
||||||
controller: controller.buyerPhoneController,
|
|
||||||
label: 'تلفن خریدار',
|
|
||||||
keyboardType: TextInputType.phone,
|
|
||||||
borderColor: AppColor.darkGreyLight,
|
|
||||||
maxLength: 11,
|
|
||||||
validator: (value) {
|
|
||||||
if (value == null || value.isEmpty) {
|
|
||||||
return 'لطفاً شماره موبایل را وارد کنید';
|
|
||||||
}
|
|
||||||
// حذف کاماها برای اعتبارسنجی
|
|
||||||
String cleaned = value.replaceAll(',', '');
|
|
||||||
if (cleaned.length != 11) {
|
|
||||||
return 'شماره موبایل باید ۱۱ رقم باشد';
|
|
||||||
}
|
|
||||||
if (!cleaned.startsWith('09')) {
|
|
||||||
return 'شماره موبایل باید با 09 شروع شود';
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
RTextField(
|
|
||||||
controller: controller.buyerNameController,
|
|
||||||
label: 'نام خریدار',
|
|
||||||
borderColor: AppColor.darkGreyLight,
|
|
||||||
),
|
|
||||||
RTextField(
|
|
||||||
controller: controller.buyerLastNameController,
|
|
||||||
label: 'نام خانوادگی خریدار',
|
|
||||||
borderColor: AppColor.darkGreyLight,
|
|
||||||
),
|
|
||||||
|
|
||||||
RTextField(
|
|
||||||
controller: controller.buyerUnitNameController,
|
|
||||||
label: 'نام واحد',
|
|
||||||
borderColor: AppColor.darkGreyLight,
|
|
||||||
),
|
|
||||||
_provinceWidget(),
|
|
||||||
_cityWidget(),
|
|
||||||
submitButtonWidget(isOnEdit),
|
|
||||||
SizedBox(),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget submitButtonWidget(bool isOnEdit) {
|
|
||||||
return ObxValue((data) {
|
|
||||||
return RElevated(
|
|
||||||
text: isOnEdit ? 'ویرایش' : 'ثبت',
|
|
||||||
onPressed: data.value
|
|
||||||
? () async {
|
|
||||||
var res = await controller.createBuyer();
|
|
||||||
if (res) {
|
|
||||||
Get.back();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
: null,
|
|
||||||
height: 40,
|
|
||||||
);
|
|
||||||
}, controller.isBuyerSubmitButtonEnabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _provinceWidget() {
|
|
||||||
return Obx(() {
|
|
||||||
return OverlayDropdownWidget<IranProvinceCityModel>(
|
|
||||||
items: controller.rootLogic.provinces,
|
|
||||||
onChanged: (value) {
|
|
||||||
controller.selectedProvince.value = value;
|
|
||||||
print('Selected Product: ${value.name}');
|
|
||||||
},
|
|
||||||
selectedItem: controller.selectedProvince.value,
|
|
||||||
itemBuilder: (item) => Text(item.name ?? 'بدون نام'),
|
|
||||||
labelBuilder: (item) => Text(item?.name ?? 'انتخاب استان'),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _cityWidget() {
|
|
||||||
return ObxValue((data) {
|
|
||||||
return OverlayDropdownWidget<IranProvinceCityModel>(
|
|
||||||
items: data,
|
|
||||||
onChanged: (value) {
|
|
||||||
controller.selectedCity.value = value;
|
|
||||||
print('Selected Product: ${value.name}');
|
|
||||||
},
|
|
||||||
selectedItem: controller.selectedCity.value,
|
|
||||||
itemBuilder: (item) => Text(item.name ?? 'بدون نام'),
|
|
||||||
labelBuilder: (item) => Text(item?.name ?? 'انتخاب شهر'),
|
|
||||||
);
|
|
||||||
}, controller.cites);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,597 +0,0 @@
|
|||||||
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.saleLogic.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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,13 +1,8 @@
|
|||||||
import 'dart:io';
|
|
||||||
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:rasadyar_chicken/data/models/response/iran_province_city/iran_province_city_model.dart';
|
import 'package:rasadyar_chicken/presentation/pages/sales_out_of_province_buyers/view.dart';
|
||||||
import 'package:rasadyar_chicken/data/models/response/roles_products/roles_products.dart';
|
import 'package:rasadyar_chicken/presentation/pages/sales_out_of_province_sales_list/view.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/pages/buyers_page.dart';
|
|
||||||
import 'package:rasadyar_chicken/presentation/pages/sales_out_of_province/pages/sales_page.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/page_route.dart';
|
||||||
import 'package:rasadyar_core/core.dart';
|
import 'package:rasadyar_core/core.dart';
|
||||||
|
|
||||||
import 'logic.dart';
|
import 'logic.dart';
|
||||||
@@ -18,12 +13,22 @@ class SalesOutOfProvincePage extends GetView<SalesOutOfProvinceLogic> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BasePage(
|
return BasePage(
|
||||||
routes: controller.routesName,
|
routesWidget: ObxValue(
|
||||||
|
(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(),
|
||||||
widgets: [
|
widgets: [
|
||||||
segmentWidget()
|
segmentWidget(),
|
||||||
|
Expanded(
|
||||||
|
child: ObxValue((index) {
|
||||||
|
return index.value == 0
|
||||||
|
? SalesOutOfProvinceSalesListPage()
|
||||||
|
: SalesOutOfProvinceBuyersPage();
|
||||||
|
}, controller.selectedSegmentIndex),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -35,12 +40,13 @@ class SalesOutOfProvincePage extends GetView<SalesOutOfProvinceLogic> {
|
|||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: RSegment(
|
child: RSegment(
|
||||||
children: ['در انتظار', 'همه'],
|
children: ['فروش', 'خریداران'],
|
||||||
selectedIndex: 0,
|
selectedIndex: controller.selectedSegmentIndex.value,
|
||||||
borderColor: const Color(0xFFB4B4B4),
|
borderColor: const Color(0xFFB4B4B4),
|
||||||
selectedBorderColor: AppColor.blueNormal,
|
selectedBorderColor: AppColor.blueNormal,
|
||||||
selectedBackgroundColor: AppColor.blueLight,
|
selectedBackgroundColor: AppColor.blueLight,
|
||||||
onSegmentSelected: (index) => controller.selectedSegmentIndex.value = index,
|
onSegmentSelected: (index) =>
|
||||||
|
controller.selectedSegmentIndex.value = index,
|
||||||
backgroundColor: AppColor.whiteGreyNormal,
|
backgroundColor: AppColor.whiteGreyNormal,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -55,14 +61,20 @@ class SalesOutOfProvincePage extends GetView<SalesOutOfProvinceLogic> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
spacing: 16,
|
spacing: 16,
|
||||||
children: [
|
children: [
|
||||||
Text('فیلترها', style: AppFonts.yekan16Bold.copyWith(color: AppColor.darkGreyDarkHover)),
|
Text(
|
||||||
|
'فیلترها',
|
||||||
|
style: AppFonts.yekan16Bold.copyWith(
|
||||||
|
color: AppColor.darkGreyDarkHover,
|
||||||
|
),
|
||||||
|
),
|
||||||
Row(
|
Row(
|
||||||
spacing: 8,
|
spacing: 8,
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: dateFilterWidget(
|
child: dateFilterWidget(
|
||||||
date: controller.fromDateFilter,
|
date: controller.fromDateFilter,
|
||||||
onChanged: (jalali) => controller.fromDateFilter.value = jalali,
|
onChanged: (jalali) =>
|
||||||
|
controller.fromDateFilter.value = jalali,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
@@ -88,5 +100,4 @@ class SalesOutOfProvincePage extends GetView<SalesOutOfProvinceLogic> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:rasadyar_core/core.dart';
|
|
||||||
|
|
||||||
Widget emptyWidget() {
|
|
||||||
return Expanded(
|
|
||||||
child: Center(
|
|
||||||
child: Text('داده ای دریافت نشد!', style: AppFonts.yekan16.copyWith(color: AppColor.darkGreyDarkHover)),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:rasadyar_core/core.dart';
|
|
||||||
|
|
||||||
ObxValue<RxBool> searchWidget(
|
|
||||||
RxBool searchIsSelected,
|
|
||||||
void Function(String) onChanged,
|
|
||||||
) {
|
|
||||||
return ObxValue((data) {
|
|
||||||
return AnimatedContainer(
|
|
||||||
duration: Duration(milliseconds: 300),
|
|
||||||
padding: EdgeInsets.only(top: 5),
|
|
||||||
curve: Curves.easeInOut,
|
|
||||||
height: data.value ? 50 : 0,
|
|
||||||
child: Visibility(
|
|
||||||
visible: data.value,
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
|
||||||
child: RTextField(
|
|
||||||
suffixIcon: Padding(
|
|
||||||
padding: const EdgeInsets.all(12.0),
|
|
||||||
child: Assets.vec.searchSvg.svg(
|
|
||||||
width: 10,
|
|
||||||
height: 10,
|
|
||||||
colorFilter: ColorFilter.mode(
|
|
||||||
AppColor.blueNormal,
|
|
||||||
BlendMode.srcIn,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
hintText: 'جستجو',
|
|
||||||
onChanged: onChanged,
|
|
||||||
controller: TextEditingController(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}, searchIsSelected);
|
|
||||||
}
|
|
||||||
@@ -1,15 +1,208 @@
|
|||||||
import 'package:get/get.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:rasadyar_auth/data/utils/safe_call.dart';
|
||||||
|
import 'package:rasadyar_chicken/data/models/response/iran_province_city/iran_province_city_model.dart';
|
||||||
|
import 'package:rasadyar_chicken/data/models/response/out_province_carcasses_buyer/out_province_carcasses_buyer.dart';
|
||||||
|
import 'package:rasadyar_chicken/presentation/pages/root/logic.dart';
|
||||||
|
import 'package:rasadyar_chicken/presentation/pages/sale/logic.dart';
|
||||||
|
import 'package:rasadyar_chicken/presentation/pages/sales_out_of_province/logic.dart';
|
||||||
|
import 'package:rasadyar_chicken/presentation/utils/utils.dart';
|
||||||
|
import 'package:rasadyar_core/core.dart';
|
||||||
|
|
||||||
class SalesOutOfProvinceBuyersLogic extends GetxController {
|
class SalesOutOfProvinceBuyersLogic extends GetxController {
|
||||||
|
RootLogic get rootLogic => Get.find<RootLogic>();
|
||||||
|
|
||||||
|
SaleLogic get saleLogic => Get.find<SaleLogic>();
|
||||||
|
|
||||||
|
SalesOutOfProvinceLogic get saleOutOfProvince =>
|
||||||
|
Get.find<SalesOutOfProvinceLogic>();
|
||||||
|
|
||||||
|
RxInt currentPage = 1.obs;
|
||||||
|
RxList<int> isExpandedList = <int>[].obs;
|
||||||
|
Rx<Jalali> fromDateFilter = Jalali.now().obs;
|
||||||
|
Rx<Jalali> toDateFilter = Jalali.now().obs;
|
||||||
|
RxnString searchedValue = RxnString();
|
||||||
|
|
||||||
|
RxBool isLoadingMoreAllocationsMade = false.obs;
|
||||||
|
RxBool isBuyerSubmitButtonEnabled = false.obs;
|
||||||
|
|
||||||
|
RxList<IranProvinceCityModel> cites = <IranProvinceCityModel>[].obs;
|
||||||
|
Rxn<IranProvinceCityModel> selectedProvince = Rxn();
|
||||||
|
Rxn<IranProvinceCityModel> selectedCity = Rxn();
|
||||||
|
|
||||||
|
GlobalKey<FormState> formKey = GlobalKey<FormState>();
|
||||||
|
TextEditingController buyerNameController = TextEditingController();
|
||||||
|
TextEditingController buyerLastNameController = TextEditingController();
|
||||||
|
TextEditingController buyerPhoneController = TextEditingController();
|
||||||
|
TextEditingController buyerUnitNameController = TextEditingController();
|
||||||
|
String? key;
|
||||||
|
|
||||||
|
Rx<Resource<PaginationModel<OutProvinceCarcassesBuyer>>> buyerList =
|
||||||
|
Resource<PaginationModel<OutProvinceCarcassesBuyer>>.loading().obs;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onInit() {
|
||||||
|
super.onInit();
|
||||||
|
getOutProvinceCarcassesBuyer();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onReady() {
|
void onReady() {
|
||||||
// TODO: implement onReady
|
|
||||||
super.onReady();
|
super.onReady();
|
||||||
|
|
||||||
|
selectedProvince.listen((p0) => getCites());
|
||||||
|
|
||||||
|
debounce(
|
||||||
|
searchedValue,
|
||||||
|
(callback) => getOutProvinceCarcassesBuyer(),
|
||||||
|
time: Duration(milliseconds: timeDebounce),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onClose() {
|
void onClose() {
|
||||||
// TODO: implement onClose
|
buyerNameController.dispose();
|
||||||
|
buyerLastNameController.dispose();
|
||||||
|
buyerPhoneController.dispose();
|
||||||
|
buyerUnitNameController.dispose();
|
||||||
|
selectedCity.value = null;
|
||||||
|
selectedProvince.value = null;
|
||||||
|
isExpandedList.clear();
|
||||||
super.onClose();
|
super.onClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> getOutProvinceCarcassesBuyer([
|
||||||
|
bool isLoadingMore = false,
|
||||||
|
]) async {
|
||||||
|
if (isLoadingMore) {
|
||||||
|
isLoadingMoreAllocationsMade.value = true;
|
||||||
|
} else {
|
||||||
|
buyerList.value =
|
||||||
|
Resource<PaginationModel<OutProvinceCarcassesBuyer>>.loading();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (searchedValue.value != null &&
|
||||||
|
searchedValue.value!.trim().isNotEmpty &&
|
||||||
|
currentPage.value > 1) {
|
||||||
|
currentPage.value = 1; // Reset to first page if search value is set
|
||||||
|
}
|
||||||
|
|
||||||
|
await safeCall(
|
||||||
|
call: () => rootLogic.chickenRepository.getOutProvinceCarcassesBuyer(
|
||||||
|
token: rootLogic.tokenService.accessToken.value!,
|
||||||
|
queryParameters: buildQueryParams(
|
||||||
|
pageSize: 20,
|
||||||
|
page: currentPage.value,
|
||||||
|
state: 'buyer-list',
|
||||||
|
search: 'filter',
|
||||||
|
role: 'Steward',
|
||||||
|
value: searchedValue.value ?? '',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onError: (error, stackTrace) =>
|
||||||
|
isLoadingMoreAllocationsMade.value = false,
|
||||||
|
onSuccess: (res) {
|
||||||
|
if ((res?.count ?? 0) == 0) {
|
||||||
|
buyerList.value =
|
||||||
|
Resource<PaginationModel<OutProvinceCarcassesBuyer>>.empty();
|
||||||
|
} else {
|
||||||
|
buyerList.value =
|
||||||
|
Resource<PaginationModel<OutProvinceCarcassesBuyer>>.success(
|
||||||
|
PaginationModel<OutProvinceCarcassesBuyer>(
|
||||||
|
count: res?.count ?? 0,
|
||||||
|
next: res?.next,
|
||||||
|
previous: res?.previous,
|
||||||
|
results: [
|
||||||
|
...(buyerList.value.data?.results ?? []),
|
||||||
|
...(res?.results ?? []),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
isLoadingMoreAllocationsMade.value = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void resetSubmitForm() {
|
||||||
|
buyerNameController.clear();
|
||||||
|
buyerLastNameController.clear();
|
||||||
|
buyerPhoneController.clear();
|
||||||
|
buyerUnitNameController.clear();
|
||||||
|
selectedProvince.value = null;
|
||||||
|
selectedCity.value = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> getCites() async {
|
||||||
|
await safeCall(
|
||||||
|
call: () => rootLogic.chickenRepository.getCity(
|
||||||
|
provinceName: selectedProvince.value?.name ?? '',
|
||||||
|
),
|
||||||
|
onSuccess: (result) {
|
||||||
|
if (result != null && result.isNotEmpty) {
|
||||||
|
cites.value = result;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setupListeners() {
|
||||||
|
buyerNameController.addListener(checkBuyerFormValid);
|
||||||
|
buyerLastNameController.addListener(checkBuyerFormValid);
|
||||||
|
buyerPhoneController.addListener(checkBuyerFormValid);
|
||||||
|
buyerUnitNameController.addListener(checkBuyerFormValid);
|
||||||
|
ever(selectedProvince, (_) => checkBuyerFormValid());
|
||||||
|
ever(selectedCity, (_) => checkBuyerFormValid());
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkBuyerFormValid() {
|
||||||
|
isBuyerSubmitButtonEnabled.value =
|
||||||
|
buyerNameController.text.isNotEmpty &&
|
||||||
|
buyerLastNameController.text.isNotEmpty &&
|
||||||
|
buyerPhoneController.text.isNotEmpty &&
|
||||||
|
buyerUnitNameController.text.isNotEmpty &&
|
||||||
|
selectedProvince.value != null &&
|
||||||
|
selectedCity.value != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> createBuyer() async {
|
||||||
|
bool res = false;
|
||||||
|
if (!(formKey.currentState?.validate() ?? false)) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
await safeCall(
|
||||||
|
call: () async {
|
||||||
|
OutProvinceCarcassesBuyer buyer = OutProvinceCarcassesBuyer(
|
||||||
|
province: selectedProvince.value!.name,
|
||||||
|
city: selectedCity.value!.name,
|
||||||
|
firstName: buyerNameController.text,
|
||||||
|
lastName: buyerLastNameController.text,
|
||||||
|
unitName: buyerUnitNameController.text,
|
||||||
|
mobile: buyerPhoneController.text,
|
||||||
|
role: 'Steward',
|
||||||
|
);
|
||||||
|
final res = await rootLogic.chickenRepository
|
||||||
|
.createOutProvinceCarcassesBuyer(
|
||||||
|
token: rootLogic.tokenService.accessToken.value!,
|
||||||
|
body: buyer,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
onSuccess: (result) {
|
||||||
|
getOutProvinceCarcassesBuyer();
|
||||||
|
resetSubmitForm();
|
||||||
|
res = true;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
isBuyerSubmitButtonEnabled.value = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,272 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:rasadyar_chicken/data/models/response/iran_province_city/iran_province_city_model.dart';
|
||||||
|
import 'package:rasadyar_chicken/data/models/response/out_province_carcasses_buyer/out_province_carcasses_buyer.dart';
|
||||||
|
import 'package:rasadyar_chicken/presentation/widget/list_item/list_item.dart';
|
||||||
|
import 'package:rasadyar_chicken/presentation/widget/list_row_item.dart';
|
||||||
|
import 'package:rasadyar_core/core.dart';
|
||||||
|
|
||||||
import 'logic.dart';
|
import 'logic.dart';
|
||||||
|
|
||||||
class SalesOutOfProvinceBuyersPage extends StatelessWidget {
|
class SalesOutOfProvinceBuyersPage
|
||||||
const SalesOutOfProvinceBuyersPage({Key? key}) : super(key: key);
|
extends GetView<SalesOutOfProvinceBuyersLogic> {
|
||||||
|
const SalesOutOfProvinceBuyersPage({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final SalesOutOfProvinceBuyersLogic logic = Get.put(SalesOutOfProvinceBuyersLogic());
|
return Scaffold(
|
||||||
|
body: ObxValue((data) {
|
||||||
|
return RPaginatedListView(
|
||||||
|
onLoadMore: () async => controller.getOutProvinceCarcassesBuyer(true),
|
||||||
|
onRefresh: () async {
|
||||||
|
controller.currentPage.value = 1;
|
||||||
|
await controller.getOutProvinceCarcassesBuyer();
|
||||||
|
},
|
||||||
|
listType: ListType.separated,
|
||||||
|
resource: data.value,
|
||||||
|
padding: EdgeInsets.fromLTRB(8, 8, 8, 80),
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
var item = data.value.data!.results![index];
|
||||||
|
return ObxValue((val) {
|
||||||
|
return ListItem2(
|
||||||
|
selected: val.contains(index),
|
||||||
|
onTap: () => controller.isExpandedList.toggle(index),
|
||||||
|
index: index,
|
||||||
|
child: itemListWidget(item),
|
||||||
|
secondChild: itemListExpandedWidget(item),
|
||||||
|
labelColor: AppColor.blueLight,
|
||||||
|
labelIcon: Assets.vec.timerSvg.path,
|
||||||
|
);
|
||||||
|
}, controller.isExpandedList);
|
||||||
|
},
|
||||||
|
itemCount: data.value.data?.results?.length ?? 0,
|
||||||
|
separatorBuilder: (context, index) => SizedBox(height: 8.h),
|
||||||
|
);
|
||||||
|
}, controller.buyerList),
|
||||||
|
floatingActionButton: RFab.add(
|
||||||
|
onPressed: () {
|
||||||
|
Get.bottomSheet(
|
||||||
|
addOrEditBuyerBottomSheet(),
|
||||||
|
isScrollControlled: true,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
floatingActionButtonLocation: FloatingActionButtonLocation.startFloat,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return Container();
|
Widget addOrEditBuyerBottomSheet([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,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
RTextField(
|
||||||
|
controller: controller.buyerPhoneController,
|
||||||
|
label: 'تلفن خریدار',
|
||||||
|
keyboardType: TextInputType.phone,
|
||||||
|
borderColor: AppColor.darkGreyLight,
|
||||||
|
maxLength: 11,
|
||||||
|
validator: (value) {
|
||||||
|
if (value == null || value.isEmpty) {
|
||||||
|
return 'لطفاً شماره موبایل را وارد کنید';
|
||||||
|
}
|
||||||
|
// حذف کاماها برای اعتبارسنجی
|
||||||
|
String cleaned = value.replaceAll(',', '');
|
||||||
|
if (cleaned.length != 11) {
|
||||||
|
return 'شماره موبایل باید ۱۱ رقم باشد';
|
||||||
|
}
|
||||||
|
if (!cleaned.startsWith('09')) {
|
||||||
|
return 'شماره موبایل باید با 09 شروع شود';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
RTextField(
|
||||||
|
controller: controller.buyerNameController,
|
||||||
|
label: 'نام خریدار',
|
||||||
|
borderColor: AppColor.darkGreyLight,
|
||||||
|
),
|
||||||
|
RTextField(
|
||||||
|
controller: controller.buyerLastNameController,
|
||||||
|
label: 'نام خانوادگی خریدار',
|
||||||
|
borderColor: AppColor.darkGreyLight,
|
||||||
|
),
|
||||||
|
|
||||||
|
RTextField(
|
||||||
|
controller: controller.buyerUnitNameController,
|
||||||
|
label: 'نام واحد',
|
||||||
|
borderColor: AppColor.darkGreyLight,
|
||||||
|
),
|
||||||
|
_provinceWidget(),
|
||||||
|
_cityWidget(),
|
||||||
|
submitButtonWidget(isOnEdit),
|
||||||
|
SizedBox(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget submitButtonWidget(bool isOnEdit) {
|
||||||
|
return ObxValue((data) {
|
||||||
|
return RElevated(
|
||||||
|
text: isOnEdit ? 'ویرایش' : 'ثبت',
|
||||||
|
onPressed: data.value
|
||||||
|
? () async {
|
||||||
|
var res = await controller.createBuyer();
|
||||||
|
if (res) {
|
||||||
|
Get.back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
height: 40,
|
||||||
|
);
|
||||||
|
}, controller.isBuyerSubmitButtonEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _provinceWidget() {
|
||||||
|
return Obx(() {
|
||||||
|
return OverlayDropdownWidget<IranProvinceCityModel>(
|
||||||
|
items: controller.rootLogic.provinces,
|
||||||
|
onChanged: (value) {
|
||||||
|
controller.selectedProvince.value = value;
|
||||||
|
print('Selected Product: ${value.name}');
|
||||||
|
},
|
||||||
|
selectedItem: controller.selectedProvince.value,
|
||||||
|
itemBuilder: (item) => Text(item.name ?? 'بدون نام'),
|
||||||
|
labelBuilder: (item) => Text(item?.name ?? 'انتخاب استان'),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _cityWidget() {
|
||||||
|
return ObxValue((data) {
|
||||||
|
return OverlayDropdownWidget<IranProvinceCityModel>(
|
||||||
|
items: data,
|
||||||
|
onChanged: (value) {
|
||||||
|
controller.selectedCity.value = value;
|
||||||
|
print('Selected Product: ${value.name}');
|
||||||
|
},
|
||||||
|
selectedItem: controller.selectedCity.value,
|
||||||
|
itemBuilder: (item) => Text(item.name ?? 'بدون نام'),
|
||||||
|
labelBuilder: (item) => Text(item?.name ?? 'انتخاب شهر'),
|
||||||
|
);
|
||||||
|
}, controller.cites);
|
||||||
|
}
|
||||||
|
|
||||||
|
itemListWidget(OutProvinceCarcassesBuyer item) {
|
||||||
|
return Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
|
children: [
|
||||||
|
SizedBox(width: 12),
|
||||||
|
|
||||||
|
Expanded(
|
||||||
|
flex: 2,
|
||||||
|
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),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
Expanded(
|
||||||
|
flex: 2,
|
||||||
|
child: Text(
|
||||||
|
'${item.unitName}',
|
||||||
|
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.darkGreyDark),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
itemListExpandedWidget(OutProvinceCarcassesBuyer item) {
|
||||||
|
return 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.setEditDataBuyer(item);
|
||||||
|
Get.bottomSheet(
|
||||||
|
addOrEditBuyerBottomSheet(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),
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
buildRow(title: 'مشخصات خریدار', value: item.fullname ?? 'N/A'),
|
||||||
|
buildRow(title: 'نام واحد', value: item.unitName ?? 'N/A'),
|
||||||
|
buildRow(
|
||||||
|
title: 'تعداد درخواست ها',
|
||||||
|
value: '${item.requestsInfo?.numberOfRequests.separatedByComma}',
|
||||||
|
),
|
||||||
|
buildRow(
|
||||||
|
title: 'وزن',
|
||||||
|
value: '${item.requestsInfo?.totalWeight.separatedByComma}',
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,213 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:rasadyar_auth/data/utils/safe_call.dart';
|
||||||
|
import 'package:rasadyar_chicken/data/models/request/steward_free_sale_bar/steward_free_sale_bar_request.dart';
|
||||||
|
import 'package:rasadyar_chicken/data/models/response/iran_province_city/iran_province_city_model.dart';
|
||||||
|
import 'package:rasadyar_chicken/data/models/response/out_province_carcasses_buyer/out_province_carcasses_buyer.dart';
|
||||||
|
import 'package:rasadyar_chicken/data/models/response/roles_products/roles_products.dart';
|
||||||
|
import 'package:rasadyar_chicken/data/models/response/steward_free_sale_bar/steward_free_sale_bar.dart';
|
||||||
|
import 'package:rasadyar_chicken/presentation/pages/root/logic.dart';
|
||||||
|
import 'package:rasadyar_chicken/presentation/pages/sale/logic.dart';
|
||||||
|
import 'package:rasadyar_chicken/presentation/pages/sales_out_of_province_buyers/logic.dart';
|
||||||
|
import 'package:rasadyar_chicken/presentation/utils/utils.dart';
|
||||||
|
import 'package:rasadyar_core/core.dart';
|
||||||
|
|
||||||
|
class SalesOutOfProvinceSalesListLogic extends GetxController {
|
||||||
|
RootLogic get rootLogic => Get.find<RootLogic>();
|
||||||
|
|
||||||
|
SaleLogic get saleLogic => Get.find<SaleLogic>();
|
||||||
|
|
||||||
|
SalesOutOfProvinceBuyersLogic get buyerLogic =>
|
||||||
|
Get.find<SalesOutOfProvinceBuyersLogic>();
|
||||||
|
|
||||||
|
RxInt selectedSegmentIndex = 0.obs;
|
||||||
|
RxBool isExpanded = false.obs;
|
||||||
|
RxInt currentPage = 1.obs;
|
||||||
|
RxBool isSaleSubmitButtonEnabled = false.obs;
|
||||||
|
RxList<int> isExpandedList = <int>[].obs;
|
||||||
|
Rx<Jalali> fromDateFilter = Jalali.now().obs;
|
||||||
|
Rx<Jalali> toDateFilter = Jalali.now().obs;
|
||||||
|
RxnString searchedValue = RxnString();
|
||||||
|
RxList<String> routesName = RxList();
|
||||||
|
RxBool isLoadingMoreAllocationsMade = false.obs;
|
||||||
|
Rxn<IranProvinceCityModel> selectedCity = Rxn();
|
||||||
|
|
||||||
|
//TODO add this to Di
|
||||||
|
ImagePicker imagePicker = ImagePicker();
|
||||||
|
|
||||||
|
GlobalKey<FormState> formKey = GlobalKey<FormState>();
|
||||||
|
TextEditingController quarantineCodeController = TextEditingController();
|
||||||
|
TextEditingController saleWeightController = TextEditingController();
|
||||||
|
Rx<Jalali> saleDate = Jalali.now().obs;
|
||||||
|
String? key;
|
||||||
|
|
||||||
|
Rx<Resource<PaginationModel<StewardFreeSaleBar>>> salesList =
|
||||||
|
Resource<PaginationModel<StewardFreeSaleBar>>.loading().obs;
|
||||||
|
|
||||||
|
Rxn<ProductModel> selectedProduct = Rxn();
|
||||||
|
Rxn<OutProvinceCarcassesBuyer> selectedBuyer = Rxn();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onInit() {
|
||||||
|
super.onInit();
|
||||||
|
getOutProvinceSales();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onReady() {
|
||||||
|
super.onReady();
|
||||||
|
|
||||||
|
debounce(
|
||||||
|
searchedValue,
|
||||||
|
(callback) => getOutProvinceSales(),
|
||||||
|
time: Duration(milliseconds: timeDebounce),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onClose() {
|
||||||
|
// TODO: implement onClose
|
||||||
|
super.onClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> getOutProvinceSales([bool isLoadingMore = false]) async {
|
||||||
|
if (isLoadingMore) {
|
||||||
|
isLoadingMoreAllocationsMade.value = true;
|
||||||
|
} else {
|
||||||
|
salesList.value = Resource<PaginationModel<StewardFreeSaleBar>>.loading();
|
||||||
|
}
|
||||||
|
await safeCall(
|
||||||
|
call: () => rootLogic.chickenRepository.getStewardFreeSaleBar(
|
||||||
|
token: rootLogic.tokenService.accessToken.value!,
|
||||||
|
queryParameters: buildQueryParams(
|
||||||
|
pageSize: 20,
|
||||||
|
page: currentPage.value,
|
||||||
|
state: 'buyer-list',
|
||||||
|
search: 'filter',
|
||||||
|
role: 'Steward',
|
||||||
|
value: searchedValue.value ?? '',
|
||||||
|
fromDate: fromDateFilter.value.toDateTime(),
|
||||||
|
toDate: toDateFilter.value.toDateTime(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onSuccess: (res) {
|
||||||
|
if ((res?.count ?? 0) == 0) {
|
||||||
|
salesList.value =
|
||||||
|
Resource<PaginationModel<StewardFreeSaleBar>>.empty();
|
||||||
|
} else {
|
||||||
|
salesList.value =
|
||||||
|
Resource<PaginationModel<StewardFreeSaleBar>>.success(
|
||||||
|
PaginationModel<StewardFreeSaleBar>(
|
||||||
|
count: res?.count ?? 0,
|
||||||
|
next: res?.next,
|
||||||
|
previous: res?.previous,
|
||||||
|
results: [
|
||||||
|
...(salesList.value.data?.results ?? []),
|
||||||
|
...(res?.results ?? []),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
isLoadingMoreAllocationsMade.value = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setupListeners() {
|
||||||
|
saleWeightController.addListener(checkSalesFormValid);
|
||||||
|
quarantineCodeController.addListener(checkSalesFormValid);
|
||||||
|
ever(selectedBuyer, (_) => checkSalesFormValid);
|
||||||
|
ever(selectedProduct, (_) => checkSalesFormValid);
|
||||||
|
ever(saleDate, (_) => checkSalesFormValid());
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkSalesFormValid() {
|
||||||
|
isSaleSubmitButtonEnabled.value =
|
||||||
|
saleDate.value.toString().isNotEmpty &&
|
||||||
|
selectedProduct.value != null &&
|
||||||
|
selectedBuyer.value != null &&
|
||||||
|
saleWeightController.text.isNotEmpty &&
|
||||||
|
quarantineCodeController.text.isNotEmpty;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setEditDataSales(StewardFreeSaleBar item) {
|
||||||
|
quarantineCodeController.text = item.clearanceCode ?? '';
|
||||||
|
saleWeightController.text =
|
||||||
|
item.weightOfCarcasses?.toInt().toString() ?? '';
|
||||||
|
saleDate.value = Jalali.fromDateTime(DateTime.parse(item.date!));
|
||||||
|
selectedCity.value = IranProvinceCityModel(name: item.city);
|
||||||
|
selectedBuyer.value = buyerLogic.buyerList.value.data?.results?.firstWhere(
|
||||||
|
(element) => element.key == item.buyer?.key,
|
||||||
|
);
|
||||||
|
selectedProduct.value = saleLogic.rolesProductsModel.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,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void resetSubmitForm() {
|
||||||
|
selectedCity.value = null;
|
||||||
|
selectedProduct.value = null;
|
||||||
|
key = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,429 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:rasadyar_chicken/data/models/response/out_province_carcasses_buyer/out_province_carcasses_buyer.dart';
|
||||||
|
import 'package:rasadyar_chicken/data/models/response/roles_products/roles_products.dart';
|
||||||
|
import 'package:rasadyar_chicken/data/models/response/steward_free_sale_bar/steward_free_sale_bar.dart';
|
||||||
|
import 'package:rasadyar_chicken/presentation/widget/list_item/list_item.dart';
|
||||||
|
import 'package:rasadyar_chicken/presentation/widget/list_row_item.dart';
|
||||||
|
import 'package:rasadyar_core/core.dart';
|
||||||
|
|
||||||
|
import 'logic.dart';
|
||||||
|
|
||||||
|
class SalesOutOfProvinceSalesListPage
|
||||||
|
extends GetView<SalesOutOfProvinceSalesListLogic> {
|
||||||
|
const SalesOutOfProvinceSalesListPage({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
body: ObxValue((data) {
|
||||||
|
return RPaginatedListView(
|
||||||
|
onLoadMore: () async => controller.getOutProvinceSales(true),
|
||||||
|
onRefresh: () async {
|
||||||
|
controller.currentPage.value = 1;
|
||||||
|
await controller.getOutProvinceSales();
|
||||||
|
},
|
||||||
|
listType: ListType.separated,
|
||||||
|
resource: data.value,
|
||||||
|
padding: EdgeInsets.fromLTRB(8, 8, 8, 80),
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
var item = data.value.data!.results![index];
|
||||||
|
return ObxValue((val) {
|
||||||
|
return ListItem2(
|
||||||
|
selected: val.contains(index),
|
||||||
|
onTap: () => controller.isExpandedList.toggle(index),
|
||||||
|
index: index,
|
||||||
|
child: itemListWidget(item),
|
||||||
|
secondChild: itemListExpandedWidget(item),
|
||||||
|
labelColor: AppColor.blueLight,
|
||||||
|
labelIcon: Assets.vec.timerSvg.path,
|
||||||
|
);
|
||||||
|
}, controller.isExpandedList);
|
||||||
|
},
|
||||||
|
itemCount: data.value.data?.results?.length ?? 0,
|
||||||
|
separatorBuilder: (context, index) => SizedBox(height: 8.h),
|
||||||
|
);
|
||||||
|
}, controller.salesList),
|
||||||
|
floatingActionButton: RFab.add(
|
||||||
|
onPressed: () {
|
||||||
|
Get.bottomSheet(addOrEditSaleBottomSheet(), isScrollControlled: true);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
floatingActionButtonLocation: FloatingActionButtonLocation.startFloat,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
itemListWidget(StewardFreeSaleBar item) {
|
||||||
|
return Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
|
children: [
|
||||||
|
SizedBox(width: 12),
|
||||||
|
Expanded(
|
||||||
|
flex: 3,
|
||||||
|
child: Text(
|
||||||
|
item.date?.formattedJalaliDate ?? 'N/A',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: AppFonts.yekan12.copyWith(color: AppColor.bgDark),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(width: 4),
|
||||||
|
Expanded(
|
||||||
|
flex: 5,
|
||||||
|
child: Column(
|
||||||
|
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),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
itemListExpandedWidget(StewardFreeSaleBar item) {
|
||||||
|
return 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!),
|
||||||
|
onRefresh: () => controller.getOutProvinceSales(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
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(
|
||||||
|
title: 'تاریخ',
|
||||||
|
value: item.date?.formattedJalaliDateYHMS ?? 'N/A',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
buildRow(
|
||||||
|
title: 'مشخصات خریدار',
|
||||||
|
value: item.buyer?.fullname ?? 'N/A',
|
||||||
|
),
|
||||||
|
buildRow(title: 'تلفن خریدار', value: item.buyer?.mobile ?? 'N/A'),
|
||||||
|
buildRow(title: 'نام واحد', value: item.buyer?.unitName ?? 'N/A'),
|
||||||
|
buildRow(
|
||||||
|
title: 'وزن لاشه',
|
||||||
|
value: '${item.weightOfCarcasses?.separatedByComma}',
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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.buyerLogic.buyerList.value.data?.results ?? [],
|
||||||
|
onChanged: (value) {
|
||||||
|
controller.selectedBuyer.value = value;
|
||||||
|
},
|
||||||
|
selectedItem: controller.selectedBuyer.value,
|
||||||
|
itemBuilder: (item) => Text(item.buyer?.fullname ?? 'بدون نام'),
|
||||||
|
labelBuilder: (item) => Text(item?.buyer?.fullname ?? 'انتخاب خریدار'),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _productWidget() {
|
||||||
|
return ObxValue((data) {
|
||||||
|
return OverlayDropdownWidget<ProductModel>(
|
||||||
|
items: controller.saleLogic.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;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,6 +22,9 @@ import 'package:rasadyar_chicken/presentation/widget/base_page/logic.dart';
|
|||||||
import 'package:rasadyar_chicken/presentation/widget/search/logic.dart';
|
import 'package:rasadyar_chicken/presentation/widget/search/logic.dart';
|
||||||
import 'package:rasadyar_core/core.dart';
|
import 'package:rasadyar_core/core.dart';
|
||||||
|
|
||||||
|
import '../pages/sales_out_of_province_buyers/logic.dart';
|
||||||
|
import '../pages/sales_out_of_province_sales_list/logic.dart';
|
||||||
|
|
||||||
sealed class ChickenPages {
|
sealed class ChickenPages {
|
||||||
ChickenPages._();
|
ChickenPages._();
|
||||||
|
|
||||||
@@ -80,10 +83,13 @@ sealed class ChickenPages {
|
|||||||
page: () => SalesOutOfProvincePage(),
|
page: () => SalesOutOfProvincePage(),
|
||||||
middlewares: [AuthMiddleware()],
|
middlewares: [AuthMiddleware()],
|
||||||
binding: BindingsBuilder(() {
|
binding: BindingsBuilder(() {
|
||||||
Get.lazyPut(() => SalesOutOfProvinceLogic());
|
|
||||||
Get.lazyPut(() => RootLogic());
|
Get.lazyPut(() => RootLogic());
|
||||||
Get.lazyPut(() => BaseLogic());
|
Get.lazyPut(() => BaseLogic());
|
||||||
Get.lazyPut(() => SearchLogic());
|
Get.lazyPut(() => SearchLogic());
|
||||||
|
Get.lazyPut(() => SalesOutOfProvinceLogic());
|
||||||
|
Get.lazyPut(() => SalesOutOfProvinceBuyersLogic());
|
||||||
|
Get.lazyPut(() => SalesOutOfProvinceSalesListLogic());
|
||||||
|
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
GetPage(
|
GetPage(
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
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';
|
||||||
@@ -16,4 +17,5 @@ abstract class PaginationModel<T> with _$PaginationModel<T> {
|
|||||||
Map<String, dynamic> json,
|
Map<String, dynamic> json,
|
||||||
T Function(Object?) fromJsonT,
|
T Function(Object?) fromJsonT,
|
||||||
) => _$PaginationModelFromJson(json, fromJsonT);
|
) => _$PaginationModelFromJson(json, fromJsonT);
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user