import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:rasadyar_chicken/data/models/response/guild/guild_model.dart'; import 'package:rasadyar_chicken/data/models/response/roles_products/roles_products.dart'; import 'package:rasadyar_chicken/data/models/response/segmentation_model/segmentation_model.dart'; import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart'; import 'package:rasadyar_chicken/presentation/widget/filter_bottom_sheet.dart'; import 'package:rasadyar_core/core.dart'; import 'logic.dart'; class SegmentationPage extends GetView { final today = Jalali.now(); final oneDayAgo = Jalali.now().addDays(-1); final twoDaysAgo = Jalali.now().addDays(-2); @override Widget build(BuildContext context) { return ChickenBasePage( routes: controller.routesName, onSearchChanged: (data) => controller.setSearchValue(data), onFilterTap: () { Get.bottomSheet(filterBottomSheet()); }, onRefresh: controller.onRefresh, hasBack: false, child: Stack( children: [ Positioned.fill( child: ObxValue((data) { return RPaginatedListView( onLoadMore: () async => controller.getAllSegmentation(true), hasMore: data.value.data?.next != null, 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 ExpandableListItem2( selected: val.value == index, onTap: () => controller.toggleExpansion(index: index), index: index, child: itemListWidget(item), secondChild: itemListExpandedWidget(item, index), labelColor: AppColor.blueLight, labelIconColor: AppColor.customGrey, labelIcon: Assets.vec.convertCubeSvg.path, ); }, controller.expandedListIndex); }, itemCount: data.value.data?.results?.length ?? 0, separatorBuilder: (context, index) => SizedBox(height: 8.h), ); }, controller.segmentationList), ), Positioned( right: 10, bottom: 90.h, child: RFab.add( onPressed: () { Get.bottomSheet( addOrEditBottomSheet(), isScrollControlled: true, ignoreSafeArea: false, ).whenComplete(() { controller.clearForm(); //defaultShowSuccessMessage('با موفقیت ثبت شد'); }); }, ), ), ], ), ); } Widget filterBottomSheet() => filterBottomSheetWidget( fromDate: controller.fromDateFilter, onChangedFromDate: (jalali) => controller.fromDateFilter.value = jalali, toDate: controller.toDateFilter, onChangedToDate: (jalali) => controller.toDateFilter.value = jalali, onSubmit: () => controller.getAllSegmentation(), ); itemListWidget(SegmentationModel item) { return Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ SizedBox(width: 12), Expanded( flex: 3, child: Column( mainAxisAlignment: MainAxisAlignment.center, spacing: 4, children: [ Text( item.toGuild != null ? 'قطعه‌بند' : 'مباشر', textAlign: TextAlign.center, style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal), ), Text( item.date?.formattedJalaliDate ?? 'N/A', textAlign: TextAlign.center, style: AppFonts.yekan12.copyWith(color: AppColor.bgDark), ), ], ), ), SizedBox(width: 4), Expanded( flex: 5, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( item.toGuild != null ? item.toGuild?.user?.fullname ?? 'N/A' : item.buyer?.fullname ?? 'N/A', textAlign: TextAlign.center, style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal), ), SizedBox(height: 2), Text( item.toGuild != null ? item.toGuild?.guildsName ?? 'N/A' : item.buyer?.shop ?? 'N/A', textAlign: TextAlign.center, style: AppFonts.yekan14.copyWith(color: AppColor.bgDark), ), ], ), ), SizedBox(width: 4), Expanded( flex: 2, child: Column( spacing: 4, mainAxisAlignment: MainAxisAlignment.center, children: [ Text( item.weight.separatedByCommaFa.addKg, textAlign: TextAlign.center, textDirection: TextDirection.ltr, style: AppFonts.yekan14Bold.copyWith(color: AppColor.blueNormal), ), Text( item.saleType == "governmental" ? 'دولتی' : 'آزاد', textAlign: TextAlign.center, textDirection: TextDirection.ltr, style: AppFonts.yekan14Bold.copyWith( color: item.saleType == "governmental" ? AppColor.blueNormal : AppColor.greenNormal, ), ), ], ), ), ], ); } itemListExpandedWidget(SegmentationModel item, int index) { return Container( padding: EdgeInsets.symmetric(horizontal: 8), decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8)), child: Column( spacing: 8, children: [ Container( height: 32, padding: EdgeInsets.symmetric(horizontal: 8), decoration: ShapeDecoration( color: AppColor.blueLight, shape: RoundedRectangleBorder( side: BorderSide(width: 1, color: AppColor.blueLightHover), borderRadius: BorderRadius.circular(8), ), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( spacing: 3, children: [ Text( DateTimeExtensions(item.date)?.toJalali().formatter.wN ?? 'N/A', style: AppFonts.yekan14.copyWith(color: AppColor.textColor), ), Text( '${DateTimeExtensions(item.date)?.toJalali().formatter.d} ${DateTimeExtensions(item.date)?.toJalali().formatter.mN ?? 'N/A'}', style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal), ), ], ), Text( '${DateTimeExtensions(item.date)?.toJalali().formatter.y}', style: AppFonts.yekan20.copyWith(color: AppColor.textColor), ), Text( '${DateTimeExtensions(item.date)?.toJalali().formatter.tHH}:${DateTimeExtensions(item.date)?.toJalali().formatter.tMM ?? 'N/A'}', style: AppFonts.yekan14.copyWith(color: AppColor.textColor), ), ], ), ), buildRow( title: 'مشخصات خریدار', value: item.toGuild != null ? item.toGuild?.user?.fullname ?? 'N/A' : item.buyer?.fullname ?? 'N/A', ), buildRow( title: 'تلفن خریدار', value: item.toGuild != null ? item.toGuild?.user?.mobile ?? 'N/A' : item.buyer?.mobile ?? 'N/A', ), buildRow( title: 'نام واحد', value: item.toGuild != null ? item.toGuild?.guildsName ?? 'N/A' : item.buyer?.shop ?? 'N/A', ), buildRow(title: 'ماهیت', value: item.toGuild != null ? 'قطعه‌بند' : 'مباشر'), buildRow(title: 'نوع فروش', value: item.saleType == "governmental" ? 'دولتی' : 'آزاد'), buildRow(title: 'انبار فروش', value: item.quota == "governmental" ? 'دولتی' : 'آزاد'), buildRow( title: 'تاریخ تولید گوشت', value: item.productionDate?.toJalali.formatCompactDate() ?? 'ندارد', ), buildRow( title: 'وزن قطعه‌بندی', value: item.weight!.separatedByCommaFa, valueLabel: 'کیلوگرم', ), Row( mainAxisAlignment: MainAxisAlignment.center, spacing: 16.w, children: [ RElevated( text: 'ویرایش', width: 150.w, height: 40.h, onPressed: () { controller.setEditData(item); Get.bottomSheet( addOrEditBottomSheet(true), isScrollControlled: true, ignoreSafeArea: false, ).whenComplete(() { controller.clearForm(); }); }, textStyle: AppFonts.yekan20.copyWith(color: Colors.white), backgroundColor: AppColor.greenNormal, ), ROutlinedElevated( text: 'حذف', textStyle: AppFonts.yekan20.copyWith(color: AppColor.redNormal), width: 150.w, height: 40.h, onPressed: () { buildDeleteDialog( onConfirm: () async { controller.toggleExpansion(); controller.deleteSegmentation(item.key!); }, onRefresh: () => controller.onRefresh(), ); }, borderColor: AppColor.redNormal, ), ], ), ], ), ); } Widget addOrEditBottomSheet([bool isOnEdit = false]) { return BaseBottomSheet( height: isOnEdit ? 350.h : 650.h, child: SingleChildScrollView( child: Form( key: controller.formKey, child: Column( spacing: 16, children: [ Text( isOnEdit ? 'ویرایش قطعه‌بندی' : 'افزودن قطعه‌بندی', style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal), ), _productDropDown(), Visibility( visible: isOnEdit == false, child: Column( spacing: 12, children: [ Container( padding: EdgeInsets.all(8), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(8), border: Border.all(color: AppColor.darkGreyLight, width: 1), ), child: Column( children: [ const SizedBox(height: 8), SizedBox( height: 40, child: ObxValue((data) { return RadioGroup( onChanged: (value) { controller.segmentType.value = value!; controller.selectedGuildModel.value = null; controller.selectedGuildModel.refresh(); }, groupValue: controller.segmentType.value, child: Row( mainAxisAlignment: MainAxisAlignment.start, children: [ Radio(value: 1), Text('قطعه‌بندی(کاربر)', style: AppFonts.yekan14), SizedBox(width: 12), Radio(value: 2), Text('تخصیص به قطعه‌بند', style: AppFonts.yekan14), ], ), ); }, controller.saleType), ), const SizedBox(height: 12), ObxValue((data) { return Visibility(visible: data.value == 2, child: guildsDropDown()); }, controller.segmentType), ], ), ), Container( height: 50.h, clipBehavior: Clip.none, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(8), border: Border.all(color: AppColor.darkGreyLight, width: 1), ), child: Stack( fit: StackFit.expand, alignment: Alignment.center, clipBehavior: Clip.none, children: [ Positioned( child: Container(color: Colors.white, child: Text("نوع فروش")), top: -10, right: 8, ), Obx(() { return RadioGroup( groupValue: controller.saleType.value, onChanged: (value) { controller.saleType.value = 2 ?? 0; controller.selectedGuildModel.value = null; controller.selectedGuildModel.refresh(); }, child: Row( mainAxisAlignment: MainAxisAlignment.start, children: [ Expanded( child: GestureDetector( onTap: () { //controller.saleType.value = 1; }, child: Row( children: [ Radio(value: 1, enabled: false), Text( 'قیمت دولتی', style: AppFonts.yekan14.copyWith( color: AppColor.mediumGreyDark, ), ), ], ), ), ), Expanded( child: GestureDetector( onTap: () { controller.saleType.value = 2; }, child: Row( children: [ Radio(value: 2), Text('قیمت آزاد', style: AppFonts.yekan14), ], ), ), ), ], ), ); }), ], ), ), Container( height: 50.h, clipBehavior: Clip.none, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(8), border: Border.all(color: AppColor.darkGreyLight, width: 1), ), child: Stack( fit: StackFit.expand, alignment: Alignment.center, clipBehavior: Clip.none, children: [ Positioned( child: Container(color: Colors.white, child: Text("نوع انبار")), top: -10, right: 8, ), Obx(() { return RadioGroup( groupValue: controller.quotaType.value, onChanged: (value) { controller.quotaType.value = value ?? 0; }, child: Row( mainAxisAlignment: MainAxisAlignment.start, children: [ Expanded( child: GestureDetector( onTap: (controller .rootLogic .stewardSalesInfoDashboard .value ?.totalGovernmentalRemainWeight ?? -1) > 0 ? () { controller.quotaType.value = 1; } : null, child: Row( children: [ Radio( value: 1, enabled: (controller .rootLogic .stewardSalesInfoDashboard .value ?.totalGovernmentalRemainWeight ?? -1) > 0, ), Text( 'انبار دولتی', style: AppFonts.yekan14.copyWith( color: ((controller .rootLogic .stewardSalesInfoDashboard .value ?.totalGovernmentalRemainWeight ?? -1) > 0) ? AppColor.textColor : AppColor.labelTextColor, ), ), ], ), ), ), Expanded( child: GestureDetector( onTap: (controller .rootLogic .stewardSalesInfoDashboard .value ?.totalFreeRemainWeight ?? -1) > 0 ? () { controller.quotaType.value = 2; } : null, child: Row( children: [ Radio( value: 2, enabled: (controller .rootLogic .stewardSalesInfoDashboard .value ?.totalFreeRemainWeight ?? -1) > 0, ), Text( 'انبار آزاد', style: AppFonts.yekan14.copyWith( color: ((controller .rootLogic .stewardSalesInfoDashboard .value ?.totalFreeRemainWeight ?? -1) > 0) ? AppColor.textColor : AppColor.labelTextColor, ), ), ], ), ), ), ], ), ); }), ], ), ), Obx(() { return MonthlyDataCalendar( label: 'تاریخ تولید گوشت', selectedDate: controller.productionDate.value?.formatCompactDate(), onDateSelect: (value) => controller.productionDate..value = value.date, dayData: controller.quotaType.value == 1 ? controller.governmentalProductionDateData : controller.freeProductionDateData, ); }), ], ), ), Container( padding: EdgeInsets.all(8), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(8), border: Border.all(color: AppColor.darkGreyLight, width: 1), ), child: Column( spacing: 12, children: [ UnitTextField( hint: 'وزن', unit: 'کیلوگرم', controller: controller.weightController, inputFormatters: [ FilteringTextInputFormatter.digitsOnly, SeparatorInputFormatter(), ], validator: (value) { if (value == null) { return 'لطفاً وزن لاشه را وارد کنید'; } return null; }, ), submitButtonWidget(isOnEdit), ], ), ), SizedBox(), ], ), ), ), ); } Widget submitButtonWidget(bool isOnEdit) { return ObxValue((data) { return RElevated( isFullWidth: true, backgroundColor: AppColor.greenNormal, text: isOnEdit ? 'ویرایش' : 'ثبت', onPressed: data.value ? () async { var res = isOnEdit ? await controller.editSegment() : await controller.createSegment(); if (res) { Get.back(); } } : null, height: 40, ); }, controller.isSubmitButtonEnabled); } Widget _productDropDown() { return Obx(() { return OverlayDropdownWidget( items: controller.rootLogic.rolesProductsModel, height: 56, hasDropIcon: false, background: Colors.white, onChanged: (value) { controller.selectedProduct.value = value; }, selectedItem: controller.selectedProduct.value, initialValue: controller.selectedProduct.value, itemBuilder: (item) => Text(item.name ?? 'بدون نام'), labelBuilder: (item) => Row( spacing: 8, children: [ (item?.name?.contains('مرغ گرم') ?? false) ? Assets.images.chicken.image(width: 40, height: 40) : Assets.vec.placeHolderSvg.svg(width: 40, height: 40), Text(item?.name ?? 'انتخاب محصول'), Spacer(), Text( 'موجودی: ${controller.rootLogic.inventoryModel.value?.totalRemainWeight.separatedByCommaFa ?? 0} کیلوگرم', ), ], ), ); }); } Widget guildsDropDown() { return Obx(() { final item = controller.selectedGuildModel.value; return OverlayDropdownWidget( key: ValueKey(item?.user?.fullname ?? ''), items: controller.guildsModel, onChanged: (value) { controller.selectedGuildModel.value = value; }, selectedItem: item, itemBuilder: (item) => Text( item.user != null ? '${item.steward == true ? 'مباشر' : 'صنف'} ${item.user!.fullname} (${item.user!.mobile})' : 'بدون نام', ), labelBuilder: (item) => Text( item?.user != null ? '${item?.steward == true ? 'مباشر' : 'صنف'} ${item?.user!.fullname} (${item?.user!.mobile})' : 'انتخاب مباشر/صنف', ), ); }); } Container modalDatePicker(ValueChanged onDateSelected) { Jalali currentDate = Jalali.now(); Jalali? tempPickedDate; return Container( height: 250, color: Colors.white, child: Column( mainAxisSize: MainAxisSize.min, children: [ 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, maximumDate: currentDate.addDays(3), minimumDate: currentDate .toDateTime() .subtract(Duration(days: 1)) .toString() .toJalali, maximumYear: currentDate.year, minimumYear: currentDate.year, onDateTimeChanged: (dateTime) { tempPickedDate = dateTime; }, ), ), ), ], ), ); } }