From 4c22d1666eb59ac12854ba84e637d964674680e8 Mon Sep 17 00:00:00 2001 From: "mr.mojtaba" Date: Sun, 22 Jun 2025 16:51:22 +0330 Subject: [PATCH] fix : sale out of Province --- assets/icons/hot_chicken.svg | 5 + .../lib/presentation/pages/home/logic.dart | 14 +- .../lib/presentation/pages/home/view.dart | 285 +++------ .../pages/out_of_province/logic.dart | 17 - .../pages/out_of_province/view.dart | 575 +----------------- .../lib/presentation/pages/root/logic.dart | 8 +- .../lib/presentation/pages/root/view.dart | 8 +- .../pages/sales_out_of_province/logic.dart | 69 ++- .../pages/sales_out_of_province/view.dart | 467 ++++++++------ .../lib/presentation/routes/pages.dart | 23 +- packages/core/lib/core.dart | 2 + .../lib/presentation/common/assets.gen.dart | 8 + .../presentation/widget/inputs/r_input.dart | 4 + .../widget/overlay_dropdown_widget/view.dart | 99 ++- packages/core/lib/utils/num_utils.dart | 2 +- .../lib/utils/separator_input_formatter.dart | 27 + packages/core/lib/utils/string_utils.dart | 11 + 17 files changed, 536 insertions(+), 1088 deletions(-) create mode 100644 assets/icons/hot_chicken.svg create mode 100644 packages/core/lib/utils/separator_input_formatter.dart create mode 100644 packages/core/lib/utils/string_utils.dart diff --git a/assets/icons/hot_chicken.svg b/assets/icons/hot_chicken.svg new file mode 100644 index 0000000..17b35aa --- /dev/null +++ b/assets/icons/hot_chicken.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/packages/chicken/lib/presentation/pages/home/logic.dart b/packages/chicken/lib/presentation/pages/home/logic.dart index 4360c92..bb344e2 100644 --- a/packages/chicken/lib/presentation/pages/home/logic.dart +++ b/packages/chicken/lib/presentation/pages/home/logic.dart @@ -7,7 +7,7 @@ import 'package:rasadyar_chicken/presentation/utils/utils.dart'; import 'package:rasadyar_core/core.dart'; class HomeLogic extends GetxController { - RootLogic root = Get.find(); + RootLogic rootLogic = Get.find(); RxnInt totalWeightTodayBars = RxnInt(); Rxn inventoryModel = Rxn(); Rxn killHouseDistributionInfo = Rxn(); @@ -23,8 +23,8 @@ class HomeLogic extends GetxController { Future getTodayBars() async { await safeCall( - call: () async => await root.chickenRepository.getGeneralBarInformation( - token: root.tokenService.accessToken.value!, + call: () async => await rootLogic.chickenRepository.getGeneralBarInformation( + token: rootLogic.tokenService.accessToken.value!, queryParameters: buildQueryParams(fromDate: DateTime.now(), toDate: DateTime.now()), ), onSuccess: (result) { @@ -49,7 +49,7 @@ class HomeLogic extends GetxController { Future getInventory() async { await safeCall?>( - call: () async => await root.chickenRepository.getInventory(token: root.tokenService.accessToken.value!), + call: () async => await rootLogic.chickenRepository.getInventory(token: rootLogic.tokenService.accessToken.value!), onSuccess: (result) { if (result != null) { inventoryModel.value = result.first; @@ -72,12 +72,10 @@ class HomeLogic extends GetxController { Future getDistributionInformation() async { await safeCall( - call: () async => await root.chickenRepository.getIKillHouseDistributionInfo(token: root.tokenService.accessToken.value!), + call: () async => await rootLogic.chickenRepository.getIKillHouseDistributionInfo(token: rootLogic.tokenService.accessToken.value!), onSuccess: (result) { if (result != null) { - iLog(result); killHouseDistributionInfo.value = result; - iLog(killHouseDistributionInfo.value); } }, onError: (error, stackTrace) {}, @@ -87,7 +85,7 @@ class HomeLogic extends GetxController { void errorHandler(DioException error) { handleGeneric(error, () { - root.tokenService.deleteTokens(); + rootLogic.tokenService.deleteTokens(); }); } diff --git a/packages/chicken/lib/presentation/pages/home/view.dart b/packages/chicken/lib/presentation/pages/home/view.dart index fa00a71..718a0c8 100644 --- a/packages/chicken/lib/presentation/pages/home/view.dart +++ b/packages/chicken/lib/presentation/pages/home/view.dart @@ -2,6 +2,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:rasadyar_chicken/data/models/response/inventory/inventory_model.dart'; import 'package:rasadyar_chicken/data/models/response/kill_house_distribution_info/kill_house_distribution_info.dart'; +import 'package:rasadyar_chicken/presentation/routes/routes.dart'; import 'package:rasadyar_core/core.dart'; import 'logic.dart'; @@ -104,8 +105,12 @@ class HomePage extends GetView { widelyUsed( title: 'خرید خارج استان', iconPath: Assets.vec.cubeSearchSvg.path, - onTap: () { - // Get.toNamed(ChickenRoutes.enteringTheWarehouse); + onTap:() async{ + iLog('on tap :خرید خارج استان '); + controller.rootLogic.currentPage.value =1; + controller.rootLogic.currentPage.refresh(); + await Future.delayed(Duration(milliseconds: 100)); + Get.toNamed(ChickenRoutes.salesOutOfProvince, id: 1); }, ), SizedBox(width: 15), @@ -146,7 +151,7 @@ class HomePage extends GetView { child: _informationIconCard( title: 'توزیع داخل استان', isLoading: data.value == null, - description: data.value?.freeSalesWeight.toFormatted ?? '0', + description: data.value?.freeSalesWeight.separatedByComma ?? '0', iconPath: Assets.vec.truckSvg.path, iconColor: const Color.fromRGBO(85, 97, 93, 1), bgDescriptionColor: const Color(0xFFE6FAF5), @@ -157,7 +162,7 @@ class HomePage extends GetView { child: _informationIconCard( title: 'توزیع خارج استان', isLoading: data.value == null, - description: data.value?.stewardAllocationsWeight.toFormatted ?? '0', + description: data.value?.stewardAllocationsWeight.separatedByComma ?? '0', iconPath: Assets.vec.truckFastSvg.path, iconColor: Color(0xFF647379), bgDescriptionColor: const Color(0xFFEAEFFF), @@ -193,8 +198,8 @@ class HomePage extends GetView { isLoading: data.value == null, description: data.value != null ? ((data.value?.provinceGovernmentalCarcassesWeight ?? 0) + - (data.value?.provinceFreeCarcassesWeight ?? 0)) - .toFormatted + (data.value?.provinceFreeCarcassesWeight ?? 0)) + .separatedByComma : '0', iconPath: Assets.vec.a3dCubeSquareSvg.path, iconColor: const Color(0xFF6C5D60), @@ -206,7 +211,7 @@ class HomePage extends GetView { child: _informationLabelCard( title: 'خارج استان', isLoading: data.value == null, - description: data.value?.freeBuyingCarcassesWeight.toFormatted ?? '0', + description: data.value?.freeBuyingCarcassesWeight.separatedByComma ?? '0', iconPath: Assets.vec.cubeSearchSvg.path, iconColor: Color(0xFF2D5FFF), bgLabelColor: const Color(0xFFAFCBFF), @@ -230,7 +235,7 @@ class HomePage extends GetView { child: _informationLabelCard( title: 'مانده انبار', isLoading: data.value == null, - description: data.value?.totalRemainWeight.toFormatted ?? '0', + description: data.value?.totalRemainWeight.separatedByComma ?? '0', iconPath: Assets.vec.cubeSearchSvg.path, iconColor: const Color(0xFF426060), bgDescriptionColor: const Color(0xFFC7DFE0), @@ -241,7 +246,7 @@ class HomePage extends GetView { child: _informationLabelCard( title: 'توزیع شده', isLoading: data.value == null, - description: data.value?.realAllocatedWeight.toFormatted ?? '0', + description: data.value?.realAllocatedWeight.separatedByComma ?? '0', iconPath: Assets.vec.cubeRotateSvg.path, iconColor: Color(0xFF5C4D64), bgLabelColor: Color(0xFFC8B8D1), @@ -290,21 +295,21 @@ class HomePage extends GetView { child: data.value == null ? CupertinoActivityIndicator() : Column( - mainAxisAlignment: MainAxisAlignment.center, - spacing: 4, - children: [ - Text( - data.value.toFormatted, - textAlign: TextAlign.right, - style: AppFonts.yekan16.copyWith(color: AppColor.textColor), - ), - Text( - 'کیلوگرم', - textAlign: TextAlign.center, - style: AppFonts.yekan12.copyWith(color: AppColor.textColor), - ), - ], - ), + mainAxisAlignment: MainAxisAlignment.center, + spacing: 4, + children: [ + Text( + data.value.separatedByComma, + textAlign: TextAlign.right, + style: AppFonts.yekan16.copyWith(color: AppColor.textColor), + ), + Text( + 'کیلوگرم', + textAlign: TextAlign.center, + style: AppFonts.yekan12.copyWith(color: AppColor.textColor), + ), + ], + ), ), ], ), @@ -362,21 +367,21 @@ class HomePage extends GetView { child: isLoading ? Center(child: CupertinoActivityIndicator()) : Column( - mainAxisAlignment: MainAxisAlignment.center, - spacing: 4, - children: [ - Text( - description, - textAlign: TextAlign.right, - style: AppFonts.yekan16.copyWith(color: AppColor.mediumGreyDarkActive), - ), - Text( - unit, - textAlign: TextAlign.center, - style: AppFonts.yekan12.copyWith(color: AppColor.mediumGreyDarkActive), - ), - ], - ), + mainAxisAlignment: MainAxisAlignment.center, + spacing: 4, + children: [ + Text( + description, + textAlign: TextAlign.right, + style: AppFonts.yekan16.copyWith(color: AppColor.mediumGreyDarkActive), + ), + Text( + unit, + textAlign: TextAlign.center, + style: AppFonts.yekan12.copyWith(color: AppColor.mediumGreyDarkActive), + ), + ], + ), ), ), ], @@ -425,10 +430,10 @@ class HomePage extends GetView { isLoading ? Center(child: CupertinoActivityIndicator()) : Text( - description, - textAlign: TextAlign.right, - style: AppFonts.yekan16.copyWith(color: AppColor.mediumGreyDarkActive), - ), + description, + textAlign: TextAlign.right, + style: AppFonts.yekan16.copyWith(color: AppColor.mediumGreyDarkActive), + ), Text( unit, textAlign: TextAlign.center, @@ -463,37 +468,39 @@ class HomePage extends GetView { } Widget widelyUsed({required String title, required String iconPath, required VoidCallback onTap}) { - return Column( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.start, - spacing: 4, - children: [ - Container( - width: 48, - height: 48, - padding: EdgeInsets.all(4), - decoration: ShapeDecoration( - color: const Color(0xFFBECDFF), - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), - ), - child: Container( - width: 40, - height: 40, - decoration: ShapeDecoration( - color: AppColor.blueNormal, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + return GestureDetector( + onTap: onTap, + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.start, + spacing: 4, + children: [ + Container( + width: 48, + height: 48, + padding: EdgeInsets.all(4), + decoration: ShapeDecoration( + color: const Color(0xFFBECDFF), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + ), + child: Container( + width: 40, + height: 40, + decoration: ShapeDecoration( + color: AppColor.blueNormal, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + ), + child: SvgGenImage.vec(iconPath).svg( + width: 24, + height: 24, + colorFilter: ColorFilter.mode(Colors.white, BlendMode.srcIn), + fit: BoxFit.cover, + ), + ), ), - child: SvgGenImage.vec(iconPath).svg( - width: 24, - height: 24, - colorFilter: ColorFilter.mode(Colors.white, BlendMode.srcIn), - fit: BoxFit.cover, - ), - ), - ), - Text(title, style: AppFonts.yekan10.copyWith(color: AppColor.blueNormal)), - ], - ); + Text(title, style: AppFonts.yekan10.copyWith(color: AppColor.blueNormal)), + ], + )); } Widget addWidelyUsed({required VoidCallback onTap}) { @@ -522,112 +529,6 @@ class HomePage extends GetView { ); } - /* Column oldPage() { - return Column( - children: [ - inventoryWidget(), - ObxValue((data) => broadcastInformationWidget(data.value), controller.killHouseDistributionInfo), - SizedBox(height: 20), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 8.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - cardWidget( - title: 'ورود به انبار', - iconPath: Assets.icons.whareHouse.path, - onTap: () { - Get.toNamed(ChickenRoutes.enteringTheWarehouse); - }, - ), - cardWidget( - title: 'فروش داخل استان', - iconPath: Assets.icons.inside.path, - onTap: () { - Get.toNamed(ChickenRoutes.salesInProvince); - }, - ), - cardWidget( - title: 'فروش خارج استان', - iconPath: Assets.icons.outside.path, - onTap: () { - Get.toNamed(ChickenRoutes.salesOutOfProvince); - }, - ), - ], - ), - ), - ], - ); - } - - Widget inventoryWidget() { - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 8.0), - child: Column( - children: [ - const SizedBox(height: 20), - Align( - alignment: Alignment.centerRight, - child: Text('موجودی انبار', style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal)), - ), - SizedBox(height: 4), - ObxValue( - (data) => data.isEmpty - ? Container( - margin: const EdgeInsets.symmetric(vertical: 2), - height: 80, - padding: EdgeInsets.all(6), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - border: Border.all(color: AppColor.blueNormal, width: 1), - ), - child: Center(child: CircularProgressIndicator()), - ) - : ListView.separated( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - itemCount: controller.inventoryList.length, - separatorBuilder: (context, index) => const SizedBox(height: 8), - itemBuilder: (context, index) { - return ObxValue((expand) { - return GestureDetector( - onTap: () { - controller.toggleExpanded(index); - }, - behavior: HitTestBehavior.opaque, - child: AnimatedContainer( - onEnd: () { - controller.inventoryExpandedList[index] = !controller.inventoryExpandedList[index]!; - }, - margin: const EdgeInsets.symmetric(vertical: 2), - padding: EdgeInsets.all(6), - curve: Curves.easeInOut, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - border: Border.all(color: AppColor.blueNormal, width: 1), - ), - duration: const Duration(seconds: 1), - height: expand.keys.contains(index) ? 250 : 80, - child: inventoryItem( - isExpanded: expand.keys.contains(index) && expand[index]!, - index: index, - model: controller.inventoryList[index], - ), - ), - ); - }, controller.inventoryExpandedList); - }, - ), - controller.inventoryList, - ), - ], - ), - ); - }*/ - Widget inventoryItem({required bool isExpanded, required int index, required InventoryModel model}) { return Column( mainAxisAlignment: MainAxisAlignment.center, @@ -691,19 +592,19 @@ class HomePage extends GetView { ), child: model != null ? Column( - crossAxisAlignment: CrossAxisAlignment.start, - spacing: 10, - children: [ - Text( - 'اطلاعات ارسالی', - textAlign: TextAlign.right, - style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal), - ), - const SizedBox(height: 12), - buildRow('فروش و توزیع داخل استان (کیلوگرم)', model.stewardAllocationsWeight!.toInt().toString()), - buildRow('فروش و توزیع خارج استان (کیلوگرم)', model.freeSalesWeight!.toInt().toString()), - ], - ) + crossAxisAlignment: CrossAxisAlignment.start, + spacing: 10, + children: [ + Text( + 'اطلاعات ارسالی', + textAlign: TextAlign.right, + style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal), + ), + const SizedBox(height: 12), + buildRow('فروش و توزیع داخل استان (کیلوگرم)', model.stewardAllocationsWeight!.toInt().toString()), + buildRow('فروش و توزیع خارج استان (کیلوگرم)', model.freeSalesWeight!.toInt().toString()), + ], + ) : const Center(child: CircularProgressIndicator()), ); } diff --git a/packages/chicken/lib/presentation/pages/out_of_province/logic.dart b/packages/chicken/lib/presentation/pages/out_of_province/logic.dart index d39eb9e..06c59a4 100644 --- a/packages/chicken/lib/presentation/pages/out_of_province/logic.dart +++ b/packages/chicken/lib/presentation/pages/out_of_province/logic.dart @@ -121,23 +121,6 @@ class OutOfProvinceLogic extends GetxController { ); } -/* Future getKillHouseDashBord() async { - safeCall( - call: () async => - await rootLogic.chickenRepository.getDashboardKillHouseFreeBar( - token: rootLogic.tokenService.accessToken.value!, - stratDate: DateTime.now().formattedDashedGregorian, - endDate: DateTime.now().formattedDashedGregorian, - ), - onSuccess: (result) { - if (result != null) { - killHouseDashboard.value = result; - } - }, - onError: (error, stacktrace) {}, - ); - }*/ - Future submitAllocation() async {} @override diff --git a/packages/chicken/lib/presentation/pages/out_of_province/view.dart b/packages/chicken/lib/presentation/pages/out_of_province/view.dart index 07c369b..4315ca2 100644 --- a/packages/chicken/lib/presentation/pages/out_of_province/view.dart +++ b/packages/chicken/lib/presentation/pages/out_of_province/view.dart @@ -54,76 +54,12 @@ class OutOfProvincePage extends GetView { title: 'فروش خارج استان', iconPath: Assets.vec.cubeTopRotationSvg.path, foregroundColor: AppColor.greenDark, - onTap: () { - Get.toNamed(ChickenRoutes.buysOutOfProvince,id: 1); - }, + onTap: () {}, ), ), ], ), ), - - /* SizedBox(height: 12), - ObxValue((model) => summaryOfInformation(model.value), controller.stewardFreeDashboard), - Expanded( - child: ListView.separated( - padding: const EdgeInsets.fromLTRB(8, 12, 8, 100), - shrinkWrap: true, - physics: BouncingScrollPhysics(), - itemBuilder: (BuildContext context, int index) { - return Container( - padding: EdgeInsets.symmetric(horizontal: 8, vertical: 10), - - decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8)), - child: Column( - spacing: 8, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Assets.vec.editSvg.svg( - width: 20, - height: 20, - colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn), - ), - - Text( - 'لرستان - خرم آباد', - textAlign: TextAlign.center, - style: AppFonts.yekan16.copyWith(color: AppColor.greenDark), - ), - - 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('تاریخ', '07:15:00 - 1402/07/01'), - ), - - buildRow('مشخصات فروشنده', 'افلاک - 09203659874'), - buildRow('وزن خریداری شده', '200 کیلوگرم'), - buildRow('لاشه خریداری شده', '200 عدد'), - ], - ), - ); - }, - separatorBuilder: (BuildContext context, int index) => SizedBox(height: 6), - itemCount: 3, - ), - ),*/ ], ), ); @@ -257,513 +193,4 @@ class OutOfProvincePage extends GetView { ), ); } - - /* Widget inventoryWidget() { - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 8.0), - child: Column( - children: [ - const SizedBox(height: 20), - Align( - alignment: Alignment.centerRight, - child: Text( - 'خرید های خارج استان', - style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal), - ), - ), - SizedBox(height: 4), - ObxValue( - (data) => data.isEmpty - ? Container( - margin: const EdgeInsets.symmetric(vertical: 2), - height: 80, - padding: EdgeInsets.all(6), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - border: Border.all(color: AppColor.blueNormal, width: 1), - ), - child: Center(child: CircularProgressIndicator()), - ) - : ListView.separated( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - itemCount: controller.rootLogic.inventoryList.length, - separatorBuilder: (context, index) => - const SizedBox(height: 8), - itemBuilder: (context, index) { - return ObxValue((expand) { - return GestureDetector( - onTap: () { - controller.rootLogic.toggleExpanded(index); - }, - behavior: HitTestBehavior.opaque, - child: AnimatedContainer( - onEnd: () { - controller - .rootLogic - .inventoryExpandedList[index] = !controller - .rootLogic - .inventoryExpandedList[index]!; - }, - margin: const EdgeInsets.symmetric(vertical: 2), - padding: EdgeInsets.all(6), - curve: Curves.easeInOut, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - border: Border.all( - color: AppColor.blueNormal, - width: 1, - ), - ), - duration: const Duration(seconds: 1), - height: expand.keys.contains(index) ? 250 : 80, - child: inventoryItem( - isExpanded: - expand.keys.contains(index) && expand[index]!, - index: index, - model: controller.rootLogic.inventoryList[index], - ), - ), - ); - }, controller.rootLogic.inventoryExpandedList); - }, - ), - controller.rootLogic.inventoryList, - ), - ], - ), - ); - }*/ - - /* Widget inventoryItem({ - required bool isExpanded, - required int index, - required InventoryModel model, - }) { - return Column( - mainAxisAlignment: MainAxisAlignment.center, - spacing: 8, - children: [ - buildRow('نام محصول', model.name ?? ''), - Visibility( - visible: isExpanded, - child: Column( - spacing: 8, - children: [ - buildRow('وزن خریدهای دولتی داخل استان (کیلوگرم)', '0326598653'), - buildRow( - 'وزن خریدهای آزاد داخل استان (کیلوگرم)', - model.receiveFreeCarcassesWeight.toString(), - ), - buildRow( - 'وزن خریدهای خارج استان (کیلوگرم)', - model.freeBuyingCarcassesWeight.toString(), - ), - buildRow( - 'کل ورودی به انبار (کیلوگرم)', - model.totalFreeBarsCarcassesWeight.toString(), - ), - buildRow( - 'کل فروش (کیلوگرم)', - model.realAllocatedWeight.toString(), - ), - buildRow( - 'مانده انبار (کیلوگرم)', - model.totalRemainWeight.toString(), - ), - ], - ), - ), - ], - ); - } - - - - Widget allocationsMade() { - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 8.0), - child: Column( - children: [ - const SizedBox(height: 20), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'تخصیصات صورت گرفته', - style: AppFonts.yekan16Bold.copyWith( - color: AppColor.blueNormal, - ), - ), - RElevated( - text: 'تایید یکجا', - height: 30, - onPressed: () { - controller.confirmAllAllocations(); - }, - ), - ], - ), - SizedBox(height: 4), - ObxValue((data) { - if (data.value == null) { - return Container( - height: 80, - margin: const EdgeInsets.all(8), - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - border: Border.all(color: AppColor.blueNormal, width: 1), - ), - child: Center(child: CircularProgressIndicator()), - ); - } else if (data.value?.results?.isEmpty ?? true) { - return Container( - height: 80, - margin: const EdgeInsets.all(8), - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - border: Border.all(color: AppColor.blueNormal, width: 1), - ), - child: Center(child: Text('هیچ تخصیصات صورت نگرفته است ')), - ); - } else { - return Container( - margin: const EdgeInsets.symmetric(vertical: 2), - height: 700, - padding: const EdgeInsets.all(6), - child: ListView.separated( - padding: const EdgeInsets.all(8.0), - itemCount: data.value?.results?.length ?? 0, - itemBuilder: (BuildContext context, int index) { - final result = data.value!.results![index]; - return Card( - margin: const EdgeInsets.symmetric(vertical: 4.0), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - side: const BorderSide( - color: AppColor.blueNormal, - width: 1, - ), - ), - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - buildRow('ردیف', '${index + 1}'), - buildRow( - 'تاریخ ثبت', - result.date!.formattedJalaliDate ?? 'N/A', - ), - buildRow( - 'نوع تخصیص', - result.allocation_type?.faAllocationType ?? 'N/A', - ), - buildRow( - 'مشخصات خریدار', - '${result.to_guilds?.user?.fullname} - ${result.to_guilds?.guilds_name}' ?? - 'N/A', - ), - buildRow( - 'مشخصات فروشنده', - result.steward?.user?.fullname ?? 'N/A', - ), - buildRow( - 'نوع فروش', - result.sell_type?.faItem ?? 'N/A', - ), - buildRow( - 'قیمت هر کیلو', - '${result.amount ?? 0} ریال ', - ), - buildRow( - 'قیمت کل', - '${result.total_amount ?? 0} ریال', - ), - buildRow( - 'وزن تخصیصی', - '${result.weight_of_carcasses?.toInt() ?? 0} کیلوگرم', - ), - buildRow( - 'کداحراز', - result.registration_code?.toString() ?? 'N/A', - ), - buildRow( - 'وضعیت کد احراز', - result.system_registration_code == true - ? "ارسال شده" - : "ارسال نشده" ?? 'N/A', - ), - buildRow( - 'افت وزن(کیلوگرم)', - result.weight_loss_of_carcasses - ?.toInt() - .toString() ?? - 'N/A', - ), - buildRow( - 'وضعیت', - result.receiver_state?.faItem ?? 'N/A', - ), - - Row( - spacing: 10, - children: [ - Expanded( - child: RElevated( - height: 40, - text: 'تایید', - onPressed: () { - ConformAllocation confromation = - ConformAllocation( - allocation_key: result.key, - number_of_carcasses: - result.number_of_carcasses, - weight_of_carcasses: result - .weight_of_carcasses - ?.toInt(), - amount: result.amount, - total_amount: result.total_amount, - ); - - controller.confirmAllocation( - confromation, - ); - }, - ), - ), - Expanded( - child: RElevated( - height: 40, - backgroundColor: AppColor.error, - text: 'رد', - onPressed: () { - controller.denyAllocation( - result.key ?? '', - ); - }, - ), - ), - ], - ), - ], - ), - ), - ); - }, - separatorBuilder: (BuildContext context, int index) => - SizedBox(height: 8), - ), - ); - } - }, controller.allocatedMadeModel), - ], - ), - ); - } - - void showAddBottomSheet() { - Get.bottomSheet( - SafeArea( - child: BaseBottomSheet( - height: 700, - child: Padding( - padding: EdgeInsets.only( - left: 16, - right: 16, - top: 16, - bottom: MediaQuery.of(Get.context!).viewInsets.bottom + 16, - ), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - 'ثبت توزیع/ فروش', - style: AppFonts.yekan16Bold.copyWith( - color: AppColor.blueNormal, - ), - ), - const SizedBox(height: 12), - RTextField( - controller: TextEditingController(), - label: 'تاریخ', - enabled: false, - initText: Jalali.now().formatCompactDate(), - ), - const SizedBox(height: 12), - Material( - type: MaterialType.transparency, - child: productDropDown(), - ), - const SizedBox(height: 12), - SizedBox( - height: 40, - child: ObxValue((data) { - return Row( - children: [ - Radio( - value: 1, - groupValue: controller.saleType.value, - onChanged: (value) { - controller.saleType.value = value!; - }, - ), - Text('فروش اختصاصی', style: AppFonts.yekan14), - SizedBox(width: 12), - Radio( - value: 2, - groupValue: controller.saleType.value, - onChanged: (value) { - controller.saleType.value = value!; - }, - ), - Text('فروش آزاد', style: AppFonts.yekan14), - ], - ); - }, controller.saleType), - ), - const SizedBox(height: 12), - - Material( - type: MaterialType.transparency, - child: guildsDropDown(), - ), - - const SizedBox(height: 12), - RTextField( - controller: controller.weightController, - keyboardType: TextInputType.number, - onChanged: (p0) { - controller.weight.value = int.tryParse(p0) ?? 0; - }, - label: 'وزن لاشه', - ), - const SizedBox(height: 12), - RTextField( - controller: controller.pricePerKiloController, - onChanged: (p0) { - controller.pricePerKilo.value = int.tryParse(p0) ?? 0; - }, - keyboardType: TextInputType.number, - label: 'قیمت هر کیلو', - ), - const SizedBox(height: 12), - ObxValue( - (p0) => RTextField( - enabled: false, - keyboardType: TextInputType.number, - initText: controller.totalCost.value.toString(), - controller: controller.totalCostController, - label: 'هزینه کل', - ), - controller.totalCost, - ), - const SizedBox(height: 20), - ObxValue((data) { - return RElevated( - text: 'ثبت', - onPressed: data.value - ? () { - controller.submitAllocation(); - } - : null, - ); - }, controller.isValid), - const SizedBox(height: 20), - ], - ), - ), - ), - ), - isScrollControlled: true, - backgroundColor: Colors.transparent, - ); - } - - Widget guildsDropDown() { - return ObxValue((p0) { - return DropdownButtonFormField( - value: controller.selectedGuildModel.value, - decoration: const InputDecoration( - labelText: 'انتخاب مباشر/صنف', - border: OutlineInputBorder(), - ), - isExpanded: true, - items: controller.guildsModel.map((guild) { - return DropdownMenuItem( - value: guild, - child: Text( - '${guild.steward == true ? 'مباشر' : 'صنف'} ${guild.user?.fullname} (${guild.user?.mobile})', - ), - ); - }).toList(), - onChanged: (value) { - if (value != null) { - controller.setSelectedGuild(value); - controller.checkVerfication(); - } - }, - ); - }, controller.guildsModel); - */ /* return GetBuilder( - builder: (controller) { - return DropdownButtonFormField( - value: controller.selectedGuildModel.value, - decoration: const InputDecoration( - labelText: 'انتخاب مباشر/صنف', - border: OutlineInputBorder(), - ), - isExpanded: true, - items: controller.guildsModel.map((guild) { - return DropdownMenuItem( - value: guild, - child: Text( - '${guild.steward == true ? 'مباشر' : 'صنف'} ${guild.user - ?.fullname} (${guild.user?.mobile})', - ), - ); - }).toList(), - onChanged: (value) { - if (value != null) { - controller.setSelectedGuild(value); - } - }, - ); - }, - );*/ /* - } - - Widget productDropDown() { - return GetBuilder( - builder: (controller) { - return DropdownButtonFormField( - value: controller.selectedProductModel.value, - decoration: const InputDecoration( - labelText: 'انتخاب محصول', - border: OutlineInputBorder(), - ), - isExpanded: true, - items: controller.rolesProductsModel.map((guild) { - return DropdownMenuItem( - value: guild, - child: Text('${guild.name}'), - ); - }).toList(), - onChanged: (value) { - if (value != null) { - controller.setSelectedProduct(value); - controller.checkVerfication(); - } - }, - ); - }, - ); - }*/ } diff --git a/packages/chicken/lib/presentation/pages/root/logic.dart b/packages/chicken/lib/presentation/pages/root/logic.dart index 352f0e9..26603a0 100644 --- a/packages/chicken/lib/presentation/pages/root/logic.dart +++ b/packages/chicken/lib/presentation/pages/root/logic.dart @@ -21,13 +21,7 @@ class RootLogic extends GetxController { Container(color: Colors.amber), ]; - final List> navigatorKeys = [ - GlobalKey(), - GlobalKey(), - GlobalKey(), - GlobalKey(), - GlobalKey(), - ]; + late DioRemote dioRemote; var tokenService = Get.find(); diff --git a/packages/chicken/lib/presentation/pages/root/view.dart b/packages/chicken/lib/presentation/pages/root/view.dart index 81c54f0..32bae60 100644 --- a/packages/chicken/lib/presentation/pages/root/view.dart +++ b/packages/chicken/lib/presentation/pages/root/view.dart @@ -14,7 +14,7 @@ class RootPage extends GetView { body: IndexedStack( children: [ Navigator( - key: controller.navigatorKeys[0], + key: Get.nestedKey(0), onGenerateRoute: (settings) => GetPageRoute(page: () => controller.pages[0]), ), @@ -33,17 +33,17 @@ class RootPage extends GetView { }, ), Navigator( - key: controller.navigatorKeys[2], + key: Get.nestedKey(2), onGenerateRoute: (settings) => GetPageRoute(page: () => controller.pages[2]), ), Navigator( - key: controller.navigatorKeys[3], + key: Get.nestedKey(3), onGenerateRoute: (settings) => GetPageRoute(page: () => controller.pages[3]), ), Navigator( - key: controller.navigatorKeys[4], + key: Get.nestedKey(4), onGenerateRoute: (settings) => GetPageRoute(page: () => controller.pages[4]), ), diff --git a/packages/chicken/lib/presentation/pages/sales_out_of_province/logic.dart b/packages/chicken/lib/presentation/pages/sales_out_of_province/logic.dart index ccb35a8..c22cda4 100644 --- a/packages/chicken/lib/presentation/pages/sales_out_of_province/logic.dart +++ b/packages/chicken/lib/presentation/pages/sales_out_of_province/logic.dart @@ -31,9 +31,9 @@ class SalesOutOfProvinceLogic extends GetxController { OutOfProvinceLogic get outOfTheProvinceLogic => Get.find(); + GlobalKey formKey = GlobalKey(); TextEditingController sellerNameController = TextEditingController(); TextEditingController sellerPhoneController = TextEditingController(); - TextEditingController carcassVolumeController = TextEditingController(); TextEditingController carcassWeightController = TextEditingController(); Rx fromDateFilter = Jalali.now().obs; @@ -45,6 +45,11 @@ class SalesOutOfProvinceLogic extends GetxController { super.onReady(); getStewardPurchaseOutOfProvince(); selectedProvince.listen((p0) => getCites()); + tLog(selectedProduct.value); + outOfTheProvinceLogic.rolesProductsModel.listen((lists) { + selectedProduct.value = lists.first; + },); + tLog(selectedProduct.value); setupListeners(); debounce(searchedValue, (callback) => getStewardPurchaseOutOfProvince(), time: Duration(milliseconds: 2000)); ever(searchIsSelected, (data) { @@ -58,8 +63,9 @@ class SalesOutOfProvinceLogic extends GetxController { void onClose() { sellerNameController.dispose(); sellerPhoneController.dispose(); - carcassVolumeController.dispose(); carcassWeightController.dispose(); + isExpandedList.clear(); + super.onClose(); } @@ -101,7 +107,6 @@ class SalesOutOfProvinceLogic extends GetxController { void setupListeners() { sellerNameController.addListener(checkFormValid); sellerPhoneController.addListener(checkFormValid); - carcassVolumeController.addListener(checkFormValid); carcassWeightController.addListener(checkFormValid); ever(selectedProvince, (_) => checkFormValid()); @@ -119,7 +124,6 @@ class SalesOutOfProvinceLogic extends GetxController { isSubmitButtonEnabled.value = sellerNameController.text.isNotEmpty && sellerPhoneController.text.isNotEmpty && - carcassVolumeController.text.isNotEmpty && carcassWeightController.text.isNotEmpty && selectedProvince.value != null && selectedCity.value != null && @@ -127,33 +131,40 @@ class SalesOutOfProvinceLogic extends GetxController { selectedImage.value != null; } - Future createStewardPurchaseOutOfProvince() async => await safeCall( - call: () async { - CreateStewardFreeBar createStewardFreeBar = CreateStewardFreeBar( - productKey: selectedProduct.value!.key, - killHouseName: sellerNameController.text, - killHouseMobile: sellerPhoneController.text, - province: selectedProvince.value!.name, - city: selectedCity.value!.name, - weightOfCarcasses: int.parse(carcassWeightController.text), - barImage: _base64Image.value, - date: DateTime.now().formattedYHMS, - ); - final res = await rootLogic.chickenRepository.createStewardPurchasesOutSideOfTheProvince( - token: rootLogic.tokenService.accessToken.value!, - body: createStewardFreeBar, - ); - }, - onSuccess: (result) { - getStewardPurchaseOutOfProvince(); - resetSubmitForm(); - }, - ); + Future createStewardPurchaseOutOfProvince() async { + bool res = false; + if (!(formKey.currentState?.validate() ?? false)) { + return res; + } + await safeCall( + call: () async { + CreateStewardFreeBar createStewardFreeBar = CreateStewardFreeBar( + productKey: selectedProduct.value!.key, + killHouseName: sellerNameController.text, + killHouseMobile: sellerPhoneController.text, + province: selectedProvince.value!.name, + city: selectedCity.value!.name, + weightOfCarcasses: int.parse(carcassWeightController.text.clearComma), + barImage: _base64Image.value, + date: DateTime.now().formattedYHMS, + ); + final res = await rootLogic.chickenRepository.createStewardPurchasesOutSideOfTheProvince( + token: rootLogic.tokenService.accessToken.value!, + body: createStewardFreeBar, + ); + }, + onSuccess: (result) { + getStewardPurchaseOutOfProvince(); + resetSubmitForm(); + res = true; + }, + ); + return res; + } void resetSubmitForm() { sellerNameController.clear(); sellerPhoneController.clear(); - carcassVolumeController.clear(); carcassWeightController.clear(); selectedProvince.value = null; selectedCity.value = null; @@ -166,12 +177,10 @@ class SalesOutOfProvinceLogic extends GetxController { } void setEditData(StewardFreeBar item) { - iLog(item.barImage); editImageUrl.value = item.barImage; sellerNameController.text = item.killHouseName ?? ''; sellerPhoneController.text = item.killHouseMobile ?? ''; - carcassVolumeController.text = item.weightOfCarcasses?.toString() ?? ''; - carcassWeightController.text = item.weightOfCarcasses?.toString() ?? ''; + carcassWeightController.text = item.weightOfCarcasses?.toInt().toString() ?? ''; selectedProvince.value = IranProvinceCityModel(name: item.province); selectedCity.value = IranProvinceCityModel(name: item.city); selectedProduct.value = outOfTheProvinceLogic.rolesProductsModel.firstWhere( diff --git a/packages/chicken/lib/presentation/pages/sales_out_of_province/view.dart b/packages/chicken/lib/presentation/pages/sales_out_of_province/view.dart index 0aa3adf..d165e09 100644 --- a/packages/chicken/lib/presentation/pages/sales_out_of_province/view.dart +++ b/packages/chicken/lib/presentation/pages/sales_out_of_province/view.dart @@ -2,6 +2,7 @@ import 'dart:io'; 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/roles_products/roles_products.dart'; import 'package:rasadyar_chicken/data/models/response/steward_free_bar/steward_free_bar.dart'; @@ -21,6 +22,7 @@ class SalesOutOfProvincePage extends GetView { hasBack: true, onBackPressed: () { Get.back(id: 1); + }, leadingWidth: 155, leading: Row( @@ -125,162 +127,187 @@ class SalesOutOfProvincePage extends GetView { controller.isExpandedList.add(index); } }, - child: AnimatedContainer( + child: AnimatedSize( duration: Duration(milliseconds: 400), alignment: Alignment.center, - height: expandList.contains(index) ? 175 : 56, child: Stack( clipBehavior: Clip.none, alignment: Alignment.centerRight, children: [ - AnimatedContainer( - width: Get.width - 30, + AnimatedSize( duration: Duration(milliseconds: 300), - height: expandList.contains(index) ? 175 : 56, - alignment: Alignment.center, - decoration: BoxDecoration( - color: Colors.transparent, - borderRadius: BorderRadius.circular(8), - border: Border.all(width: 0.5, color: AppColor.darkGreyNormal), - ), - child: AnimatedCrossFade( + child: Container( + width: Get.width - 30, alignment: Alignment.center, - firstChild: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - Text( - item.date?.formattedJalaliDate ?? 'N/A', - textAlign: TextAlign.center, - style: AppFonts.yekan14.copyWith(color: AppColor.bgDark), - ), - Text( - item.killHouseName ?? 'N/A', - textAlign: TextAlign.center, - style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal), - ), - Text( - 'kg ${item.weightOfCarcasses} ${item.product?.name}', - textAlign: TextAlign.center, - style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal), - ), - - Text( - '${item.province}-${item.city}', - textAlign: TextAlign.center, - style: AppFonts.yekan14.copyWith(color: AppColor.bgDark), - ), - - Icon(CupertinoIcons.chevron_down, size: 12), - ], + decoration: BoxDecoration( + color: Colors.transparent, + borderRadius: BorderRadius.circular(8), + border: Border.all(width: 0.5, color: AppColor.darkGreyNormal), ), - secondChild: Container( - padding: EdgeInsets.fromLTRB(8, 12, 14, 12), - - decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8)), - child: Column( - spacing: 8, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - GestureDetector( - onTap: () { - controller.setEditData(item); - Get.bottomSheet( - addPurchasedInformationBottomSheet(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}', + 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: Text( + item.date?.formattedJalaliDate ?? 'N/A', 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), + style: AppFonts.yekan14.copyWith(color: AppColor.bgDark), ), ), - child: buildRow('تاریخ', item.date?.formattedJalaliDateYHMS ?? 'N/A'), - ), - - buildRow('مشخصات فروشنده', '${item.killHouseName} - ${item.killHouseMobile ?? 'N/A'}'), - buildRow('وزن خریداری شده', '${item.weightOfCarcasses?.toInt()} کیلوگرم'), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - //RTextButton(text: , onPressed: () {}, textStyle: AppFonts.yekan14,height: 20,width: 81,backgroundColor: AppColor.warning,), - GestureDetector( - onTap: () { - Get.bottomSheet( - BaseBottomSheet( - height: 400, - child: Column( - spacing: 16, - children: [ - Text( - 'بارنامه', - style: AppFonts.yekan16Bold.copyWith(color: AppColor.darkGreyDarkHover), - ), - - Image.network( - item.barImage ?? '', - fit: BoxFit.cover, - height: 300, - errorBuilder: (context, error, stackTrace) { - eLog(error.toString()); - return Center(child: Text('خطایی پیش آمده!')); - }, - loadingBuilder: (context, child, loadingProgress) { - if (loadingProgress == null) return child; - print('Loading progress: $loadingProgress'); - return CupertinoActivityIndicator(); - }, - ), - ], - ), - ), - ); - }, - child: Text('مشاهده بارنامه', style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal)), + Expanded( + flex: 3, + child: Text( + item.killHouseName ?? 'N/A', + textAlign: TextAlign.center, + style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal), ), - Icon(CupertinoIcons.chevron_up, size: 12), - ], - ), - ], + ), + SizedBox(width: 8,), + Expanded( + flex: 2, + child: Column( + children: [ + Text( + '${item.weightOfCarcasses?.separatedByComma}kg', + textAlign: TextAlign.left, + style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal), + ), + + SizedBox(height: 2,), + Visibility( + visible: item.product?.name?.contains('مرغ گرم') ?? false, + child: Assets.vec.hotChickenSvg.svg(width: 24,height: 24, colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn))), + + ], + ), + ), + Expanded( + flex: 2, + child: Text( + '${item.province}\n${item.city}', + textAlign: TextAlign.center, + style: AppFonts.yekan12.copyWith(color: AppColor.bgDark), + ), + ), + 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.setEditData(item); + Get.bottomSheet( + addPurchasedInformationBottomSheet(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.killHouseName} - ${item.killHouseMobile ?? 'N/A'}'), + buildRow('وزن خریداری شده', '${item.weightOfCarcasses?.toInt()} کیلوگرم'), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + GestureDetector( + onTap: () { + Get.bottomSheet( + BaseBottomSheet( + height: 400, + child: Column( + spacing: 16, + children: [ + Text( + 'بارنامه', + style: AppFonts.yekan16Bold.copyWith(color: AppColor.darkGreyDarkHover), + ), + + Image.network( + item.barImage ?? '', + fit: BoxFit.cover, + height: 300, + errorBuilder: (context, error, stackTrace) { + eLog(error.toString()); + return Center(child: Text('خطایی پیش آمده!')); + }, + loadingBuilder: (context, child, loadingProgress) { + if (loadingProgress == null) return child; + print('Loading progress: $loadingProgress'); + return CupertinoActivityIndicator(); + }, + ), + ], + ), + ), + ); + }, + child: Text('مشاهده بارنامه', style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal)), + ), + Icon(CupertinoIcons.chevron_up, size: 12), + ], + ), + ], + ), + ), + crossFadeState: expandList.contains(index) ? CrossFadeState.showSecond : CrossFadeState.showFirst, + duration: Duration(milliseconds: 300), ), - crossFadeState: expandList.contains(index) ? CrossFadeState.showSecond : CrossFadeState.showFirst, - duration: Duration(milliseconds: 300), ), ), Positioned( @@ -354,6 +381,7 @@ class SalesOutOfProvincePage extends GetView { child: Text( value, textAlign: TextAlign.left, + style: AppFonts.yekan14.copyWith(color: AppColor.darkGreyDarkHover), ), ), @@ -361,50 +389,89 @@ class SalesOutOfProvincePage extends GetView { ), ); } + Widget buildRow2(String title, String value) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 4.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + title, + textAlign: TextAlign.right, + style: AppFonts.yekan14.copyWith(color: AppColor.darkGreyDarkHover), + ), + SizedBox(width: 8,), + Expanded( + child: Container + ( + color: Colors.green, + child: Text( + value, + textAlign: TextAlign.left, + + style: AppFonts.yekan14.copyWith(color: AppColor.darkGreyDarkHover), + ), + ), + ), + ], + ), + ); + } + Widget addPurchasedInformationBottomSheet([bool isOnEdit = false]) { return BaseBottomSheet( child: SingleChildScrollView( - child: Column( - spacing: 16, - children: [ - Text( - isOnEdit ? 'ویرایش اطلاعات خرید' : 'ثبت اطلاعات خرید', - style: AppFonts.yekan16Bold.copyWith(color: AppColor.darkGreyDarkHover), - ), - _productTypeWidget(), - RTextField( - controller: controller.sellerNameController, - label: 'نام فروشنده', - borderColor: AppColor.darkGreyLight, - ), - RTextField( - controller: controller.sellerPhoneController, - label: 'تلفن فروشنده', - keyboardType: TextInputType.phone, - borderColor: AppColor.darkGreyLight, - ), - _provinceWidget(), - _cityWidget(), - RTextField( - controller: controller.carcassWeightController, - label: 'وزن لاشه', - keyboardType: TextInputType.number, - borderColor: AppColor.darkGreyLight, - ), - RTextField( - controller: controller.carcassVolumeController, - label: 'حجم لاشه', - onChanged: (p0) { - iLog(controller.carcassVolumeController.text); - }, - keyboardType: TextInputType.number, - borderColor: AppColor.darkGreyLight, - ), - _imageCarcasesWidget(isOnEdit), - submitButtonWidget(isOnEdit), - SizedBox(), - ], + child: Form( + key: controller.formKey, + child: Column( + spacing: 16, + children: [ + Text( + isOnEdit ? 'ویرایش اطلاعات خرید' : 'ثبت اطلاعات خرید', + style: AppFonts.yekan16Bold.copyWith(color: AppColor.darkGreyDarkHover), + ), + _productTypeWidget(), + RTextField( + controller: controller.sellerNameController, + label: 'نام فروشنده', + borderColor: AppColor.darkGreyLight, + ), + RTextField( + controller: controller.sellerPhoneController, + 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; + }, + ), + _provinceWidget(), + _cityWidget(), + RTextField( + controller: controller.carcassWeightController, + label: 'وزن لاشه', + keyboardType: TextInputType.number, + borderColor: AppColor.darkGreyLight, + inputFormatters: [FilteringTextInputFormatter.digitsOnly, SeparatorInputFormatter()], + ), + _imageCarcasesWidget(isOnEdit), + submitButtonWidget(isOnEdit), + SizedBox(), + ], + ), ), ), ); @@ -413,11 +480,13 @@ class SalesOutOfProvincePage extends GetView { Widget submitButtonWidget(bool isOnEdit) { return ObxValue((data) { return RElevated( - text: isOnEdit ? 'ویرایش خرید' : 'ثبت خرید جدید', + text: isOnEdit ? 'ویرایش' : 'ثبت خرید', onPressed: data.value ? () async { - await controller.createStewardPurchaseOutOfProvince(); - Get.back(); + var res = await controller.createStewardPurchaseOutOfProvince(); + if (res) { + Get.back(); + } } : null, height: 40, @@ -426,14 +495,16 @@ class SalesOutOfProvincePage extends GetView { } Widget _productTypeWidget() { + tLog(controller.outOfTheProvinceLogic.rolesProductsModel); + iLog(controller.selectedProduct.value); return Obx(() { return OverlayDropdownWidget( items: controller.outOfTheProvinceLogic.rolesProductsModel, onChanged: (value) { controller.selectedProduct.value = value; - print('Selected Product: ${value.name}'); }, selectedItem: controller.selectedProduct.value, + initialValue: controller.selectedProduct.value, itemBuilder: (item) => Text(item.name ?? 'بدون نام'), labelBuilder: (item) => Text(item?.name ?? 'انتخاب محصول'), ); @@ -676,19 +747,31 @@ class SalesOutOfProvincePage extends GetView { children: [ Container( child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - CupertinoButton( - child: Text('تایید', style: AppFonts.yekan14), + children: [ + SizedBox(width: 20), + RElevated( + height: 35, + width: 70, + textStyle: AppFonts.yekan14.copyWith(color: Colors.white), onPressed: () { onDateSelected(tempPickedDate ?? Jalali.now()); Get.back(); }, + text: 'تایید', ), - CupertinoButton( - child: Text('لغو', style: AppFonts.yekan14.copyWith(color: AppColor.error)), - onPressed: () => Get.back(), + 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), ], ), ), diff --git a/packages/chicken/lib/presentation/routes/pages.dart b/packages/chicken/lib/presentation/routes/pages.dart index f86a54f..07f6cc2 100644 --- a/packages/chicken/lib/presentation/routes/pages.dart +++ b/packages/chicken/lib/presentation/routes/pages.dart @@ -48,8 +48,8 @@ sealed class ChickenPages { page: () => EnteringTheWarehousePage(), middlewares: [AuthMiddleware()], binding: BindingsBuilder(() { - Get.put(EnteringTheWarehouseLogic()); - Get.put(RootLogic()); + Get.lazyPut(()=>EnteringTheWarehouseLogic()); + Get.lazyPut(()=>RootLogic()); }), ), GetPage( @@ -57,8 +57,8 @@ sealed class ChickenPages { page: () => SalesInProvincePage(), middlewares: [AuthMiddleware()], binding: BindingsBuilder(() { - Get.put(SalesInProvinceLogic()); - Get.put(RootLogic()); + Get.lazyPut(()=>SalesInProvinceLogic()); + Get.lazyPut(()=>RootLogic()); }), ), @@ -69,9 +69,10 @@ sealed class ChickenPages { page: () => OutOfProvincePage(), middlewares: [AuthMiddleware()], binding: BindingsBuilder(() { - Get.put(OutOfProvinceLogic()); - Get.put(SalesOutOfProvinceLogic()); - Get.put(RootLogic()); + Get.lazyPut(()=>OutOfProvinceLogic()); + + Get.lazyPut(()=>SalesOutOfProvinceLogic()); + Get.lazyPut(()=>RootLogic()); }), ), @@ -80,8 +81,8 @@ sealed class ChickenPages { page: () => SalesOutOfProvincePage(), middlewares: [AuthMiddleware()], binding: BindingsBuilder(() { - Get.put(SalesOutOfProvinceLogic()); - Get.put(RootLogic()); + Get.lazyPut(()=>SalesOutOfProvinceLogic()); + Get.lazyPut(()=>RootLogic()); }), ), @@ -90,8 +91,8 @@ sealed class ChickenPages { page: () => BuysOutOfProvincePage(), middlewares: [AuthMiddleware()], binding: BindingsBuilder(() { - Get.put(BuysOutOfProvinceLogic()); - Get.put(RootLogic()); + Get.lazyPut(()=>BuysOutOfProvinceLogic()); + Get.lazyPut(()=>RootLogic()); }), ), ]; diff --git a/packages/core/lib/core.dart b/packages/core/lib/core.dart index cd79f4b..35d1a04 100644 --- a/packages/core/lib/core.dart +++ b/packages/core/lib/core.dart @@ -50,3 +50,5 @@ export 'utils/date_time_utils.dart'; export 'utils/num_utils.dart'; export 'utils/map_utils.dart'; export 'utils/route_utils.dart'; +export 'utils/string_utils.dart'; +export 'utils/separator_input_formatter.dart'; diff --git a/packages/core/lib/presentation/common/assets.gen.dart b/packages/core/lib/presentation/common/assets.gen.dart index f33b3bb..6af7271 100644 --- a/packages/core/lib/presentation/common/assets.gen.dart +++ b/packages/core/lib/presentation/common/assets.gen.dart @@ -87,6 +87,9 @@ class $AssetsIconsGen { /// File path: assets/icons/home.svg SvgGenImage get home => const SvgGenImage('assets/icons/home.svg'); + /// File path: assets/icons/hot_chicken.svg + SvgGenImage get hotChicken => const SvgGenImage('assets/icons/hot_chicken.svg'); + /// File path: assets/icons/information.svg SvgGenImage get information => const SvgGenImage('assets/icons/information.svg'); @@ -209,6 +212,7 @@ class $AssetsIconsGen { filterOutline, gps, home, + hotChicken, information, inside, inspection, @@ -348,6 +352,9 @@ class $AssetsVecGen { /// File path: assets/vec/home.svg.vec SvgGenImage get homeSvg => const SvgGenImage.vec('assets/vec/home.svg.vec'); + /// File path: assets/vec/hot_chicken.svg.vec + SvgGenImage get hotChickenSvg => const SvgGenImage.vec('assets/vec/hot_chicken.svg.vec'); + /// File path: assets/vec/information.svg.vec SvgGenImage get informationSvg => const SvgGenImage.vec('assets/vec/information.svg.vec'); @@ -470,6 +477,7 @@ class $AssetsVecGen { filterOutlineSvg, gpsSvg, homeSvg, + hotChickenSvg, informationSvg, insideSvg, inspectionSvg, diff --git a/packages/core/lib/presentation/widget/inputs/r_input.dart b/packages/core/lib/presentation/widget/inputs/r_input.dart index 3debe30..9ff9aec 100644 --- a/packages/core/lib/presentation/widget/inputs/r_input.dart +++ b/packages/core/lib/presentation/widget/inputs/r_input.dart @@ -1,5 +1,6 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:rasadyar_core/core.dart'; enum RTextFieldVariant { @@ -38,6 +39,7 @@ class RTextField extends StatefulWidget { final FormFieldValidator? validator; final void Function(String)? onChanged; final void Function(String)? onSubmitted; + final List? inputFormatters; const RTextField({ super.key, @@ -69,6 +71,7 @@ class RTextField extends StatefulWidget { this.onChanged, this.onSubmitted, this.borderColor, + this.inputFormatters }); @@ -147,6 +150,7 @@ class _RTextFieldState extends State { maxLines: widget.maxLines, onChanged: widget.onChanged, validator: widget.validator, + inputFormatters: widget.inputFormatters, enabled: widget.enabled, obscureText: obscure, onTapOutside: (_) => FocusScope.of(context).unfocus(), diff --git a/packages/core/lib/presentation/widget/overlay_dropdown_widget/view.dart b/packages/core/lib/presentation/widget/overlay_dropdown_widget/view.dart index df217a3..629d9c9 100644 --- a/packages/core/lib/presentation/widget/overlay_dropdown_widget/view.dart +++ b/packages/core/lib/presentation/widget/overlay_dropdown_widget/view.dart @@ -2,9 +2,6 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:rasadyar_core/presentation/common/app_color.dart'; -import 'package:rasadyar_core/presentation/common/app_fonts.dart'; - - class OverlayDropdownWidget extends StatefulWidget { final List items; @@ -15,7 +12,7 @@ class OverlayDropdownWidget extends StatefulWidget { final void Function(T selected)? onChanged; final EdgeInsets? contentPadding; - const OverlayDropdownWidget({ + const OverlayDropdownWidget({ super.key, required this.items, required this.itemBuilder, @@ -23,7 +20,7 @@ class OverlayDropdownWidget extends StatefulWidget { this.initialValue, this.onChanged, this.selectedItem, - this.contentPadding + this.contentPadding, }); @override @@ -34,7 +31,7 @@ class _OverlayDropdownState extends State> { final GlobalKey _key = GlobalKey(); OverlayEntry? _overlayEntry; final RxBool _isOpen = false.obs; - T? selectedItem ; + T? selectedItem; @override void initState() { @@ -48,51 +45,54 @@ class _OverlayDropdownState extends State> { final offset = renderBox.localToGlobal(Offset.zero); _overlayEntry = OverlayEntry( - builder: - (_) => GestureDetector( - onTap: _removeOverlay, - behavior: HitTestBehavior.translucent, - child: Stack( - children: [ - Positioned( - left: offset.dx, - top: offset.dy + size.height + 4, - width: size.width, - child: Material( - elevation: 4, + builder: (_) => GestureDetector( + onTap: _removeOverlay, + behavior: HitTestBehavior.translucent, + child: Stack( + children: [ + Positioned( + left: offset.dx, + top: offset.dy + size.height + 4, + width: size.width, + child: Material( + elevation: 4, + borderRadius: BorderRadius.circular(8), + child: Container( + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: AppColor.darkGreyLight), borderRadius: BorderRadius.circular(8), - child: Container( - decoration: BoxDecoration( - color: Colors.white, - border: Border.all(color: AppColor.darkGreyLight), - borderRadius: BorderRadius.circular(8), - ), - child: ListView( - padding: EdgeInsets.zero, - shrinkWrap: true, - children: - widget.items.map((item) { - return InkWell( - onTap: () { - widget.onChanged?.call(item); - setState(() { - selectedItem = item; - }); - _removeOverlay(); - }, - child: Padding( - padding:widget.contentPadding?? const EdgeInsets.symmetric(horizontal: 8, vertical: 4), - child: widget.itemBuilder(item), - ), - ); - }).toList(), - ), + ), + child: Container( + constraints: BoxConstraints(maxHeight: 300), + child: ListView( + padding: EdgeInsets.only(bottom: 50), + shrinkWrap: true, + physics: BouncingScrollPhysics(), + scrollDirection: Axis.vertical, + children: widget.items.map((item) { + return InkWell( + onTap: () { + widget.onChanged?.call(item); + setState(() { + selectedItem = item; + }); + _removeOverlay(); + }, + child: Padding( + padding: widget.contentPadding ?? const EdgeInsets.symmetric(horizontal: 8, vertical: 4), + child: widget.itemBuilder(item), + ), + ); + }).toList(), ), ), ), - ], + ), ), - ), + ], + ), + ), ); Overlay.of(context).insert(_overlayEntry!); @@ -130,12 +130,7 @@ class _OverlayDropdownState extends State> { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ widget.labelBuilder(selectedItem), - Icon( - _isOpen.value - ? CupertinoIcons.chevron_up - : CupertinoIcons.chevron_down, - size: 14, - ), + Icon(_isOpen.value ? CupertinoIcons.chevron_up : CupertinoIcons.chevron_down, size: 14), ], ), ), diff --git a/packages/core/lib/utils/num_utils.dart b/packages/core/lib/utils/num_utils.dart index 4df60b5..880d901 100644 --- a/packages/core/lib/utils/num_utils.dart +++ b/packages/core/lib/utils/num_utils.dart @@ -1,7 +1,7 @@ import 'package:intl/intl.dart'; extension XNumExtension on num? { - String get toFormatted { + String get separatedByComma { final formatter = NumberFormat('#,###', 'fa_IR'); return this == null ? '':formatter.format(this); } diff --git a/packages/core/lib/utils/separator_input_formatter.dart b/packages/core/lib/utils/separator_input_formatter.dart new file mode 100644 index 0000000..cc87a5f --- /dev/null +++ b/packages/core/lib/utils/separator_input_formatter.dart @@ -0,0 +1,27 @@ +import 'package:flutter/services.dart'; +import 'package:intl/intl.dart'; + +class SeparatorInputFormatter extends TextInputFormatter { + final NumberFormat _formatter; + + SeparatorInputFormatter() : _formatter = NumberFormat('#,###'); + + @override + TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) { + if (newValue.text.isEmpty) { + return newValue; + } + String tmpText = newValue.text; + String cleanedText = tmpText.replaceAll(RegExp(r'\D'), ''); + int? number = int.tryParse(cleanedText); + if (number == null) { + return oldValue; + } + String formattedText = _formatter.format(number); + int selectionIndex = formattedText.length; + return TextEditingValue( + text: formattedText, + selection: TextSelection.collapsed(offset: selectionIndex), + ); + } +} diff --git a/packages/core/lib/utils/string_utils.dart b/packages/core/lib/utils/string_utils.dart new file mode 100644 index 0000000..278e287 --- /dev/null +++ b/packages/core/lib/utils/string_utils.dart @@ -0,0 +1,11 @@ +import 'package:intl/intl.dart'; + +extension XString on String { + get separatedByComma { + final formatter = NumberFormat('#,###'); + return formatter.format(this); + } + get clearComma{ + return replaceAll(RegExp(r'\D'), ''); + } +}